| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | # $NetBSD: t_wait.sh,v 1.6 2016/03/08 14:24:06 christos Exp $ | | 1 | # $NetBSD: t_wait.sh,v 1.7 2016/03/27 14:50:40 christos Exp $ |
2 | # | | 2 | # |
3 | # Copyright (c) 2008, 2009, 2010 The NetBSD Foundation, Inc. | | 3 | # Copyright (c) 2008, 2009, 2010 The NetBSD Foundation, Inc. |
4 | # All rights reserved. | | 4 | # All rights reserved. |
5 | # | | 5 | # |
6 | # Redistribution and use in source and binary forms, with or without | | 6 | # Redistribution and use in source and binary forms, with or without |
7 | # modification, are permitted provided that the following conditions | | 7 | # modification, are permitted provided that the following conditions |
8 | # are met: | | 8 | # are met: |
9 | # 1. Redistributions of source code must retain the above copyright | | 9 | # 1. Redistributions of source code must retain the above copyright |
10 | # notice, this list of conditions and the following disclaimer. | | 10 | # notice, this list of conditions and the following disclaimer. |
11 | # 2. Redistributions in binary form must reproduce the above copyright | | 11 | # 2. Redistributions in binary form must reproduce the above copyright |
12 | # notice, this list of conditions and the following disclaimer in the | | 12 | # notice, this list of conditions and the following disclaimer in the |
13 | # documentation and/or other materials provided with the distribution. | | 13 | # documentation and/or other materials provided with the distribution. |
14 | # | | 14 | # |
| @@ -17,84 +17,179 @@ | | | @@ -17,84 +17,179 @@ |
17 | # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 17 | # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
18 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 18 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
19 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 19 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 20 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 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 | | 22 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 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 | | 24 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 | # POSSIBILITY OF SUCH DAMAGE. | | 25 | # POSSIBILITY OF SUCH DAMAGE. |
26 | # | | 26 | # |
27 | # the implementation of "sh" to test | | 27 | # the implementation of "sh" to test |
28 | : ${TEST_SH:="/bin/sh"} | | 28 | : ${TEST_SH:="/bin/sh"} |
29 | | | 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 | |
30 | atf_test_case individual | | 51 | atf_test_case individual |
31 | individual_head() { | | 52 | individual_head() { |
32 | atf_set "descr" "Tests that waiting for individual jobs works" | | 53 | atf_set "descr" "Tests that waiting for individual processes works" |
33 | } | | 54 | } |
34 | individual_body() { | | 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() { |
35 | # atf-sh confuses wait for some reason; work it around by creating | | 87 | # atf-sh confuses wait for some reason; work it around by creating |
36 | # a helper script that executes /bin/sh directly. | | 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 | |
37 | cat >individualhelper.sh <<\EOF | | 95 | cat >individualhelper.sh <<\EOF |
38 | sleep 3 & | | 96 | sleep 3 & |
39 | sleep 1 & | | 97 | sleep 1 & |
40 | | | 98 | |
41 | wait %1 | | 99 | wait %1 |
42 | if [ $? -ne 0 ]; then | | 100 | if [ $? -ne 0 ]; then |
43 | echo "Waiting of first job failed" | | 101 | echo "Waiting for first job failed" |
44 | exit 1 | | 102 | exit 1 |
45 | fi | | 103 | fi |
46 | | | 104 | |
47 | wait %2 | | 105 | wait %2 |
48 | if [ $? -ne 0 ]; then | | 106 | if [ $? -ne 0 ]; then |
49 | echo "Waiting of second job failed" | | 107 | echo "Waiting for second job failed" |
50 | exit 1 | | 108 | exit 1 |
51 | fi | | 109 | fi |
52 | | | 110 | |
53 | exit 0 | | 111 | exit 0 |
54 | EOF | | 112 | EOF |
55 | output=$("${TEST_SH}" individualhelper.sh) | | 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) |
56 | [ $? -eq 0 ] || atf_fail "${output}" | | 138 | [ $? -eq 0 ] || atf_fail "${output}" |
57 | rm -f individualhelper.sh | | | |
58 | } | | 139 | } |
59 | | | 140 | |
60 | atf_test_case kill | | 141 | atf_test_case kill |
61 | kill_head() { | | 142 | kill_head() { |
62 | atf_set "descr" "Tests that killing the shell while in wait calls trap" | | 143 | atf_set "descr" "Tests that killing the shell while in wait calls trap" |
63 | } | | 144 | } |
64 | kill_body() { | | 145 | kill_body() { |
65 | # atf-sh confuses wait for some reason; work it around by creating | | 146 | atf_require_prog sleep |
66 | # a helper script that executes /bin/sh directly. | | 147 | atf_require_prog kill |
67 | local s=$PWD/killhelper.sh | | 148 | |
68 | local z=/tmp/killhelper.$$ | | 149 | s=killhelper.sh |
69 | local pid= | | 150 | z=/tmp/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' |
70 | | | 161 | |
71 | sed 's!${SH}!'"${TEST_SH}!" >$s <<\EOF | | | |
72 | #! ${SH} | | | |
73 | trap "echo SIGHUP" 1 | | 162 | trap "echo SIGHUP" 1 |
74 | (sleep 5; exit 3) & | | 163 | (sleep 5; exit 3) & |
75 | sl=$! | | 164 | sl=$! |
76 | wait | | 165 | wait |
77 | S=$? | | 166 | S=$? |
78 | echo $S | | 167 | echo $S |
79 | while [ $S -ne 0 ] && [ $S != 127 ]; do wait $sl; S=$?; echo $S; done | | 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 |
80 | EOF | | 174 | EOF |
81 | chmod +x $s | | | |
82 | | | 175 | |
83 | $s > $z & | | 176 | ${TEST_SH} $s > $z & |
84 | pid=$! | | 177 | pid=$! |
85 | sleep 1 | | 178 | sleep 1 |
86 | | | 179 | |
87 | kill -HUP $pid | | 180 | kill -HUP "${pid}" |
88 | wait | | 181 | wait |
89 | | | 182 | |
90 | output="$(cat $z | tr '\n' ' ')" | | 183 | output="$(cat $z | tr '\n' ' ')" |
91 | rm -f $s $z | | 184 | |
92 | if [ "$output" != "SIGHUP 129 3 127 " ]; then | | 185 | if [ "$output" != "SIGHUP 129 3 127 " ]; then |
93 | atf_fail "${output} != 'SIGHUP 129 3 127 '" | | 186 | atf_fail "${output} != 'SIGHUP 129 3 127 '" |
94 | fi | | 187 | fi |
95 | } | | 188 | } |
96 | | | 189 | |
97 | atf_init_test_cases() { | | 190 | atf_init_test_cases() { |
| | | 191 | atf_add_test_case basic_wait |
98 | atf_add_test_case individual | | 192 | atf_add_test_case individual |
| | | 193 | atf_add_test_case jobs |
99 | atf_add_test_case kill | | 194 | atf_add_test_case kill |
100 | } | | 195 | } |