. "$BST_LIB" # slang 2.3.3 -- the TERMINAL/SCREEN half. Ported under BRINTOS-401, which # closed on upstream's src/test corpus; this suite covers what that corpus does # not reach. See docs/brintos-test-plan.md in wasm_linux (BRINTOS-623). # # --------------------------------------------------------------------------- # WHY THIS SUITE EXISTS BESIDE A PASSING UPSTREAM ONE # # S-Lang is an interpreted extension language AND a terminal/screen-management # library -- the pair behind jed, most and slrn. Upstream's src/test corpus is # the INTERPRETER's regression suite: arrays, structs, exceptions, sscanf, # regexp, the POSIX wrappers. It does not exercise SLtt, SLsmg, slcurses or # SLkp at any point. 42-slang.test scores that corpus; this file scores the # other half. # # slsh cannot stand in for a probe here. It registers NO terminal intrinsics # at all. The names that look like them -- tt_tgetnum, tt_set_color, # tt_goto_column and their siblings -- are static C functions in sldisply.c, # visible in the binary's symbol pool and callable from nowhere; at the prompt # each answers `undefined`. SLtt_*, SLsmg_*, SLkp_* and the slcurses entry # points are all linked into the binary -- libslang.a is static -- but none is # reachable from S-Lang code. Hence THREE compiled probes, one per layer, # cross-linked with wasmcc-glibc against the very /usr/lib/libslang.a that # ships. # # --------------------------------------------------------------------------- # WHAT IS MEASURED, AND WHAT DELIBERATELY IS NOT # # Both probes read their results back off SLsmg's OWN VIRTUAL SCREEN # (SLsmg_char_at), not off the terminal. So every asserted value is the # library's own bookkeeping -- a character code, a blank, a cursor row/column, # a colour index -- identical on any machine and diffable byte-for-byte against # data/slang-{smg,curses}-native.txt, the x86_64 controls that # src/slang_screen_mknative.sh regenerates. # # WHETHER ANYTHING APPEARED ON THE GLASS IS NOT ASSERTED ANYWHERE, and that is # deliberate rather than an omission. No probe can see the terminal. A suite # that claimed to would be reporting a guess. That judgement belongs to the # hand-walk in BRINTOS-623, and the split is what makes each half meaningful: # # green here + blank screen -> the defect is BELOW SLsmg (SLtt's output, the # tty layer, or the emulator) # red here -> the defect is SLsmg or the port # # Neither conclusion is available from a probe that only paints and asks # someone to look. # # THE INTERACTIVE HALF IS NOT RUN HERE. slang-curses-probe has a `keys` mode # that drives nodelay()/timeout(0) -- the shape brintos/linux#51 reports, a # curses TUI painting blanks and never receiving a keystroke -- against a # blocking read as its control. It needs someone pressing keys, so it cannot # live in an unattended suite; it is driven by hand and recorded on the ticket. # # --------------------------------------------------------------------------- # THE HARNESS MUST GIVE THE PROBES A TERMINAL, AND IF IT DOES NOT, THAT IS A # SKIP AND NOT A RED # # SLtt_get_terminfo() answers for a dumb terminal when stdout is not a tty, and # SLsmg_init_smg() then sizes its cell array from a default. Every cell # assertion below would fail, and would be reporting the HARNESS rather than # slang -- the single most misleading red this suite could produce. So the # probe's own geometry answers are read first and the family is skipped, with # the reason, when they say there was no usable terminal. # --------------------------------------------------------------------------- # STAGING, AND WHY `test -x` APPEARS NOWHERE BELOW # # The recipe installs everything under data/ with mode 0644, so a shipped probe # is copied out and made executable before it is run -- the idiom 82-zlog.test # and 57-qrencode.test already use. # # BRINTOS-WORKAROUND: linux#19 revisit -- [ -x ] aborts busybox's shell on this # image (getgroups(2) ENOSYS); presence is asserted with -f instead, and # executability is proved by the probe running. # # `[ -x file ]` is deliberately avoided. The staged data files carry the build # uid rather than root, so busybox's -x falls through to the supplementary-group # check and calls getgroups(2), which is ENOSYS on this image: the shell prints # "sh: getgroups: Function not implemented" and ABORTS THE WHOLE FILE, which is # reported as zero cases rather than as a failure of anything slang does. # Presence is asserted with -f; executability is proved by the probe running. require slsh TT_SRC=$BST_DATA/slang-tt-probe SMG_SRC=$BST_DATA/slang-smg-probe CUR_SRC=$BST_DATA/slang-curses-probe D=${TMPDIR:-/tmp}/bst-slang-screen.$$ rm -rf "$D"; mkdir -p "$D" TT=$D/slang-tt-probe SMG=$D/slang-smg-probe CUR=$D/slang-curses-probe cp "$TT_SRC" "$TT" 2>/dev/null && chmod +x "$TT" 2>/dev/null cp "$SMG_SRC" "$SMG" 2>/dev/null && chmod +x "$SMG" 2>/dev/null cp "$CUR_SRC" "$CUR" 2>/dev/null && chmod +x "$CUR" 2>/dev/null # TERM is pinned to what the control was generated under: the capability and # geometry answers come from the terminfo entry, so a run under a different TERM # is not comparable with the control at all. TERM=xterm-256color export TERM # --- files ------------------------------------------------------------------ if [ -f "$TT_SRC" ]; then bst_ok slang-screen/tt-probe-present else bst_notok slang-screen/tt-probe-present "absent: $TT_SRC"; fi if [ -f "$SMG_SRC" ]; then bst_ok slang-screen/smg-probe-present else bst_notok slang-screen/smg-probe-present "absent: $SMG_SRC"; fi if [ -f "$CUR_SRC" ]; then bst_ok slang-screen/curses-probe-present else bst_notok slang-screen/curses-probe-present "absent: $CUR_SRC"; fi if [ -f /usr/include/slcurses.h ]; then bst_ok slang-screen/slcurses-header else bst_notok slang-screen/slcurses-header "absent: /usr/include/slcurses.h"; fi # --- SLtt ------------------------------------------------------------------- # # The lowest layer: terminfo lookup, the capability strings a cursor and a clear # need, and whether colour was claimed. It is probed from C for the same reason # the other two are -- slsh registers NO terminal intrinsics at all. The names # that looked like intrinsics (tt_tgetnum and friends) are static C functions in # sldisply.c, visible in the binary's symbol pool and callable from nowhere. # # The probe also PAINTS, and that part is asserted nowhere: no process can see # its own terminal. Only the TT- lines are scored; TTX- carry geometry and # capability numbers that legitimately differ between terminals. if [ ! -f "$TT" ]; then bst_notok slang-screen/tt-stage "cannot stage $TT_SRC into $D" else out=$("$TT" 2>&1) if ! printf '%s\n' "$out" | grep -q '^TT-END$'; then bst_notok slang-screen/tt-complete "no TT-END; run was cut short" else bst_ok slang-screen/tt-complete fi case "$(printf '%s\n' "$out" | grep '^TT-A1 terminfo_resolved' | tail -1)" in *"= 1") ctl=$BST_DATA/slang-tt-native.txt printf '%s\n' "$out" | grep '^TT-' > "$D/tt.got" grep '^TT-' "$ctl" 2>/dev/null > "$D/tt.ctl" if [ ! -s "$D/tt.ctl" ]; then bst_notok slang-screen/tt-native-byte-identical "control absent or empty: $ctl" elif cmp -s "$D/tt.ctl" "$D/tt.got"; then bst_ok slang-screen/tt-native-byte-identical else bst_notok slang-screen/tt-native-byte-identical \ "first diff: $(diff "$D/tt.ctl" "$D/tt.got" 2>/dev/null | sed -n '2,3p' | tr '\n' ' ' | cut -c1-90)" fi ;; *) bst_skip slang-screen/tt-native-byte-identical \ "no terminfo entry resolved -- harness gave no terminal, not a slang result" ;; esac fi # --- SLsmg ------------------------------------------------------------------ if [ ! -f "$SMG" ]; then bst_notok slang-screen/smg-stage "cannot stage $SMG_SRC into $D" else out=$("$SMG" 2>&1) if ! printf '%s\n' "$out" | grep -q '^SMG-END$'; then # No terminator: the run was cut short. Reported as its own case rather # than as a pile of missing assertions, because "it stopped" and "it # answered wrongly" are different findings. bst_notok slang-screen/smg-complete "no SMG-END; run was cut short" else bst_ok slang-screen/smg-complete fi geom=$(printf '%s\n' "$out" | grep '^SMG-A5 usable_geometry' | tail -1) init=$(printf '%s\n' "$out" | grep '^SMG-A6 init_smg_rc' | tail -1) case "$geom" in *"= 1") case "$init" in *"= -1") bst_skip slang-screen/smg-native-byte-identical \ "SLsmg_init_smg() failed -- no usable terminal in this harness, not a slang result" ;; *) bst_ok slang-screen/smg-init ctl=$BST_DATA/slang-smg-native.txt printf '%s\n' "$out" | grep '^SMG-' > "$D/smg.got" grep '^SMG-' "$ctl" 2>/dev/null > "$D/smg.ctl" if [ ! -s "$D/smg.ctl" ]; then bst_notok slang-screen/smg-native-byte-identical "control absent or empty: $ctl" elif cmp -s "$D/smg.ctl" "$D/smg.got"; then bst_ok slang-screen/smg-native-byte-identical else bst_notok slang-screen/smg-native-byte-identical \ "first diff: $(diff "$D/smg.ctl" "$D/smg.got" 2>/dev/null | sed -n '2,3p' | tr '\n' ' ' | cut -c1-90)" fi ;; esac ;; *) # Not a slang failure: the harness gave the probe no terminal to paint on. bst_skip slang-screen/smg-native-byte-identical \ "no usable terminal geometry ($geom) -- harness, not slang" ;; esac fi # --- slcurses --------------------------------------------------------------- if [ ! -f "$CUR" ]; then bst_notok slang-screen/curses-stage "cannot stage $CUR_SRC into $D" else out=$("$CUR" paint 2>&1) if ! printf '%s\n' "$out" | grep -q '^CUR-END$'; then bst_notok slang-screen/curses-complete "no CUR-END; run was cut short" else bst_ok slang-screen/curses-complete fi initscr=$(printf '%s\n' "$out" | grep '^CUR-A1 initscr_ok' | tail -1) geom=$(printf '%s\n' "$out" | grep '^CUR-A4 usable_geometry' | tail -1) case "$initscr" in *"= 1") bst_ok slang-screen/curses-initscr ;; *) bst_notok slang-screen/curses-initscr "initscr() returned NULL" ;; esac case "$geom" in *"= 1") ctl=$BST_DATA/slang-curses-native.txt printf '%s\n' "$out" | grep '^CUR-' > "$D/cur.got" grep '^CUR-' "$ctl" 2>/dev/null > "$D/cur.ctl" if [ ! -s "$D/cur.ctl" ]; then bst_notok slang-screen/curses-native-byte-identical "control absent or empty: $ctl" elif cmp -s "$D/cur.ctl" "$D/cur.got"; then bst_ok slang-screen/curses-native-byte-identical else bst_notok slang-screen/curses-native-byte-identical \ "first diff: $(diff "$D/cur.ctl" "$D/cur.got" 2>/dev/null | sed -n '2,3p' | tr '\n' ' ' | cut -c1-90)" fi ;; *) bst_skip slang-screen/curses-native-byte-identical \ "no usable terminal geometry ($geom) -- harness, not slang" ;; esac fi # --- the interactive half, driven by hand and recorded ----------------------- # # It needs a person pressing keys, so an unattended suite cannot assert it. It # is a SKIP carrying the hand-run result rather than a red: the result exists, # it is just not this runner's to reproduce. Re-drive it with # cp $CUR_SRC /tmp/p && chmod +x /tmp/p && TERM=xterm-256color /tmp/p keys # # 2026-08-10, local guest under run-machine.mjs, TERM=xterm-256color, 8/8: # nonblocking_saw_key=1 key=32 blocking_saw_key=1 key=32 # up_arrow=257 is_special=1 f1=513 is_special=1 # Both halves saw the keystroke, so the nodelay()/timeout(0) shape that # brintos/linux#51 reports does NOT reproduce here, and keypad() decoding of # arrows and function keys is intact. bst_skip slang-screen/keys-nodelay \ "interactive -- hand-run 2026-08-10 on the local guest: 8/8 green, nodelay and blocking both saw the key, keypad decoded arrows and F1 (brintos/linux#51 does not reproduce)" rm -rf "$D" 2>/dev/null