// native_bridge/tests/shm_selfcheck.cpp // Self-check for SharedMemoryIPC helpers (assert-based, no framework). // POSIX path runs on Linux/macOS; Win32 path guarded (runs on Windows build). #include "../include/SharedMemoryIPC.h" #include "../src/SharedMemoryIPC.cpp" #include #include #include int main() { // Use a test-only name to avoid clashing with a live DAW bridge. ShmHandle* h = shm_open("SonicForge_SelfCheck_IPC"); assert(h != nullptr); SharedAudioBufferIPC* ipc = shm_ptr(h); assert(ipc != nullptr); // Reset state (POSIX shm may survive an aborted previous run). std::memset(ipc, 0, sizeof(SharedAudioBufferIPC)); // 1. MIDI event write + read back (A12: data2/data3 for CC/program/pitch bend) assert(shm_write_midi(h, 0x9, 2, 60, 100, 37)); assert(ipc->midiQueueCount == 1); assert(ipc->midiQueue[0].command == 0x9); assert(ipc->midiQueue[0].channel == 2); assert(ipc->midiQueue[0].pitch == 60); assert(ipc->midiQueue[0].velocity == 100); assert(ipc->midiQueue[0].sampleOffset == 37); assert(ipc->midiQueue[0].data2 == 0 && ipc->midiQueue[0].data3 == 0); assert(shm_write_midi(h, 0xB, 3, 64, 0, 0, 127)); // CC64 sustain = 127 assert(shm_write_midi(h, 0xE, 3, 0, 0, 0, 0x00, 0x40)); // pitch bend MSB assert(ipc->midiQueue[1].data2 == 127); assert(ipc->midiQueue[2].data3 == 0x40); assert(ipc->midiQueueCount == 3); // 2. Control event with path + channel (A10) assert(shm_write_control(h, 2, 1 /*SOUNDFONT_SF2_SF3*/, 0, 4, "C:\\sf\\SGM.sf2")); assert(ipc->controlQueueCount == 1); assert(ipc->controlQueue[0].type == 2); assert(ipc->controlQueue[0].arg0 == 1); assert(ipc->controlQueue[0].channel == 4); assert(std::strcmp(ipc->controlQueue[0].arg2, "C:\\sf\\SGM.sf2") == 0); // TRANSPORT (A13): STOP with playhead arg assert(shm_write_control(h, 3, 0, 44100, 0, "")); assert(ipc->controlQueue[1].type == 3 && ipc->controlQueue[1].arg0 == 0 && ipc->controlQueue[1].arg1 == 44100); // 3. Queue capacity guard for (int i = 0; i < 70; ++i) shm_write_midi(h, 0x8, 0, 40, 0, 0); assert(ipc->midiQueueCount == 64); // capped, not overflowed // 4. Audio block round-trip for (uint32_t i = 0; i < AUDIO_BLOCK_SIZE; ++i) ipc->masterLeft[i] = (float)i; ipc->bridgeWriteIndex++; ipc->blockTimestamp = 123456; assert(ipc->masterLeft[255] == 255.0f); assert(ipc->bridgeWriteIndex == 1); assert(ipc->blockTimestamp == 123456); // 5. Layout stability — MUST match Rust src-tauri/src/shm.rs assert(sizeof(SharedAudioBufferIPC::MidiEventIPC) == 12); assert(sizeof(SharedAudioBufferIPC::ControlEventIPC) == 1040); std::printf("SHM self-check OK (sizeof struct = %zu bytes)\n", sizeof(SharedAudioBufferIPC)); shm_close(h); return 0; }