Files
m3te/tests/hit_test.sx
swipelab a7b41ccbca migrate to the new for-loop syntax
Drop the ':' before captures (for xs (x) / for 0..n (i)); the index
capture becomes the trailing open range (for xs, 0.. (x, i)). 136
headers across 26 files, mechanical.

Five headless tests (banner_layout, hit_test, swipe_commit,
swipe_intent, swipe_reshuffle) also gain a direct
#import "modules/ui/types.sx" — they named Point/Frame through a
transitive import, which bare visibility no longer permits.

Gates: sx build --target ios-sim main.sx links; tools/run_tests.sh
23/23.
2026-06-10 20:39:59 +03:00

70 lines
3.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Hit-test golden (P4.4): lock the touch→cell mapping `BoardLayout.point_to_cell`
// as the exact inverse of `cell_frame`. The two are written independently — one
// multiplies a cell index by cell_size, the other divides a point by cell_size
// and truncates — so round-tripping every cell center back to its own cell is a
// real check, not a tautology. BoardView and P5's swap input both reuse this
// mapping, so a drift here would silently send taps/swaps to the wrong cell.
//
// Imports BoardLayout (no GL/stb), not BoardView, so it links headless. It also
// avoids tests/test.sx, whose modules/process.sx → modules/trace.sx pulls in a
// second `Frame` struct that collides with the UI `Frame`. Failure is signalled
// via a non-zero exit code (the runner checks exit code AND stdout).
#import "modules/std.sx";
#import "modules/ui/types.sx";
#import "board.sx";
#import "board_layout.sx";
main :: () -> s32 {
// 800×600 with no safe inset → a 600px square grid, cell 75, centered: the
// grid origin lands at (100, 0). Integer math keeps the dump deterministic.
lay : BoardLayout = ---;
lay.compute(Frame.make(0.0, 0.0, 800.0, 600.0), EdgeInsets.zero());
print("grid origin ({},{}) cell {}\n",
cast(s64) lay.origin.x, cast(s64) lay.origin.y, cast(s64) lay.cell_size);
fails : s64 = 0;
// Every cell center must map back to its own cell.
hits : s64 = 0;
for 0..BOARD_ROWS (row) {
for 0..BOARD_COLS (col) {
cf := lay.cell_frame(col, row);
center := Point.{ x = cf.mid_x(), y = cf.mid_y() };
if h := lay.point_to_cell(center) {
if h.col == col and h.row == row { hits += 1; }
}
}
}
if hits != BOARD_CELLS { fails += 1; }
print("ok: {}/{} cell centers round-trip\n", hits, BOARD_CELLS);
// A cell's top-left corner belongs to that cell (the leading edge is
// inclusive), so corner-of-(3,5) resolves to (3,5).
corner := Point.{ x = lay.origin.x + 3.0 * lay.cell_size, y = lay.origin.y + 5.0 * lay.cell_size };
corner_col : s64 = -1;
corner_row : s64 = -1;
if h := lay.point_to_cell(corner) { corner_col = h.col; corner_row = h.row; }
if corner_col != 3 or corner_row != 5 { fails += 1; }
print("corner maps to ({},{})\n", corner_col, corner_row);
// Off-board taps reject (null): left of, above, and right of the grid. None
// should resolve to a cell, so the on-board count must stay 0.
off_left := Point.{ x = lay.origin.x - 5.0, y = lay.origin.y + 10.0 };
off_above := Point.{ x = lay.origin.x + 10.0, y = lay.origin.y - 5.0 };
off_right := Point.{ x = lay.origin.x + 8.0 * lay.cell_size + 1.0, y = lay.origin.y + 10.0 };
on_board : s64 = 0;
if h := lay.point_to_cell(off_left) { on_board += 1; print("off_left hit ({},{})\n", h.col, h.row); }
if h := lay.point_to_cell(off_above) { on_board += 1; print("off_above hit ({},{})\n", h.col, h.row); }
if h := lay.point_to_cell(off_right) { on_board += 1; print("off_right hit ({},{})\n", h.col, h.row); }
if on_board != 0 { fails += 1; }
print("ok: {} off-board taps resolved to a cell\n", on_board);
if fails == 0 {
print("ok: hit-test mapping is the inverse of the layout\n");
return 0;
}
print("FAIL: {} hit-test checks failed\n", fails);
return 1;
}