. "$BST_LIB" require dialog dialog/present work=${TMPDIR:-/tmp}/bst-dialog.$$ mkdir -p "$work" # --- the surface that runs BEFORE curses ------------------------------------- # dialog.c handles --version and --create-rc in main() ahead of init_dialog(), so # these need no terminal and run here rather than in the pty payload. They go # first on purpose: if expect is ever absent, the `require` below ends the file, # and by then everything a piped runner can assert has already reported. check_out dialog/version "Version: 1.3-20240307" dialog --version check_out dialog/print-version "Version: 1.3-20240307" dialog --print-version check_out dialog/help "ComeOn Dialog" dialog --help # --create-rc SERIALISES DIALOG'S WHOLE CONFIGURATION MODEL — 45 settings: the # three scalars, the two booleans, and forty colour/attribute triples, several of # which are emitted as a REFERENCE to another key (`darrow_color = uarrow_color`) # rather than a literal. That makes it the one non-interactive artifact big # enough to be worth a byte-exact cross-check, and data/dialog-native.txt is # exactly this output from a native x86_64 build of the identical source. Colour # constants are enum lookups and the attribute triples are bitfield formatting, # so a wasm32 divergence here would be a codegen or an enum-width answer, not a # curses one. Comments are stripped before the compare: the values are the # assertion, upstream's explanatory prose around them is not. dialog --create-rc "$work/rc1" 2>/dev/null grep -v '^#' "$work/rc1" 2>/dev/null | grep -v '^$' > "$work/rc1.settings" check_eq dialog/rc-count 45 "$(wc -l < "$work/rc1.settings" | tr -d ' ')" if cmp -s "$work/rc1.settings" "$BST_DATA/dialog-native.txt"; then bst_ok dialog/rc-native else bst_notok dialog/rc-native "$(_bst_1line "$(diff "$BST_DATA/dialog-native.txt" "$work/rc1.settings" 2>&1)")" fi # The same code path READ back: hand dialog an rc with three settings changed and # ask it to write one out again. Round-tripping them proves the PARSER, which # --create-rc alone never exercises — it only ever prints built-in defaults. sed -e 's/^aspect = 0/aspect = 7/' \ -e 's/^tab_len = 0/tab_len = 4/' \ -e 's/^use_shadow = ON/use_shadow = OFF/' "$work/rc1" > "$work/rc2" DIALOGRC="$work/rc2" dialog --create-rc "$work/rc3" 2>/dev/null check_eq dialog/rc-aspect "aspect = 7" "$(grep '^aspect ' "$work/rc3" 2>/dev/null)" check_eq dialog/rc-tablen "tab_len = 4" "$(grep '^tab_len ' "$work/rc3" 2>/dev/null)" check_eq dialog/rc-shadow "use_shadow = OFF" "$(grep '^use_shadow ' "$work/rc3" 2>/dev/null)" # --- the widgets: a real pty, real keystrokes, machine-readable answers ------- # Everything above is preamble; dialog's subject is a curses widget driven from a # shell script. expect supplies the terminal (45-expect.test covers whether that # machinery works at all); the payload runs nine sessions, each redirecting the # widget's ANSWER to .out and its exit status to .rc. The verdicts # below read those files — dialog hands back a parseable result by design, so # unlike 58-nano.test nothing here has to infer intent from a repaint. require expect dialog/expect-present printf '%s\n' 'line one' 'line two' 'line three' > "$work/pager.txt" out=$(expect "$BST_DATA/selftest_dialog.exp" "$work" 2>&1); rc=$? case "$out" in *ALL-DIALOG-OK*) all=1 ;; *) all=0 ;; esac if [ "$rc" -eq 0 ] && [ "$all" -eq 1 ]; then bst_ok dialog/all-ok else bst_notok dialog/all-ok "rc=$rc $(_bst_1line "$out")"; fi # Each session came up under a real terminal and exited of its own accord rather # than being reaped by the payload's timeout. for tag in D1maxsize inputtyped inputdefault yesyes yesno menudown checkspace D8gauge textbox; do case "$out" in *"D-$tag OK"*) bst_ok "dialog/$tag" ;; *) bst_notok "dialog/$tag" "session did not complete in payload (rc=$rc)" ;; esac done rd() { cat "$work/$1" 2>/dev/null; } # THE TERMINAL LAYER, on its own and before any widget, asserted in two steps so # a failure names the layer that broke. First the kernel's: the payload set the # pty to 24x80 with TIOCSWINSZ and `stty size` must read it back — a round-trip # through the winsize ioctls that every full-screen program on this image depends # on and that nothing else in the suite asserts directly. Then curses': dialog # calls initscr() with $TERM resolved through /etc/terminfo and reports SLINES x # SCOLS, which must agree. A silently wrong size would not fail outright — it # would mis-lay-out every widget below — so it is checked rather than assumed. check_eq dialog/tty-resize "24 80" "$(rd sttysize.out)" check_eq dialog/maxsize "MaxSize: 24, 80" "$(rd maxsize.out)" # inputbox: the typed bytes reached the answer channel unmangled, and the preset # default survived being accepted untouched (two different sources for one field). check_eq dialog/input-typed "brintos288" "$(rd inputtyped.out)" check_eq dialog/input-default "preset-value" "$(rd inputdefault.out)" # yesno: the exit status IS the answer. Enter takes the focused Yes (0); Tab then # Enter takes No (1). Both, because a widget stuck at 0 would pass either alone. check_eq dialog/yesno-yes 0 "$(rd yesyes.rc)" check_eq dialog/yesno-no 1 "$(rd yesno.rc)" # THE ESCAPE-SEQUENCE VERDICT. The payload sent Down (ESC O B, application cursor # mode) then Enter against a three-item menu. "two" means ncurses matched the # whole sequence as one key inside its disambiguation window; "one" would mean the # cursor never moved; exit 255 with no answer would mean the lone ESC was taken as # cancel — the failure this substrate's timer behaviour would actually produce. check_eq dialog/menu-down two "$(rd menudown.out)" check_eq dialog/menu-rc 0 "$(rd menudown.rc)" # checklist: space toggled the focused item on and Enter returned the SET — a # different result-formatting path from the single tag the menu returns. check_eq dialog/checklist one "$(rd checkspace.out)" check_eq dialog/checklist-rc 0 "$(rd checkspace.rc)" # gauge consumed its percentages from a PIPE and exited on EOF with no keystroke — # the one widget here whose stdin is not the terminal. check_eq dialog/gauge-rc 0 "$(rd gauge.rc)" # textbox paged a file through the widget (a read path none of the others take) # and its Exit button was pressed. check_eq dialog/textbox-rc 0 "$(rd textbox.rc)" rm -rf "$work"