summaryrefslogtreecommitdiff
path: root/corebinutils/kill/tests
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:26:05 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:26:05 +0300
commit997dd21c2f45e9a586e9ef459381de1d540a9cfb (patch)
tree5648d5924a91841c15ae95b9e7b56a9b07a9b284 /corebinutils/kill/tests
parent3d884ae8958e9e060e76d6e8165eb33ae86829d4 (diff)
parent4888cfe1b3ad8e83935dc7b061bdbdade5d3ebfd (diff)
downloadProject-Tick-997dd21c2f45e9a586e9ef459381de1d540a9cfb.tar.gz
Project-Tick-997dd21c2f45e9a586e9ef459381de1d540a9cfb.zip
Add 'corebinutils/kill/' from commit '4888cfe1b3ad8e83935dc7b061bdbdade5d3ebfd'
git-subtree-dir: corebinutils/kill git-subtree-mainline: 3d884ae8958e9e060e76d6e8165eb33ae86829d4 git-subtree-split: 4888cfe1b3ad8e83935dc7b061bdbdade5d3ebfd
Diffstat (limited to 'corebinutils/kill/tests')
-rw-r--r--corebinutils/kill/tests/test.sh322
1 files changed, 322 insertions, 0 deletions
diff --git a/corebinutils/kill/tests/test.sh b/corebinutils/kill/tests/test.sh
new file mode 100644
index 0000000000..c8ea94d941
--- /dev/null
+++ b/corebinutils/kill/tests/test.sh
@@ -0,0 +1,322 @@
+#!/bin/sh
+set -eu
+
+ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
+KILL_BIN=${KILL_BIN:-"$ROOT/out/kill"}
+CC=${CC:-cc}
+TMPDIR=${TMPDIR:-/tmp}
+WORKDIR=$(mktemp -d "$TMPDIR/kill-test.XXXXXX")
+HELPER_C="$WORKDIR/signal-helper.c"
+HELPER_BIN="$WORKDIR/signal-helper"
+STDOUT_FILE="$WORKDIR/stdout"
+STDERR_FILE="$WORKDIR/stderr"
+ACTIVE_PID=
+ACTIVE_LOG=
+ACTIVE_READY=
+trap '
+ if [ -n "${ACTIVE_PID}" ]; then
+ kill -KILL "$ACTIVE_PID" 2>/dev/null || true
+ wait "$ACTIVE_PID" 2>/dev/null || true
+ fi
+ rm -rf "$WORKDIR"
+' EXIT INT TERM
+
+export LC_ALL=C
+
+USAGE_OUTPUT=$(cat <<'EOF'
+usage: kill [-s signal_name] pid ...
+ kill -l [exit_status]
+ kill -signal_name pid ...
+ kill -signal_number pid ...
+EOF
+)
+
+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' "$expected" >&2
+ printf '\n%s\n' "--- actual ---" >&2
+ printf '%s' "$actual" >&2
+ printf '\n' >&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' "$text" >&2
+ printf '\n' >&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
+}
+
+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")
+}
+
+build_helper() {
+cat >"$HELPER_C" <<'EOF'
+#define _POSIX_C_SOURCE 200809L
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static volatile sig_atomic_t received_signal;
+
+static void
+handle_signal(int signo)
+{
+ received_signal = signo;
+}
+
+static const char *
+signal_name(int signo)
+{
+ switch (signo) {
+ case SIGTERM:
+ return "TERM";
+ case SIGUSR1:
+ return "USR1";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct sigaction sa;
+ FILE *fp;
+
+ if (argc != 2)
+ return (2);
+
+ if (setpgid(0, 0) != 0)
+ return (3);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handle_signal;
+ if (sigemptyset(&sa.sa_mask) != 0)
+ return (4);
+ if (sigaction(SIGTERM, &sa, NULL) != 0)
+ return (5);
+ if (sigaction(SIGUSR1, &sa, NULL) != 0)
+ return (6);
+
+ if (printf("%ld %ld\n", (long)getpid(), (long)getpgrp()) < 0)
+ return (7);
+ if (fflush(stdout) != 0)
+ return (8);
+
+ while (received_signal == 0)
+ pause();
+
+ fp = fopen(argv[1], "w");
+ if (fp == NULL)
+ return (9);
+ if (fprintf(fp, "%s\n", signal_name(received_signal)) < 0) {
+ fclose(fp);
+ return (10);
+ }
+ if (fclose(fp) != 0)
+ return (11);
+
+ return (0);
+}
+EOF
+
+ "$CC" -D_POSIX_C_SOURCE=200809L -O2 -std=c17 -Wall -Wextra -Werror \
+ "$HELPER_C" -o "$HELPER_BIN" \
+ || fail "failed to build helper with $CC"
+}
+
+start_helper() {
+ name=$1
+ ACTIVE_LOG="$WORKDIR/$name.log"
+ ACTIVE_READY="$WORKDIR/$name.ready"
+ rm -f "$ACTIVE_LOG" "$ACTIVE_READY"
+ mkfifo "$ACTIVE_READY"
+
+ "$HELPER_BIN" "$ACTIVE_LOG" >"$ACTIVE_READY" &
+ ACTIVE_PID=$!
+
+ if ! IFS=' ' read -r HELPER_PID HELPER_PGID <"$ACTIVE_READY"; then
+ fail "failed to read helper readiness"
+ fi
+ rm -f "$ACTIVE_READY"
+ ACTIVE_READY=
+
+ [ -n "$HELPER_PID" ] || fail "helper pid missing"
+ [ -n "$HELPER_PGID" ] || fail "helper pgid missing"
+}
+
+wait_helper() {
+ wait "$ACTIVE_PID" || fail "helper exited with failure"
+ ACTIVE_PID=
+}
+
+wait_helper_signaled() {
+ if wait "$ACTIVE_PID"; then
+ fail "helper was expected to terminate by signal"
+ fi
+ ACTIVE_PID=
+}
+
+[ -x "$KILL_BIN" ] || fail "missing binary: $KILL_BIN"
+build_helper
+
+run_capture "$KILL_BIN"
+assert_status "usage without args status" 2 "$LAST_STATUS"
+assert_empty "usage without args stdout" "$LAST_STDOUT"
+assert_eq "usage without args stderr" "$USAGE_OUTPUT" "$LAST_STDERR"
+
+run_capture "$KILL_BIN" -l
+assert_status "list signals status" 0 "$LAST_STATUS"
+assert_empty "list signals stderr" "$LAST_STDERR"
+assert_contains "list signals contains HUP" "$LAST_STDOUT" "HUP"
+assert_contains "list signals contains KILL" "$LAST_STDOUT" "KILL"
+assert_contains "list signals contains TERM" "$LAST_STDOUT" "TERM"
+
+run_capture "$KILL_BIN" -l 15
+assert_status "list signal 15 status" 0 "$LAST_STATUS"
+assert_eq "list signal 15 stdout" "TERM" "$LAST_STDOUT"
+assert_empty "list signal 15 stderr" "$LAST_STDERR"
+
+run_capture "$KILL_BIN" -l 143
+assert_status "list signal 143 status" 0 "$LAST_STATUS"
+assert_eq "list signal 143 stdout" "TERM" "$LAST_STDOUT"
+assert_empty "list signal 143 stderr" "$LAST_STDERR"
+
+run_capture "$KILL_BIN" -l 0
+assert_status "list signal 0 status" 0 "$LAST_STATUS"
+assert_eq "list signal 0 stdout" "0" "$LAST_STDOUT"
+assert_empty "list signal 0 stderr" "$LAST_STDERR"
+
+run_capture "$KILL_BIN" -l TERM
+assert_status "list TERM status" 0 "$LAST_STATUS"
+assert_eq "list TERM stdout" "15" "$LAST_STDOUT"
+assert_empty "list TERM stderr" "$LAST_STDERR"
+
+run_capture "$KILL_BIN" -s
+assert_status "missing -s argument status" 2 "$LAST_STATUS"
+assert_empty "missing -s argument stdout" "$LAST_STDOUT"
+assert_contains "missing -s argument stderr" "$LAST_STDERR" \
+ "kill: option requires an argument -- s"
+
+run_capture "$KILL_BIN" -NOPE 1
+assert_status "unknown option signal status" 2 "$LAST_STATUS"
+assert_empty "unknown option signal stdout" "$LAST_STDOUT"
+assert_contains "unknown option signal stderr" "$LAST_STDERR" \
+ "kill: unknown signal NOPE"
+
+run_capture "$KILL_BIN" abc
+assert_status "invalid pid status" 2 "$LAST_STATUS"
+assert_empty "invalid pid stdout" "$LAST_STDOUT"
+assert_eq "invalid pid stderr" "kill: illegal process id: abc" "$LAST_STDERR"
+
+run_capture "$KILL_BIN" %1
+assert_status "job spec status" 2 "$LAST_STATUS"
+assert_empty "job spec stdout" "$LAST_STDOUT"
+assert_eq "job spec stderr" \
+ "kill: job control process specifications require a shell builtin: %1" \
+ "$LAST_STDERR"
+
+start_helper probe
+
+run_capture "$KILL_BIN" -0 "$HELPER_PID"
+assert_status "signal zero short form status" 0 "$LAST_STATUS"
+assert_empty "signal zero short form stdout" "$LAST_STDOUT"
+assert_empty "signal zero short form stderr" "$LAST_STDERR"
+
+run_capture "$KILL_BIN" -s 0 "$HELPER_PID"
+assert_status "signal zero -s status" 0 "$LAST_STATUS"
+assert_empty "signal zero -s stdout" "$LAST_STDOUT"
+assert_empty "signal zero -s stderr" "$LAST_STDERR"
+
+run_capture "$KILL_BIN" -9 "$HELPER_PID"
+assert_status "signal 9 short form status" 0 "$LAST_STATUS"
+assert_empty "signal 9 short form stdout" "$LAST_STDOUT"
+assert_empty "signal 9 short form stderr" "$LAST_STDERR"
+wait_helper_signaled
+[ ! -e "$ACTIVE_LOG" ] || fail "signal 9 helper log should not exist"
+
+start_helper numeric_s
+run_capture "$KILL_BIN" -s 9 "$HELPER_PID"
+assert_status "signal 9 with -s status" 0 "$LAST_STATUS"
+assert_empty "signal 9 with -s stdout" "$LAST_STDOUT"
+assert_empty "signal 9 with -s stderr" "$LAST_STDERR"
+wait_helper_signaled
+[ ! -e "$ACTIVE_LOG" ] || fail "signal 9 with -s helper log should not exist"
+
+start_helper probe
+run_capture "$KILL_BIN" -s SIGUSR1 "$HELPER_PID"
+assert_status "send SIGUSR1 with -s status" 0 "$LAST_STATUS"
+assert_empty "send SIGUSR1 with -s stdout" "$LAST_STDOUT"
+assert_empty "send SIGUSR1 with -s stderr" "$LAST_STDERR"
+wait_helper
+assert_eq "SIGUSR1 helper log" "USR1" "$(cat "$ACTIVE_LOG")"
+
+start_helper default_term
+run_capture "$KILL_BIN" "$HELPER_PID"
+assert_status "default TERM status" 0 "$LAST_STATUS"
+assert_empty "default TERM stdout" "$LAST_STDOUT"
+assert_empty "default TERM stderr" "$LAST_STDERR"
+wait_helper
+assert_eq "default TERM helper log" "TERM" "$(cat "$ACTIVE_LOG")"
+
+start_helper group_term
+run_capture "$KILL_BIN" -TERM -- "-$HELPER_PGID"
+assert_status "group TERM status" 0 "$LAST_STATUS"
+assert_empty "group TERM stdout" "$LAST_STDOUT"
+assert_empty "group TERM stderr" "$LAST_STDERR"
+wait_helper
+assert_eq "group TERM helper log" "TERM" "$(cat "$ACTIVE_LOG")"
+
+printf '%s\n' "PASS"