about summary refs log tree commit diff stats
path: root/tests/infrastructure/driver.sh
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-11-30 23:08:21 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-11-30 23:08:21 +0100
commitc0e331f216f5cb25636a07a764c60e0af6be98fa (patch)
tree868f8bded8b99e77b86a24a1ee82aaf5e1c11070 /tests/infrastructure/driver.sh
parentfeat(modules/lf): Add a keymap for cd-ing to the download directory (diff)
downloadnixos-config-c0e331f216f5cb25636a07a764c60e0af6be98fa.tar.gz
nixos-config-c0e331f216f5cb25636a07a764c60e0af6be98fa.zip
tests(infrastructure/driver): Support executing commands
Diffstat (limited to '')
-rw-r--r--tests/infrastructure/driver.sh92
1 files changed, 88 insertions, 4 deletions
diff --git a/tests/infrastructure/driver.sh b/tests/infrastructure/driver.sh
index f8688161..4992b5bc 100644
--- a/tests/infrastructure/driver.sh
+++ b/tests/infrastructure/driver.sh
@@ -1,4 +1,4 @@
-#! /usr/bin/env sh
+#! /usr/bin/env bash
 set -e
 
 msg() {
@@ -9,6 +9,65 @@ msg() {
     fi
 }
 
+# Use bash built-ins to trim a string
+# source: https://stackoverflow.com/a/3352015
+trim() {
+    local var="$*"
+    # remove leading whitespace characters
+    var="${var#"${var%%[![:space:]]*}"}"
+    # remove trailing whitespace characters
+    var="${var%"${var##*[![:space:]]}"}"
+    printf '%s' "$var"
+}
+
+# contains(string, substring)
+#
+# Returns 0 if the specified string contains the specified substring,
+# otherwise returns 1.
+contains() {
+    string="$1"
+    substring="$2"
+    if [ "${string#*"$substring"}" != "$string" ]; then
+        return 0 # $substring is in $string
+    else
+        return 1 # $substring is not in $string
+    fi
+}
+
+__test_wait_for_pid() {
+    local pre_pids_file="$1"
+
+    exec_pids="$(mktemp)"
+    ps -eo tty,pid | awk "--assign=tmuxTty=$tmux_tty" '{if ($1 == tmuxTty) {print $2}}' >"$exec_pids"
+
+    while read -r pid; do
+        sed --in-place "s/$pid//" "$exec_pids"
+    done <"$pre_pids_file"
+
+    gawk --include inplace '{if (NF) {print $0}}' "$exec_pids"
+
+    if [ "$(wc -l <"$exec_pids")" -eq 0 ]; then
+        # No further spawned processes left
+        return 0
+    else
+        # Some other program is still running
+        pid="$(tail -n 1 "$exec_pids")"
+        rm "$exec_pids"
+        name="$(trim "$(tr '\0' ' ' <"/proc/$pid/cmdline")")"
+
+        msg "Waiting until command ('$name') finishes (has pid: $pid).."
+
+        # This allows waiting for non-children of the current shell
+        # source: https://stackoverflow.com/a/76046235
+        tail --pid "$pid" --follow /dev/null &
+        wait $!
+
+        # Give the `testShell` some time, to process the next command from a chained command.
+        sleep 0.2
+        __test_wait_for_pid "$pre_pids_file"
+    fi
+}
+
 __test_eval() {
     tmux="$__TEST_TMUX"
     tpane="$__TEST_TMUX_PANE"
@@ -24,11 +83,36 @@ __test_eval() {
             msg "Sleeping for '$args' seconds.."
             sleep "$args"
             ;;
+        "Exec")
+            local pre_exec_pids
+            local tmux_tty
+
+            msg "Executing command '$args'.."
+            tmux_tty="$("$tmux" list-panes -t "$tpane" -F "#{pane_tty}" | sed 's|/dev/||')"
+
+            pre_exec_pids="$(mktemp)"
+            ps -eo tty,pid | awk "--assign=tmuxTty=$tmux_tty" '{if ($1 == tmuxTty) {print $2}}' >"$pre_exec_pids"
+
+            "$tmux" send-keys -t "$tpane": "$args" "Enter"
+            sleep 1
+
+            __test_wait_for_pid "$pre_exec_pids"
+
+            rm "$pre_exec_pids"
+            msg "Finished command '$args'."
+            ;;
         "Expect" | "ExpectNot")
             msg "Trying to match regex ('$args') for currently visible content.."
 
+            get_plane_text() {
+                alternate=""
+                [ "$__TEST_EVAL_USE_ALTERNATE_SCREEN" = "true" ] && alternate="-a"
+
+                "$tmux" capture-pane -t "$tpane" -p $alternate -S 0 -E -
+            }
+
             matched=""
-            if "$tmux" capture-pane -t "$tpane" -p -S 0 -E - | grep "$args"; then
+            if get_plane_text | grep "$args"; then
                 matched=true
             else
                 matched=false
@@ -41,7 +125,7 @@ __test_eval() {
                 else
                     msg "Failed to find string, matched by regex '$args' on the screen"
                     msg current screen:
-                    "$tmux" capture-pane -t "$tpane" -p -S 0 -E - | msg
+                    get_plane_text | msg
 
                     exit 1
                 fi
@@ -52,7 +136,7 @@ __test_eval() {
                 else
                     msg "Found to find string, matched by regex '$args' on the screen. But expected none"
                     msg current screen:
-                    "$tmux" capture-pane -t "$tpane" -p -S 0 -E - | msg
+                    get_plane_text | msg
 
                     exit 1
                 fi