-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathkillers_unittest
executable file
·147 lines (123 loc) · 3.89 KB
/
killers_unittest
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
#!/bin/bash
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Return a list of all currently existing PIDs.
getAllPids() {
exec ps --no-headers -opid --deselect -C ps
}
# Poll until the provided PID appears.
pollForPid() {
local pid=$1
[[ -z "${pid}" ]] && return
until kill -0 "${pid}" 2> /dev/null; do
sleep .1
done
}
tearDown() {
# TODO(cmasone): Remove ps when http://crbug.com/442027 is sorted.
ps -f --forest -u $(id -u)
pkill -KILL -e -P $$
echo "------------------------------ Test complete."
echo
}
# Asserts that the given PID is alive.
assertPid() {
[[ $# -eq 1 ]] || fail "assertPid requires 1 arg, you passed $@"
local pid=$1
kill -0 "${pid}"
assertEquals "${pid} should not have been killed." 0 $?
}
readonly ASSERT_NO_PID_TIMEOUT=20000 # Timeout in msec. Chosen arbitrarily.
# Asserts that the given PID is not alive.
assertNoPid() {
[[ $# -eq 1 ]] || fail "assertPid requires 1 arg, you passed $@"
local pid=$1 i=0
while [[ ${i} -lt ${ASSERT_NO_PID_TIMEOUT} ]]; do
if ! kill -0 "${pid}" 2> /dev/null; then
return
fi
sleep .1
: $(( i += 100 ))
echo "Waited ${i} msec for ${pid} to die."
done
fail "${pid} should not be alive."
}
# Runs a background process that holds open a file under ${SHUNIT_TMPDIR}.
# Passing "untermable" as the sole argument will make this process ignore TERM.
# Upon return, the process will be backgrounded and the pid is in $!.
runBackgroundProcess() {
local untermable
if [[ $# -gt 0 && "$1" == "untermable" ]]; then
untermable="trap : SIGTERM;"
fi
local tmpfile=$(mktemp -p "${SHUNIT_TMPDIR}" "killers_$$_$1_XXXXXXXX")
touch "${tmpfile}" || fail "Could not create ${tmpfile}"
bash -c "exec 3<'${tmpfile}'; ${untermable} kill -STOP \$\$" &
pollForPid $!
}
# Run a test of kill_with_open_files_on. Pass "untermable" as the sole
# argument to test terminating processes that ignore SIGTERM.
doKillWithOpenFilesTest() {
local pid1 pid2
runBackgroundProcess "$@"
pid1=$!
runBackgroundProcess "$@"
pid2=$!
kill_with_open_files_on "" "${SHUNIT_TMPDIR}"/*
assertNoPid "${pid1}"
assertNoPid "${pid2}"
}
testKillWithOpenFiles() {
doKillWithOpenFilesTest
}
testKillWithOpenFiles_NonTERMable() {
doKillWithOpenFilesTest untermable
}
testKillWithOpenFiles_EmptyParams() {
local before_pids=$(getAllPids)
local error_out=$(kill_with_open_files_on "" "" 2>&1)
local after_pids=$(getAllPids)
assertNotNull "${before_pids}"
assertNotNull "${after_pids}"
assertEquals "${error_out}" "${before_pids}" "${after_pids}"
}
testKillWithOpenFiles_UnresolvedGlob() {
local before_pids=$(getAllPids)
local error_out=$(kill_with_open_files_on "" "${SHUNIT_TMPDIR}"/* 2>&1)
local after_pids=$(getAllPids)
assertNotNull "${before_pids}"
assertNotNull "${after_pids}"
assertEquals "${error_out}" "${before_pids}" "${after_pids}"
}
testKillWithOpenFiles_PathFilter() {
local pid1 pid2
runBackgroundProcess foo
pid1=$!
runBackgroundProcess bar
pid2=$!
kill_with_open_files_on_path_and_mountpoints ".*_foo_" "" "${SHUNIT_TMPDIR}"/*
assertNoPid "${pid1}"
assertPid "${pid2}"
}
main() {
if [[ $# -ne 0 ]]; then
echo "Usage: $0" >&2
exit 1
fi
echo "Note: Messages like 'Killed bash -c \"...\"' are normal"
# Detect whether we're being run inside a pid namespace where we are init.
# If not, start such a pid namespace. This is to ensure we don't kill real
# processes on the system during tests.
if ! grep -Eqs "$0|pid ns: init" /proc/1/cmdline ]] && \
[[ -z ${UNSHARE} ]]; then
exec sudo UNSHARE=true unshare -f -p --mount-proc "$0" "$@"
fi
# Default to the temp dir ($T) that portage has set up for us.
# This is needed when doing out of tree builds.
TMPDIR="${T:-.}"
. ./killers
LOGPATH="${TMPDIR}/${LOGPATH##*/}"
. /usr/bin/shunit2
}
main "$@"