3 # SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 # Copyright (c) 2021 Axcient
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
10 # 1. Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 atf_test_case both_pidfile cleanup
32 atf_set "descr" "daemon should write pid files for itself and its child"
35 daemon -P daemon.pid -p sleep.pid sleep 300
36 atf_check -s exit:0 test -f daemon.pid
37 atf_check -s exit:0 -o match:"daemon: sleep" ps -p `cat daemon.pid`
38 atf_check -s exit:0 test -f sleep.pid
39 atf_check -s exit:0 -o match:"[0-9] sleep 300$" ps -p `cat sleep.pid`
41 both_pidfile_cleanup() {
42 if [ -f daemon.pid ]; then
43 daemon_pid=`cat daemon.pid`
45 if [ -f sleep_pid ]; then
46 sleep_pid=`cat sleep.pid`
48 [ -n "$sleep_pid" ] && kill $sleep_pid
49 # NB: killing the sleep should kill the daemon too, so we musn't fail
50 # the test if the second kill fails with ESRCH
51 [ -n "$daemon_pid" ] && kill $daemon_pid || true
54 atf_test_case chdir cleanup
56 atf_set "descr" "daemon should chdir to /"
59 # Executing sleep by relative path will only work from /
60 daemon -p ${PWD}/sleep.pid -c bin/sleep 300
61 atf_check -s exit:0 test -f sleep.pid
62 atf_check -s exit:0 -o match:"[0-9] bin/sleep 300$" \
66 [ -f sleep.pid ] && kill `cat sleep.pid`
69 atf_test_case child_pidfile cleanup
70 child_pidfile_head() {
71 atf_set "descr" "daemon should write its child's pid to a pidfile"
73 child_pidfile_body() {
74 daemon -p sleep.pid sleep 300
75 atf_check -s exit:0 test -f sleep.pid
76 atf_check -s exit:0 -o match:"[0-9] sleep 300$" ps -p `cat sleep.pid`
78 child_pidfile_cleanup() {
79 [ -f sleep.pid ] && kill `cat sleep.pid`
82 atf_test_case child_pidfile_lock cleanup
83 child_pidfile_lock_head() {
84 atf_set "descr" "daemon should refuse to clobber an existing child"
86 child_pidfile_lock_body() {
87 daemon -p sleep.pid sleep 300
88 atf_check -s exit:0 test -f sleep.pid
89 atf_check -s not-exit:0 -e match:"process already running" \
90 daemon -p sleep.pid sleep 300
92 child_pidfile_lock_cleanup() {
93 [ -f sleep.pid ] && kill `cat sleep.pid`
96 atf_test_case newsyslog cleanup
98 atf_set "descr" "daemon should close and reopen the output file on SIGHUP"
101 cat > child.sh <<HERE
109 daemon -P daemon.pid -H -o output_file ./child.sh
110 atf_check -s exit:0 test -f daemon.pid
112 mv output_file output_file.0
113 kill -HUP `cat daemon.pid`
115 atf_check -s exit:0 test -s output_file.0
116 atf_check -s exit:0 test -s output_file
118 newsyslog_cleanup() {
119 [ -f daemon.pid ] && kill `cat daemon.pid`
122 atf_test_case output_file
124 atf_set "descr" "daemon should redirect stdout to a file"
127 daemon -o output_file seq 1 5
128 seq 1 5 > expected_file
129 atf_check -s exit:0 cmp output_file expected_file
132 atf_test_case restart_child cleanup
133 restart_child_head() {
134 atf_set "descr" "daemon should restart a dead child"
136 restart_child_body() {
137 daemon -rP daemon.pid -p sleep.pid sleep 300
138 atf_check -s exit:0 test -f daemon.pid
139 atf_check -s exit:0 test -f sleep.pid
140 orig_sleep_pid=`cat sleep.pid`
142 # Wait up to 10s for the daemon to restart the child.
143 for t in `seq 0 0.1 10`; do
144 new_sleep_pid=`cat sleep.pid`
145 [ "$orig_sleep_pid" -ne "$new_sleep_pid" ] && break
148 [ "$orig_sleep_pid" -ne "$new_sleep_pid" ] || \
149 atf_fail "child was not restarted"
152 restart_child_cleanup() {
153 [ -f daemon.pid ] && kill `cat daemon.pid`
156 atf_test_case supervisor_pidfile cleanup
157 supervisor_pidfile_head() {
158 atf_set "descr" "daemon should write its own pid to a pidfile"
160 supervisor_pidfile_body() {
161 daemon -P daemon.pid sleep 300
162 atf_check -s exit:0 test -f daemon.pid
163 atf_check -s exit:0 -o match:"daemon: sleep" ps -p `cat daemon.pid`
165 supervisor_pidfile_cleanup() {
166 [ -f daemon.pid ] && kill `cat daemon.pid`
169 atf_test_case supervisor_pidfile_lock cleanup
170 supervisor_pidfile_lock_head() {
171 atf_set "descr" "daemon should refuse to clobber an existing instance"
173 supervisor_pidfile_lock_body() {
174 daemon -P daemon.pid sleep 300
175 atf_check -s exit:0 test -f daemon.pid
176 atf_check -s not-exit:0 -e match:"process already running" \
177 daemon -p daemon.pid sleep 300
179 supervisor_pidfile_lock_cleanup() {
180 [ -f daemon.pid ] && kill `cat daemon.pid`
183 atf_test_case title cleanup
185 atf_set "descr" "daemon should change its process title"
188 daemon -P daemon.pid -t "I'm a title!" sleep 300
189 atf_check -s exit:0 test -f daemon.pid
190 atf_check -s exit:0 -o match:"daemon: I'm a title!" \
191 ps -p `cat daemon.pid`
194 [ -f daemon.pid ] && kill `cat daemon.pid`
197 atf_test_case user cleanup
199 atf_set "descr" "daemon should drop privileges"
200 atf_set "require.user" "root"
203 daemon -p sleep.pid -u nobody sleep 300
204 atf_check -s exit:0 test -f sleep.pid
205 atf_check -s exit:0 -o match:"^nobody" ps -up `cat sleep.pid`
208 [ -f sleep.pid ] && kill `cat sleep.pid`
212 atf_init_test_cases() {
213 atf_add_test_case both_pidfile
214 atf_add_test_case chdir
215 atf_add_test_case child_pidfile
216 atf_add_test_case child_pidfile_lock
217 atf_add_test_case newsyslog
218 atf_add_test_case output_file
219 atf_add_test_case restart_child
220 atf_add_test_case supervisor_pidfile
221 atf_add_test_case supervisor_pidfile_lock
222 atf_add_test_case title
223 atf_add_test_case user