#include "../src/shm_protocol.h"
#include <cassert>
#include <cstdio>
#include <cstring>
static int tests_passed = 0;
#define TEST(name) \
do { \
printf(" %-40s", #name "..."); \
} while (0)
#define PASS() \
do { \
printf("PASS\n"); \
tests_passed++; \
} while (0)
void test_struct_sizes() {
TEST(struct_sizes);
assert(sizeof(BridgeHeader) == 64);
assert(sizeof(ObjectEntry) == 32);
assert(OBJECT_TABLE_OFFSET == 64);
PASS();
}
void test_shm_create_destroy() {
TEST(shm_create_destroy);
ShmRegion region;
assert(region.create("/test_bb_create", 4096));
assert(region.valid());
assert(region.ptr() != nullptr);
assert(region.size() == 4096);
region.destroy();
assert(!region.valid());
PASS();
}
void test_shm_open_shared() {
TEST(shm_open_shared);
ShmRegion owner;
assert(owner.create("/test_bb_shared", 4096));
// Write some data from the owner
memset(owner.ptr(), 0xAB, 16);
// Open from a "reader"
ShmRegion reader;
assert(reader.open("/test_bb_shared", 4096));
assert(reader.valid());
// Reader should see the same data
uint8_t *rp = static_cast<uint8_t *>(reader.ptr());
assert(rp[0] == 0xAB);
assert(rp[15] == 0xAB);
reader.destroy();
owner.destroy();
PASS();
}
void test_header_readwrite() {
TEST(header_readwrite);
ShmRegion region;
assert(region.create("/test_bb_hdr", 4096));
BridgeHeader hdr = {};
hdr.magic[0] = 'B';
hdr.magic[1] = 'G';
hdr.magic[2] = 'O';
hdr.magic[3] = 'D';
hdr.version = 1;
hdr.direction = 0;
hdr.sequence = 42;
hdr.object_count = 3;
hdr.frame_number = 12345;
write_header(region.ptr(), hdr);
BridgeHeader read_hdr = read_header(region.ptr());
assert(read_hdr.magic[0] == 'B');
assert(read_hdr.magic[1] == 'G');
assert(read_hdr.magic[2] == 'O');
assert(read_hdr.magic[3] == 'D');
assert(read_hdr.version == 1);
assert(read_hdr.direction == 0);
assert(read_hdr.sequence == 42);
assert(read_hdr.object_count == 3);
assert(read_hdr.frame_number == 12345);
region.destroy();
PASS();
}
void test_object_entry_readwrite() {
TEST(object_entry_readwrite);
ShmRegion region;
assert(region.create("/test_bb_obj", 4096));
ObjectEntry entry = {};
entry.object_id = 100;
entry.object_type = OBJ_MESH;
entry.update_type = UPDATE_TRANSFORM;
entry.data_offset = 512;
entry.data_size = 64;
entry.sequence = 7;
write_object_entry(region.ptr(), 0, entry);
ObjectEntry read_entry = read_object_entry(region.ptr(), 0);
assert(read_entry.object_id == 100);
assert(read_entry.object_type == OBJ_MESH);
assert(read_entry.update_type == UPDATE_TRANSFORM);
assert(read_entry.data_offset == 512);
assert(read_entry.data_size == 64);
assert(read_entry.sequence == 7);
region.destroy();
PASS();
}
void test_multiple_object_entries() {
TEST(multiple_object_entries);
ShmRegion region;
assert(region.create("/test_bb_multi", 4096));
for (uint32_t i = 0; i < 10; i++) {
ObjectEntry entry = {};
entry.object_id = i * 10;
entry.object_type = (i % 2 == 0) ? OBJ_MESH : OBJ_LIGHT;
entry.update_type = UPDATE_FULL;
entry.data_offset = 1024 + i * 128;
entry.data_size = 128;
entry.sequence = i;
write_object_entry(region.ptr(), i, entry);
}
for (uint32_t i = 0; i < 10; i++) {
ObjectEntry read_entry = read_object_entry(region.ptr(), i);
assert(read_entry.object_id == i * 10);
assert(read_entry.data_offset == 1024 + i * 128);
assert(read_entry.sequence == i);
}
region.destroy();
PASS();
}
void test_data_blob_offset() {
TEST(data_blob_offset);
// With 10 max objects: 64 (header) + 10 * 32 (entries) = 384
assert(data_blob_offset(10) == 64 + 10 * 32);
assert(data_blob_offset(0) == 64);
assert(data_blob_offset(100) == 64 + 100 * 32);
PASS();
}
void test_cross_process_visibility() {
TEST(cross_process_visibility);
ShmRegion writer;
assert(writer.create("/test_bb_xproc", 4096));
// Write a header
BridgeHeader hdr = {};
hdr.magic[0] = 'B';
hdr.magic[1] = 'G';
hdr.magic[2] = 'O';
hdr.magic[3] = 'D';
hdr.version = 1;
hdr.direction = 1; // blender→godot
hdr.sequence = 99;
hdr.object_count = 1;
write_header(writer.ptr(), hdr);
// Write an object entry
ObjectEntry entry = {};
entry.object_id = 42;
entry.object_type = OBJ_CAMERA;
entry.update_type = UPDATE_VERTEX;
entry.data_offset = 256;
entry.data_size = 48;
write_object_entry(writer.ptr(), 0, entry);
// Open as reader and verify
ShmRegion reader;
assert(reader.open("/test_bb_xproc", 4096));
BridgeHeader rh = read_header(reader.ptr());
assert(rh.direction == 1);
assert(rh.sequence == 99);
assert(rh.object_count == 1);
ObjectEntry re = read_object_entry(reader.ptr(), 0);
assert(re.object_id == 42);
assert(re.object_type == OBJ_CAMERA);
assert(re.update_type == UPDATE_VERTEX);
reader.destroy();
writer.destroy();
PASS();
}
int main() {
printf("=== SHM Protocol Tests ===\n");
test_struct_sizes();
test_shm_create_destroy();
test_shm_open_shared();
test_header_readwrite();
test_object_entry_readwrite();
test_multiple_object_entries();
test_data_blob_offset();
test_cross_process_visibility();
printf("\nAll %d tests passed.\n", tests_passed);
return 0;
}