Ξ-W2-T1 remediation: print master gain into the bake, derive the window from the dialed sound, reset play mode to Trigger

This commit is contained in:
2026-08-01 17:05:28 -04:00
parent 60308a3655
commit 39c2d1cdb4
31 changed files with 679 additions and 201 deletions
+84 -8
View File
@@ -1,13 +1,17 @@
// Standalone tests for reasampler::wire::bake_wire — no VST3, no REAPER, no framework.
// Same fast assert loop as the sibling wire tests.
//
// Covers: request + outcome round-trips including bytes that would break a delimiter-based
// format; the refusals every house wire record shares (wrong tag, truncation, trailing
// garbage, a swapped record kind); an unrecognized status integer degrading to Failed
// rather than to Ok; and the action lookup name's leading underscore.
// Covers: the exact bytes each record encodes to (the two artifacts ship independently, so
// a field reorder or an inserted field must fail here rather than pass a round-trip and
// break a mixed-version pair); request + outcome round-trips including bytes that would
// break a delimiter-based format; the refusals every house wire record shares (wrong tag,
// truncation, trailing garbage, a swapped record kind); an unrecognized status integer
// degrading to Failed rather than to Ok; and the action lookup name's leading underscore.
#include "../src/core/wire/bake_wire.h"
#include "../src/core/version/app_version.h"
#include <cstdio>
#include <string>
@@ -18,6 +22,54 @@ static int g_fail = 0;
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
int main() {
// --- The exact bytes on the wire -------------------------------------------------
// A round-trip alone would pass a reordered or inserted field; the tags exist to guard
// the LAYOUT, so the layout is what is pinned. Changing either literal below means an
// already-shipped pair of artifacts can no longer talk — bump the tag, don't edit it.
{
BakeRequest req;
req.instanceGuid = "abcd";
req.stagedFilePath = "T/b.wav";
req.sourceSampleId = "cap-1";
req.sourceRelativePath = "bank/k.wav";
req.sourceDisplayName = "Kick";
req.ownUsageKey = "rsusage_abcd";
req.rootNote = 36;
req.generation = 1893456000;
CHECK(encodeBakeRequest(req) ==
"rsbakereq1"
"4:abcd"
"7:T/b.wav"
"5:cap-1"
"10:bank/k.wav"
"4:Kick"
"12:rsusage_abcd"
"2:36"
"10:1893456000");
BakeOutcome out;
out.status = BakeStatus::Ok;
out.sampleId = "bake-1";
out.relativePath = "bank/k2.wav";
out.displayName = "Kick r2";
out.rootNote = 36;
out.channelCount = 2;
out.replaced = true;
out.message = "replaced";
out.generation = 1893456000;
CHECK(encodeBakeOutcome(out) ==
"rsbakeout1"
"1:0"
"6:bake-1"
"11:bank/k2.wav"
"7:Kick r2"
"2:36"
"1:2"
"1:1"
"8:replaced"
"10:1893456000");
}
// --- Request round-trip, with hostile field content -----------------------------
{
BakeRequest req;
@@ -96,15 +148,39 @@ int main() {
CHECK(decoded.has_value());
CHECK(decoded->status == BakeStatus::Failed); // never Ok
CHECK(decoded->generation == 7);
// Every status this build DOES know survives its own round trip — including the
// most recently appended one, which an older reader will see as Failed.
for (const BakeStatus s :
{BakeStatus::Ok, BakeStatus::Failed, BakeStatus::NoProject,
BakeStatus::StagedMissing, BakeStatus::NoSource, BakeStatus::IndexRejected,
BakeStatus::WrongProject}) {
BakeOutcome one;
one.status = s;
const auto back = decodeBakeOutcome(encodeBakeOutcome(one));
CHECK(back.has_value() && back->status == s);
}
}
// --- The lookup name carries the underscore the registration string does not -------
// The load-bearing half is the REGISTRATION string: main.cpp registers that spelling
// verbatim, and NamedCommandLookup needs exactly one underscore in front of it. If
// channelCommandId ever grew one of its own, the lookup would carry two and resolve to
// nothing.
{
const std::string registered =
reasampler::version::channelCommandId(kBakeActionSuffix);
const std::string lookup = bakeActionLookupName();
CHECK(!lookup.empty());
CHECK(lookup[0] == '_');
CHECK(lookup.find(kBakeActionSuffix) != std::string::npos);
CHECK(lookup.find(kBakeActionSuffix) > 0u);
const std::size_t suffixLen = std::string(kBakeActionSuffix).size();
CHECK(!registered.empty());
CHECK(registered.front() != '_');
CHECK(lookup.size() == registered.size() + 1);
CHECK(lookup.front() == '_' && lookup[1] != '_');
CHECK(lookup.compare(1, std::string::npos, registered) == 0);
// The suffix is the TAIL of the id — the channel prefix goes in front of it, and a
// suffix that drifted into the middle would name a different action.
CHECK(lookup.size() > suffixLen);
CHECK(lookup.compare(lookup.size() - suffixLen, suffixLen, kBakeActionSuffix) == 0);
}
if (g_fail == 0) std::printf("bake_wire: all tests passed\n");