Q-W1 pt2: core/shell/app relocation + sub-namespaces; one concrete ui::Rect (LTRB fork retired); slot_map split from bank_book; BankIndex→BankModel; 59/59 green

This commit is contained in:
2026-07-28 20:48:56 -04:00
parent 67a41728f3
commit 847936f813
222 changed files with 2247 additions and 2079 deletions
+37 -36
View File
@@ -1,4 +1,4 @@
// Standalone tests for reasampler::vst::keyboard_strip — no VST3, no REAPER, no framework.
// Standalone tests for reasampler::instrument::ui::keyboard_strip — no VST3, no REAPER, no framework.
// Same fast assert loop as the sibling pure tests. Assert the capture-first editor's
// keyboard-strip layout, root marker, key mapping, zone-bar hit regions, and the drag-delta
// note resolver directly — the geometry that backs the single-capture root-set and the opt-in
@@ -14,11 +14,12 @@
// no-ops; isNaturalKey across a full octave (C4..B4), at boundary notes 0 and 127, and with
// out-of-range inputs that clamp to [0,127].
#include "../src/vst/keyboard_strip.h"
#include "../src/core/instrument/ui/keyboard_strip.h"
#include <cstdio>
using namespace reasampler::vst;
using namespace reasampler;
using namespace reasampler::instrument::ui;
static int g_fail = 0;
#define CHECK(cond) do { if(!(cond)) { \
@@ -32,13 +33,13 @@ static StripLayout wideStrip() { return layoutStrip(1280, 40); }
static void testLayoutNormalArea() {
const StripLayout L = layoutStrip(640, 40);
CHECK(L.keys.left == 0 && L.keys.top == 0);
CHECK(L.keys.right == 640 && L.keys.bottom == 40);
CHECK(L.keys.x == 0 && L.keys.y == 0);
CHECK(L.keys.right() == 640 && L.keys.bottom() == 40);
}
static void testLayoutZeroArea() {
const StripLayout L = layoutStrip(0, 0);
CHECK(L.keys.width() == 0 && L.keys.height() == 0);
CHECK(L.keys.width == 0 && L.keys.height == 0);
}
// --- keyLeftX / keyRect / rootMarkerRect --------------------------------------
@@ -46,8 +47,8 @@ static void testLayoutZeroArea() {
static void testKeyLeftMonotonicAndBounds() {
const StripLayout L = wideStrip();
// Key 0's left edge is the band left; the 128 boundary is the band right.
CHECK(keyLeftX(L, 0) == L.keys.left);
CHECK(keyLeftX(L, 128) == L.keys.right);
CHECK(keyLeftX(L, 0) == L.keys.x);
CHECK(keyLeftX(L, 128) == L.keys.right());
// Strictly non-decreasing across the span.
int prev = keyLeftX(L, 0);
for (int n = 1; n <= 128; ++n) {
@@ -62,17 +63,17 @@ static void testKeyLeftMonotonicAndBounds() {
static void testKeyRectHalfOpen() {
const StripLayout L = wideStrip();
const Rect k = keyRect(L, 60);
CHECK(k.left == keyLeftX(L, 60));
CHECK(k.right == keyLeftX(L, 61));
CHECK(k.top == L.keys.top && k.bottom == L.keys.bottom);
CHECK(k.width() == 10); // 10px/key
CHECK(k.x == keyLeftX(L, 60));
CHECK(k.right() == keyLeftX(L, 61));
CHECK(k.y == L.keys.y && k.bottom() == L.keys.bottom());
CHECK(k.width == 10); // 10px/key
}
static void testRootMarkerEqualsKeyRect() {
const StripLayout L = wideStrip();
const Rect m = rootMarkerRect(L, 64);
const Rect k = keyRect(L, 64);
CHECK(m.left == k.left && m.right == k.right && m.top == k.top && m.bottom == k.bottom);
CHECK(m.x == k.x && m.right() == k.right() && m.y == k.y && m.bottom() == k.bottom());
}
// --- keyAtPoint ---------------------------------------------------------------
@@ -81,17 +82,17 @@ static void testKeyAtPointInverts() {
const StripLayout L = wideStrip();
// A point in the middle of key 60's cell resolves to 60.
const Rect k = keyRect(L, 60);
CHECK(keyAtPoint(L, k.left + 5, k.top + 2) == 60);
CHECK(keyAtPoint(L, k.x + 5, k.y + 2) == 60);
// The very left of the band is key 0; just inside the right edge is key 127.
CHECK(keyAtPoint(L, L.keys.left, 2) == 0);
CHECK(keyAtPoint(L, L.keys.right - 1, 2) == 127);
CHECK(keyAtPoint(L, L.keys.x, 2) == 0);
CHECK(keyAtPoint(L, L.keys.right() - 1, 2) == 127);
}
static void testKeyAtPointOffBand() {
const StripLayout L = wideStrip();
CHECK(keyAtPoint(L, -5, 2) == -1); // left of band
CHECK(keyAtPoint(L, L.keys.right + 5, 2) == -1); // right of band
CHECK(keyAtPoint(L, 100, L.keys.bottom + 5) == -1); // below band
CHECK(keyAtPoint(L, L.keys.right() + 5, 2) == -1); // right of band
CHECK(keyAtPoint(L, 100, L.keys.bottom() + 5) == -1); // below band
}
// --- zoneBarRect --------------------------------------------------------------
@@ -99,17 +100,17 @@ static void testKeyAtPointOffBand() {
static void testZoneBarSpansInclusive() {
const StripLayout L = wideStrip();
const Rect bar = zoneBarRect(L, 12, 23); // C1..B1 inclusive
CHECK(bar.left == keyLeftX(L, 12));
CHECK(bar.right == keyLeftX(L, 24)); // high+1 -> the bar covers key 23 fully
CHECK(bar.width() == 120); // 12 keys * 10px
CHECK(bar.x == keyLeftX(L, 12));
CHECK(bar.right() == keyLeftX(L, 24)); // high+1 -> the bar covers key 23 fully
CHECK(bar.width == 120); // 12 keys * 10px
}
static void testZoneBarMalformedCollapses() {
const StripLayout L = wideStrip();
// low > high must collapse, never invert.
const Rect bar = zoneBarRect(L, 80, 40);
CHECK(bar.width() >= 0);
CHECK(bar.right >= bar.left);
CHECK(bar.width >= 0);
CHECK(bar.right() >= bar.x);
}
// --- zoneGrabAt ---------------------------------------------------------------
@@ -117,23 +118,23 @@ static void testZoneBarMalformedCollapses() {
static void testZoneGrabEdgesAndBody() {
const StripLayout L = wideStrip();
const Rect bar = zoneBarRect(L, 20, 60); // wide bar with a clear body
const int y = L.keys.top + 2;
const int y = L.keys.y + 2;
// Near the left edge -> low; near the right edge -> high; the middle -> body.
CHECK(zoneGrabAt(L, 20, 60, bar.left + 1, y) == ZoneGrab::kLowEdge);
CHECK(zoneGrabAt(L, 20, 60, bar.right - 1, y) == ZoneGrab::kHighEdge);
CHECK(zoneGrabAt(L, 20, 60, bar.left + bar.width() / 2, y) == ZoneGrab::kBody);
CHECK(zoneGrabAt(L, 20, 60, bar.x + 1, y) == ZoneGrab::kLowEdge);
CHECK(zoneGrabAt(L, 20, 60, bar.right() - 1, y) == ZoneGrab::kHighEdge);
CHECK(zoneGrabAt(L, 20, 60, bar.x + bar.width / 2, y) == ZoneGrab::kBody);
// Off the bar entirely -> none.
CHECK(zoneGrabAt(L, 20, 60, bar.right + 20, y) == ZoneGrab::kNone);
CHECK(zoneGrabAt(L, 20, 60, bar.right() + 20, y) == ZoneGrab::kNone);
}
static void testZoneGrabNarrowBarSplitsAtMidpointLowWins() {
const StripLayout L = wideStrip();
// A 1-key bar is narrower than 2*edge: no body; the low edge wins the exact midpoint.
const Rect bar = zoneBarRect(L, 50, 50);
const int y = L.keys.top + 2;
const int mid = bar.left + bar.width() / 2;
const int y = L.keys.y + 2;
const int mid = bar.x + bar.width / 2;
CHECK(zoneGrabAt(L, 50, 50, mid, y) == ZoneGrab::kLowEdge); // tie -> low
CHECK(zoneGrabAt(L, 50, 50, bar.right - 1, y) == ZoneGrab::kHighEdge);
CHECK(zoneGrabAt(L, 50, 50, bar.right() - 1, y) == ZoneGrab::kHighEdge);
}
// --- zoneBarAtPoint -----------------------------------------------------------
@@ -143,8 +144,8 @@ static void testZoneBarAtPointFirstMatch() {
const int lows[2] = {20, 30}; // zone 0 and zone 1 overlap on [30,50]
const int highs[2] = {50, 70};
const Rect overlap = zoneBarRect(L, 30, 50);
const int y = L.keys.top + 2;
const int cx = overlap.left + overlap.width() / 2;
const int y = L.keys.y + 2;
const int cx = overlap.x + overlap.width / 2;
// A point in the overlap resolves to the FIRST covering zone (draw order).
const ZoneBarHit hit = zoneBarAtPoint(L, lows, highs, 2, cx, y);
CHECK(hit.zoneIndex == 0);
@@ -219,7 +220,7 @@ static void testResolveDragProportionalNonDivisibleWidth() {
// a drag from note 0 by (width-1) pixels must land at keyAtPoint(width-1), which is 127.
const int width = 544;
const StripLayout L = layoutStrip(width, 40);
CHECK(keyAtPoint(L, width - 1, L.keys.top + 1) == 127);
CHECK(keyAtPoint(L, width - 1, L.keys.y + 1) == 127);
CHECK(resolveDragNote(L, 0, width - 1) == 127);
// Also verify mid-strip coherence: for each key N, a drag from 0 by N's left-edge
@@ -227,12 +228,12 @@ static void testResolveDragProportionalNonDivisibleWidth() {
// rounding may round down). The critical direction is that it must NOT over-shoot by
// more than 0 (it must reach at least the right key).
for (int n = 1; n < kStripKeyCount; ++n) {
const int leftPx = keyRect(L, n).left;
const int leftPx = keyRect(L, n).x;
const int resolved = resolveDragNote(L, 0, leftPx);
// The left edge of key N is the first pixel "in" that key, so we expect resolved == N.
// Allow resolved == N-1 only when the pixel is at the exact boundary (keyEdgeToX may
// produce the same x for adjacent keys when keys share a pixel). Disallow over-shoot.
const int expected = keyAtPoint(L, leftPx, L.keys.top + 1);
const int expected = keyAtPoint(L, leftPx, L.keys.y + 1);
CHECK(resolved >= expected - 1 && resolved <= expected + 1);
}
}