blob: 004bd9f372a2249c694b2b356a862a95f98678ec (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
#!/bin/sh
# ps tests
#
# Assumptions:
# - PS_BIN points to the newly built ps
# - TEST_HELPER points to tests/spin_helper.c compiled into out/tests/spin_helper
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'
fail() {
printf "${RED}FAIL: %s${NC}\n" "$1" >&2
exit 1
}
pass() {
printf "${GREEN}PASS: %s${NC}\n" "$1"
}
# Build a ps-specific helper in shared out/ roots to avoid name collisions
# with other test suites (e.g. pkill also has a spin_helper).
HELPER_DIR="$(dirname "$0")"
OUT_DIR="$(dirname "${PS_BIN}")"
HELPER_BIN="${OUT_DIR}/ps_spin_helper"
HELPER_SRC="${HELPER_DIR}/spin_helper.c"
CC_BIN="${CC:-cc}"
if [ ! -x "${HELPER_BIN}" ] || [ "${HELPER_SRC}" -nt "${HELPER_BIN}" ]; then
"${CC_BIN}" -O2 "${HELPER_SRC}" -o "${HELPER_BIN}" || fail "failed to compile spin_helper"
fi
# 1. Basic sanity: run without arguments
# Should output at least headers and some processes.
${PS_BIN} > /tmp/ps_out || fail "ps failed to run"
grep -q "PID" /tmp/ps_out || fail "ps output lacks PID header"
grep -q "COMMAND" /tmp/ps_out || fail "ps output lacks COMMAND header"
pass "Basic sanity (no args)"
# 2. Process selection: -p
# Start a helper, then find it with ps.
${HELPER_BIN} test-ps-select &
HELPER_PID=$!
sleep 0.1
${PS_BIN} -p ${HELPER_PID} > /tmp/ps_p_out || fail "ps -p failed"
grep -q "${HELPER_PID}" /tmp/ps_p_out || fail "ps -p did not find helper pid ${HELPER_PID}"
kill ${HELPER_PID}
pass "Process selection (-p pid)"
# 3. Format selection: -j
${HELPER_BIN} test-ps-fmt-j &
HELPER_PID=$!
sleep 0.1
${PS_BIN} -j -p ${HELPER_PID} > /tmp/ps_j_out || fail "ps -j failed"
grep -q "USER" /tmp/ps_j_out || fail "ps -j output lacks USER header"
grep -q "PPID" /tmp/ps_j_out || fail "ps -j output lacks PPID header"
grep -q "SID" /tmp/ps_j_out || fail "ps -j output lacks SID header"
kill ${HELPER_PID}
pass "Format selection (-j)"
# 4. Format selection: -u
${HELPER_BIN} test-ps-fmt-u &
HELPER_PID=$!
sleep 0.1
${PS_BIN} -u -p ${HELPER_PID} > /tmp/ps_u_out || fail "ps -u failed"
grep -q "%CPU" /tmp/ps_u_out || fail "ps -u output lacks %CPU header"
grep -q "%MEM" /tmp/ps_u_out || fail "ps -u output lacks %MEM header"
grep -q "VSZ" /tmp/ps_u_out || fail "ps -u output lacks VSZ header"
grep -q "RSS" /tmp/ps_u_out || fail "ps -u output lacks RSS header"
kill ${HELPER_PID}
pass "Format selection (-u)"
# 5. Format selection: -o (custom)
${HELPER_BIN} test-ps-fmt-o &
HELPER_PID=$!
sleep 0.1
${PS_BIN} -o pid,comm,nice -p ${HELPER_PID} > /tmp/ps_o_out || fail "ps -o failed"
grep -q "PID" /tmp/ps_o_out || fail "ps -o output lacks PID header"
grep -q "COMMAND" /tmp/ps_o_out || fail "ps -o output lacks COMMAND header"
grep -q "NI" /tmp/ps_o_out || fail "ps -o output lacks NI header"
# First line is header, second line should contain the PID.
grep -q "${HELPER_PID}" /tmp/ps_o_out || fail "ps -o did not find helper pid"
kill ${HELPER_PID}
pass "Format selection (-o pid,comm,nice)"
# 6. Sorting: -m (by memory) and -r (by cpu)
${PS_BIN} -m -A > /dev/null || fail "ps -m -A failed"
${PS_BIN} -r -A > /dev/null || fail "ps -r -A failed"
pass "Sorting (-m, -r)"
# 7. Negative test: invalid pid
${PS_BIN} -p 999999 > /tmp/ps_neg_out 2>&1
# FreeBSD ps should just print header and exits 1 if no matches found?
# Actually, standard behavior varies. Let's check status.
EXIT_CODE=$?
if [ ${EXIT_CODE} -ne 1 ]; then
# In some versions, no match means exit 1. In others, exit 0.
# FreeBSD ps.c: main() calls exit(1) if nkept == 0.
fail "ps -p invalid_pid should exit 1 (got ${EXIT_CODE})"
fi
pass "Negative test (invalid pid)"
# 8. Negative test: invalid flag
${PS_BIN} -Y > /dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ps -Y should fail"
fi
pass "Negative test (invalid flag)"
# 9. Width test: -w
${HELPER_BIN} test-ps-width-very-long-name-to-check-truncation &
HELPER_PID=$!
sleep 0.1
# Record output without -w (should truncate or at least be limited)
${PS_BIN} -u -p ${HELPER_PID} > /tmp/ps_w1
# Record output with -ww (no limit)
${PS_BIN} -u -ww -p ${HELPER_PID} > /tmp/ps_w2
# Compare -w2 should be longer or equal to -w1 in terms of line length
LEN1=$(awk '{ print length }' /tmp/ps_w1 | sort -nr | head -1)
LEN2=$(awk '{ print length }' /tmp/ps_w2 | sort -nr | head -1)
if [ "${LEN2}" -lt "${LEN1}" ]; then
fail "ps -ww output shorter than normal output"
fi
kill ${HELPER_PID}
pass "Width control (-w, -ww)"
# 10. Headers control: -h
# Start 30 helpers safely.
I=1
while [ ${I} -le 30 ]; do
${HELPER_BIN} test-ps-h-${I} &
H_PIDS="${H_PIDS} $!"
I=$((I+1))
done
sleep 0.1
# Run ps -h -A (repeat headers every 22 lines or so)
${PS_BIN} -h -A | grep "PID" | wc -l > /tmp/ps_h_count
COUNT=$(cat /tmp/ps_h_count)
if [ "${COUNT}" -lt 2 ]; then
fail "ps -h should repeat headers (got ${COUNT} headers for 30+ processes)"
fi
kill ${H_PIDS}
pass "Header repetition (-h)"
# Clean up
rm -f /tmp/ps_*
printf "${GREEN}All tests passed!${NC}\n"
exit 0
|