diff options
| author | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-02 18:30:06 +0300 |
|---|---|---|
| committer | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-02 18:30:06 +0300 |
| commit | b82d29b6d7d6e7f092f705bb3a1387367562aa24 (patch) | |
| tree | eff5fec85e6ee67626d2d8530edf3b30f178d9b4 /corebinutils/timeout/tests | |
| parent | 22343fc2bb8db94066d3e314c5a20a9b9278f4c9 (diff) | |
| parent | 2625a98c83fe53dabba3e3c7743d0fbb77c235a2 (diff) | |
| download | Project-Tick-b82d29b6d7d6e7f092f705bb3a1387367562aa24.tar.gz Project-Tick-b82d29b6d7d6e7f092f705bb3a1387367562aa24.zip | |
Add 'corebinutils/timeout/' from commit '2625a98c83fe53dabba3e3c7743d0fbb77c235a2'
git-subtree-dir: corebinutils/timeout
git-subtree-mainline: 22343fc2bb8db94066d3e314c5a20a9b9278f4c9
git-subtree-split: 2625a98c83fe53dabba3e3c7743d0fbb77c235a2
Diffstat (limited to 'corebinutils/timeout/tests')
| -rwxr-xr-x | corebinutils/timeout/tests/test.sh | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/corebinutils/timeout/tests/test.sh b/corebinutils/timeout/tests/test.sh new file mode 100755 index 0000000000..c9018c50f1 --- /dev/null +++ b/corebinutils/timeout/tests/test.sh @@ -0,0 +1,285 @@ +#!/bin/sh +set -eu + +ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) +TIMEOUT_BIN=${TIMEOUT_BIN:-"$ROOT/out/timeout"} +TMPDIR=${TMPDIR:-/tmp} +WORKDIR=$(mktemp -d "$TMPDIR/timeout-test.XXXXXX") +STDOUT_FILE="$WORKDIR/stdout" +STDERR_FILE="$WORKDIR/stderr" +LAST_STATUS=0 +LAST_ELAPSED=0 +LAST_STDOUT= +LAST_STDERR= +trap 'rm -rf "$WORKDIR"' EXIT INT TERM + +export LC_ALL=C + +USAGE_TEXT='Usage: timeout [-f | --foreground] [-k time | --kill-after time] [-p | --preserve-status] [-s signal | --signal signal] [-v | --verbose] <duration> <command> [arg ...]' + +fail() { + printf '%s\n' "FAIL: $1" >&2 + exit 1 +} + +assert_eq() { + name=$1 + expected=$2 + actual=$3 + if [ "$expected" != "$actual" ]; then + printf '%s\n' "FAIL: $name" >&2 + printf '%s\n' "--- expected ---" >&2 + printf '%s\n' "$expected" >&2 + printf '%s\n' "--- actual ---" >&2 + printf '%s\n' "$actual" >&2 + exit 1 + fi +} + +assert_contains() { + name=$1 + text=$2 + pattern=$3 + case $text in + *"$pattern"*) ;; + *) fail "$name" ;; + esac +} + +assert_empty() { + name=$1 + text=$2 + if [ -n "$text" ]; then + printf '%s\n' "FAIL: $name" >&2 + printf '%s\n' "--- expected empty ---" >&2 + printf '%s\n' "--- actual ---" >&2 + printf '%s\n' "$text" >&2 + exit 1 + fi +} + +assert_status() { + name=$1 + expected=$2 + actual=$3 + if [ "$expected" -ne "$actual" ]; then + printf '%s\n' "FAIL: $name" >&2 + printf '%s\n' "expected status: $expected" >&2 + printf '%s\n' "actual status: $actual" >&2 + exit 1 + fi +} + +assert_ge() { + name=$1 + actual=$2 + minimum=$3 + if [ "$actual" -lt "$minimum" ]; then + printf '%s\n' "FAIL: $name" >&2 + printf '%s\n' "expected >= $minimum" >&2 + printf '%s\n' "actual: $actual" >&2 + exit 1 + fi +} + +assert_le() { + name=$1 + actual=$2 + maximum=$3 + if [ "$actual" -gt "$maximum" ]; then + printf '%s\n' "FAIL: $name" >&2 + printf '%s\n' "expected <= $maximum" >&2 + printf '%s\n' "actual: $actual" >&2 + exit 1 + fi +} + +run_capture() { + if "$@" >"$STDOUT_FILE" 2>"$STDERR_FILE"; then + LAST_STATUS=0 + else + LAST_STATUS=$? + fi + LAST_STDOUT=$(cat "$STDOUT_FILE") + LAST_STDERR=$(cat "$STDERR_FILE") +} + +run_timed_capture() { + start=$(date +%s) + if "$@" >"$STDOUT_FILE" 2>"$STDERR_FILE"; then + LAST_STATUS=0 + else + LAST_STATUS=$? + fi + end=$(date +%s) + LAST_ELAPSED=$((end - start)) + LAST_STDOUT=$(cat "$STDOUT_FILE") + LAST_STDERR=$(cat "$STDERR_FILE") +} + +[ -x "$TIMEOUT_BIN" ] || fail "missing binary: $TIMEOUT_BIN" + +run_capture "$TIMEOUT_BIN" +assert_status "usage status" 125 "$LAST_STATUS" +assert_empty "usage stdout" "$LAST_STDOUT" +assert_eq "usage stderr" "$USAGE_TEXT" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" -z +assert_status "invalid option status" 125 "$LAST_STATUS" +assert_empty "invalid option stdout" "$LAST_STDOUT" +assert_eq "invalid option stderr" "$USAGE_TEXT" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" -- 1 sh -c 'exit 0' +assert_status "double-dash separator status" 0 "$LAST_STATUS" +assert_empty "double-dash separator stdout" "$LAST_STDOUT" +assert_empty "double-dash separator stderr" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" invalid sleep 0 +assert_status "invalid duration token status" 125 "$LAST_STATUS" +assert_empty "invalid duration token stdout" "$LAST_STDOUT" +assert_eq "invalid duration token stderr" \ + "timeout: duration is not a number" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" -k invalid 1 sleep 0 +assert_status "invalid kill-after status" 125 "$LAST_STATUS" +assert_empty "invalid kill-after stdout" "$LAST_STDOUT" +assert_eq "invalid kill-after stderr" \ + "timeout: duration is not a number" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" 42D sleep 0 +assert_status "invalid duration unit status" 125 "$LAST_STATUS" +assert_empty "invalid duration unit stdout" "$LAST_STDOUT" +assert_eq "invalid duration unit stderr" \ + "timeout: duration unit suffix invalid" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" 1ss sleep 0 +assert_status "duration suffix too long status" 125 "$LAST_STATUS" +assert_empty "duration suffix too long stdout" "$LAST_STDOUT" +assert_eq "duration suffix too long stderr" \ + "timeout: duration unit suffix too long" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" -- -1 sleep 0 +assert_status "negative duration status" 125 "$LAST_STATUS" +assert_empty "negative duration stdout" "$LAST_STDOUT" +assert_eq "negative duration stderr" \ + "timeout: duration out of range" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" inf sleep 0 +assert_status "non-finite duration status" 125 "$LAST_STATUS" +assert_empty "non-finite duration stdout" "$LAST_STDOUT" +assert_eq "non-finite duration stderr" \ + "timeout: duration out of range" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" -s not-a-signal 1 sleep 0 +assert_status "invalid signal status" 125 "$LAST_STATUS" +assert_empty "invalid signal stdout" "$LAST_STDOUT" +assert_eq "invalid signal stderr" \ + "timeout: invalid signal: not-a-signal" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" 1 sh -c 'exit 7' +assert_status "normal exit passthrough status" 7 "$LAST_STATUS" +assert_empty "normal exit passthrough stdout" "$LAST_STDOUT" +assert_empty "normal exit passthrough stderr" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" 0 sh -c 'exit 23' +assert_status "zero duration status passthrough status" 23 "$LAST_STATUS" +assert_empty "zero duration status passthrough stdout" "$LAST_STDOUT" +assert_empty "zero duration status passthrough stderr" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" 1 sleep 5 +assert_status "timeout status" 124 "$LAST_STATUS" +assert_empty "timeout stdout" "$LAST_STDOUT" +assert_empty "timeout stderr" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" -v 1 sleep 5 +assert_status "verbose timeout status" 124 "$LAST_STATUS" +assert_empty "verbose timeout stdout" "$LAST_STDOUT" +assert_contains "verbose timeout stderr marker" "$LAST_STDERR" "time limit reached" + +run_capture "$TIMEOUT_BIN" -p 1 sleep 5 +assert_status "preserve timeout status" 143 "$LAST_STATUS" +assert_empty "preserve timeout stdout" "$LAST_STDOUT" +assert_empty "preserve timeout stderr" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" -p -s KILL 1 sleep 5 +assert_status "preserve timeout SIGKILL status" 137 "$LAST_STATUS" +assert_empty "preserve timeout SIGKILL stdout" "$LAST_STDOUT" +assert_empty "preserve timeout SIGKILL stderr" "$LAST_STDERR" + +run_capture "$TIMEOUT_BIN" -p -k 1 1 sh -c 'trap "" TERM; sleep 10' +assert_status "kill-after escalation status" 137 "$LAST_STATUS" +assert_empty "kill-after escalation stdout" "$LAST_STDOUT" +assert_empty "kill-after escalation stderr" "$LAST_STDERR" + +NOEXEC="$WORKDIR/noexec.sh" +printf '%s\n' '#!/bin/sh' 'exit 0' >"$NOEXEC" +chmod 0644 "$NOEXEC" +run_capture "$TIMEOUT_BIN" 1 "$NOEXEC" +assert_status "non-executable command status" 126 "$LAST_STATUS" +assert_empty "non-executable command stdout" "$LAST_STDOUT" +assert_contains "non-executable command stderr path" "$LAST_STDERR" "exec($NOEXEC)" + +run_capture "$TIMEOUT_BIN" 1 does-not-exist-timeout-test-cmd +assert_status "missing command status" 127 "$LAST_STATUS" +assert_empty "missing command stdout" "$LAST_STDOUT" +assert_contains "missing command stderr cmd" "$LAST_STDERR" "exec(does-not-exist-timeout-test-cmd)" + +"$TIMEOUT_BIN" 30 sleep 10 >"$STDOUT_FILE" 2>"$STDERR_FILE" & +bg_timeout_pid=$! +sleep 1 +kill -ALRM "$bg_timeout_pid" +if wait "$bg_timeout_pid"; then + bg_timeout_status=0 +else + bg_timeout_status=$? +fi +assert_status "SIGALRM external timeout status" 124 "$bg_timeout_status" +assert_empty "SIGALRM external timeout stdout" "$(cat "$STDOUT_FILE")" +assert_empty "SIGALRM external timeout stderr" "$(cat "$STDERR_FILE")" + +"$TIMEOUT_BIN" 30 sh -c 'trap "exit 77" USR1; while :; do sleep 1; done' \ + >"$STDOUT_FILE" 2>"$STDERR_FILE" & +prop_pid=$! +sleep 1 +kill -USR1 "$prop_pid" +if wait "$prop_pid"; then + prop_status=0 +else + prop_status=$? +fi +assert_status "signal propagation status" 77 "$prop_status" +assert_empty "signal propagation stdout" "$(cat "$STDOUT_FILE")" +assert_empty "signal propagation stderr" "$(cat "$STDERR_FILE")" + +PIDFILE="$WORKDIR/desc.pid" +run_timed_capture \ + "$TIMEOUT_BIN" -s INT 1 \ + sh -c '(trap "" INT HUP; sleep 5) & echo $! >"$1"; sleep 10' \ + sh "$PIDFILE" +assert_status "non-foreground descendant wait status" 124 "$LAST_STATUS" +assert_ge "non-foreground descendant wait elapsed seconds" "$LAST_ELAPSED" 4 +assert_empty "non-foreground descendant wait stdout" "$LAST_STDOUT" +assert_empty "non-foreground descendant wait stderr" "$LAST_STDERR" +[ -s "$PIDFILE" ] || fail "missing descendant pid for non-foreground case" +desc_pid=$(cat "$PIDFILE") +if kill -0 "$desc_pid" 2>/dev/null; then + fail "descendant still alive after non-foreground timeout" +fi + +rm -f "$PIDFILE" +run_timed_capture \ + "$TIMEOUT_BIN" -f -s INT 1 \ + sh -c '(trap "" INT HUP; sleep 5) & echo $! >"$1"; sleep 10' \ + sh "$PIDFILE" +assert_status "foreground timeout status" 124 "$LAST_STATUS" +assert_le "foreground timeout elapsed seconds" "$LAST_ELAPSED" 3 +assert_empty "foreground timeout stdout" "$LAST_STDOUT" +assert_empty "foreground timeout stderr" "$LAST_STDERR" +[ -s "$PIDFILE" ] || fail "missing descendant pid for foreground case" +desc_pid=$(cat "$PIDFILE") +if ! kill -0 "$desc_pid" 2>/dev/null; then + fail "descendant not alive after foreground timeout" +fi +kill -KILL "$desc_pid" 2>/dev/null || true + +printf '%s\n' "PASS" |
