// Standalone tests for reasampler::instrument::ui::embed_strip — no VST3, no REAPER, no framework. // Same fast assert loop as the sibling pure tests (editor_geometry et al.): assert the // embedded TCP/MCP strip's layout math + zone hit-testing + level fill directly. // // Covers: layoutEmbed splitting a normal area into keymap + level band, a tiny area // (band yields to the keymap minimum, no inversion), and a zero area (all empty); // zoneSegmentRect mapping the 128-key span linearly, tiling adjacent zones seamlessly, // clamping out-of-range/inverted notes; zoneAtPoint hitting the covering zone, first-match // on overlap, missing on uncovered keys and off-band, and rejecting a null/empty list; // levelFillRect clamping 0..1 and its endpoints. #include "../src/core/instrument/ui/embed_strip.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) // --- layoutEmbed -------------------------------------------------------------- static void testLayoutNormalArea() { // A comfortable inline strip: keymap band on top, thin level band pinned to the bottom. const EmbedLayout L = layoutEmbed(300, 40); CHECK(L.keymap.x == 0 && L.keymap.y == 0 && L.keymap.right() == 300); CHECK(L.levelBand.x == 0 && L.levelBand.right() == 300); // Level band is the fixed height at the very bottom; keymap fills the rest, contiguous. CHECK(L.levelBand.height == kEmbedLevelBandHeight); CHECK(L.levelBand.bottom() == 40); CHECK(L.keymap.bottom() == L.levelBand.y); CHECK(L.keymap.height == 40 - kEmbedLevelBandHeight); } static void testLayoutTinyAreaKeepsKeymap() { // A very short area: the level band must yield so the keymap keeps its minimum, and no // rect inverts. const EmbedLayout L = layoutEmbed(300, 8); CHECK(L.keymap.height >= 0); CHECK(L.levelBand.height >= 0); CHECK(L.keymap.bottom() == L.levelBand.y); CHECK(L.levelBand.bottom() == 8); // The keymap is not starved below its floor when the area allows it. CHECK(L.keymap.height >= kEmbedKeymapMinHeight || 8 < kEmbedKeymapMinHeight); } static void testLayoutZeroArea() { const EmbedLayout L = layoutEmbed(0, 0); CHECK(L.keymap.width <= 0 && L.keymap.height <= 0); CHECK(L.levelBand.width <= 0 && L.levelBand.height <= 0); // Negative dimensions clamp to a zero-area, non-inverted rect. const EmbedLayout N = layoutEmbed(-50, -50); CHECK(N.keymap.right() >= N.keymap.x && N.keymap.bottom() >= N.keymap.y); } // --- zoneSegmentRect ---------------------------------------------------------- static void testZoneSegmentFullSpan() { // A zone covering the whole keyboard spans the entire keymap band width. const EmbedLayout L = layoutEmbed(256, 40); const Rect r = zoneSegmentRect(L, 0, 127); CHECK(r.x == L.keymap.x); CHECK(r.right() == L.keymap.right()); CHECK(r.y == L.keymap.y && r.bottom() == L.keymap.bottom()); } static void testAdjacentZonesTileSeamlessly() { // 256px band, 128 keys -> 2px/key. Zones 0..59 and 60..127 must abut with no gap or // overlap: the low zone's right == the high zone's left. const EmbedLayout L = layoutEmbed(256, 40); const Rect lo = zoneSegmentRect(L, 0, 59); const Rect hi = zoneSegmentRect(L, 60, 127); CHECK(lo.x == L.keymap.x); CHECK(hi.right() == L.keymap.right()); CHECK(lo.right() == hi.x); // seamless tile — the load-bearing assertion CHECK(lo.right() == L.keymap.x + 60 * 2); // 60 keys * 2px } static void testZoneSegmentClampsBadNotes() { const EmbedLayout L = layoutEmbed(256, 40); // Out-of-range notes clamp into the band; an inverted zone (low > high) collapses to a // zero-or-positive-width rect, never inverts. const Rect over = zoneSegmentRect(L, -10, 200); CHECK(over.x == L.keymap.x && over.right() == L.keymap.right()); const Rect inv = zoneSegmentRect(L, 100, 20); CHECK(inv.right() >= inv.x); } // --- zoneAtPoint -------------------------------------------------------------- static void testZoneAtPointHits() { const EmbedLayout L = layoutEmbed(256, 40); const EmbedZone zones[2] = {{0, 59}, {60, 127}}; // A point inside the low zone's segment resolves to zone 0; inside the high zone, 1. const Rect lo = zoneSegmentRect(L, 0, 59); const Rect hi = zoneSegmentRect(L, 60, 127); const int yMid = (L.keymap.y + L.keymap.bottom()) / 2; CHECK(zoneAtPoint(L, zones, 2, lo.x + 1, yMid) == 0); CHECK(zoneAtPoint(L, zones, 2, hi.right() - 1, yMid) == 1); } static void testZoneAtPointFirstMatchOnOverlap() { const EmbedLayout L = layoutEmbed(256, 40); // Two overlapping zones; the FIRST in order must win the contested keys. const EmbedZone zones[2] = {{0, 127}, {40, 80}}; const int yMid = (L.keymap.y + L.keymap.bottom()) / 2; const Rect contested = zoneSegmentRect(L, 40, 80); CHECK(zoneAtPoint(L, zones, 2, contested.x + 1, yMid) == 0); // zone 0 wins } static void testZoneAtPointMisses() { const EmbedLayout L = layoutEmbed(256, 40); const EmbedZone zones[1] = {{60, 72}}; // a narrow zone; most keys uncovered const int yMid = (L.keymap.y + L.keymap.bottom()) / 2; // A key left of the zone is uncovered -> -1. CHECK(zoneAtPoint(L, zones, 1, L.keymap.x + 1, yMid) == -1); // A point in the level band (below the keymap) is off the keymap -> -1. CHECK(zoneAtPoint(L, zones, 1, L.levelBand.x + 4, L.levelBand.y) == -1); // Empty / null list -> -1. CHECK(zoneAtPoint(L, zones, 0, L.keymap.x + 1, yMid) == -1); CHECK(zoneAtPoint(L, nullptr, 3, L.keymap.x + 1, yMid) == -1); } // --- levelFillRect ------------------------------------------------------------ static void testLevelFillClamps() { const EmbedLayout L = layoutEmbed(200, 40); // Zero / negative -> empty. CHECK(levelFillRect(L, 0.0).width <= 0); CHECK(levelFillRect(L, -1.0).width <= 0); // Full / over-full -> the whole band width. CHECK(levelFillRect(L, 1.0).width == L.levelBand.width); CHECK(levelFillRect(L, 5.0).width == L.levelBand.width); // Half -> ~half the band, pinned to the band's left and vertical extent. const Rect half = levelFillRect(L, 0.5); CHECK(half.x == L.levelBand.x); CHECK(half.y == L.levelBand.y && half.bottom() == L.levelBand.bottom()); CHECK(half.width == L.levelBand.width / 2); } int main() { testLayoutNormalArea(); testLayoutTinyAreaKeepsKeymap(); testLayoutZeroArea(); testZoneSegmentFullSpan(); testAdjacentZonesTileSeamlessly(); testZoneSegmentClampsBadNotes(); testZoneAtPointHits(); testZoneAtPointFirstMatchOnOverlap(); testZoneAtPointMisses(); testLevelFillClamps(); if (g_fail == 0) std::printf("embed_strip: all tests passed\n"); else std::printf("embed_strip: %d FAILED\n", g_fail); return g_fail == 0 ? 0 : 1; }