// Standalone tests for reasampler::instrument::map::bridge_marshal — no VST3, no REAPER, no test // framework. Same fast assert loop as the sibling pure tests: assert the REAPER // bridge-read marshalling (GetProjExtState result decode) directly, so the DAW-facing // shell only has to invoke the API. // // Covers: decodeGetProjExtState hit/absent/zero-return/empty-buffer (the stale-buffer // guard). The S1 spike's extractJsonStringField string-scan reader was retired in S4 // (the instrument now parses the bank through the shared bank_book JSON path), so its // cases are gone with it. #include "../src/core/instrument/map/bridge_marshal.h" #include using namespace reasampler; using namespace reasampler::instrument::map; static int g_fail = 0; #define CHECK(cond) do { if(!(cond)) { \ std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0) // --- decodeGetProjExtState ---------------------------------------------------- static void testDecodeHit() { // REAPER reports a non-zero length and filled the buffer: that IS the value. auto v = decodeGetProjExtState(5, "hello"); CHECK(v.has_value()); CHECK(v && *v == "hello"); } static void testDecodeAbsentKey() { // REAPER returns 0 for an absent key. Even if a caller passed a dirty buffer, the // decoder must NOT surface it — the zero return means "no value". auto v = decodeGetProjExtState(0, "stale-bytes-from-a-prior-read"); CHECK(!v.has_value()); } static void testDecodeNegativeReturn() { auto v = decodeGetProjExtState(-1, "whatever"); CHECK(!v.has_value()); } static void testDecodeEmptyBuffer() { // Positive return but empty buffer — treat as no value (defensive). auto v = decodeGetProjExtState(3, ""); CHECK(!v.has_value()); } int main() { testDecodeHit(); testDecodeAbsentKey(); testDecodeNegativeReturn(); testDecodeEmptyBuffer(); if (g_fail == 0) std::printf("bridge_marshal: all tests passed\n"); return g_fail != 0; }