86 lines
4.6 KiB
C++
86 lines
4.6 KiB
C++
// test_app_version_padding.cpp — the ALWAYS-ON anti-normalization guard for the version
|
|
// string threading (Phase V, V1 leading-zero fidelity). No REAPER, no framework.
|
|
//
|
|
// WHY THIS EXECUTABLE EXISTS: test_app_version.cpp pins stampVersion() relative to the
|
|
// live configure_file'd version string — but a relative assertion (e.g. appVersion() ==
|
|
// stampVersion()) is version-shape-blind: it holds whether the string was threaded
|
|
// verbatim or reconstructed from numeric components, at any version, padded or not.
|
|
// The live suite therefore cannot detect a reconstruct-from-components regression at all.
|
|
// Padded and unpadded versions are both legitimate (Daniel's ruling), so the guard must
|
|
// not depend on the shipped version's shape.
|
|
//
|
|
// MECHANISM: CMakeLists.txt runs the SAME src/version_generated.h.in template through
|
|
// configure_file a second time with a SYNTHETIC zero-padded version ("0.9.01") into
|
|
// generated_padding_canary/, and this executable compiles the SAME src/app_version.cpp
|
|
// against that header (include-dir substitution — this target never sees the live
|
|
// generated/ dir). The exact production derivation path — template substitution →
|
|
// REASAMPLER_VERSION_STRING → stampVersion()/appVersion() — is thereby exercised with an
|
|
// input whose normalized form provably differs from its verbatim form. If anyone
|
|
// reimplements the version string by reconstructing it from numeric components (a
|
|
// parse-and-reprint inside app_version.cpp, or project(VERSION) numeric macros added to
|
|
// the template), this binary renders "0.9.1" and the checks below fail — at ANY live
|
|
// version, which is exactly the property the live-version assertion cannot provide.
|
|
//
|
|
// The "0.9.01" literals below are the synthetic fixture and MUST match the canary
|
|
// configure_file input in CMakeLists.txt. They are NOT the shipped version: never bump
|
|
// them on release — their padded shape is the entire point.
|
|
|
|
#include "../src/app_version.h"
|
|
|
|
#include <cstdio>
|
|
#include <string>
|
|
|
|
using namespace reasampler;
|
|
|
|
static int g_fail = 0;
|
|
#define CHECK(cond) do { if(!(cond)) { \
|
|
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
|
|
|
|
static void testPaddedVersionSurvivesThreadingVerbatim() {
|
|
// The verbatim-threading invariant, exercised with an input where reconstruction and
|
|
// verbatim DIFFER: a normalized render would be "0.9.1" and fail both checks.
|
|
CHECK(stampVersion() == "0.9.01");
|
|
if (isBeta()) CHECK(appVersion() == "0.9.01-beta");
|
|
else CHECK(appVersion() == "0.9.01");
|
|
}
|
|
|
|
static void testPaddedStampStillClassifiesStamped() {
|
|
// A padded stamp stays classifiable on read-back: parse tolerates leading zeros
|
|
// (raw preserved verbatim, triple normalized to integers — {0,9,1}).
|
|
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);
|
|
}
|
|
|
|
static void testCanaryFixtureIsNonVacuous() {
|
|
// Self-check: the canary fixture must be zero-padded so that its verbatim string
|
|
// differs from what a parse-and-reprint of its numeric triple would produce.
|
|
// If the fixture is ever "fixed" to an unpadded form (e.g. "0.9.1"), the checks in
|
|
// testPaddedVersionSurvivesThreadingVerbatim become vacuous — a reconstructed
|
|
// string would match the fixture and the canary would pass even if the threading
|
|
// regressed. Parse stampVersion() and reprint the triple; they must NOT match.
|
|
WritingVersion wv = classifyWritingVersion(stampVersion());
|
|
CHECK(wv.kind == WritingVersion::Kind::Stamped); // fixture must be parseable
|
|
const std::string reprinted =
|
|
std::to_string(wv.parsed.major) + "." +
|
|
std::to_string(wv.parsed.minor) + "." +
|
|
std::to_string(wv.parsed.patch);
|
|
// If this fails, one of two causes: (1) the fixture was changed to an unpadded form
|
|
// (e.g. "0.9.1") — restore a zero-padded fixture (e.g. "0.9.01") in CMakeLists.txt
|
|
// and update the matching literals in this file; or (2) the fixture is still padded
|
|
// but app_version.cpp regressed to parse-and-reprint — in that case
|
|
// testPaddedVersionSurvivesThreadingVerbatim also fails, pointing at the real cause.
|
|
CHECK(reprinted != stampVersion());
|
|
}
|
|
|
|
int main() {
|
|
testPaddedVersionSurvivesThreadingVerbatim();
|
|
testPaddedStampStillClassifiesStamped();
|
|
testCanaryFixtureIsNonVacuous();
|
|
|
|
if (g_fail == 0) std::printf("app_version_padding: all tests passed\n");
|
|
else std::printf("app_version_padding: %d CHECK(s) FAILED\n", g_fail);
|
|
return g_fail == 0 ? 0 : 1;
|
|
}
|