change: UI and migrate to gtest
This commit is contained in:
+180
-181
@@ -23,6 +23,7 @@
|
||||
// layout) and every control-plane message build/parse pair. No Qt, no GL.
|
||||
|
||||
#include <assert.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -58,7 +59,7 @@ static void assert_json_eq(const char *produced, const char *expected)
|
||||
if (strcmp(produced, expected) != 0) {
|
||||
fprintf(stderr, "JSON mismatch:\n produced: %s\n expected: %s\n",
|
||||
produced, expected);
|
||||
assert(0);
|
||||
EXPECT_TRUE(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,79 +71,79 @@ static void test_shm(void)
|
||||
int needed = oakengine_ipc_shm_make_key(pid, 0, NULL, 0);
|
||||
char expected[64];
|
||||
snprintf(expected, sizeof(expected), "olive-rw-%lld-0", (long long)pid);
|
||||
assert(needed == (int)strlen(expected));
|
||||
assert(oakengine_ipc_shm_make_key(pid, 0, key, sizeof(key)) == needed);
|
||||
assert(strcmp(key, expected) == 0);
|
||||
assert(oakengine_ipc_shm_make_key(pid, 0, key, 6) == needed); // truncated
|
||||
assert(strcmp(key, "olive") == 0);
|
||||
EXPECT_TRUE(needed == (int)strlen(expected));
|
||||
EXPECT_TRUE(oakengine_ipc_shm_make_key(pid, 0, key, sizeof(key)) == needed);
|
||||
EXPECT_TRUE(strcmp(key, expected) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_make_key(pid, 0, key, 6) == needed); // truncated
|
||||
EXPECT_TRUE(strcmp(key, "olive") == 0);
|
||||
// A different worker index produces a different key.
|
||||
char key1[OAK_IPC_SHM_KEY_CAP];
|
||||
assert(oakengine_ipc_shm_make_key(pid, 1, key1, sizeof(key1)) == needed);
|
||||
assert(strcmp(key1, expected) != 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_make_key(pid, 1, key1, sizeof(key1)) == needed);
|
||||
EXPECT_TRUE(strcmp(key1, expected) != 0);
|
||||
|
||||
const int key_len = oakengine_ipc_shm_make_key(pid, 0, key, sizeof(key));
|
||||
(void)key_len;
|
||||
|
||||
// Attaching to a missing segment fails and reports an error.
|
||||
OakSharedMemoryRegion *missing = oakengine_ipc_shm_create();
|
||||
assert(oakengine_ipc_shm_open(missing, key, 4096,
|
||||
EXPECT_TRUE(oakengine_ipc_shm_open(missing, key, 4096,
|
||||
OAK_IPC_SHM_MODE_ATTACH) == 0);
|
||||
assert(oakengine_ipc_shm_is_valid(missing) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_is_valid(missing) == 0);
|
||||
char err[256];
|
||||
assert(oakengine_ipc_shm_error(missing, err, sizeof(err)) > 0);
|
||||
assert(strlen(err) > 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_error(missing, err, sizeof(err)) > 0);
|
||||
EXPECT_TRUE(strlen(err) > 0);
|
||||
oakengine_ipc_shm_free(missing);
|
||||
|
||||
// Create the owner: valid, sized, zero-initialized.
|
||||
OakSharedMemoryRegion *owner = oakengine_ipc_shm_create();
|
||||
assert(oakengine_ipc_shm_open(owner, key, 8192, OAK_IPC_SHM_MODE_CREATE) ==
|
||||
EXPECT_TRUE(oakengine_ipc_shm_open(owner, key, 8192, OAK_IPC_SHM_MODE_CREATE) ==
|
||||
1);
|
||||
assert(oakengine_ipc_shm_is_valid(owner) == 1);
|
||||
assert(oakengine_ipc_shm_size(owner) == 8192);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_is_valid(owner) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_size(owner) == 8192);
|
||||
unsigned char *data = (unsigned char *)oakengine_ipc_shm_data(owner);
|
||||
assert(data != NULL);
|
||||
EXPECT_TRUE(data != NULL);
|
||||
for (int i = 0; i < 8192; i++) {
|
||||
assert(data[i] == 0);
|
||||
EXPECT_TRUE(data[i] == 0);
|
||||
}
|
||||
|
||||
// key() round-trips the opened key.
|
||||
char opened_key[OAK_IPC_SHM_KEY_CAP];
|
||||
assert(oakengine_ipc_shm_key(owner, opened_key, sizeof(opened_key)) ==
|
||||
EXPECT_TRUE(oakengine_ipc_shm_key(owner, opened_key, sizeof(opened_key)) ==
|
||||
key_len);
|
||||
assert(strcmp(opened_key, key) == 0);
|
||||
EXPECT_TRUE(strcmp(opened_key, key) == 0);
|
||||
|
||||
// A peer attaches by the same key and sees the owner's bytes.
|
||||
data[0] = 0xAB;
|
||||
data[8191] = 0xCD;
|
||||
OakSharedMemoryRegion *peer = oakengine_ipc_shm_create();
|
||||
assert(oakengine_ipc_shm_open(peer, key, 8192, OAK_IPC_SHM_MODE_ATTACH) ==
|
||||
EXPECT_TRUE(oakengine_ipc_shm_open(peer, key, 8192, OAK_IPC_SHM_MODE_ATTACH) ==
|
||||
1);
|
||||
assert(oakengine_ipc_shm_size(peer) == 8192);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_size(peer) == 8192);
|
||||
const unsigned char *peer_data =
|
||||
(const unsigned char *)oakengine_ipc_shm_data(peer);
|
||||
assert(peer_data[0] == 0xAB && peer_data[8191] == 0xCD);
|
||||
EXPECT_TRUE(peer_data[0] == 0xAB && peer_data[8191] == 0xCD);
|
||||
peer_data = NULL;
|
||||
|
||||
// The peer closes without unlinking; the owner stays valid.
|
||||
oakengine_ipc_shm_close(peer);
|
||||
assert(oakengine_ipc_shm_is_valid(peer) == 0);
|
||||
assert(oakengine_ipc_shm_is_valid(owner) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_is_valid(peer) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_is_valid(owner) == 1);
|
||||
oakengine_ipc_shm_free(peer);
|
||||
|
||||
// The owner unlinks on close: a late attach must fail.
|
||||
oakengine_ipc_shm_close(owner);
|
||||
assert(oakengine_ipc_shm_is_valid(owner) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_is_valid(owner) == 0);
|
||||
OakSharedMemoryRegion *late = oakengine_ipc_shm_create();
|
||||
assert(oakengine_ipc_shm_open(late, key, 8192, OAK_IPC_SHM_MODE_ATTACH) ==
|
||||
EXPECT_TRUE(oakengine_ipc_shm_open(late, key, 8192, OAK_IPC_SHM_MODE_ATTACH) ==
|
||||
0);
|
||||
oakengine_ipc_shm_free(late);
|
||||
oakengine_ipc_shm_free(owner);
|
||||
|
||||
// NULL safety.
|
||||
oakengine_ipc_shm_close(NULL);
|
||||
assert(oakengine_ipc_shm_is_valid(NULL) == 0);
|
||||
assert(oakengine_ipc_shm_data(NULL) == NULL);
|
||||
assert(oakengine_ipc_shm_size(NULL) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_is_valid(NULL) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_data(NULL) == NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_size(NULL) == 0);
|
||||
oakengine_ipc_shm_free(NULL);
|
||||
}
|
||||
|
||||
@@ -152,51 +153,51 @@ static void test_framepool(void)
|
||||
const size_t k_slot_bytes = 256;
|
||||
|
||||
// bytes_needed stays 64-aligned and grows with geometry.
|
||||
assert(oakengine_ipc_framepool_bytes_needed(k_slots, k_slot_bytes) % 64 ==
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_bytes_needed(k_slots, k_slot_bytes) % 64 ==
|
||||
0);
|
||||
assert(oakengine_ipc_framepool_bytes_needed(2, 65) ==
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_bytes_needed(2, 65) ==
|
||||
oakengine_ipc_framepool_bytes_needed(2, 128));
|
||||
assert(oakengine_ipc_framepool_bytes_needed(1, 64) <
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_bytes_needed(1, 64) <
|
||||
oakengine_ipc_framepool_bytes_needed(2, 64));
|
||||
|
||||
const size_t bytes =
|
||||
oakengine_ipc_framepool_bytes_needed(k_slots, k_slot_bytes);
|
||||
void *mem = malloc(bytes);
|
||||
assert(mem != NULL);
|
||||
EXPECT_TRUE(mem != NULL);
|
||||
|
||||
OakFrameSlotPool *filler =
|
||||
oakengine_ipc_framepool_create(mem, k_slots, k_slot_bytes);
|
||||
assert(filler != NULL);
|
||||
assert(oakengine_ipc_framepool_is_valid(filler) == 1);
|
||||
assert(oakengine_ipc_framepool_slot_count(filler) == k_slots);
|
||||
assert(oakengine_ipc_framepool_slot_data_bytes(filler) == k_slot_bytes);
|
||||
EXPECT_TRUE(filler != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_is_valid(filler) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_slot_count(filler) == k_slots);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_slot_data_bytes(filler) == k_slot_bytes);
|
||||
|
||||
// Peer maps the same memory; a copy of the handle views it too.
|
||||
OakFrameSlotPool *drainer = oakengine_ipc_framepool_attach(mem);
|
||||
assert(oakengine_ipc_framepool_is_valid(drainer) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_is_valid(drainer) == 1);
|
||||
OakFrameSlotPool *drainer_copy = oakengine_ipc_framepool_copy(drainer);
|
||||
assert(drainer_copy != NULL && drainer_copy != drainer);
|
||||
assert(oakengine_ipc_framepool_slot_count(drainer_copy) == k_slots);
|
||||
EXPECT_TRUE(drainer_copy != NULL && drainer_copy != drainer);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_slot_count(drainer_copy) == k_slots);
|
||||
|
||||
// Free slots are issued FIFO; the pool then reports exhausted.
|
||||
uint32_t held[3];
|
||||
for (uint32_t i = 0; i < k_slots; i++) {
|
||||
assert(oakengine_ipc_framepool_acquire(filler, &held[i]) == 1);
|
||||
assert(held[i] == i);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_acquire(filler, &held[i]) == 1);
|
||||
EXPECT_TRUE(held[i] == i);
|
||||
}
|
||||
uint32_t overflow = 99;
|
||||
assert(oakengine_ipc_framepool_acquire(filler, &overflow) == 0);
|
||||
assert(overflow == 99);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_acquire(filler, &overflow) == 0);
|
||||
EXPECT_TRUE(overflow == 99);
|
||||
|
||||
// Fill slot 0 with a pattern + full metadata and publish it.
|
||||
unsigned char *data =
|
||||
(unsigned char *)oakengine_ipc_framepool_slot_data(filler, held[0]);
|
||||
assert(data != NULL);
|
||||
EXPECT_TRUE(data != NULL);
|
||||
for (size_t i = 0; i < k_slot_bytes; i++) {
|
||||
data[i] = (unsigned char)(i & 0xFF);
|
||||
}
|
||||
oak_frame_slot_meta *meta = oakengine_ipc_framepool_meta(filler, held[0]);
|
||||
assert(meta != NULL);
|
||||
EXPECT_TRUE(meta != NULL);
|
||||
meta->id = -4242;
|
||||
meta->time_num = 1001;
|
||||
meta->time_den = 30000;
|
||||
@@ -208,48 +209,48 @@ static void test_framepool(void)
|
||||
meta->data_size = (int32_t)k_slot_bytes;
|
||||
strncpy(meta->colorspace, "acescg", sizeof(meta->colorspace) - 1);
|
||||
meta->colorspace[sizeof(meta->colorspace) - 1] = '\0';
|
||||
assert(oakengine_ipc_framepool_publish(filler, held[0]) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_publish(filler, held[0]) == 1);
|
||||
|
||||
// Publish slot 2 then slot 1: consume order follows publish order.
|
||||
assert(oakengine_ipc_framepool_publish(filler, held[2]) == 1);
|
||||
assert(oakengine_ipc_framepool_publish(filler, held[1]) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_publish(filler, held[2]) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_publish(filler, held[1]) == 1);
|
||||
|
||||
uint32_t got = 99;
|
||||
assert(oakengine_ipc_framepool_consume(drainer, &got) == 1);
|
||||
assert(got == held[0]);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_consume(drainer, &got) == 1);
|
||||
EXPECT_TRUE(got == held[0]);
|
||||
|
||||
// Metadata and pixels arrive intact on the drainer side.
|
||||
const oak_frame_slot_meta *out =
|
||||
oakengine_ipc_framepool_meta_const(drainer, got);
|
||||
assert(out != NULL);
|
||||
assert(out->id == -4242);
|
||||
assert(out->time_num == 1001 && out->time_den == 30000);
|
||||
assert(out->width == 3840 && out->height == 2160);
|
||||
assert(out->format == 17 && out->channel_count == 4);
|
||||
assert(out->linesize == 3840 * 4 * 4);
|
||||
assert(out->data_size == (int32_t)k_slot_bytes);
|
||||
assert(strcmp(out->colorspace, "acescg") == 0);
|
||||
EXPECT_TRUE(out != NULL);
|
||||
EXPECT_TRUE(out->id == -4242);
|
||||
EXPECT_TRUE(out->time_num == 1001 && out->time_den == 30000);
|
||||
EXPECT_TRUE(out->width == 3840 && out->height == 2160);
|
||||
EXPECT_TRUE(out->format == 17 && out->channel_count == 4);
|
||||
EXPECT_TRUE(out->linesize == 3840 * 4 * 4);
|
||||
EXPECT_TRUE(out->data_size == (int32_t)k_slot_bytes);
|
||||
EXPECT_TRUE(strcmp(out->colorspace, "acescg") == 0);
|
||||
const unsigned char *out_data =
|
||||
(const unsigned char *)oakengine_ipc_framepool_slot_data_const(drainer,
|
||||
got);
|
||||
assert(out_data != NULL);
|
||||
EXPECT_TRUE(out_data != NULL);
|
||||
for (size_t i = 0; i < k_slot_bytes; i++) {
|
||||
assert(out_data[i] == (unsigned char)(i & 0xFF));
|
||||
EXPECT_TRUE(out_data[i] == (unsigned char)(i & 0xFF));
|
||||
}
|
||||
assert(oakengine_ipc_framepool_release(drainer, got) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_release(drainer, got) == 1);
|
||||
|
||||
// The copied handle consumes the remaining slots in publish order.
|
||||
assert(oakengine_ipc_framepool_consume(drainer_copy, &got) == 1);
|
||||
assert(got == held[2]);
|
||||
assert(oakengine_ipc_framepool_release(drainer_copy, got) == 1);
|
||||
assert(oakengine_ipc_framepool_consume(drainer_copy, &got) == 1);
|
||||
assert(got == held[1]);
|
||||
assert(oakengine_ipc_framepool_release(drainer_copy, got) == 1);
|
||||
assert(oakengine_ipc_framepool_consume(drainer, &got) == 0); // drained
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_consume(drainer_copy, &got) == 1);
|
||||
EXPECT_TRUE(got == held[2]);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_release(drainer_copy, got) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_consume(drainer_copy, &got) == 1);
|
||||
EXPECT_TRUE(got == held[1]);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_release(drainer_copy, got) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_consume(drainer, &got) == 0); // drained
|
||||
|
||||
// Released slots cycle back to the filler.
|
||||
uint32_t again = 0;
|
||||
assert(oakengine_ipc_framepool_acquire(filler, &again) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_acquire(filler, &again) == 1);
|
||||
|
||||
oakengine_ipc_framepool_free(drainer_copy);
|
||||
oakengine_ipc_framepool_free(drainer);
|
||||
@@ -258,21 +259,21 @@ static void test_framepool(void)
|
||||
|
||||
// A region without the pool magic attaches as invalid.
|
||||
void *raw = calloc(1, oakengine_ipc_framepool_bytes_needed(2, 64));
|
||||
assert(raw != NULL);
|
||||
EXPECT_TRUE(raw != NULL);
|
||||
OakFrameSlotPool *bad = oakengine_ipc_framepool_attach(raw);
|
||||
assert(bad != NULL);
|
||||
assert(oakengine_ipc_framepool_is_valid(bad) == 0);
|
||||
assert(oakengine_ipc_framepool_slot_count(bad) == 0);
|
||||
assert(oakengine_ipc_framepool_slot_data_bytes(bad) == 0);
|
||||
EXPECT_TRUE(bad != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_is_valid(bad) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_slot_count(bad) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_slot_data_bytes(bad) == 0);
|
||||
oakengine_ipc_framepool_free(bad);
|
||||
free(raw);
|
||||
|
||||
// NULL safety.
|
||||
assert(oakengine_ipc_framepool_is_valid(NULL) == 0);
|
||||
assert(oakengine_ipc_framepool_slot_count(NULL) == 0);
|
||||
assert(oakengine_ipc_framepool_slot_data(NULL, 0) == NULL);
|
||||
assert(oakengine_ipc_framepool_meta(NULL, 0) == NULL);
|
||||
assert(oakengine_ipc_framepool_acquire(NULL, &again) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_is_valid(NULL) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_slot_count(NULL) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_slot_data(NULL, 0) == NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_meta(NULL, 0) == NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_acquire(NULL, &again) == 0);
|
||||
oakengine_ipc_framepool_free(NULL);
|
||||
}
|
||||
|
||||
@@ -280,7 +281,7 @@ static void test_framepool(void)
|
||||
static void test_framepool_over_shm(void)
|
||||
{
|
||||
char key[OAK_IPC_SHM_KEY_CAP];
|
||||
assert(oakengine_ipc_shm_make_key(getpid(), 7, key, sizeof(key)) > 0);
|
||||
EXPECT_TRUE(oakengine_ipc_shm_make_key(getpid(), 7, key, sizeof(key)) > 0);
|
||||
|
||||
const uint32_t k_slots = 2;
|
||||
const size_t k_slot_bytes = 64;
|
||||
@@ -288,35 +289,35 @@ static void test_framepool_over_shm(void)
|
||||
oakengine_ipc_framepool_bytes_needed(k_slots, k_slot_bytes);
|
||||
|
||||
OakSharedMemoryRegion *owner = oakengine_ipc_shm_create();
|
||||
assert(oakengine_ipc_shm_open(owner, key, bytes, OAK_IPC_SHM_MODE_CREATE) ==
|
||||
EXPECT_TRUE(oakengine_ipc_shm_open(owner, key, bytes, OAK_IPC_SHM_MODE_CREATE) ==
|
||||
1);
|
||||
OakSharedMemoryRegion *peer = oakengine_ipc_shm_create();
|
||||
assert(oakengine_ipc_shm_open(peer, key, bytes, OAK_IPC_SHM_MODE_ATTACH) ==
|
||||
EXPECT_TRUE(oakengine_ipc_shm_open(peer, key, bytes, OAK_IPC_SHM_MODE_ATTACH) ==
|
||||
1);
|
||||
|
||||
OakFrameSlotPool *filler = oakengine_ipc_framepool_create(
|
||||
oakengine_ipc_shm_data(owner), k_slots, k_slot_bytes);
|
||||
OakFrameSlotPool *drainer = oakengine_ipc_framepool_attach(
|
||||
oakengine_ipc_shm_data(peer));
|
||||
assert(oakengine_ipc_framepool_is_valid(filler) == 1);
|
||||
assert(oakengine_ipc_framepool_is_valid(drainer) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_is_valid(filler) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_is_valid(drainer) == 1);
|
||||
|
||||
uint32_t idx = 0;
|
||||
assert(oakengine_ipc_framepool_acquire(filler, &idx) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_acquire(filler, &idx) == 1);
|
||||
oak_frame_slot_meta *meta = oakengine_ipc_framepool_meta(filler, idx);
|
||||
meta->id = 77;
|
||||
meta->data_size = (int32_t)k_slot_bytes;
|
||||
memset(oakengine_ipc_framepool_slot_data(filler, idx), 0x5A, k_slot_bytes);
|
||||
assert(oakengine_ipc_framepool_publish(filler, idx) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_publish(filler, idx) == 1);
|
||||
|
||||
uint32_t got = 0;
|
||||
assert(oakengine_ipc_framepool_consume(drainer, &got) == 1);
|
||||
assert(got == idx);
|
||||
assert(oakengine_ipc_framepool_meta_const(drainer, got)->id == 77);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_consume(drainer, &got) == 1);
|
||||
EXPECT_TRUE(got == idx);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_meta_const(drainer, got)->id == 77);
|
||||
const unsigned char *d = (const unsigned char *)
|
||||
oakengine_ipc_framepool_slot_data_const(drainer, got);
|
||||
assert(d[0] == 0x5A && d[k_slot_bytes - 1] == 0x5A);
|
||||
assert(oakengine_ipc_framepool_release(drainer, got) == 1);
|
||||
EXPECT_TRUE(d[0] == 0x5A && d[k_slot_bytes - 1] == 0x5A);
|
||||
EXPECT_TRUE(oakengine_ipc_framepool_release(drainer, got) == 1);
|
||||
|
||||
oakengine_ipc_framepool_free(drainer);
|
||||
oakengine_ipc_framepool_free(filler);
|
||||
@@ -337,28 +338,28 @@ static void test_handshake(void)
|
||||
hs.input_slot_data_bytes = 128ll * 1024 * 1024;
|
||||
|
||||
const int needed = oakengine_ipc_handshake_to_json(&hs, NULL, 0);
|
||||
assert(needed > 0);
|
||||
EXPECT_TRUE(needed > 0);
|
||||
char *json = (char *)malloc(size_t(needed) + 1);
|
||||
assert(json != NULL);
|
||||
assert(oakengine_ipc_handshake_to_json(&hs, json, needed + 1) == needed);
|
||||
assert((int)strlen(json) == needed);
|
||||
EXPECT_TRUE(json != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_to_json(&hs, json, needed + 1) == needed);
|
||||
EXPECT_TRUE((int)strlen(json) == needed);
|
||||
|
||||
// buf/size convention: a short buffer truncates but reports the full size.
|
||||
char tiny[8];
|
||||
assert(oakengine_ipc_handshake_to_json(&hs, tiny, sizeof(tiny)) == needed);
|
||||
assert(strlen(tiny) == sizeof(tiny) - 1);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_to_json(&hs, tiny, sizeof(tiny)) == needed);
|
||||
EXPECT_TRUE(strlen(tiny) == sizeof(tiny) - 1);
|
||||
|
||||
assert(oakengine_ipc_message_type(json) == OAK_IPC_MSGTYPE_HANDSHAKE);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type(json) == OAK_IPC_MSGTYPE_HANDSHAKE);
|
||||
|
||||
oak_ipc_handshake back;
|
||||
assert(oakengine_ipc_handshake_parse(json, &back) == 1);
|
||||
assert(back.protocol_version == hs.protocol_version);
|
||||
assert(strcmp(back.shm_key, hs.shm_key) == 0);
|
||||
assert(strcmp(back.input_shm_key, hs.input_shm_key) == 0);
|
||||
assert(back.input_slots == hs.input_slots);
|
||||
assert(back.output_slots == hs.output_slots);
|
||||
assert(back.slot_data_bytes == hs.slot_data_bytes);
|
||||
assert(back.input_slot_data_bytes == hs.input_slot_data_bytes);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_parse(json, &back) == 1);
|
||||
EXPECT_TRUE(back.protocol_version == hs.protocol_version);
|
||||
EXPECT_TRUE(strcmp(back.shm_key, hs.shm_key) == 0);
|
||||
EXPECT_TRUE(strcmp(back.input_shm_key, hs.input_shm_key) == 0);
|
||||
EXPECT_TRUE(back.input_slots == hs.input_slots);
|
||||
EXPECT_TRUE(back.output_slots == hs.output_slots);
|
||||
EXPECT_TRUE(back.slot_data_bytes == hs.slot_data_bytes);
|
||||
EXPECT_TRUE(back.input_slot_data_bytes == hs.input_slot_data_bytes);
|
||||
free(json);
|
||||
|
||||
// Exact wire text: same field names and compact shape the Qt builder emits.
|
||||
@@ -373,8 +374,8 @@ static void test_handshake(void)
|
||||
small.input_slot_data_bytes = 128;
|
||||
const int n2 = oakengine_ipc_handshake_to_json(&small, NULL, 0);
|
||||
char *json2 = (char *)malloc(size_t(n2) + 1);
|
||||
assert(json2 != NULL);
|
||||
assert(oakengine_ipc_handshake_to_json(&small, json2, n2 + 1) == n2);
|
||||
EXPECT_TRUE(json2 != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_to_json(&small, json2, n2 + 1) == n2);
|
||||
assert_json_eq(json2,
|
||||
"{\"input_shm_key\":\"in\",\"input_slot_data_bytes\":128,"
|
||||
"\"input_slots\":4,\"output_slots\":6,\"protocol_version\":1,"
|
||||
@@ -382,9 +383,9 @@ static void test_handshake(void)
|
||||
"\"type\":\"handshake\"}");
|
||||
free(json2);
|
||||
|
||||
assert(oakengine_ipc_handshake_to_json(NULL, NULL, 0) == -1);
|
||||
assert(oakengine_ipc_handshake_parse("not json", &back) == 0);
|
||||
assert(oakengine_ipc_handshake_parse(NULL, &back) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_to_json(NULL, NULL, 0) == -1);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_parse("not json", &back) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_parse(NULL, &back) == 0);
|
||||
}
|
||||
|
||||
static void test_render_frame(void)
|
||||
@@ -412,26 +413,26 @@ static void test_render_frame(void)
|
||||
|
||||
const int needed = oakengine_ipc_render_frame_to_json(&rf, NULL, 0);
|
||||
char *json = (char *)malloc(size_t(needed) + 1);
|
||||
assert(json != NULL);
|
||||
assert(oakengine_ipc_render_frame_to_json(&rf, json, needed + 1) == needed);
|
||||
assert(oakengine_ipc_message_type(json) == OAK_IPC_MSGTYPE_RENDER_FRAME);
|
||||
EXPECT_TRUE(json != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_render_frame_to_json(&rf, json, needed + 1) == needed);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type(json) == OAK_IPC_MSGTYPE_RENDER_FRAME);
|
||||
|
||||
oak_ipc_render_frame back;
|
||||
assert(oakengine_ipc_render_frame_parse(json, &back) == 1);
|
||||
assert(back.ticket_id == rf.ticket_id);
|
||||
assert(strcmp(back.node_uuid, rf.node_uuid) == 0);
|
||||
assert(back.time_num == rf.time_num);
|
||||
assert(back.time_den == rf.time_den);
|
||||
assert(back.width == rf.width && back.height == rf.height);
|
||||
assert(back.format == rf.format && back.channel_count == rf.channel_count);
|
||||
assert(back.mode == rf.mode);
|
||||
assert(back.input_slot == rf.input_slot);
|
||||
assert(back.input_slot_count == 2);
|
||||
assert(back.input_slots[0] == 2 && back.input_slots[1] == 3);
|
||||
assert(back.has_color_transform == 1 && back.color_is_display == 1);
|
||||
assert(strcmp(back.color_output, rf.color_output) == 0);
|
||||
assert(strcmp(back.color_view, rf.color_view) == 0);
|
||||
assert(strcmp(back.color_look, rf.color_look) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_render_frame_parse(json, &back) == 1);
|
||||
EXPECT_TRUE(back.ticket_id == rf.ticket_id);
|
||||
EXPECT_TRUE(strcmp(back.node_uuid, rf.node_uuid) == 0);
|
||||
EXPECT_TRUE(back.time_num == rf.time_num);
|
||||
EXPECT_TRUE(back.time_den == rf.time_den);
|
||||
EXPECT_TRUE(back.width == rf.width && back.height == rf.height);
|
||||
EXPECT_TRUE(back.format == rf.format && back.channel_count == rf.channel_count);
|
||||
EXPECT_TRUE(back.mode == rf.mode);
|
||||
EXPECT_TRUE(back.input_slot == rf.input_slot);
|
||||
EXPECT_TRUE(back.input_slot_count == 2);
|
||||
EXPECT_TRUE(back.input_slots[0] == 2 && back.input_slots[1] == 3);
|
||||
EXPECT_TRUE(back.has_color_transform == 1 && back.color_is_display == 1);
|
||||
EXPECT_TRUE(strcmp(back.color_output, rf.color_output) == 0);
|
||||
EXPECT_TRUE(strcmp(back.color_view, rf.color_view) == 0);
|
||||
EXPECT_TRUE(strcmp(back.color_look, rf.color_look) == 0);
|
||||
free(json);
|
||||
|
||||
// Without a color transform the color keys are omitted from the wire text.
|
||||
@@ -452,9 +453,9 @@ static void test_render_frame(void)
|
||||
plain.input_slot_count = 2;
|
||||
const int n2 = oakengine_ipc_render_frame_to_json(&plain, NULL, 0);
|
||||
char *json2 = (char *)malloc(size_t(n2) + 1);
|
||||
assert(json2 != NULL);
|
||||
assert(oakengine_ipc_render_frame_to_json(&plain, json2, n2 + 1) == n2);
|
||||
assert(strstr(json2, "has_color_transform") == NULL);
|
||||
EXPECT_TRUE(json2 != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_render_frame_to_json(&plain, json2, n2 + 1) == n2);
|
||||
EXPECT_TRUE(strstr(json2, "has_color_transform") == NULL);
|
||||
assert_json_eq(json2,
|
||||
"{\"channels\":4,\"format\":3,\"height\":1080,"
|
||||
"\"input_slot\":2,\"input_slots\":[2,3],\"mode\":1,"
|
||||
@@ -464,32 +465,32 @@ static void test_render_frame(void)
|
||||
|
||||
// Defaults for a sparse message, mirroring the Qt from_json defaults.
|
||||
oak_ipc_render_frame sparse;
|
||||
assert(oakengine_ipc_render_frame_parse("{\"type\":\"render_frame\"}",
|
||||
EXPECT_TRUE(oakengine_ipc_render_frame_parse("{\"type\":\"render_frame\"}",
|
||||
&sparse) == 1);
|
||||
assert(sparse.ticket_id == 0);
|
||||
assert(sparse.time_num == 0 && sparse.time_den == 1);
|
||||
assert(sparse.width == 0 && sparse.height == 0);
|
||||
assert(sparse.format == -1 && sparse.channel_count == 0 && sparse.mode == 0);
|
||||
assert(sparse.input_slot == -1 && sparse.input_slot_count == 0);
|
||||
assert(sparse.has_color_transform == 0);
|
||||
EXPECT_TRUE(sparse.ticket_id == 0);
|
||||
EXPECT_TRUE(sparse.time_num == 0 && sparse.time_den == 1);
|
||||
EXPECT_TRUE(sparse.width == 0 && sparse.height == 0);
|
||||
EXPECT_TRUE(sparse.format == -1 && sparse.channel_count == 0 && sparse.mode == 0);
|
||||
EXPECT_TRUE(sparse.input_slot == -1 && sparse.input_slot_count == 0);
|
||||
EXPECT_TRUE(sparse.has_color_transform == 0);
|
||||
|
||||
// Legacy scalar input_slot folds into the array when it is absent.
|
||||
oak_ipc_render_frame legacy;
|
||||
assert(oakengine_ipc_render_frame_parse(
|
||||
EXPECT_TRUE(oakengine_ipc_render_frame_parse(
|
||||
"{\"type\":\"render_frame\",\"ticket\":5,\"input_slot\":3}",
|
||||
&legacy) == 1);
|
||||
assert(legacy.input_slot == 3);
|
||||
assert(legacy.input_slot_count == 1 && legacy.input_slots[0] == 3);
|
||||
EXPECT_TRUE(legacy.input_slot == 3);
|
||||
EXPECT_TRUE(legacy.input_slot_count == 1 && legacy.input_slots[0] == 3);
|
||||
|
||||
// Type mismatches are rejected.
|
||||
oak_ipc_handshake hs;
|
||||
memset(&hs, 0, sizeof(hs));
|
||||
const int hn = oakengine_ipc_handshake_to_json(&hs, NULL, 0);
|
||||
char *hjson = (char *)malloc(size_t(hn) + 1);
|
||||
assert(hjson != NULL);
|
||||
assert(oakengine_ipc_handshake_to_json(&hs, hjson, hn + 1) == hn);
|
||||
assert(oakengine_ipc_render_frame_parse(hjson, &back) == 0);
|
||||
assert(oakengine_ipc_handshake_parse(hjson, &hs) == 1);
|
||||
EXPECT_TRUE(hjson != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_to_json(&hs, hjson, hn + 1) == hn);
|
||||
EXPECT_TRUE(oakengine_ipc_render_frame_parse(hjson, &back) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_handshake_parse(hjson, &hs) == 1);
|
||||
free(hjson);
|
||||
}
|
||||
|
||||
@@ -501,13 +502,13 @@ static void test_small_messages(void)
|
||||
fr.output_slot = 2;
|
||||
const int fn = oakengine_ipc_frame_ready_to_json(&fr, NULL, 0);
|
||||
char *fjson = (char *)malloc(size_t(fn) + 1);
|
||||
assert(fjson != NULL);
|
||||
assert(oakengine_ipc_frame_ready_to_json(&fr, fjson, fn + 1) == fn);
|
||||
EXPECT_TRUE(fjson != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_frame_ready_to_json(&fr, fjson, fn + 1) == fn);
|
||||
assert_json_eq(fjson, "{\"slot\":2,\"ticket\":99,\"type\":\"frame_ready\"}");
|
||||
assert(oakengine_ipc_message_type(fjson) == OAK_IPC_MSGTYPE_FRAME_READY);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type(fjson) == OAK_IPC_MSGTYPE_FRAME_READY);
|
||||
oak_ipc_frame_ready fr_back;
|
||||
assert(oakengine_ipc_frame_ready_parse(fjson, &fr_back) == 1);
|
||||
assert(fr_back.ticket_id == 99 && fr_back.output_slot == 2);
|
||||
EXPECT_TRUE(oakengine_ipc_frame_ready_parse(fjson, &fr_back) == 1);
|
||||
EXPECT_TRUE(fr_back.ticket_id == 99 && fr_back.output_slot == 2);
|
||||
free(fjson);
|
||||
|
||||
// cancel
|
||||
@@ -515,15 +516,15 @@ static void test_small_messages(void)
|
||||
cancel.ticket_id = 7;
|
||||
const int cn = oakengine_ipc_cancel_to_json(&cancel, NULL, 0);
|
||||
char *cjson = (char *)malloc(size_t(cn) + 1);
|
||||
assert(cjson != NULL);
|
||||
assert(oakengine_ipc_cancel_to_json(&cancel, cjson, cn + 1) == cn);
|
||||
EXPECT_TRUE(cjson != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_cancel_to_json(&cancel, cjson, cn + 1) == cn);
|
||||
assert_json_eq(cjson, "{\"ticket\":7,\"type\":\"cancel\"}");
|
||||
assert(oakengine_ipc_message_type(cjson) == OAK_IPC_MSGTYPE_CANCEL);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type(cjson) == OAK_IPC_MSGTYPE_CANCEL);
|
||||
oak_ipc_cancel cancel_back;
|
||||
assert(oakengine_ipc_cancel_parse(cjson, &cancel_back) == 1);
|
||||
assert(cancel_back.ticket_id == 7);
|
||||
EXPECT_TRUE(oakengine_ipc_cancel_parse(cjson, &cancel_back) == 1);
|
||||
EXPECT_TRUE(cancel_back.ticket_id == 7);
|
||||
// cancel rejects a frame_ready payload.
|
||||
assert(oakengine_ipc_cancel_parse("{\"slot\":2,\"ticket\":7,\"type\":"
|
||||
EXPECT_TRUE(oakengine_ipc_cancel_parse("{\"slot\":2,\"ticket\":7,\"type\":"
|
||||
"\"frame_ready\"}",
|
||||
&cancel_back) == 0);
|
||||
free(cjson);
|
||||
@@ -533,51 +534,51 @@ static void test_small_messages(void)
|
||||
strcpy(load.path, "/tmp/oak-render-graph-abc123.ove");
|
||||
const int ln = oakengine_ipc_load_graph_to_json(&load, NULL, 0);
|
||||
char *ljson = (char *)malloc(size_t(ln) + 1);
|
||||
assert(ljson != NULL);
|
||||
assert(oakengine_ipc_load_graph_to_json(&load, ljson, ln + 1) == ln);
|
||||
EXPECT_TRUE(ljson != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_load_graph_to_json(&load, ljson, ln + 1) == ln);
|
||||
assert_json_eq(ljson,
|
||||
"{\"path\":\"/tmp/oak-render-graph-abc123.ove\",\"type\":"
|
||||
"\"load_graph\"}");
|
||||
assert(oakengine_ipc_message_type(ljson) == OAK_IPC_MSGTYPE_LOAD_GRAPH);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type(ljson) == OAK_IPC_MSGTYPE_LOAD_GRAPH);
|
||||
oak_ipc_load_graph load_back;
|
||||
assert(oakengine_ipc_load_graph_parse(ljson, &load_back) == 1);
|
||||
assert(strcmp(load_back.path, load.path) == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_load_graph_parse(ljson, &load_back) == 1);
|
||||
EXPECT_TRUE(strcmp(load_back.path, load.path) == 0);
|
||||
free(ljson);
|
||||
|
||||
// shutdown
|
||||
const int sn = oakengine_ipc_shutdown_to_json(NULL, 0);
|
||||
char *sjson = (char *)malloc(size_t(sn) + 1);
|
||||
assert(sjson != NULL);
|
||||
assert(oakengine_ipc_shutdown_to_json(sjson, sn + 1) == sn);
|
||||
EXPECT_TRUE(sjson != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_shutdown_to_json(sjson, sn + 1) == sn);
|
||||
assert_json_eq(sjson, "{\"type\":\"shutdown\"}");
|
||||
assert(oakengine_ipc_shutdown_parse(sjson) == 1);
|
||||
assert(oakengine_ipc_shutdown_parse("{\"type\":\"cancel\"}") == 0);
|
||||
assert(oakengine_ipc_message_type(sjson) == OAK_IPC_MSGTYPE_SHUTDOWN);
|
||||
EXPECT_TRUE(oakengine_ipc_shutdown_parse(sjson) == 1);
|
||||
EXPECT_TRUE(oakengine_ipc_shutdown_parse("{\"type\":\"cancel\"}") == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type(sjson) == OAK_IPC_MSGTYPE_SHUTDOWN);
|
||||
free(sjson);
|
||||
|
||||
// error
|
||||
const int en = oakengine_ipc_error_to_json("boom", NULL, 0);
|
||||
char *ejson = (char *)malloc(size_t(en) + 1);
|
||||
assert(ejson != NULL);
|
||||
assert(oakengine_ipc_error_to_json("boom", ejson, en + 1) == en);
|
||||
EXPECT_TRUE(ejson != NULL);
|
||||
EXPECT_TRUE(oakengine_ipc_error_to_json("boom", ejson, en + 1) == en);
|
||||
assert_json_eq(ejson, "{\"message\":\"boom\",\"type\":\"error\"}");
|
||||
assert(oakengine_ipc_message_type(ejson) == OAK_IPC_MSGTYPE_ERROR);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type(ejson) == OAK_IPC_MSGTYPE_ERROR);
|
||||
char msg[OAK_IPC_ERROR_MESSAGE_CAP];
|
||||
assert(oakengine_ipc_error_parse(ejson, msg, sizeof(msg)) == 1);
|
||||
assert(strcmp(msg, "boom") == 0);
|
||||
assert(oakengine_ipc_error_parse("{\"type\":\"shutdown\"}", msg,
|
||||
EXPECT_TRUE(oakengine_ipc_error_parse(ejson, msg, sizeof(msg)) == 1);
|
||||
EXPECT_TRUE(strcmp(msg, "boom") == 0);
|
||||
EXPECT_TRUE(oakengine_ipc_error_parse("{\"type\":\"shutdown\"}", msg,
|
||||
sizeof(msg)) == 0);
|
||||
free(ejson);
|
||||
|
||||
// Unknown and malformed input.
|
||||
assert(oakengine_ipc_message_type("{\"type\":\"nope\"}") ==
|
||||
EXPECT_TRUE(oakengine_ipc_message_type("{\"type\":\"nope\"}") ==
|
||||
OAK_IPC_MSGTYPE_UNKNOWN);
|
||||
assert(oakengine_ipc_message_type("garbage") == OAK_IPC_MSGTYPE_UNKNOWN);
|
||||
assert(oakengine_ipc_message_type(NULL) == OAK_IPC_MSGTYPE_UNKNOWN);
|
||||
assert(OAK_IPC_MSGTYPE_GRAPH_UPDATE != OAK_IPC_MSGTYPE_UNKNOWN);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type("garbage") == OAK_IPC_MSGTYPE_UNKNOWN);
|
||||
EXPECT_TRUE(oakengine_ipc_message_type(NULL) == OAK_IPC_MSGTYPE_UNKNOWN);
|
||||
EXPECT_TRUE(OAK_IPC_MSGTYPE_GRAPH_UPDATE != OAK_IPC_MSGTYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
int main()
|
||||
TEST(OakEngineIpc, Main)
|
||||
{
|
||||
test_shm();
|
||||
test_framepool();
|
||||
@@ -586,6 +587,4 @@ int main()
|
||||
test_render_frame();
|
||||
test_small_messages();
|
||||
|
||||
printf("oakengine_ipc_test: all assertions passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user