. "$BST_LIB" # BST-TIMEOUT: 2400 # an estimate, not yet measured: Xvfb, the window manager, # # eleven cold starts of the front end and the session's # # restarts, each readiness wait bounded by wall clock below. # 99-nrf-station-ui.test -- nrf-station-ui, the nRF9151 SOM station's front end, # and nrf-station-session, the X session that runs it full screen at boot. # # THE LIVE HALF RUNS AGAINST Xvfb, NOT Xorg. The local verify boots with no DRM # device, so Xorg cannot come up there; Xvfb speaks the same protocol. The board # is not here either, so som-program-nrf91, som-recover-nrf91 and som-test-nrf91 # are stand-ins put first on PATH: what is measured is the front end, not the # commands it runs. som-console is the real one, searching a constructed sysfs # (SOM_SYSFS). --run takes the same path as the button, without Recover's # confirmation; the keyboard cases press the buttons and answer the confirmation # with nrf-station-xsend's synthetic keys and clicks. # # NOTHING HERE RELIES ON A SIGNAL (brintos/linux#21). Each front-end run ends on # its own through --exit; the window manager is asked to leave over X. Xvfb has # no such request and is left idle on its private display. S=nrf-station-ui bst_ok $S/suite-canary # first line: absorbs brintos/linux#96, which drops it require nrf-station-ui $S/present UI=/usr/bin/nrf-station-ui TITLE="nRF9151 SOM station" # --- 1. what arrived ---------------------------------------------------------- check $S/exec test -x "$UI" SESS=/usr/bin/nrf-station-session check $S/session-exec test -x "$SESS" check_out $S/session-ui-default 'UI=${NRF_STATION_UI:-/usr/bin/nrf-station-ui}' sed -n p "$SESS" check_out $S/session-runs-ui '"$UI" --announce /dev/console' sed -n p "$SESS" XSEND=/usr/libexec/nrf-station-xsend check $S/xsend-exec test -x "$XSEND" check_out $S/session-execs-wm "exec matchbox-window-manager" sed -n p "$SESS" bst_run 60 env -u DISPLAY "$SESS" --version case "$rc:$out" in 1:*"nrf-station-session: no DISPLAY"*) bst_ok $S/session-needs-display ;; *) bst_notok $S/session-needs-display "rc=$rc got: $(printf '%s' "$out" | head -n 2 | tr '\n' ' ' | cut -c1-200)" ;; esac # On the station image the X session runs x-session-manager, and that is this. if bst_have_pkg brintos-nrf-station; then case "$(readlink -f /usr/bin/x-session-manager)" in "$SESS") bst_ok $S/session-manager-is-station ;; *) bst_notok $S/session-manager-is-station "x-session-manager is $(readlink -f /usr/bin/x-session-manager)" ;; esac # The desktop's terminal session must not come with it. if command -v xterm >/dev/null 2>&1; then bst_notok $S/no-xterm "xterm is installed: $(command -v xterm)" else bst_ok $S/no-xterm; fi else bst_skip $S/session-manager-is-station "not the nRF station image" bst_skip $S/no-xterm "not the nRF station image" fi # In Developer mode the site runs this page, and the page drives the X pointer. # A page that sends only relative motion leaves a click short of its button, so # look for its absolute-axis record (EV_ABS ABS_X) in the shipped page. RTP=/boot/hardwarejs.html if [ -s "$RTP" ]; then if grep -qF '{type:3,code:0,value:' "$RTP"; then bst_ok $S/runtime-absolute-pointer else bst_notok $S/runtime-absolute-pointer "$RTP sends no EV_ABS ABS_X record: the X pointer would be relative"; fi else bst_skip $S/runtime-absolute-pointer "no $RTP on this image" fi # --- 2. without a display ------------------------------------------------------- check_out $S/version "nrf-station-ui 1.0" "$UI" --version check_rc $S/usage-unknown-arg 2 "$UI" --bogus check_rc $S/usage-exit-needs-run 2 "$UI" --exit check_rc $S/usage-unknown-action 2 "$UI" --run erase check_out $S/usage-lists-actions "check, install, recover, test, full-test or qa" "$UI" --help bst_run 60 env -u DISPLAY "$UI" check_eq $S/nodisplay-rc 1 "$rc" case "$out" in *"Can't open display"*) bst_ok $S/nodisplay-message ;; *) bst_notok $S/nodisplay-message "got: $(printf '%s' "$out" | cut -c1-200)" ;; esac # --- 2a. the session restarts the front end for as long as it runs --------------- # A stand-in front end that exits at once, five times, and then stays (blocked on # a FIFO nobody writes); a stand-in window manager that exits at once. The old # session gave up after three quick exits; this one waits 1, 2, 4, 8, 16 s. up() { read -r _u _ < /proc/uptime; echo "${_u%.*}"; } SW=${TMPDIR:-/tmp}/bst-nsui-session.$$ mkdir -p "$SW/bin" printf '%s\n' '#!/bin/sh' 'exit 0' > "$SW/bin/matchbox-window-manager" cat > "$SW/ui" <> "$SW/starts" [ \$(grep -c "" "$SW/starts") -ge 6 ] && exec sh -c 'read -r x < "\$1"' sh "$SW/hold" exit 0 EOF chmod 755 "$SW/bin/matchbox-window-manager" "$SW/ui" if mkfifo "$SW/hold" 2>/dev/null; then env DISPLAY=:99 PATH="$SW/bin:$PATH" NRF_STATION_UI="$SW/ui" NRF_STATION_LOG="$SW/log" \ "$SESS" < /dev/null > "$SW/out" 2>&1 _s0=$(up) while [ "$(grep -c "" "$SW/starts" 2>/dev/null)" -lt 6 ] && [ $(( $(up) - _s0 )) -lt 180 ]; do sleep 1; done n=$(grep -c "" "$SW/starts" 2>/dev/null) if [ "${n:-0}" -ge 6 ]; then bst_ok $S/session-restarts-past-three else bst_notok $S/session-restarts-past-three "${n:-0} start(s) in 180 s, want 6: $(tail -n 2 "$SW/log" 2>/dev/null | tr '\n' ' ' | cut -c1-300)"; fi set -- $(sed -n p "$SW/starts" 2>/dev/null) if [ $# -ge 6 ] && [ $(( ($6 - $5) - ($2 - $1) )) -ge 8 ]; then bst_ok $S/session-delay-grows else bst_notok $S/session-delay-grows "starts at uptime $*: want the 5th gap at least 8 s longer than the 1st"; fi else bst_notok $S/session-restarts-past-three "cannot make a FIFO in $SW" bst_notok $S/session-delay-grows "cannot make a FIFO in $SW" fi # --- 3. the live window ---------------------------------------------------------- # wait_for : poll by wall clock; sleep(1) is not a timer here. wait_for() { _wt=$1; shift; _w0=$(up) while :; do bst_bound 30 "$@" >/dev/null 2>&1 && return 0 [ $(( $(up) - _w0 )) -ge "$_wt" ] && return 1 sleep 1 done } LIVE="xvfb-up wm-claims-root check-rc check-ran-command check-pass-line \ install-window-drawn install-window-mapped install-window-managed install-window-full-width \ install-output-live install-rc install-pass-line test-rc test-fail-line \ recover-rc recover-args recover-pass-line full-test-args full-test-fail-line \ qa-args qa-fail-line ttl232r-check-console ttl232r-test-console ttl232r-full-test-console \ ttl232r-qa-console ttl232r-install-console ttl232r-install-rc missing-command-rc missing-command-fail-line check-passes-console \ recover-no-console esc-ignored-running close-ignored-running stop-asks-command stop-banner \ stop-rc recover-no-stop recover-runs-to-end no-console-check-refused no-console-install-refused \ two-consoles-refused mixed-consoles-refused console-id-setting lock-held-shown esc-ignored-idle lock-free-shown \ close-exits-idle check-banner-result test-banner-result qa-banner-result \ focus-back-after-action recover-confirm-asks recover-enter-no-erase recover-esc-cancels \ focus-back-after-cancel recover-erase-button-runs focus-back-after-recover recover-tab-space-cancels \ kbd-close-exits \ wm-exits-on-request" missing="" for p in Xvfb xset xprop xwininfo matchbox-window-manager matchbox-remote som-lock som-console "$XSEND"; do command -v "$p" >/dev/null 2>&1 || missing="$missing $p" done if [ -n "$missing" ]; then for c in $LIVE; do bst_skip $S/$c "the live cases need$missing, which this image does not have"; done exit 0 fi W=${TMPDIR:-/tmp}/bst-nsui.$$ mkdir -p "$W/bin" "$W/fw/asset_tracker_v2" "$W/fw/hello_mcuboot" "$W/fc" # Stand-ins: a check returns at once, an install blocks on the $W/release FIFO # until the suite writes to it, so the window can be inspected while a command # runs; a recover passes; every test fails. Each prints its arguments ending " .". # A check and a test end on a result line as the real commands do; the check # prints an earlier one too, as som-program-nrf91 --check does. # With NSUI_STOPPABLE the install ignores TERM and ends only on a stop request. cat > "$W/bin/som-program-nrf91" </dev/null < "\$SOM_LOCK.stop" [ "\$p" = "\$\$" ] && { echo "som-program-nrf91: FAIL -- stand-in stopped by request"; exit 143; } sleep 1 done exit 1 fi read _go < "$W/release" echo "som-program-nrf91: PASS -- stand-in install" exit 0 EOF cat > "$W/bin/som-recover-nrf91" < "$W/bin/som-test-nrf91" <"$W/xvfb.log" 2>&1 & if wait_for 180 xset -display $D q; then bst_ok $S/xvfb-up else bst_notok $S/xvfb-up "Xvfb $D did not answer within 180 s: $(tail -n 3 "$W/xvfb.log" | tr '\n' ' ')"; fi # A scoped fontconfig with a cache in $W: an uncached scan maps each font, and # under load one of those mappings is refused (linux-in-the-browser#72/#165). cat > "$W/fc/fonts.conf" < /usr/share/fonts/X11/misc$W/fc/cache EOF FONTCONFIG_FILE="$W/fc/fonts.conf" matchbox-window-manager -display $D -use_titlebar no >"$W/wm.log" 2>&1 & if wait_for 120 sh -c "xprop -display $D -root _NET_SUPPORTING_WM_CHECK | grep -q 'window id'"; then bst_ok $S/wm-claims-root chk=$(bst_bound 30 xprop -display $D -root _NET_SUPPORTING_WM_CHECK 2>/dev/null | sed -n 's/.*window id # \(0x[0-9a-f]*\).*/\1/p') else bst_notok $S/wm-claims-root "no _NET_SUPPORTING_WM_CHECK on the root within 120 s: $(tail -n 3 "$W/wm.log" | tr '\n' ' ')" fi # The USB bus som-console searches. sys-one holds the starter kit's FT230X beside # a CP2104, which som-console's default ids would take too but is no nRF console; # sys-none the CP2104 alone; sys-two two FT230X; sys-ttl a TTL-232R cable, the # console of a board on another carrier, alone; sys-mix the FT230X and the TTL-232R. mkdev() { # [driver] _d=$1/devices/usb1/$2; _v=${7:-ftdi_sio} mkdir -p "$_d/$2:1.0/$6" "$1/bus/usb-serial/drivers/$_v" "$1/bus/usb-serial/devices" printf '%s\n' "$3" >"$_d/idVendor"; printf '%s\n' "$4" >"$_d/idProduct"; printf '%s\n' "$5" >"$_d/serial" ln -s "$1/bus/usb-serial/drivers/$_v" "$_d/$2:1.0/$6/driver" ln -s "$_d/$2:1.0/$6" "$1/bus/usb-serial/devices/$6" } mkdev "$W/sys-one" 1-1 10c4 ea60 0129344F ttyUSB0 cp210x mkdev "$W/sys-one" 1-2 0403 6015 DK0AAAAA ttyUSB1 mkdev "$W/sys-none" 1-1 10c4 ea60 0129344F ttyUSB0 cp210x mkdev "$W/sys-ttl" 1-1 0403 6001 FTD0WB6J ttyUSB0 mkdev "$W/sys-mix" 1-1 0403 6001 FTD0WB6J ttyUSB0 mkdev "$W/sys-mix" 1-2 0403 6015 DK0AAAAA ttyUSB1 mkdev "$W/sys-two" 1-1 0403 6015 DK0AAAAA ttyUSB0 mkdev "$W/sys-two" 1-2 0403 6015 DK0BBBBB ttyUSB1 UIENV="PATH=$W/bin:$PATH NRF_STATION_FW_DIR=$W/fw SOM_LOCK=$W/board.lock SOM_SYSFS=$W/sys-one SOM_DEVDIR=/dev" # Check: the release picked by default, the command's own output, PASS, and # the starter kit's console, found by its id among the two and passed on. bst_run 300 env $UIENV "$UI" -display $D --run check --exit check_eq $S/check-rc 0 "$rc" case "$out" in *"stand-in som-program-nrf91 --app asset_tracker_v2 --check"*) bst_ok $S/check-ran-command ;; *) bst_notok $S/check-ran-command "got: $(printf '%s' "$out" | tail -n 4 | tr '\n' ' ' | cut -c1-300)" ;; esac case "$out" in *"PASS -- Check asset_tracker_v2 (exit 0"*) bst_ok $S/check-pass-line ;; *) bst_notok $S/check-pass-line "got: $(printf '%s' "$out" | tail -n 2 | tr '\n' ' ' | cut -c1-300)" ;; esac case "$out" in *"som-console --find --id \"0403:6015 0403:6001\""*"stand-in som-program-nrf91 --app asset_tracker_v2 --check --console /dev/ttyUSB1"*) bst_ok $S/check-passes-console ;; *) bst_notok $S/check-passes-console "got: $(printf '%s' "$out" | grep -E 'stand-in|som-console|/dev/' | tr '\n' ' ' | cut -c1-300)" ;; esac # The banner, printed as shown: the verdict, then the command's last result line. case "$out" in *"nrf-station-ui: som-program-nrf91: PASS -- resolved"*) bst_notok $S/check-banner-result "the banner took an earlier result line: $(printf '%s' "$out" | grep '^nrf-station-ui: som-' | cut -c1-300)" ;; *"nrf-station-ui: PASS -- Check asset_tracker_v2 (exit 0, "*" s) nrf-station-ui: som-program-nrf91: PASS -- stand-in check"*) bst_ok $S/check-banner-result ;; *) bst_notok $S/check-banner-result "got: $(printf '%s' "$out" | tail -n 3 | tr '\n' ' ' | cut -c1-300)" ;; esac # Recover takes no console, and runs where there is none. bst_run 300 env $UIENV SOM_SYSFS=$W/sys-none "$UI" -display $D --run recover --exit case "$rc:$out" in *"stand-in som-recover-nrf91"*"--console"*) bst_notok $S/recover-no-console "got: $(printf '%s' "$out" | grep stand-in | cut -c1-200)" ;; 0:*"stand-in som-recover-nrf91"*) bst_ok $S/recover-no-console ;; *) bst_notok $S/recover-no-console "rc=$rc, want 0 and a recover line: $(printf '%s' "$out" | tail -n 2 | tr '\n' ' ' | cut -c1-200)" ;; esac # Install: the window is up, managed and full width while the command runs, and # the command's output reaches the log before it ends. cat > "$W/run-install.sh" < "$W/install.out" 2>&1 echo \$? > "$W/install.rc" EOF sh "$W/run-install.sh" & if wait_for 300 grep -q "window drawn" "$W/shown"; then bst_ok $S/install-window-drawn else bst_notok $S/install-window-drawn "no 'window drawn' line within 300 s: $(tail -n 3 "$W/install.out" | tr '\n' ' ' | cut -c1-300)"; fi if wait_for 60 xwininfo -display $D -name "$TITLE"; then bst_ok $S/install-window-mapped else bst_notok $S/install-window-mapped "no window titled '$TITLE'"; fi xid=$(bst_bound 30 xwininfo -display $D -name "$TITLE" 2>/dev/null | sed -n 's/^xwininfo: Window id: \(0x[0-9a-f]*\).*/\1/p') if [ -n "$xid" ] && wait_for 30 sh -c "xprop -display $D -id $xid WM_STATE | grep -q 'window state: Normal'"; then bst_ok $S/install-window-managed else bst_notok $S/install-window-managed "window '$xid' carries no WM_STATE Normal" fi width=$(bst_bound 30 xwininfo -display $D -id "${xid:-0}" 2>/dev/null | sed -n 's/^ *Width: *\([0-9]*\).*/\1/p') check_eq $S/install-window-full-width 1024 "$width" if wait_for 60 grep -q "stand-in som-program-nrf91 --app asset_tracker_v2" "$W/install.out"; then bst_ok $S/install-output-live else bst_notok $S/install-output-live "the running install's first line is not in the log: $(tail -n 3 "$W/install.out" | tr '\n' ' ' | cut -c1-300)" fi bst_bound 60 sh -c "echo go > '$W/release'" if wait_for 120 test -s "$W/install.rc"; then check_eq $S/install-rc 0 "$(cat "$W/install.rc")" else bst_notok $S/install-rc "the front end did not exit within 120 s of the install ending"; fi check_out $S/install-pass-line "PASS -- Install asset_tracker_v2 (exit 0" sed -n p "$W/install.out" # Quick test: the release it tests, and a failing command ends on FAIL, which # --exit reports. bst_run 300 env $UIENV "$UI" -display $D --run test --exit check_eq $S/test-rc 1 "$rc" case "$out" in *"stand-in som-test-nrf91 --app asset_tracker_v2 --quick --console /dev/ttyUSB1 ."*"FAIL -- Quick test asset_tracker_v2 (exit 1"*) bst_ok $S/test-fail-line ;; *) bst_notok $S/test-fail-line "got: $(printf '%s' "$out" | tail -n 3 | tr '\n' ' ' | cut -c1-300)" ;; esac case "$out" in *"nrf-station-ui: FAIL -- Quick test asset_tracker_v2 (exit 1, "*" s) nrf-station-ui: som-test-nrf91: FAIL -- 9 pass, 1 fail, 2 skip across 12 checks (profile asset_tracker; "*) bst_ok $S/test-banner-result ;; *) bst_notok $S/test-banner-result "got: $(printf '%s' "$out" | tail -n 3 | tr '\n' ' ' | cut -c1-300)" ;; esac # Recover: the release and --yes, and never --force, which would erase an open board. bst_run 300 env $UIENV "$UI" -display $D --run recover --exit check_eq $S/recover-rc 0 "$rc" case "$out" in *"stand-in som-recover-nrf91 --app asset_tracker_v2 --yes ."*) bst_ok $S/recover-args ;; *) bst_notok $S/recover-args "got: $(printf '%s' "$out" | grep stand-in | cut -c1-300)" ;; esac case "$out" in *"PASS -- Recover asset_tracker_v2 (exit 0"*) bst_ok $S/recover-pass-line ;; *) bst_notok $S/recover-pass-line "got: $(printf '%s' "$out" | tail -n 2 | tr '\n' ' ' | cut -c1-300)" ;; esac # Full test: the default suites, so the release and the console and nothing else. bst_run 300 env $UIENV "$UI" -display $D --run full-test --exit case "$out" in *"stand-in som-test-nrf91 --app asset_tracker_v2 --console /dev/ttyUSB1 ."*) bst_ok $S/full-test-args ;; *) bst_notok $S/full-test-args "got: $(printf '%s' "$out" | grep stand-in | cut -c1-300)" ;; esac case "$rc:$out" in 1:*"FAIL -- Full test asset_tracker_v2 (exit 1"*) bst_ok $S/full-test-fail-line ;; *) bst_notok $S/full-test-fail-line "rc=$rc got: $(printf '%s' "$out" | tail -n 2 | tr '\n' ' ' | cut -c1-300)" ;; esac # QA suite: the release, resets allowed, and the file-system writes of 3.6. bst_run 300 env $UIENV "$UI" -display $D --run qa --exit case "$out" in *"stand-in som-test-nrf91 --app asset_tracker_v2 --suite qa --allow-reset --allow-fs-writes --console /dev/ttyUSB1 ."*) bst_ok $S/qa-args ;; *) bst_notok $S/qa-args "got: $(printf '%s' "$out" | grep stand-in | cut -c1-300)" ;; esac case "$rc:$out" in 1:*"FAIL -- QA suite asset_tracker_v2 (exit 1"*) bst_ok $S/qa-fail-line ;; *) bst_notok $S/qa-fail-line "rc=$rc got: $(printf '%s' "$out" | tail -n 2 | tr '\n' ' ' | cut -c1-300)" ;; esac case "$out" in *"nrf-station-ui: FAIL -- QA suite asset_tracker_v2 (exit 1, "*" s) nrf-station-ui: som-test-nrf91: FAIL -- 9 pass, 1 fail, 2 skip across 12 checks (profile asset_tracker; "*) bst_ok $S/qa-banner-result ;; *) bst_notok $S/qa-banner-result "got: $(printf '%s' "$out" | tail -n 3 | tr '\n' ' ' | cut -c1-300)" ;; esac # A TTL-232R cable alone: every action but Recover finds it and passes it on, as # it does the starter kit's FT230X. for a in check test full-test qa; do case $a in check) want="stand-in som-program-nrf91 --app asset_tracker_v2 --check --console /dev/ttyUSB0" ;; test) want="stand-in som-test-nrf91 --app asset_tracker_v2 --quick --console /dev/ttyUSB0 ." ;; full-test) want="stand-in som-test-nrf91 --app asset_tracker_v2 --console /dev/ttyUSB0 ." ;; qa) want="stand-in som-test-nrf91 --app asset_tracker_v2 --suite qa --allow-reset --allow-fs-writes --console /dev/ttyUSB0 ." ;; esac bst_run 300 env $UIENV SOM_SYSFS=$W/sys-ttl "$UI" -display $D --run $a --exit case "$out" in *"som-console --find --id \"0403:6015 0403:6001\""*"$want"*) bst_ok $S/ttl232r-$a-console ;; *) bst_notok $S/ttl232r-$a-console "rc=$rc got: $(printf '%s' "$out" | grep -E 'stand-in|som-console|/dev/|FAIL' | tr '\n' ' ' | cut -c1-300)" ;; esac done cat > "$W/run-ttl-install.sh" < "$W/ttl-install.out" 2>&1 echo \$? > "$W/ttl-install.rc" EOF sh "$W/run-ttl-install.sh" & if wait_for 300 grep -q "stand-in som-program-nrf91 --app asset_tracker_v2 --console /dev/ttyUSB0" "$W/ttl-install.out"; then bst_ok $S/ttl232r-install-console else bst_notok $S/ttl232r-install-console "got: $(grep -E 'stand-in|som-console|/dev/|FAIL' "$W/ttl-install.out" | tr '\n' ' ' | cut -c1-300)" fi bst_bound 60 sh -c "echo go > '$W/release'" if wait_for 120 test -s "$W/ttl-install.rc"; then check_eq $S/ttl232r-install-rc 0 "$(cat "$W/ttl-install.rc")" else bst_notok $S/ttl232r-install-rc "the front end did not exit within 120 s of the install ending"; fi # A command that is not there is a FAIL, not a hang. PATH holds a stand-in # som-console alone, which needs no other command to answer. mkdir -p "$W/con" cat > "$W/con/som-console" </dev/null | sed -n 's/^xwininfo: Window id: \(0x[0-9a-f]*\).*/\1/p'; } xsend() { bst_bound 30 env DISPLAY=$D "$XSEND" "$@" >/dev/null 2>&1; } # The Stop button's centre: the fourth of four columns, beside both rows of # actions (M=10, R=40 in the front end's layout). stop_at() { _sw=$(bst_bound 30 xwininfo -display $D -id "$1" 2>/dev/null | sed -n 's/^ *Width: *\([0-9]*\).*/\1/p') _bw=$(( (${_sw:-1024} - 50) / 4 )) echo "$(( 10 + 3 * (_bw + 10) + _bw / 2 )) 105" } # Install, stopped: Esc and the window's close do nothing while it runs; Stop # writes the request, which the stand-in -- deaf to TERM -- reads, and the # banner says STOPPED. cat > "$W/run-stop.sh" < "$W/stop.out" 2>&1 echo \$? > "$W/stop.rc" EOF sh "$W/run-stop.sh" & wait_for 300 grep -q "stand-in waiting for a stop request" "$W/stop.out" xid=$(winid) xsend "${xid:-0}" key Escape if wait_for 30 grep -q "Esc ignored" "$W/stop.out" && [ ! -s "$W/stop.rc" ]; then bst_ok $S/esc-ignored-running else bst_notok $S/esc-ignored-running "window '$xid': $(tail -n 3 "$W/stop.out" | tr '\n' ' ' | cut -c1-300)"; fi xsend "${xid:-0}" close if wait_for 30 grep -q "close ignored: Install is running" "$W/stop.out" && [ ! -s "$W/stop.rc" ]; then bst_ok $S/close-ignored-running else bst_notok $S/close-ignored-running "window '$xid': $(tail -n 3 "$W/stop.out" | tr '\n' ' ' | cut -c1-300)"; fi xsend "${xid:-0}" click $(stop_at "${xid:-0}") wait_for 120 test -s "$W/stop.rc" case "$(sed -n p "$W/stop.out")" in *"stop asked of Install (pid "*"stand-in stopped by request"*) bst_ok $S/stop-asks-command ;; *) bst_notok $S/stop-asks-command "got: $(grep -E 'stop|stand-in' "$W/stop.out" | tr '\n' ' ' | cut -c1-300)" ;; esac check_out $S/stop-banner "STOPPED -- Install asset_tracker_v2 (exit 143" sed -n p "$W/stop.out" check_eq $S/stop-rc 1 "$(cat "$W/stop.rc" 2>/dev/null)" # Recover has no Stop: a click there while it runs asks nothing. The Esc after # it is the barrier: its line means the click before it was handled. rm -f "$W/board.lock.stop" cat > "$W/run-recover.sh" < "$W/recover.out" 2>&1 echo \$? > "$W/recover.rc" EOF sh "$W/run-recover.sh" & wait_for 300 grep -q "stand-in som-recover-nrf91" "$W/recover.out" xid=$(winid) xsend "${xid:-0}" click $(stop_at "${xid:-0}") xsend "${xid:-0}" key Escape if wait_for 30 grep -q "Esc ignored" "$W/recover.out" && ! grep -q "stop asked" "$W/recover.out" && [ ! -e "$W/board.lock.stop" ]; then bst_ok $S/recover-no-stop else bst_notok $S/recover-no-stop "got: $(tail -n 3 "$W/recover.out" | tr '\n' ' ' | cut -c1-300)" fi bst_bound 60 sh -c "echo go > '$W/release'" wait_for 120 test -s "$W/recover.rc" case "$(cat "$W/recover.rc" 2>/dev/null):$(sed -n p "$W/recover.out")" in 0:*"PASS -- Recover asset_tracker_v2 (exit 0"*) bst_ok $S/recover-runs-to-end ;; *) bst_notok $S/recover-runs-to-end "rc=$(cat "$W/recover.rc" 2>/dev/null): $(tail -n 2 "$W/recover.out" | tr '\n' ' ' | cut -c1-300)" ;; esac # No console, or two: the action does not start, and the banner's FAIL line # carries som-console's own message, as the log does. Here, after every case # that reads $W/release, so that an install started in error cannot take one. for a in check install; do case $a in check) A=Check ;; *) A=Install ;; esac bst_run 300 env $UIENV SOM_SYSFS=$W/sys-none "$UI" -display $D --run $a --exit case "$rc:$out" in *"stand-in som-program-nrf91"*) bst_notok $S/no-console-$a-refused "it started the command: $(printf '%s' "$out" | grep stand-in | cut -c1-200)" ;; 1:*"no USB-serial port matching 0403:6015 0403:6001"*"ttyUSB0 cp210x 10c4:ea60 0129344F"*"FAIL -- $A asset_tracker_v2: no console"*) bst_ok $S/no-console-$a-refused ;; *) bst_notok $S/no-console-$a-refused "rc=$rc, want 1 and som-console's reason: $(printf '%s' "$out" | tail -n 4 | tr '\n' ' ' | cut -c1-300)" ;; esac done bst_run 300 env $UIENV SOM_SYSFS=$W/sys-two "$UI" -display $D --run install --exit case "$rc:$out" in *"stand-in som-program-nrf91"*) bst_notok $S/two-consoles-refused "it started the command: $(printf '%s' "$out" | grep stand-in | cut -c1-200)" ;; 1:*"2 ports match 0403:6015 0403:6001"*"ttyUSB0 ftdi_sio 0403:6015 DK0AAAAA"*"ttyUSB1 ftdi_sio 0403:6015 DK0BBBBB"*"FAIL -- Install asset_tracker_v2: no console"*) bst_ok $S/two-consoles-refused ;; *) bst_notok $S/two-consoles-refused "rc=$rc, want 1 and both ports: $(printf '%s' "$out" | tail -n 5 | tr '\n' ' ' | cut -c1-300)" ;; esac # The FT230X and the TTL-232R both granted are two consoles too. SOM_CONSOLE_ID # names the one id to look for, and the window then takes that one. bst_run 300 env $UIENV SOM_SYSFS=$W/sys-mix "$UI" -display $D --run check --exit case "$rc:$out" in *"stand-in som-program-nrf91"*) bst_notok $S/mixed-consoles-refused "it started the command: $(printf '%s' "$out" | grep stand-in | cut -c1-200)" ;; 1:*"2 ports match 0403:6015 0403:6001"*"ttyUSB0 ftdi_sio 0403:6001 FTD0WB6J"*"ttyUSB1 ftdi_sio 0403:6015 DK0AAAAA"*"FAIL -- Check asset_tracker_v2: no console"*) bst_ok $S/mixed-consoles-refused ;; *) bst_notok $S/mixed-consoles-refused "rc=$rc, want 1 and both ports: $(printf '%s' "$out" | tail -n 5 | tr '\n' ' ' | cut -c1-300)" ;; esac bst_run 300 env $UIENV SOM_SYSFS=$W/sys-mix SOM_CONSOLE_ID=0403:6015 "$UI" -display $D --run check --exit case "$rc:$out" in 0:*"som-console --find --id \"0403:6015\""*"stand-in som-program-nrf91 --app asset_tracker_v2 --check --console /dev/ttyUSB1"*) bst_ok $S/console-id-setting ;; *) bst_notok $S/console-id-setting "rc=$rc, want 0 and the FT230X: $(printf '%s' "$out" | grep -E 'stand-in|som-console|/dev/|FAIL' | tr '\n' ' ' | cut -c1-300)" ;; esac # Started while the board's lock is held: the status names the holder and the # actions are off; the holder releases it and they come back. Then, idle, Esc # does nothing and the window's close ends the front end. mkfifo "$W/hold" sh -c 'read -r x < "$1"' sh "$W/hold" < /dev/null > /dev/null 2>&1 & H=$! SOM_LOCK=$W/board.lock som-lock take som-test-nrf91 "$H" >/dev/null 2>&1 cat > "$W/run-idle.sh" < "$W/idle.out" 2>&1 echo \$? > "$W/idle.rc" EOF sh "$W/run-idle.sh" & wait_for 300 grep -q "window drawn" "$W/idle-shown" if wait_for 30 grep -q "the board is in use by som-test-nrf91 (pid $H, started [0-9:]* UTC); the actions are off" "$W/idle.out"; then bst_ok $S/lock-held-shown else bst_notok $S/lock-held-shown "got: $(tail -n 3 "$W/idle.out" | tr '\n' ' ' | cut -c1-300)" fi xid=$(winid) xsend "${xid:-0}" key Escape if wait_for 30 grep -q "Esc ignored" "$W/idle.out" && [ ! -s "$W/idle.rc" ]; then bst_ok $S/esc-ignored-idle else bst_notok $S/esc-ignored-idle "window '$xid': $(tail -n 3 "$W/idle.out" | tr '\n' ' ' | cut -c1-300)"; fi SOM_LOCK=$W/board.lock som-lock release "$H" >/dev/null 2>&1 bst_bound 60 sh -c "echo go > '$W/hold'" if wait_for 30 grep -q "the board is free; the actions are on" "$W/idle.out"; then bst_ok $S/lock-free-shown else bst_notok $S/lock-free-shown "got: $(tail -n 3 "$W/idle.out" | tr '\n' ' ' | cut -c1-300)"; fi xsend "${xid:-0}" close if wait_for 60 test -s "$W/idle.rc" && [ "$(cat "$W/idle.rc")" = 0 ] && grep -q ": closed" "$W/idle.out"; then bst_ok $S/close-exits-idle else bst_notok $S/close-exits-idle "rc '$(cat "$W/idle.rc" 2>/dev/null)': $(tail -n 3 "$W/idle.out" | tr '\n' ' ' | cut -c1-300)"; fi # From the keyboard. Check ends and Space runs it again: the focus is back on its # button. Tab twice reaches Recover..., whose confirmation answers Enter with # nothing and Esc with a cancel; the focus is back on Recover..., and a click on # the Erase button itself starts Recover. FLTK lays the dialog's buttons out from # its right edge by the width of their labels, Cancel rightmost, so the click # walks the button row from the left and the first button it reaches is Erase. cat > "$W/run-kbd.sh" < "$W/kbd.out" 2>&1 echo \$? > "$W/kbd.rc" EOF sh "$W/run-kbd.sh" & CONFIRM="Recover -- confirm" count() { grep -c -- "$1" "$W/kbd.out" 2>/dev/null; } ktail() { tail -n 4 "$W/kbd.out" | tr '\n' ' ' | cut -c1-300; } wait_for 300 grep -q "PASS -- Check asset_tracker_v2" "$W/kbd.out" xid=$(winid) xsend "${xid:-0}" key space if wait_for 60 sh -c "[ \$(grep -c 'PASS -- Check asset_tracker_v2' '$W/kbd.out') -ge 2 ]"; then bst_ok $S/focus-back-after-action else bst_notok $S/focus-back-after-action "Space after Check ended did not run it again: $(ktail)"; fi xsend "${xid:-0}" key Tab xsend "${xid:-0}" key Tab xsend "${xid:-0}" key space if wait_for 60 grep -q "Recover: asking to confirm" "$W/kbd.out" && wait_for 60 xwininfo -display $D -name "$CONFIRM"; then bst_ok $S/recover-confirm-asks else bst_notok $S/recover-confirm-asks "no confirmation after Tab, Tab, Space: $(ktail)" fi cid=$(bst_bound 30 xwininfo -display $D -name "$CONFIRM" 2>/dev/null | sed -n 's/^xwininfo: Window id: \(0x[0-9a-f]*\).*/\1/p') # The Esc after Enter is the barrier: its cancel means Enter was handled first. xsend "${cid:-0}" key Return xsend "${cid:-0}" key Escape wait_for 60 grep -q "Recover: cancelled" "$W/kbd.out" if grep -q "Recover: cancelled" "$W/kbd.out" && ! grep -q '^\$ som-recover-nrf91' "$W/kbd.out"; then bst_ok $S/recover-enter-no-erase else bst_notok $S/recover-enter-no-erase "Enter in the confirmation: $(grep -E 'Recover|som-recover' "$W/kbd.out" | tr '\n' ' ' | cut -c1-300)"; fi if grep -q "Recover: cancelled; nothing was erased" "$W/kbd.out" && wait_for 30 sh -c "! xwininfo -display $D -name '$CONFIRM'"; then bst_ok $S/recover-esc-cancels else bst_notok $S/recover-esc-cancels "the confirmation is still up, or no cancel: $(ktail)" fi xsend "${xid:-0}" key space if wait_for 60 sh -c "[ \$(grep -c 'Recover: asking to confirm' '$W/kbd.out') -ge 2 ]" && wait_for 60 xwininfo -display $D -name "$CONFIRM"; then bst_ok $S/focus-back-after-cancel else bst_notok $S/focus-back-after-cancel "Space after the cancel did not ask again: $(ktail)" fi cid=$(bst_bound 30 xwininfo -display $D -name "$CONFIRM" 2>/dev/null | sed -n 's/^xwininfo: Window id: \(0x[0-9a-f]*\).*/\1/p') geo=$(bst_bound 30 xwininfo -display $D -id "${cid:-0}" 2>/dev/null | sed -n -e 's/^ *Width: *\([0-9]*\).*/\1/p' -e 's/^ *Height: *\([0-9]*\).*/\1/p' | tr '\n' ' ') set -- $geo x=10 while [ "$x" -lt "${1:-410}" ] && bst_bound 10 xwininfo -display $D -id "${cid:-0}" >/dev/null 2>&1; do xsend "${cid:-0}" click "$x" $(( ${2:-103} - 22 )) x=$((x + 16)) done if wait_for 60 grep -q "PASS -- Recover asset_tracker_v2 (exit 0" "$W/kbd.out" \ && grep -q '^\$ som-recover-nrf91 --app asset_tracker_v2 --yes' "$W/kbd.out"; then bst_ok $S/recover-erase-button-runs else bst_notok $S/recover-erase-button-runs "confirmation ${geo:-?}: $(ktail)" fi xsend "${xid:-0}" key space if wait_for 60 sh -c "[ \$(grep -c 'Recover: asking to confirm' '$W/kbd.out') -ge 3 ]"; then bst_ok $S/focus-back-after-recover else bst_notok $S/focus-back-after-recover "Space after Recover ended did not ask again: $(ktail)"; fi wait_for 60 xwininfo -display $D -name "$CONFIRM" cid=$(bst_bound 30 xwininfo -display $D -name "$CONFIRM" 2>/dev/null | sed -n 's/^xwininfo: Window id: \(0x[0-9a-f]*\).*/\1/p') # The confirmation opens with the focus on Erase; Tab moves it to Cancel. xsend "${cid:-0}" key Tab xsend "${cid:-0}" key space if wait_for 30 sh -c "[ \$(grep -c 'Recover: cancelled' '$W/kbd.out') -ge 2 ]"; then bst_ok $S/recover-tab-space-cancels else bst_notok $S/recover-tab-space-cancels "Tab, Space in the confirmation: $(grep -E 'Recover|som-recover' "$W/kbd.out" | tr '\n' ' ' | cut -c1-300)"; fi xsend "${cid:-0}" key Escape xsend "${xid:-0}" close if wait_for 60 test -s "$W/kbd.rc" && [ "$(cat "$W/kbd.rc")" = 0 ] && [ "$(count '^\$ som-recover-nrf91')" = 1 ]; then bst_ok $S/kbd-close-exits else bst_notok $S/kbd-close-exits "rc '$(cat "$W/kbd.rc" 2>/dev/null)', $(count '^\$ som-recover-nrf91') recover run(s), want 1: $(ktail)"; fi bst_run 60 env DISPLAY=$D matchbox-remote -exit if [ -n "${chk:-}" ] && wait_for 30 sh -c "! xwininfo -display $D -id $chk" \ && bst_bound 30 xset -display $D q >/dev/null 2>&1; then bst_ok $S/wm-exits-on-request else bst_notok $S/wm-exits-on-request "check window '${chk:-}' still there, or Xvfb $D stopped answering" fi rm -rf "$W" rm -rf "$SW"