// Standalone tests for reasampler::instrument::ui::sample_bands — no VST3, no REAPER, no // test framework. Same fast assert loop as the sibling pure tests. // // Covers: the shared Rect vocabulary (contains() half-open + degenerate rects); the // three-band vertical inventory (chrome over waveform over decks, no overlap, no // inversion) asserted as pure geometry with no paint call; the waveform band's two-lane // floor and the bands-clip-rather-than-squeeze rule on a short window; the deck band's // bottom anchor and its exact requested height; the same stack/anchor/degrade properties // re-anchored AT the allocator's own kEditorMinWidth/kEditorMinHeight floor rather than only // below it; and the lane split (mono = one full-band lane, stereo = two lanes with the seam // gap between them). #include "../src/core/instrument/ui/sample_bands.h" #include using namespace reasampler; using namespace reasampler::instrument::ui; static int g_fail = 0; #define CHECK(cond) do { if(!(cond)) { \ std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0) // --- the shared Rect vocabulary ---------------------------------------------- static void testContainsHalfOpen() { Rect r = Rect::ltrb(10, 20, 50, 40); // [10,50) x [20,40) CHECK(contains(r, 10, 20)); // top-left inclusive CHECK(contains(r, 49, 39)); // bottom-right exclusive edge, inside CHECK(!contains(r, 50, 30)); // right edge excluded CHECK(!contains(r, 30, 40)); // bottom edge excluded CHECK(!contains(r, 9, 30)); // left of rect CHECK(!contains(r, 30, 19)); // above rect } static void testContainsDegenerate() { CHECK(!contains(Rect::ltrb(10, 10, 10, 20), 10, 15)); // zero width CHECK(!contains(Rect::ltrb(10, 10, 20, 10), 15, 10)); // zero height CHECK(!contains(Rect::ltrb(20, 10, 10, 20), 15, 15)); // inverted (right < left) } // --- the vertical inventory --------------------------------------------------- static void testBandsStackTopToBottomWithoutOverlap() { const SampleBands b = computeSampleBands(840, 620, 120); CHECK(b.chrome.y == 0); CHECK(b.chrome.height == kTitleHeight + kChromeRowHeight); // Strictly ordered, no overlap: each band starts at or after the previous one's bottom. CHECK(b.waveform.y >= b.chrome.bottom()); CHECK(b.decks.y >= b.waveform.bottom()); // No inversion anywhere. CHECK(b.chrome.height > 0 && b.waveform.height > 0 && b.decks.height > 0); CHECK(b.chrome.width > 0 && b.waveform.width > 0 && b.decks.width > 0); } static void testChromeSpansFullWidthAndLowerBandsAreInset() { const SampleBands b = computeSampleBands(840, 620, 120); CHECK(b.chrome.x == 0 && b.chrome.right() == 840); CHECK(b.waveform.x == kPad && b.waveform.right() == 840 - kPad); CHECK(b.decks.x == kPad && b.decks.right() == 840 - kPad); } static void testDeckBandIsBottomAnchoredAtItsRequestedHeight() { const int deckH = 96; const SampleBands b = computeSampleBands(840, 620, deckH); CHECK(b.decks.height == deckH); CHECK(b.decks.bottom() == 620 - kPad); // bottom-anchored inside the pad } static void testWaveformAbsorbsSlackAsTheWindowGrows() { const SampleBands small = computeSampleBands(840, 620, 120); const SampleBands big = computeSampleBands(840, 900, 120); CHECK(big.waveform.height == small.waveform.height + 280); // The fixed bands do not grow with the window. CHECK(big.chrome.height == small.chrome.height); CHECK(big.decks.height == small.decks.height); } static void testWaveformNeverShrinksBelowTheTwoLaneFloor() { // A window far too short for chrome + two lanes + deck: the floor wins and the deck band // is pushed past the bottom (clipped) rather than squeezing the waveform. const SampleBands b = computeSampleBands(840, 160, 120); CHECK(b.waveform.height == kWaveformMinHeight); CHECK(b.decks.y >= b.waveform.bottom()); CHECK(b.decks.bottom() > 160); // deliberately clipped below the window } static void testTwoLaneFloorHoldsTwoUsableLanes() { // The floor is exactly what two minimum lanes plus their seam need — not an arbitrary // number, so a lane can never be allocated below its own minimum. CHECK(kWaveformMinHeight == 2 * kLaneMinHeight + kLaneGap); const SampleBands b = computeSampleBands(840, 160, 120); const WaveformLanes lanes = waveformLanes(b.waveform, LaneSplit::Stereo); CHECK(lanes.upper.height >= kLaneMinHeight); CHECK(lanes.lower.height >= kLaneMinHeight); } static void testDegenerateWindowYieldsNoInvertedRects() { const SampleBands z = computeSampleBands(0, 0, 0); CHECK(z.chrome.width == 0 && z.chrome.height == 0); CHECK(z.waveform.width <= 0 || z.waveform.height >= 0); CHECK(z.waveform.right() >= z.waveform.x); CHECK(z.decks.right() >= z.decks.x); const SampleBands tiny = computeSampleBands(20, 20, 4); CHECK(tiny.waveform.right() >= tiny.waveform.x); CHECK(tiny.decks.right() >= tiny.decks.x); } // --- the allocator at its own floor (kEditorMinWidth x kEditorMinHeight) ------- // The allocator's own client-area floor is a fact IT owns (kEditorMinWidth/kEditorMinHeight // above); the fixtures above validate the general shape entirely below that floor (840x620, // 840x160). These anchor the same properties AT the floor itself, so a floor move that broke // the stack there would have nothing else in this file to catch it. static void testBandsStackWithoutOverlapAtTheEditorFloor() { const SampleBands b = computeSampleBands(kEditorMinWidth, kEditorMinHeight, 120); CHECK(b.chrome.y == 0); CHECK(b.chrome.width == kEditorMinWidth); CHECK(b.chrome.height == kTitleHeight + kChromeRowHeight); CHECK(b.waveform.y >= b.chrome.bottom()); CHECK(b.decks.y >= b.waveform.bottom()); CHECK(b.waveform.x == kPad && b.waveform.right() == kEditorMinWidth - kPad); CHECK(b.decks.x == kPad && b.decks.right() == kEditorMinWidth - kPad); } static void testDeckBandIsBottomAnchoredAtTheEditorFloor() { constexpr int deckH = 120; const SampleBands b = computeSampleBands(kEditorMinWidth, kEditorMinHeight, deckH); CHECK(b.decks.height == deckH); CHECK(b.decks.bottom() == kEditorMinHeight - kPad); } // At the shipped two-row deck height (216px — what test_deck_groups.cpp pins the deck to by // construction, at and above the floor width), the waveform gets exactly what the floor's own // height leaves it: an equality, not a bound, so a floor-height change that quietly ate into // the waveform's slack would fail here rather than only widen/narrow a `>=`. static void testWaveformGetsExactlyTheFloorsRemainingHeightAtATwoRowDeck() { constexpr int twoRowDeckH = 216; const SampleBands b = computeSampleBands(kEditorMinWidth, kEditorMinHeight, twoRowDeckH); const int expected = kEditorMinHeight - kPad - twoRowDeckH - 2 * kBandGap - (kTitleHeight + kChromeRowHeight); CHECK(b.waveform.height == expected); CHECK(b.waveform.height == 358); CHECK(b.waveform.height >= kWaveformMinHeight); } // The floor is not immune to the degrade path: a deck grown too tall for the floor's OWN // height still hits the floor-wins rule instead of squeezing the waveform below its usable // minimum — the sub-floor fixtures above cover the general rule; this is the same rule // exercised at the allocator's own minimum width. static void testAnOversizedDeckAtTheFloorStillDegradesGracefully() { const SampleBands b = computeSampleBands(kEditorMinWidth, kEditorMinHeight, 500); CHECK(b.waveform.height == kWaveformMinHeight); CHECK(b.decks.y >= b.waveform.bottom()); CHECK(b.decks.bottom() > kEditorMinHeight); // clipped below the floor's own window } // --- the waveform band's lanes ------------------------------------------------ static void testMonoUsesOneFullBandLane() { const Rect band = Rect::ltrb(8, 100, 832, 300); const WaveformLanes lanes = waveformLanes(band, LaneSplit::Single); CHECK(lanes.upper == band); CHECK(lanes.lower.empty()); // no redundant duplicate lane in mono } static void testStereoSplitsIntoTwoLanesWithTheSeamGap() { const Rect band = Rect::ltrb(8, 100, 832, 300); // height 200 const WaveformLanes lanes = waveformLanes(band, LaneSplit::Stereo); CHECK(lanes.upper.y == band.y); CHECK(lanes.lower.bottom() == band.bottom()); // Full width each, seam exactly kLaneGap, no overlap. CHECK(lanes.upper.x == band.x && lanes.upper.right() == band.right()); CHECK(lanes.lower.x == band.x && lanes.lower.right() == band.right()); CHECK(lanes.lower.y - lanes.upper.bottom() == kLaneGap); CHECK(lanes.upper.height + lanes.lower.height + kLaneGap == band.height); } static void testStereoOddRemainderGoesToTheUpperLane() { const Rect band = Rect::ltrb(0, 0, 100, 201); // usable 199 -> 100 / 99 const WaveformLanes lanes = waveformLanes(band, LaneSplit::Stereo); CHECK(lanes.upper.height == 100); CHECK(lanes.lower.height == 99); CHECK(lanes.lower.bottom() == band.bottom()); } static void testEmptyBandYieldsEmptyLanes() { const WaveformLanes lanes = waveformLanes(Rect{}, LaneSplit::Stereo); CHECK(lanes.upper.empty()); CHECK(lanes.lower.empty()); } int main() { testContainsHalfOpen(); testContainsDegenerate(); testBandsStackTopToBottomWithoutOverlap(); testChromeSpansFullWidthAndLowerBandsAreInset(); testDeckBandIsBottomAnchoredAtItsRequestedHeight(); testWaveformAbsorbsSlackAsTheWindowGrows(); testWaveformNeverShrinksBelowTheTwoLaneFloor(); testTwoLaneFloorHoldsTwoUsableLanes(); testDegenerateWindowYieldsNoInvertedRects(); testBandsStackWithoutOverlapAtTheEditorFloor(); testDeckBandIsBottomAnchoredAtTheEditorFloor(); testWaveformGetsExactlyTheFloorsRemainingHeightAtATwoRowDeck(); testAnOversizedDeckAtTheFloorStillDegradesGracefully(); testMonoUsesOneFullBandLane(); testStereoSplitsIntoTwoLanesWithTheSeamGap(); testStereoOddRemainderGoesToTheUpperLane(); testEmptyBandYieldsEmptyLanes(); if (g_fail == 0) { std::printf("sample_bands: all tests passed\n"); return 0; } std::printf("sample_bands: %d failure(s)\n", g_fail); return 1; }