1 # $NetBSD: t_wait.sh,v 1.8 2016/03/31 16:22:54 christos Exp $ 2 # 3 # Copyright (c) 2008, 2009, 2010 The NetBSD Foundation, Inc. 4 # All rights reserved. 5 # 6 # Redistribution and use in source and binary forms, with or without 7 # modification, are permitted provided that the following conditions 8 # are met: 9 # 1. Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # 2. Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # 15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 # POSSIBILITY OF SUCH DAMAGE. 26 # 27 # the implementation of "sh" to test 28 : ${TEST_SH:="/bin/sh"} 29 30 atf_test_case basic_wait 31 basic_wait_head() { 32 atf_set "descr" "Tests simple uses of wait" 33 } 34 basic_wait_body() { 35 atf_require_prog sleep 36 37 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 38 '(echo nothing >/dev/null) & wait' 39 40 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 41 '(exit 3) & wait $!; S=$?; test $S -eq 3 || { 42 echo "status: $S"; exit 1; }' 43 44 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 45 'sleep 3 & sleep 2 & sleep 1 & wait' 46 47 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 48 'sleep 3 & (exit 2) & sleep 1 & wait' 49 } 50 51 atf_test_case individual 52 individual_head() { 53 atf_set "descr" "Tests that waiting for individual processes works" 54 } 55 individual_body() { 56 atf_require_prog sleep 57 58 cat >individualhelper.sh <<\EOF 59 sleep 3 & P1=$! 60 sleep 1 & P2=$! 61 62 wait ${P1} 63 S=$? 64 if [ $S -ne 0 ]; then 65 echo "Waiting for first process failed: $S" 66 exit 1 67 fi 68 69 wait ${P2} 70 S=$? 71 if [ $? -ne 0 ]; then 72 echo "Waiting for second process failed" 73 exit 1 74 fi 75 76 exit 0 77 EOF 78 output=$(${TEST_SH} individualhelper.sh 2>&1) 79 [ $? -eq 0 ] || atf_fail "${output}" 80 } 81 82 atf_test_case jobs 83 jobs_head() { 84 atf_set "descr" "Tests that waiting for individual jobs works" 85 } 86 jobs_body() { 87 # atf-sh confuses wait for some reason; work it around by creating 88 # a helper script that executes /bin/sh directly. 89 90 if ! ${TEST_SH} -c 'sleep 1 & wait %1' 2>/dev/null 91 then 92 atf_skip "No job control support in this shell" 93 fi 94 95 cat >individualhelper.sh <<\EOF 96 sleep 3 & 97 sleep 1 & 98 99 wait %1 100 if [ $? -ne 0 ]; then 101 echo "Waiting for first job failed" 102 exit 1 103 fi 104 105 wait %2 106 if [ $? -ne 0 ]; then 107 echo "Waiting for second job failed" 108 exit 1 109 fi 110 111 exit 0 112 EOF 113 output=$(${TEST_SH} individualhelper.sh 2>&1) 114 [ $? -eq 0 ] || atf_fail "${output}" 115 116 cat >individualhelper.sh <<\EOF 117 { sleep 3; exit 3; } & 118 { sleep 1; exit 7; } & 119 120 wait %1 121 S=$? 122 if [ $S -ne 3 ]; then 123 echo "Waiting for first job failed - status: $S != 3 (expected)" 124 exit 1 125 fi 126 127 wait %2 128 S=$? 129 if [ $S -ne 7 ]; then 130 echo "Waiting for second job failed - status: $S != 7 (expected)" 131 exit 1 132 fi 133 134 exit 0 135 EOF 136 137 output=$(${TEST_SH} individualhelper.sh 2>&1) 138 [ $? -eq 0 ] || atf_fail "${output}" 139 } 140 141 atf_test_case kill 142 kill_head() { 143 atf_set "descr" "Tests that killing the shell while in wait calls trap" 144 } 145 kill_body() { 146 atf_require_prog sleep 147 atf_require_prog kill 148 149 s=killhelper.sh 150 z=killhelper.$$ 151 pid= 152 153 # waiting for a specific process that is not a child 154 # should return exit status of 127 according to the spec 155 # This test is here before the next, to avoid that one 156 # entering an infinite loop should the shell have a bug here. 157 158 atf_check -s exit:127 -o empty -e ignore ${TEST_SH} -c 'wait 1' 159 160 cat > "${s}" <<'EOF' 161 162 trap "echo SIGHUP" 1 163 (sleep 5; exit 3) & 164 sl=$! 165 wait 166 S=$? 167 echo $S 168 LS=9999 169 while [ $S -ne 0 ] && [ $S != 127 ]; do 170 wait $sl; S=$?; echo $S 171 test $S = $LS && { echo "wait repeats..."; exit 2; } 172 LS=$S 173 done 174 EOF 175 176 ${TEST_SH} $s > $z & 177 pid=$! 178 sleep 1 179 180 kill -HUP "${pid}" 181 wait 182 183 output="$(cat $z | tr '\n' ' ')" 184 185 if [ "$output" != "SIGHUP 129 3 127 " ]; then 186 atf_fail "${output} != 'SIGHUP 129 3 127 '" 187 fi 188 } 189 190 atf_init_test_cases() { 191 atf_add_test_case basic_wait 192 atf_add_test_case individual 193 atf_add_test_case jobs 194 atf_add_test_case kill 195 } 196