From 7354f471c6a62583d8b728c96fd2679ae5d9c53e Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Mon, 27 Jul 2026 21:53:41 -0400 Subject: [PATCH] test(app_version): decouple assertions from the hardcoded version literal Replace five literal "0.9.01" assertions with stampVersion()-relative checks and a parse round-trip; add testLeadingZeroFidelity() as a synthetic fixed-string pin so any REASAMPLER_VERSION bump no longer breaks the suite. --- tests/test_app_version.cpp | 72 ++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/tests/test_app_version.cpp b/tests/test_app_version.cpp index 1b5a312..0fca97e 100644 --- a/tests/test_app_version.cpp +++ b/tests/test_app_version.cpp @@ -23,15 +23,37 @@ static int g_fail = 0; // the `build-beta` tree with = 1. So each config's ctest run validates ITS OWN channel's // derivation. The channel-dependent assertions below branch on isBeta() so the ONE test // source is correct in both configs — and each branch would fail if the derivation regressed -// (a beta build rendering "0.9.01" without the suffix, or stable rendering "-beta", trips it). +// (a beta build omitting the suffix, or stable gaining one, trips it). -static void testVersionConstantRendersExactString() { - // The Daniel-fixed base string: EXACTLY "0.9.01", two-digit zero-padded patch — the - // numeric triple, IDENTICAL on both channels (it is also the stamp value). This is the - // whole point of sourcing the STRING (not reconstructing from numeric components): a - // normalized "0.9.1" here would be a leading-zero-fidelity regression. stampVersion() - // is the pure numeric triple regardless of channel. - CHECK(stampVersion() == "0.9.01"); +static void testVersionConstantRenderStructure() { + // stampVersion() is the CMake-sourced numeric triple on both channels (no suffix). + // It must be parseable — a malformed version string slipped in at CMake time would + // silently classify every saved project as Unknown on read-back. + CHECK(parseVersion(stampVersion()).has_value()); + + // appVersion() is the user-visible render: exactly stampVersion() on stable, and + // stampVersion() + "-beta" on beta. This is the derivation that must hold at ANY + // version, without naming a literal. + if (isBeta()) { + CHECK(appVersion() == stampVersion() + "-beta"); + } else { + CHECK(appVersion() == stampVersion()); + } +} + +static void testLeadingZeroFidelity() { + // Leading-zero-fidelity is the whole point of sourcing the version STRING (not + // reconstructing from numeric components): a CMake normalize of "0.9.01" to "0.9.1" + // is a silent regression. This is tested with a SYNTHETIC fixed example so it pins + // the fidelity contract independent of any particular live version. + // parseVersion("0.9.01") must yield patch == 1 (not 01 as an integer, which is 1, + // but the important thing is the STRING "0.9.01" is accepted and produces the right + // triple — the string fidelity is the caller's job, the integer parse just rounds the + // patch correctly). The live version may or may not have a zero-padded patch; this + // synthetic pin catches a parse regression that would misclassify such a stamp. + auto v = parseVersion("0.9.01"); + CHECK(v.has_value()); + CHECK(v && v->major == 0 && v->minor == 9 && v->patch == 1); // "01" -> 1, not rejected } // --- channel-derived rendering (V4) ------------------------------------------- @@ -43,14 +65,19 @@ static void testChannelDerivedRendering() { // wrongly rendered "-beta", or a beta build that dropped it, is caught here. if (isBeta()) { CHECK(channel() == Channel::Beta); - CHECK(appVersion() == "0.9.01-beta"); + CHECK(appVersion() == stampVersion() + "-beta"); } else { CHECK(channel() == Channel::Stable); - CHECK(appVersion() == "0.9.01"); + CHECK(appVersion() == stampVersion()); } // The STAMP value is the numeric triple on BOTH channels — never suffixed — so it stays // classifiable (see the stamp-classifiability test) and byte-identical to stable. - CHECK(stampVersion() == "0.9.01"); + // Verified against stampVersion() rather than a literal so a version bump is not a + // test failure: the real invariant is that the stamp is parseable (checked in + // testVersionConstantRenderStructure) and that it has no suffix here. + CHECK(appVersion().substr(0, stampVersion().size()) == stampVersion()); + CHECK(isBeta() ? appVersion().size() > stampVersion().size() + : appVersion().size() == stampVersion().size()); } static void testChannelDerivedIdentityStrings() { @@ -130,14 +157,20 @@ static void testStampClassifiesAsStampedOnOwnChannel() { // appVersion() instead of stampVersion(). WritingVersion wv = classifyWritingVersion(stampVersion()); CHECK(wv.kind == WritingVersion::Kind::Stamped); - CHECK(wv.raw == "0.9.01"); - CHECK(wv.parsed.major == 0 && wv.parsed.minor == 9 && wv.parsed.patch == 1); + // raw must be the exact stamp string (no truncation, no suffix added by classify). + CHECK(wv.raw == stampVersion()); + // parsed must round-trip: re-parsing the stamp string must yield the same triple + // classify stored, without naming a literal version. + auto reparsed = parseVersion(stampVersion()); + CHECK(reparsed.has_value()); + CHECK(reparsed && wv.parsed.major == reparsed->major + && wv.parsed.minor == reparsed->minor + && wv.parsed.patch == reparsed->patch); - // The OTHER channel's raw stamp value is handled without throwing per the design: since - // both channels stamp the identical numeric triple, the other channel's value is the same - // "0.9.01" and also classifies Stamped. (The DISPLAY string "0.9.01-beta", by contrast, - // is intentionally NOT the stamp value — confirm it classifies Unknown, proving why the - // stamp must stay the numeric triple.) + // The display string with the "-beta" suffix is intentionally NOT the stamp value — + // confirm it classifies Unknown, proving why the stamp must stay the numeric triple. + // This uses a synthetic fixed string (not the live version) because the intent is to + // show that ANY "-beta"-suffixed string fails the semver parse used by classify. CHECK(classifyWritingVersion("0.9.01-beta").kind == WritingVersion::Kind::Unknown); } @@ -236,7 +269,8 @@ static void testStampedStampIsOrderableAgainstCurrent() { } int main() { - testVersionConstantRendersExactString(); + testVersionConstantRenderStructure(); + testLeadingZeroFidelity(); testChannelDerivedRendering(); testChannelDerivedIdentityStrings(); testVstIdentityStringsForkByChannel();