// Standalone tests for reasampler::render_window — no REAPER, no framework. // Covers the bounds-equality number (a window's exact frame count at the project // rate), the verdict the offline backend refuses a capture on, the predicate // that decides whether REAPER's selected-items render source can express a // requested window at all, and the two short-render diagnostics. #include "../src/core/capture/render_window.h" #include #include #include using namespace reasampler::capture; 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 bool contains(const std::string& haystack, const std::string& needle) { return haystack.find(needle) != std::string::npos; } // --- frameCountFor: the bounds equality, stated as a number ------------------ static void testFrameCountIsExactNotRounded() { // A 1.5 s window at 48 kHz is exactly 72000 frames — the number a capture of // that range must produce. No rounding slack in either direction. CHECK(frameCountFor(2.0, 3.5, 48000) == 72000); // The same duration at a different offset still counts the same frames when // both edges are frame-aligned. CHECK(frameCountFor(10.0, 11.5, 48000) == 72000); // 44.1 kHz: 0.5 s = 22050 frames. CHECK(frameCountFor(1.0, 1.5, 44100) == 22050); } static void testFrameCountIsADifferenceOfIndicesNotADuration() { // Both edges land mid-frame at 100 Hz (0.005 s = half a frame). Rounding the // DURATION would give 1 frame; rounding each EDGE gives 0.005 -> frame 1 and // 0.015 -> frame 2, i.e. 1 frame. Shift the window so the edges round apart // and the count changes — the property that makes this a window, not a length. CHECK(frameCountFor(0.005, 0.015, 100) == 1); CHECK(frameCountFor(0.004, 0.016, 100) == 2); } static void testFrameCountRefusesEmptyInvertedAndUnknownRate() { CHECK(frameCountFor(3.0, 3.0, 48000) == 0); // empty CHECK(frameCountFor(3.0, 1.0, 48000) == 0); // inverted CHECK(frameCountFor(1.0, 2.0, 0) == 0); // rate unknown CHECK(frameCountFor(1.0, 2.0, -1) == 0); // rate nonsensical } static void testWindowStartingAtExactlyZero() { CHECK(frameCountFor(0.0, 1.0, 48000) == 48000); // The window from the reported blocker: it starts at 0 and its end lands a // quarter of a frame off the grid at 48 kHz. CHECK(frameCountFor(0.0, 4.067797, 48000) == 195254); } // --- renderHonoredBounds: the gate's verdict --------------------------------- static void testNonFrameAlignedWindowAcceptsItsAdjacentCounts() { // 4.067797 s at 48 kHz is 195254.26 frames — not a frame boundary. A correct // render lands on 195254, and both adjacent counts are inside the gate. const long long expected = frameCountFor(0.0, 4.067797, 48000); CHECK(expected == 195254); CHECK(renderHonoredBounds(expected, 195254)); CHECK(renderHonoredBounds(expected, 195255)); CHECK(renderHonoredBounds(expected, 195253)); // The shortfall actually reported from the DAW is 38 frames — far outside any // alignment slack, so it is a render that missed the window, and is refused. CHECK(!renderHonoredBounds(expected, 195216)); } static void testLengthDerivedAndSameConventionRenderersStayWithinOneFrame() { // What the one-frame tolerance is actually good for. Two families of renderer are // inside it at every offset swept here: one that derives its count from the // window's LENGTH (floor/ceil/round of (end-start)*rate), and one that resolves // each EDGE to a frame using the SAME convention on both edges. Every count below // is computed from the window, never from frameCountFor, so this compares two // derivations rather than restating one. Round-both-edges is omitted deliberately: // that IS frameCountFor's own convention, so asserting it would be tautological. // // 8192 is a power of two, so an eighth of a frame is exact in double there and the // .5 rounding ties are really hit; at 48000/44100 (the shipping rates) they are // only approached, which is why all three are swept. struct Window { double start; double end; }; const int rates[] = {48000, 44100, 8192}; const Window windows[] = {{3.0, 7.5}, {0.0, 4.067797}, {10.25, 10.75}}; for (int rate : rates) { for (const Window& w : windows) { for (int s = 0; s < 8; ++s) { for (int e = 0; e < 8; ++e) { const double start = w.start + s / (8.0 * rate); const double end = w.end + e / (8.0 * rate); const long long expected = frameCountFor(start, end, rate); const double length = (end - start) * rate; CHECK(renderHonoredBounds(expected, static_cast(std::floor(length)))); CHECK(renderHonoredBounds(expected, static_cast(std::ceil(length)))); CHECK(renderHonoredBounds(expected, std::llround(length))); const double startFrames = start * rate; const double endFrames = end * rate; CHECK(renderHonoredBounds( expected, static_cast(std::floor(endFrames) - std::floor(startFrames)))); CHECK(renderHonoredBounds( expected, static_cast(std::ceil(endFrames) - std::ceil(startFrames)))); } } } } } static void testMixedEdgeConventionsCanMissByTwoAndAreRefused() { // The hole in that bound, stated rather than hidden. A renderer that resolves the // two edges by DIFFERENT conventions lands two frames from frameCountFor's answer // whenever the start sits past mid-frame and the end before it (resolved outward), // or the mirror image (resolved inward). The gate refuses both — correctly if // REAPER derives its count from the window's length, wrongly if it resolves edges // this way. No unit test can settle which; see render_window.h. const int rate = 8192; // power of two: the eighth-frame offsets below are exact // Outward: start .625 into a frame, end .375 into one. const double start = 10.25 + 5.0 / (8.0 * rate); const double end = 10.75 + 3.0 / (8.0 * rate); CHECK(start * rate == 83968.625); // the premise, not an outcome — pinned so a CHECK(end * rate == 88064.375); // representability slip can't fake the result const long long expected = frameCountFor(start, end, rate); CHECK(expected == 4095); const long long outward = static_cast(std::ceil(end * rate) - std::floor(start * rate)); CHECK(outward == 4097); CHECK(!renderHonoredBounds(expected, outward)); // Inward, mirrored fractions. const double start2 = 10.25 + 3.0 / (8.0 * rate); const double end2 = 10.75 + 5.0 / (8.0 * rate); const long long expected2 = frameCountFor(start2, end2, rate); CHECK(expected2 == 4097); const long long inward = static_cast(std::floor(end2 * rate) - std::ceil(start2 * rate)); CHECK(inward == 4095); CHECK(!renderHonoredBounds(expected2, inward)); } static void testWholeItemWideningIsStillRefused() { // The defect the gate was built for: a 1 s window inside a 30 s item printing // the whole item. const long long expected = frameCountFor(5.0, 6.0, 48000); CHECK(expected == 48000); CHECK(!renderHonoredBounds(expected, 30 * 48000)); } static void testLargeShortfallIsStillRefused() { const long long expected = frameCountFor(0.0, 4.067797, 48000); CHECK(!renderHonoredBounds(expected, 190000)); // Two frames is the smallest miss outside the tolerance, in both directions — // the tolerance is one frame and stays one frame. CHECK(!renderHonoredBounds(expected, expected - 2)); CHECK(!renderHonoredBounds(expected, expected + 2)); } static void testEmptyRenderIsRefusedAgainstARealWindow() { // A render that produced nothing is a bounds miss like any other. A render whose // frames could not be MEASURED never reaches this predicate — shell/capture/ // render_bounds_gate refuses it before the comparison. CHECK(!renderHonoredBounds(48000, 0)); } // --- itemExtentPrintsWindow: can the selected-items source express this? ----- static void testRangeInsideItemCannotBeExpressed() { // The defect this whole module exists for: a 1 s selection inside a 30 s item. // The selected-items source would print the item's 30 s, not the 1 s asked for, // so the capture must NOT take that path. CHECK(!itemExtentPrintsWindow(5.0, 6.0, /*item*/ 0.0, 30.0, 48000)); } static void testRangeWiderThanItemCannotBeExpressedEither() { // The same violation in the other direction: a 10 s selection over a 6 s item // would print 6 s. Under-printing is a bounds violation exactly as much as // over-printing is. CHECK(!itemExtentPrintsWindow(0.0, 10.0, /*item*/ 2.0, 8.0, 48000)); } static void testEachEdgeAloneDisqualifies() { // Matching start, drifting end. CHECK(!itemExtentPrintsWindow(2.0, 8.0, 2.0, 9.0, 48000)); // Matching end, drifting start. CHECK(!itemExtentPrintsWindow(2.0, 8.0, 1.0, 8.0, 48000)); } static void testExtentEqualToWindowIsExpressible() { // The regression floor: a capture whose range IS the item's extent keeps the // selected-items render, byte-identical to what it produces today. CHECK(itemExtentPrintsWindow(2.0, 8.0, 2.0, 8.0, 48000)); } static void testSubFrameDriftStillPrintsTheSameFrames() { // A time selection snapped a fraction of a sample off the item edge prints the // identical frames, so it must NOT be pushed onto the time-bounded path — that // would swap the render mechanism under a capture that was already exact. const double eighthOfAFrameAt48k = 1.0 / (48000.0 * 8.0); CHECK(itemExtentPrintsWindow(2.0 + eighthOfAFrameAt48k, 8.0 - eighthOfAFrameAt48k, 2.0, 8.0, 48000)); // A full frame of drift is a real difference and must disqualify. const double oneFrameAt48k = 1.0 / 48000.0; CHECK(!itemExtentPrintsWindow(2.0 + oneFrameAt48k, 8.0, 2.0, 8.0, 48000)); } static void testUnknownRateFallsBackToExactEquality() { // With no project rate there is no frame grid to compare on. Exact equality // still recognizes the regression floor... CHECK(itemExtentPrintsWindow(2.0, 8.0, 2.0, 8.0, 0)); // ...and anything else takes the time-bounded render, which honors the request // whatever the rate turns out to be. const double eighthOfAFrameAt48k = 1.0 / (48000.0 * 8.0); CHECK(!itemExtentPrintsWindow(2.0 + eighthOfAFrameAt48k, 8.0, 2.0, 8.0, 0)); CHECK(!itemExtentPrintsWindow(5.0, 6.0, 0.0, 30.0, 0)); } static void testMultiItemUnionExtent() { // Two items spanning 1..4 and 6..9 present a 1..9 union extent to the render. // A selection over the whole union is expressible; one over only the first // item's half is not. CHECK(itemExtentPrintsWindow(1.0, 9.0, 1.0, 9.0, 48000)); CHECK(!itemExtentPrintsWindow(1.0, 4.0, 1.0, 9.0, 48000)); } // --- msFlooredEndFrameCount: the shape both live short renders had ------------ static void testMillisecondFlooredEndReproducesBothShortRenders() { // Both DAW observations, as arithmetic. 48 kHz, TailMode::None, start at 0: the // requested window's count, and the count its end floored to the millisecond // holds — which is what each render actually printed. CHECK(frameCountFor(0.0, 4.067797, 48000) == 195254); CHECK(msFlooredEndFrameCount(0.0, 4.067797, 48000) == 195216); CHECK(frameCountFor(0.0, 4.067797, 48000) - msFlooredEndFrameCount(0.0, 4.067797, 48000) == 38); CHECK(frameCountFor(0.0, 1.655172, 48000) == 79448); CHECK(msFlooredEndFrameCount(0.0, 1.655172, 48000) == 79440); CHECK(frameCountFor(0.0, 1.655172, 48000) - msFlooredEndFrameCount(0.0, 1.655172, 48000) == 8); } static void testTheSixDecimalDisplayDidNotCreateTheEffect() { // Both reported ends were printed to six decimals by the refusal. Each is one 4/4 // bar — at 59 BPM and at 145 BPM — so the full-precision doubles behind them are // 240/59 and 240/145. Same counts either way: the display rounding is not what // produces the shortfall. CHECK(frameCountFor(0.0, 240.0 / 59.0, 48000) == 195254); CHECK(msFlooredEndFrameCount(0.0, 240.0 / 59.0, 48000) == 195216); CHECK(frameCountFor(0.0, 240.0 / 145.0, 48000) == 79448); CHECK(msFlooredEndFrameCount(0.0, 240.0 / 145.0, 48000) == 79440); } static void testWindowAlreadyOnTheMillisecondGridLosesNothing() { // The "sometimes it works" case: a bar at 120 BPM is exactly 2 s. CHECK(msFlooredEndFrameCount(0.0, 2.0, 48000) == frameCountFor(0.0, 2.0, 48000)); // The binary-representation trap a bare floor would fall into. The premise, not an // outcome: 1.007 s is a whole millisecond that really does land BELOW 1007 ms in // double, so flooring it without a tolerance drops a millisecond from a window // already on the grid. CHECK(1.007 * 1000.0 < 1007.0); CHECK(frameCountFor(0.0, 1.007, 48000) == 48336); CHECK(msFlooredEndFrameCount(0.0, 1.007, 48000) == 48336); // Same end reached from a non-zero start, so nothing here rests on the window // beginning at 0. CHECK(msFlooredEndFrameCount(0.5, 1.007, 48000) == frameCountFor(0.5, 1.007, 48000)); } static void testOneFrameOfRemainderStillFloors() { // The whole-millisecond tolerance must sit far below a frame, or it would swallow // the very remainder this diagnostic exists to find. A remainder JUST BELOW a // millisecond boundary is the discriminating case: one frame short of 1.0 s is // 999.979166 ms, only ~0.0208 ms off the next whole millisecond. The shipped // nanosecond tolerance still floors it down; a tolerance any wider than ~0.021 ms // would snap it up to the millisecond instead and this test would then see 48000, // not 47952 — which is what would fail if the tolerance regressed to something // that wide. const double oneFrame = 1.0 / 48000.0; CHECK(frameCountFor(0.0, 1.0 - oneFrame, 48000) == 47999); CHECK(msFlooredEndFrameCount(0.0, 1.0 - oneFrame, 48000) == 47952); } static void testMillisecondFloorAt44100WhereAMillisecondIsNotWholeFrames() { // 44.1 kHz: a millisecond is 44.1 frames, so a floored end cannot be described as // dropping a whole number of frames — the count still resolves exactly. CHECK(frameCountFor(0.0, 0.0105, 44100) == 463); CHECK(msFlooredEndFrameCount(0.0, 0.0105, 44100) == 441); // And a window that IS on the millisecond grid there is untouched, even though its // edge is not on a frame boundary. CHECK(frameCountFor(0.0, 0.010, 44100) == 441); CHECK(msFlooredEndFrameCount(0.0, 0.010, 44100) == 441); } static void testASubMillisecondStartWouldNotHideItself() { // Both observations started at 0.000000s, the one value that hides a start-side // truncation. A window whose START carries a sub-millisecond remainder counts from // that exact start... const double start = 1.0001724, end = 2.0001724; CHECK(frameCountFor(start, end, 48000) == 48000); // ...so a start floored to the millisecond would print a DIFFERENT count — 8 frames // more, the same remainder the second observation lost off its end. A start-side // truncation is therefore visible to the same frame-count gate, not silent. CHECK(frameCountFor(1.000, end, 48000) == 48008); CHECK(!renderHonoredBounds(frameCountFor(start, end, 48000), frameCountFor(1.000, end, 48000))); } static void testTheTwoLiveShortRendersPinnedAtFullPrecision() { // 1.6551724137931001 is the console's own %.17g read-back. 4.0677966101694913 is // the double nearest the six-decimal value (4.067797) the earlier refusal actually // printed -- that refusal predates the %.17g printer (git history has no commit // introducing this literal as a console value), so it is a reconstruction, not a // captured one. 240/145 and 240/59 (testTheSixDecimalDisplayDidNotCreateTheEffect) // produce the SAME counts as the literals here, so this test cannot distinguish the // real value from the reconstruction either -- it pins the count regression (full // precision or six-decimal input, the frame counts agree), not which double REAPER // was really handed. CHECK(frameCountFor(0.0, 1.6551724137931001, 48000) == 79448); CHECK(msFlooredEndFrameCount(0.0, 1.6551724137931001, 48000) == 79440); CHECK(frameCountFor(0.0, 4.0677966101694913, 48000) == 195254); CHECK(msFlooredEndFrameCount(0.0, 4.0677966101694913, 48000) == 195216); // And the counts REAPER produced are outside the gate's tolerance in both cases — // the refusals were correct, not an artifact of the one-frame slack. CHECK(!renderHonoredBounds(79448, 79440)); CHECK(!renderHonoredBounds(195254, 195216)); } // --- isOnMillisecondGrid: whether an observation can speak to an edge ---------- static void testOnGridRecognizesWholeMillisecondsIncludingTheBinaryTrap() { CHECK(isOnMillisecondGrid(0.0)); CHECK(isOnMillisecondGrid(2.0)); CHECK(isOnMillisecondGrid(0.001)); // 1.007 s does not multiply to exactly 1007.0 in double (pinned as the premise in // testWindowAlreadyOnTheMillisecondGridLosesNothing) and must still read as on-grid. CHECK(isOnMillisecondGrid(1.007)); // A whole millisecond at 44.1 kHz is 44.1 frames — off the frame grid, on this one. CHECK(isOnMillisecondGrid(0.010)); } static void testOffGridRecognizesASubMillisecondRemainder() { CHECK(!isOnMillisecondGrid(1.6551724137931001)); CHECK(!isOnMillisecondGrid(1.0001724)); // One frame short of a whole second at 48 kHz is ~0.0208 ms off the grid — the // tightest remainder this predicate has to keep seeing. CHECK(!isOnMillisecondGrid(1.0 - 1.0 / 48000.0)); } // --- describeBoundsExperiment: the console verdict on a bounds channel -------- static void testAnExactRenderReadsExactAndNamesItsChannel() { const std::string s = describeBoundsExperiment("time selection (RENDER_BOUNDSFLAG=2)", 0.0, 1.6551724137931001, 79448, 48000); CHECK(contains(s, "EXACT")); CHECK(!contains(s, "SHORT")); CHECK(contains(s, "time selection (RENDER_BOUNDSFLAG=2)")); CHECK(contains(s, "79448")); CHECK(contains(s, "48000 Hz")); // The END here carries a sub-millisecond remainder, so this run DID test it -- // the END-untested caveat must not fire on a window it didn't apply to. CHECK(!contains(s, "END edge is UNTESTED")); } static void testTheLiveShortfallReadsShortAndNamesTheMillisecondShape() { // The observation, replayed through the verdict: 79440 produced against 79448. const std::string s = describeBoundsExperiment("custom time bounds (RENDER_BOUNDSFLAG=0)", 0.0, 1.6551724137931001, 79440, 48000); CHECK(contains(s, "SHORT")); CHECK(!contains(s, "EXACT")); CHECK(contains(s, "79440")); CHECK(contains(s, "79448")); // 79440 IS the ms-floored count, so the verdict has to say the floor did not move. CHECK(contains(s, "floored to the millisecond")); } static void testAShortfallThatIsNotTheMillisecondShapeClaimsNothingAboutIt() { // A render 3 frames short is short, but 79445 is not the floored count — the // millisecond sentence must not appear, or it would assert a shape that is absent. CHECK(msFlooredEndFrameCount(0.0, 1.6551724137931001, 48000) != 79445); const std::string s = describeBoundsExperiment("custom time bounds", 0.0, 1.6551724137931001, 79445, 48000); CHECK(contains(s, "SHORT")); CHECK(!contains(s, "floored to the millisecond")); } static void testARenderPastTheWindowReadsLong() { // The whole-item widening, through the verdict: 30 s printed for a 1 s window. const std::string s = describeBoundsExperiment("custom time bounds", 5.0, 6.0, 30 * 48000, 48000); CHECK(contains(s, "LONG")); CHECK(contains(s, "1440000 frames")); CHECK(contains(s, "the 48000 the window asks for")); } static void testAWindowAlreadyOnTheGridIsUnaffectedByTheChannelSwitch() { // A window whose end is a whole millisecond has nothing for a floor to take: the // exact count and the floored count are the same number, so an exact render reads // EXACT and the millisecond sentence never fires. CHECK(frameCountFor(0.0, 2.0, 48000) == msFlooredEndFrameCount(0.0, 2.0, 48000)); const std::string s = describeBoundsExperiment("time selection", 0.0, 2.0, 96000, 48000); CHECK(contains(s, "EXACT")); CHECK(contains(s, "96000")); CHECK(!contains(s, "floored to the millisecond")); // The false positive this window is the shape of: a render that floored either edge // alone, or both together, would have printed this identical EXACT count (every // edge here is on the grid) -- the line has to say this run cannot rule any of them // out rather than reading EXACT as settled. CHECK(contains(s, "EXACT here is not proof")); CHECK(contains(s, "floors the START edge alone")); CHECK(contains(s, "floors the END edge alone")); CHECK(contains(s, "floors START and END together")); } static void testEqualRemaindersCancelUnderAFullFloorEvenOffGrid() { // C1: a dragged, fixed-length time selection reproduces this. Neither edge sits on // the millisecond grid (isOnMillisecondGrid is false for both), but the START and // END frame-rounding remainders are EQUAL (rs == re == 8 frames), so a render that // floors both edges together lands on the identical count -- the grid predicate on // either edge alone would have missed this collision entirely. const double start = 1.0001724, end = 2.0001724; CHECK(!isOnMillisecondGrid(start)); CHECK(!isOnMillisecondGrid(end)); const long long expected = frameCountFor(start, end, 48000); CHECK(expected == 48000); // The both-edges-floored render lands on the SAME count as the exact one. CHECK(frameCountFor(1.000, 2.000, 48000) == expected); // Neither edge floored ALONE reproduces it -- only the combined floor does. CHECK(frameCountFor(1.000, end, 48000) != expected); CHECK(frameCountFor(start, 2.000, 48000) != expected); const std::string s = describeBoundsExperiment("time selection", start, end, expected, 48000); CHECK(contains(s, "EXACT")); CHECK(contains(s, "EXACT here is not proof")); CHECK(contains(s, "floors START and END together")); CHECK(!contains(s, "floors the START edge alone")); CHECK(!contains(s, "floors the END edge alone")); } static void testEndOffGridByUnderHalfAFrameStillCollidesWithAFlooredEnd() { // C1's second live shape: isOnMillisecondGrid reads this END as off-grid, but the // remainder is under half a frame at 48 kHz, so flooring it doesn't move its frame // index -- a grid test on the edge alone would still miss this collision. const double start = 0.0, end = 1.000005; CHECK(!isOnMillisecondGrid(end)); const long long expected = frameCountFor(start, end, 48000); CHECK(expected == 48000); CHECK(frameCountFor(start, 1.000, 48000) == expected); // the floored-end model matches const std::string s = describeBoundsExperiment("time selection", start, end, expected, 48000); CHECK(contains(s, "EXACT")); CHECK(contains(s, "EXACT here is not proof")); CHECK(contains(s, "floors the END edge alone")); } static void testALongVerdictNeverCarriesTheFloorSentence() { // A floor only removes frames, so LONG can never be its signature -- the sentence // must not appear even though the delta here is a "clean" one-frame LONG. const std::string s = describeBoundsExperiment("time selection", 5.0, 6.0, 48001, 48000); CHECK(contains(s, "LONG")); CHECK(!contains(s, "floored to the millisecond")); } static void testASubFrameWindowIsNotJudgedNotExact() { // A window under one frame at this rate rounds to 0 expected frames. A 0-frame // render against that is a 0-vs-0 coincidence of degenerate inputs, not a match -- // it must read NOT JUDGED, never EXACT. const double oneTenthOfAFrame = 1.0 / (48000.0 * 10.0); const long long expected = frameCountFor(0.0, oneTenthOfAFrame, 48000); CHECK(expected == 0); const std::string s = describeBoundsExperiment("time selection", 0.0, oneTenthOfAFrame, 0, 48000); CHECK(contains(s, "NOT JUDGED")); CHECK(!contains(s, "EXACT")); } static void testAWithinToleranceDeltaIsTaggedNotFloorShaped() { // One frame off frameCountFor is the gate's own edge-convention slack // (render_window.h), not the millisecond floor -- the verdict must say so rather // than reading like a genuine miss or like the floor was escaped. const std::string shortByOne = describeBoundsExperiment("time selection", 0.0, 4.067797, 195253, 48000); CHECK(contains(shortByOne, "SHORT")); CHECK(contains(shortByOne, "WITHIN TOLERANCE")); CHECK(!contains(shortByOne, "floored to the millisecond")); const std::string longByOne = describeBoundsExperiment("time selection", 0.0, 4.067797, 195255, 48000); CHECK(contains(longByOne, "LONG")); CHECK(contains(longByOne, "WITHIN TOLERANCE")); // A genuine miss (outside the tolerance) carries no such tag. const std::string shortByThree = describeBoundsExperiment("time selection", 0.0, 4.067797, 195251, 48000); CHECK(contains(shortByThree, "SHORT")); CHECK(!contains(shortByThree, "WITHIN TOLERANCE")); } static void testABypassingSourceReadsNotJudgedAndNamesTheSourceNotTheChannel() { // SelectedItems/RazorArea derive their own bounds from content -- the channel // named by channelLabel was never consulted, so a matching frame count here would // be a coincidence, not evidence the channel escaped the floor. const std::string s = describeBoundsExperiment("time selection", 0.0, 1.6551724137931001, 79448, 48000, "selected media items"); CHECK(contains(s, "NOT JUDGED")); CHECK(contains(s, "selected media items")); CHECK(!contains(s, "EXACT")); // The channel is still named at the top of the line -- only the verdict changes. CHECK(contains(s, "time selection")); } static void testANullOrEmptyBypassLabelFallsBackToTheOrdinaryVerdict() { // Off-grid, non-cancelling edges (see testEqualRemaindersCancelUnderAFullFloorEvenOffGrid // for the window shape that WOULD trip the collision caveat, whose own text also // contains "EXACT") so this assertion is pinned to the verdict word itself, not to a // caveat sentence that happens to contain the same substring. const double start = 1.0001724, end = 2.0009724; const long long expected = frameCountFor(start, end, 48000); const std::string withNull = describeBoundsExperiment("time selection", start, end, expected, 48000, nullptr); CHECK(contains(withNull, "EXACT")); CHECK(!contains(withNull, "EXACT here is not proof")); CHECK(contains(describeBoundsExperiment("time selection", start, end, expected, 48000, ""), "EXACT")); } static void testAnOnGridStartSaysTheStartEdgeIsUntested() { // Both live observations started at 0 s — the value that hides a start-side floor. const std::string s = describeBoundsExperiment("time selection", 0.0, 1.6551724137931001, 79448, 48000); CHECK(contains(s, "UNTESTED")); CHECK(contains(s, "millisecond grid")); } static void testAnOffGridStartSaysTheStartEdgeIsTested() { // The run that would genuinely settle the start question: a start carrying its own // remainder, paired with an end whose remainder does NOT cancel it (unlike // testEqualRemaindersCancelUnderAFullFloorEvenOffGrid's window, where the same shape // of start value pairs with an end that cancels it and the collision caveat fires // instead). No floored model reproduces this count, so EXACT here is unqualified. const double start = 1.0001724, end = 2.0009724; const long long expected = frameCountFor(start, end, 48000); const std::string s = describeBoundsExperiment("time selection", start, end, expected, 48000); CHECK(contains(s, "IS tested")); CHECK(!contains(s, "UNTESTED")); CHECK(contains(s, "EXACT")); CHECK(!contains(s, "EXACT here is not proof")); // A start-floored-alone render would have printed a DIFFERENT count here, so a // mismatch against `expected` on a re-run is real evidence, not ambiguous. CHECK(frameCountFor(1.000, end, 48000) != expected); CHECK(contains(describeBoundsExperiment("time selection", start, end, frameCountFor(1.000, end, 48000), 48000), "LONG")); } static void testAt44100WhereAMillisecondIsNotAWholeNumberOfFrames() { // 44.1 kHz: the window is 463 frames, the ms-floored one 441 (both pinned in // testMillisecondFloorAt44100WhereAMillisecondIsNotWholeFrames). The verdict has to // reach the same two numbers at a rate where a millisecond is 44.1 frames. const std::string exact = describeBoundsExperiment("time selection", 0.0, 0.0105, 463, 44100); CHECK(contains(exact, "EXACT")); CHECK(contains(exact, "44100 Hz")); const std::string floored = describeBoundsExperiment("custom time bounds", 0.0, 0.0105, 441, 44100); CHECK(contains(floored, "SHORT")); CHECK(contains(floored, "floored to the millisecond")); } static void testAnUnmeasuredRenderAnswersNothingRatherThanPassing() { // Auto/Manual are not judged against a frame count, and an empty render has none. // The line must still print and must not read as a pass — its silence would. const std::string s = describeBoundsExperiment("time selection", 0.0, 1.6551724137931001, 0, 0); CHECK(!s.empty()); CHECK(contains(s, "NOT JUDGED")); CHECK(!contains(s, "EXACT")); CHECK(contains(s, "time selection")); } static void testAnUnnamedChannelStillProducesAReadableLine() { CHECK(contains(describeBoundsExperiment(nullptr, 0.0, 1.0, 48000, 48000), "unnamed")); CHECK(contains(describeBoundsExperiment("", 0.0, 1.0, 48000, 48000), "unnamed")); } // --- describeBoundsDrift: the read-back's verdict ------------------------------ static void testBoundsThatReadBackUnchangedDescribeNothing() { // The answer that proves the request crossed into REAPER intact — including for a // window whose end is nowhere near a millisecond boundary. CHECK(describeBoundsDrift(0.0, 4.067797, 0.0, 4.067797, 48000).empty()); CHECK(describeBoundsDrift(1.0001724, 2.0001724, 1.0001724, 2.0001724, 48000).empty()); } static void testADriftedEndNamesBothWindowsAndBothCounts() { const std::string s = describeBoundsDrift(0.0, 4.067797, 0.0, 4.067, 48000); CHECK(!s.empty()); // Both counts as literals from the DAW observation, not re-derived from the same // functions the sentence was built with. CHECK(contains(s, "195254")); // what the request asks for CHECK(contains(s, "195216")); // what the drifted window would hold CHECK(contains(s, "48000 Hz")); } static void testTheReportPrintsEnoughDigitsToShowTheDrift() { // A report whose two numbers print identically is evidence of nothing. Two ends a // single ULP apart — far under the sixth decimal a shorter rendering would stop at // — must still read as two different numbers. Pinned as the actual %.17g literals // (not the needle the two ends share, "s)", which occurs at every precision and so // proves nothing): a report that regressed to a shorter format like %.6g would // print the same six significant digits for both ends, and these two `contains` // checks would then fail. const double asked = 4.067797; const double stored = std::nextafter(asked, 5.0); char askedBuf[32], storedBuf[32]; std::snprintf(askedBuf, sizeof(askedBuf), "%.17g", asked); std::snprintf(storedBuf, sizeof(storedBuf), "%.17g", stored); CHECK(std::string(askedBuf) != std::string(storedBuf)); const std::string s = describeBoundsDrift(0.0, asked, 0.0, stored, 48000); CHECK(!s.empty()); CHECK(contains(s, askedBuf)); CHECK(contains(s, storedBuf)); } static void testADriftedStartIsCaughtToo() { // The edge both observations could not test. const std::string s = describeBoundsDrift(1.0001724, 2.0, 1.000, 2.0, 48000); CHECK(!s.empty()); CHECK(contains(s, "1.0001724")); } static void testAnUnknownRateStillReportsTheDriftWithoutFrames() { // A project that never pinned a rate reads 0. The drift is still worth saying; a // frame count over an unknown rate is not. const std::string s = describeBoundsDrift(0.0, 4.067797, 0.0, 4.067, 0); CHECK(!s.empty()); CHECK(!contains(s, "frames")); } int main() { testFrameCountIsExactNotRounded(); testFrameCountIsADifferenceOfIndicesNotADuration(); testFrameCountRefusesEmptyInvertedAndUnknownRate(); testWindowStartingAtExactlyZero(); testNonFrameAlignedWindowAcceptsItsAdjacentCounts(); testLengthDerivedAndSameConventionRenderersStayWithinOneFrame(); testMixedEdgeConventionsCanMissByTwoAndAreRefused(); testWholeItemWideningIsStillRefused(); testLargeShortfallIsStillRefused(); testEmptyRenderIsRefusedAgainstARealWindow(); testRangeInsideItemCannotBeExpressed(); testRangeWiderThanItemCannotBeExpressedEither(); testEachEdgeAloneDisqualifies(); testExtentEqualToWindowIsExpressible(); testSubFrameDriftStillPrintsTheSameFrames(); testUnknownRateFallsBackToExactEquality(); testMultiItemUnionExtent(); testMillisecondFlooredEndReproducesBothShortRenders(); testTheSixDecimalDisplayDidNotCreateTheEffect(); testWindowAlreadyOnTheMillisecondGridLosesNothing(); testOneFrameOfRemainderStillFloors(); testMillisecondFloorAt44100WhereAMillisecondIsNotWholeFrames(); testASubMillisecondStartWouldNotHideItself(); testTheTwoLiveShortRendersPinnedAtFullPrecision(); testOnGridRecognizesWholeMillisecondsIncludingTheBinaryTrap(); testOffGridRecognizesASubMillisecondRemainder(); testAnExactRenderReadsExactAndNamesItsChannel(); testTheLiveShortfallReadsShortAndNamesTheMillisecondShape(); testAShortfallThatIsNotTheMillisecondShapeClaimsNothingAboutIt(); testARenderPastTheWindowReadsLong(); testAWindowAlreadyOnTheGridIsUnaffectedByTheChannelSwitch(); testEqualRemaindersCancelUnderAFullFloorEvenOffGrid(); testEndOffGridByUnderHalfAFrameStillCollidesWithAFlooredEnd(); testALongVerdictNeverCarriesTheFloorSentence(); testASubFrameWindowIsNotJudgedNotExact(); testAWithinToleranceDeltaIsTaggedNotFloorShaped(); testABypassingSourceReadsNotJudgedAndNamesTheSourceNotTheChannel(); testANullOrEmptyBypassLabelFallsBackToTheOrdinaryVerdict(); testAnOnGridStartSaysTheStartEdgeIsUntested(); testAnOffGridStartSaysTheStartEdgeIsTested(); testAt44100WhereAMillisecondIsNotAWholeNumberOfFrames(); testAnUnmeasuredRenderAnswersNothingRatherThanPassing(); testAnUnnamedChannelStillProducesAReadableLine(); testBoundsThatReadBackUnchangedDescribeNothing(); testADriftedEndNamesBothWindowsAndBothCounts(); testTheReportPrintsEnoughDigitsToShowTheDrift(); testADriftedStartIsCaughtToo(); testAnUnknownRateStillReportsTheDriftWithoutFrames(); if (g_fail) { std::printf("%d check(s) FAILED\n", g_fail); return 1; } std::printf("render_window: all checks passed\n"); return 0; }