Files
m3te/tests/hit_test.sx
swipelab 6f7d2f4db2 lang migration: rename signed integer types sN -> iN
Mechanical sweep of all .sx sources, plan docs, and tests/expected
snapshots for the sx language rename (s8/s16/s32/s64 -> i8/i16/i32/i64).
Verified: tools/run_tests.sh 23/23.

Note: the ios-sim build has 2 pre-existing 'restart' dot-call errors
from the sx opt-in UFCS change (sx a47ea14) — independent of this
rename (present pre-sweep); migrated in the follow-up commit.
2026-06-12 09:36:51 +03:00

70 lines
3.3 KiB
Plaintext
Raw Permalink 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 :: () -> i32 {
// 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(i64) lay.origin.x, cast(i64) lay.origin.y, cast(i64) lay.cell_size);
fails : i64 = 0;
// Every cell center must map back to its own cell.
hits : i64 = 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 : i64 = -1;
corner_row : i64 = -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 : i64 = 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;
}