t_builtins.sh revision 1.5 1 1.5 kre # $NetBSD: t_builtins.sh,v 1.5 2019/01/09 10:51:23 kre Exp $
2 1.1 kre #
3 1.2 kre # Copyright (c) 2018 The NetBSD Foundation, Inc.
4 1.1 kre # All rights reserved.
5 1.1 kre #
6 1.1 kre # Redistribution and use in source and binary forms, with or without
7 1.1 kre # modification, are permitted provided that the following conditions
8 1.1 kre # are met:
9 1.1 kre # 1. Redistributions of source code must retain the above copyright
10 1.1 kre # notice, this list of conditions and the following disclaimer.
11 1.1 kre # 2. Redistributions in binary form must reproduce the above copyright
12 1.1 kre # notice, this list of conditions and the following disclaimer in the
13 1.1 kre # documentation and/or other materials provided with the distribution.
14 1.1 kre #
15 1.1 kre # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 1.1 kre # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 1.1 kre # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 1.1 kre # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 1.1 kre # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 1.1 kre # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 1.1 kre # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 1.1 kre # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 1.1 kre # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 1.1 kre # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 kre # POSSIBILITY OF SUCH DAMAGE.
26 1.1 kre #
27 1.1 kre # the implementation of "sh" to test
28 1.1 kre : ${TEST_SH:="/bin/sh"}
29 1.1 kre
30 1.1 kre #
31 1.1 kre # This file tests the various sh builtin utilities.
32 1.1 kre #
33 1.1 kre # Those utilities that are really external programs, which are builtin in
34 1.1 kre # for (mostly) performance (printf, kill, test, ...), are tested elsewhere.
35 1.1 kre # We do test the builtin "echo" here as (in NetBSD) it is different than
36 1.1 kre # the external one.
37 1.1 kre #
38 1.1 kre # The (mostly special) builtins which appear to be more syntax than command
39 1.1 kre # are tested in other test programs, rather than here (break, continue...)
40 1.1 kre #
41 1.1 kre # And finally, those which are fundamental to the operation of the shell,
42 1.1 kre # like wait, set, shift, ... are also tested in other test programs where
43 1.1 kre # all their operations can be more thoroughly verified.
44 1.1 kre #
45 1.1 kre # This leaves those which need to be built in (cd, umask, ...) but whose
46 1.1 kre # purpose is mostly to alter the environment in which the shell operates
47 1.1 kre # of that of the commands it runs. These tests act in co-operation with
48 1.1 kre # other tests exist here (where thy do) by not duplicating tests run
49 1.1 kre # elsewhere (ulimit is one example) but just adding to those.
50 1.1 kre # One day these might be unified.
51 1.1 kre #
52 1.1 kre # We do test both standard use of the builtins (where they are standard)
53 1.1 kre # and NetBSD sh extensions (when run on a shell with no support, such tests
54 1.1 kre # should be skipped.)
55 1.1 kre #
56 1.1 kre
57 1.1 kre # Utility function able to test whether most of the builtins exist in
58 1.1 kre # the shell being tested.
59 1.1 kre have_builtin()
60 1.1 kre {
61 1.1 kre ${TEST_SH} -c "( $3 $1 $4 ) >/dev/null 2>&1" &&
62 1.1 kre LC_ALL=C ${TEST_SH} -c \
63 1.1 kre 'case "$( (type '"$1"') 2>&1)" in
64 1.1 kre (*built*) exit 0 ;;
65 1.3 kre (*reserved*) exit 0 ;; # zsh!! (reserved words are builtin)
66 1.1 kre esac
67 1.1 kre exit 1' ||
68 1.1 kre {
69 1.1 kre test -z "$2" && atf_skip "${TEST_SH} has no '$1$5' built-in"
70 1.1 kre return 1;
71 1.1 kre }
72 1.1 kre
73 1.1 kre return 0
74 1.1 kre }
75 1.1 kre
76 1.5 kre # And another to test if the shell being tested is the NetBSD shell,
77 1.5 kre # as we use these tests both to test standards conformance (correctness)
78 1.5 kre # which should be possible for all shells, and to test NetBSD
79 1.5 kre # extensions (which we mostly do by testing if the extension exists)
80 1.5 kre # and NetBSD sh behaviour for what is unspecified by the standard
81 1.5 kre # (so we will be notified via test failure should that unspecified
82 1.5 kre # behaviour alter) for which we have to discover if that shell is the
83 1.5 kre # one being tested.
84 1.5 kre
85 1.5 kre is_netbsd_sh()
86 1.5 kre {
87 1.5 kre unset NETBSD_SHELL 2>/dev/null
88 1.5 kre test -n "$( ${TEST_SH} -c 'printf %s "${NETBSD_SHELL}"')"
89 1.5 kre }
90 1.5 kre
91 1.1 kre ### Helper functions
92 1.1 kre
93 1.1 kre nl='
94 1.1 kre '
95 1.1 kre reset()
96 1.1 kre {
97 1.1 kre TEST_NUM=0
98 1.1 kre TEST_FAILURES=''
99 1.1 kre TEST_FAIL_COUNT=0
100 1.1 kre TEST_ID="$1"
101 1.1 kre
102 1.1 kre # These are used in check()
103 1.1 kre atf_require_prog tr
104 1.1 kre atf_require_prog printf
105 1.1 kre atf_require_prog mktemp
106 1.1 kre }
107 1.1 kre
108 1.1 kre # Test run & validate.
109 1.1 kre #
110 1.1 kre # $1 is the command to run (via sh -c)
111 1.1 kre # $2 is the expected output
112 1.1 kre # $3 is the expected exit status from sh
113 1.1 kre # $4 is optional extra data for the error msg (if there is one)
114 1.1 kre #
115 1.1 kre # Stderr is exxpected to be empty, unless the expected exit code ($3) is != 0
116 1.1 kre # in which case some message there is expected (and nothing is a failure).
117 1.1 kre # When non-zero exit is expected, we note a different (non-zero) value
118 1.1 kre # observed, but do not fail the test because of that.
119 1.1 kre
120 1.1 kre check()
121 1.1 kre {
122 1.1 kre fail=false
123 1.1 kre TEMP_FILE=$( mktemp OUT.XXXXXX )
124 1.1 kre TEST_NUM=$(( $TEST_NUM + 1 ))
125 1.1 kre MSG=
126 1.1 kre
127 1.1 kre # our local shell (ATF_SHELL) better do quoting correctly...
128 1.1 kre # some of the tests expect us to expand $nl internally...
129 1.1 kre CMD="$1"
130 1.1 kre
131 1.1 kre # determine what the test generates, preserving trailing \n's
132 1.1 kre result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" && printf X )"
133 1.1 kre STATUS=$?
134 1.1 kre result="${result%X}"
135 1.1 kre
136 1.1 kre
137 1.1 kre if [ "${STATUS}" -ne "$3" ]; then
138 1.1 kre MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
139 1.1 kre MSG="${MSG} expected exit code $3, got ${STATUS}"
140 1.1 kre
141 1.1 kre # don't actually fail just because of wrong exit code
142 1.1 kre # unless we either expected, or received "good"
143 1.1 kre # or something else is detected as incorrect as well.
144 1.1 kre case "$3/${STATUS}" in
145 1.1 kre (*/0|0/*) fail=true;;
146 1.1 kre esac
147 1.1 kre fi
148 1.1 kre
149 1.1 kre if [ "$3" -eq 0 ]; then
150 1.1 kre if [ -s "${TEMP_FILE}" ]; then
151 1.1 kre MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
152 1.1 kre MSG="${MSG} Messages produced on stderr unexpected..."
153 1.1 kre MSG="${MSG}${nl}$( cat "${TEMP_FILE}" )"
154 1.1 kre fail=true
155 1.1 kre fi
156 1.1 kre else
157 1.1 kre if ! [ -s "${TEMP_FILE}" ]; then
158 1.1 kre MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
159 1.1 kre MSG="${MSG} Expected messages on stderr,"
160 1.1 kre MSG="${MSG} nothing produced"
161 1.1 kre fail=true
162 1.1 kre fi
163 1.1 kre fi
164 1.1 kre rm -f "${TEMP_FILE}"
165 1.1 kre
166 1.1 kre if [ "$2" != "${result}" ]
167 1.1 kre then
168 1.1 kre MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
169 1.1 kre MSG="${MSG} Expected: <<$2>>, received: <<$result>>"
170 1.1 kre fail=true
171 1.1 kre fi
172 1.1 kre
173 1.1 kre if $fail
174 1.1 kre then
175 1.1 kre if [ -n "$4" ]; then
176 1.1 kre MSG="${MSG}${MSG:+${nl}}[$TEST_NUM] Note: ${4}"
177 1.1 kre fi
178 1.1 kre MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
179 1.1 kre MSG="${MSG} Full command: <<${CMD}>>"
180 1.1 kre fi
181 1.1 kre
182 1.1 kre $fail && test -n "$TEST_ID" && {
183 1.1 kre TEST_FAILURES="${TEST_FAILURES}${TEST_FAILURES:+${nl}}"
184 1.1 kre TEST_FAILURES="${TEST_FAILURES}${TEST_ID}[$TEST_NUM]:"
185 1.1 kre TEST_FAILURES="${TEST_FAILURES} Test of <<$1>> failed.";
186 1.1 kre TEST_FAILURES="${TEST_FAILURES}${nl}${MSG}"
187 1.1 kre TEST_FAIL_COUNT=$(( $TEST_FAIL_COUNT + 1 ))
188 1.1 kre return 0
189 1.1 kre }
190 1.1 kre $fail && atf_fail "Test[$TEST_NUM] failed: $(
191 1.1 kre # ATF does not like newlines in messages, so change them...
192 1.1 kre printf '%s' "${MSG}" | tr '\n' ';'
193 1.1 kre )"
194 1.1 kre return 0
195 1.1 kre }
196 1.1 kre
197 1.1 kre results()
198 1.1 kre {
199 1.1 kre test -n "$1" && atf_expect_fail "$1"
200 1.1 kre
201 1.1 kre test -z "${TEST_ID}" && return 0
202 1.1 kre test -z "${TEST_FAILURES}" && return 0
203 1.1 kre
204 1.1 kre echo >&2 "=========================================="
205 1.1 kre echo >&2 "While testing '${TEST_ID}'"
206 1.1 kre echo >&2 " - - - - - - - - - - - - - - - - -"
207 1.1 kre echo >&2 "${TEST_FAILURES}"
208 1.1 kre
209 1.1 kre atf_fail \
210 1.1 kre "Test ${TEST_ID}: $TEST_FAIL_COUNT (of $TEST_NUM) subtests failed - see stderr"
211 1.1 kre }
212 1.1 kre
213 1.1 kre ####### End helpers
214 1.1 kre
215 1.1 kre atf_test_case colon
216 1.1 kre colon_head() {
217 1.1 kre atf_set "descr" "Tests the shell special builtin ':' command"
218 1.1 kre }
219 1.1 kre colon_body() {
220 1.1 kre have_builtin : || return 0
221 1.1 kre
222 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c ":"
223 1.1 kre
224 1.1 kre # ':' is a special builtin, so we should exit on redirect error
225 1.1 kre # and variable assignments should persist (stupid, but it is the rule)
226 1.1 kre
227 1.1 kre atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \
228 1.1 kre ": >/foo/bar; printf %s No-exit-BUG"
229 1.1 kre atf_check -s exit:0 -e empty -o inline:OK ${TEST_SH} -c \
230 1.1 kre 'X=BUG; X=OK : ; printf %s "${X}"'
231 1.1 kre }
232 1.1 kre
233 1.1 kre atf_test_case echo
234 1.1 kre echo_head() {
235 1.1 kre atf_set "descr" "Tests the shell builtin version of echo"
236 1.1 kre }
237 1.1 kre echo_body() {
238 1.1 kre have_builtin echo || return 0
239 1.1 kre
240 1.5 kre if ! is_netbsd_sh; then
241 1.1 kre atf_skip \
242 1.1 kre "${TEST_SH%% *} is not the NetBSD shell, this test is for it alone"
243 1.1 kre return 0
244 1.1 kre fi
245 1.1 kre
246 1.1 kre reset echo
247 1.1 kre
248 1.1 kre check 'echo "hello world"' "hello world${nl}" 0
249 1.1 kre check 'echo hello world' "hello world${nl}" 0
250 1.1 kre check 'echo -n "hello world"' "hello world" 0
251 1.1 kre check 'IFS=:; echo hello world' "hello world${nl}" 0
252 1.1 kre check 'IFS=; echo hello world' "hello world${nl}" 0
253 1.1 kre
254 1.1 kre check 'echo -e "hello world"' "hello world${nl}" 0
255 1.1 kre check 'echo -e hello world' "hello world${nl}" 0
256 1.1 kre check 'IFS=:; echo -e hello world' "hello world${nl}" 0
257 1.1 kre
258 1.1 kre # only one of the options is used
259 1.1 kre check 'echo -e -n "hello world"' "-n hello world${nl}" 0
260 1.1 kre check 'echo -n -e "hello world"' "-e hello world" 0
261 1.1 kre # and only when it is alone
262 1.1 kre check 'echo -en "hello world"' "-en hello world${nl}" 0
263 1.1 kre check 'echo -ne "hello world"' "-ne hello world${nl}" 0
264 1.1 kre
265 1.1 kre # echo is specifically required to *not* support --
266 1.1 kre check 'echo -- "hello world"' "-- hello world${nl}" 0
267 1.1 kre
268 1.1 kre # similarly any other unknown option is simply part of the output
269 1.1 kre for OPT in a b c v E N Q V 0 1 2 @ , \? \[ \] \( \; . \* -help -version
270 1.1 kre do
271 1.1 kre check "echo '-${OPT}' foo" "-${OPT} foo${nl}" 0
272 1.1 kre done
273 1.1 kre
274 1.1 kre # Now test the \\ expansions, with and without -e
275 1.1 kre
276 1.1 kre # We rely upon printf %b (tested elsewhere, not only a sh test)
277 1.1 kre # to verify the output when the \\ is supposed to be expanded.
278 1.1 kre
279 1.1 kre for E in '' -e
280 1.1 kre do
281 1.1 kre for B in a b c e f n r t v \\ 04 010 012 0177
282 1.1 kre do
283 1.1 kre S="test string with \\${B} in it"
284 1.1 kre if [ -z "${E}" ]; then
285 1.1 kre R="${S}${nl}"
286 1.1 kre else
287 1.1 kre R="$(printf '%b\nX' "${S}")"
288 1.1 kre R=${R%X}
289 1.1 kre fi
290 1.1 kre check "echo $E '${S}'" "${R}" 0
291 1.1 kre done
292 1.1 kre done
293 1.1 kre
294 1.1 kre results
295 1.1 kre }
296 1.1 kre
297 1.1 kre atf_test_case eval
298 1.1 kre eval_head() {
299 1.1 kre atf_set "descr" "Tests the shell special builtin 'eval'"
300 1.1 kre }
301 1.1 kre eval_body() {
302 1.1 kre have_builtin eval || return 0
303 1.1 kre
304 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'eval "exit 0"'
305 1.1 kre atf_check -s exit:1 -e empty -o empty ${TEST_SH} -c 'eval "exit 1"'
306 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'eval exit 0'
307 1.5 kre atf_check -s exit:1 -e empty -o empty ${TEST_SH} -c 'eval exit 1'
308 1.5 kre
309 1.5 kre atf_check -s exit:0 -e empty -o inline:0 ${TEST_SH} -c \
310 1.5 kre 'eval true; printf %d $?'
311 1.5 kre atf_check -s exit:0 -e empty -o inline:1 ${TEST_SH} -c \
312 1.5 kre 'eval false; printf %d $?'
313 1.1 kre
314 1.1 kre atf_check -s exit:0 -e empty -o inline:abc ${TEST_SH} -c \
315 1.1 kre 'X=a Y=b Z=c; for V in X Y Z; do eval "printf %s \$$V"; done'
316 1.1 kre atf_check -s exit:0 -e empty -o inline:abc ${TEST_SH} -c \
317 1.1 kre 'X=a Y=b Z=c; for V in X Y Z; do eval printf %s \$$V; done'
318 1.1 kre atf_check -s exit:0 -e empty -o inline:XYZ ${TEST_SH} -c \
319 1.1 kre 'for V in X Y Z; do eval "${V}=${V}"; done; printf %s "$X$Y$Z"'
320 1.5 kre
321 1.5 kre # make sure eval'd strings affect the shell environment
322 1.5 kre
323 1.5 kre atf_check -s exit:0 -e empty -o inline:/b/ ${TEST_SH} -c \
324 1.5 kre 'X=a; eval "X=b"; printf /%s/ "${X-unset}"'
325 1.5 kre atf_check -s exit:0 -e empty -o inline:/b/ ${TEST_SH} -c \
326 1.5 kre 'X=a; Y=X; Z=b; eval "$Y=$Z"; printf /%s/ "${X-unset}"'
327 1.5 kre atf_check -s exit:0 -e empty -o inline:/unset/ ${TEST_SH} -c \
328 1.5 kre 'X=a; eval "unset X"; printf /%s/ "${X-unset}"'
329 1.5 kre atf_check -s exit:0 -e empty -o inline:// ${TEST_SH} -c \
330 1.5 kre 'unset X; eval "X="; printf /%s/ "${X-unset}"'
331 1.5 kre atf_check -s exit:0 -e empty -o inline:'2 y Z ' ${TEST_SH} -c \
332 1.5 kre 'set -- X y Z; eval shift; printf "%s " "$#" "$@"'
333 1.5 kre
334 1.5 kre # ensure an error in an eval'd string causes the shell to exit
335 1.5 kre # unless 'eval' is preceded by 'command' (in which case the
336 1.5 kre # string is not eval'd but execution continues)
337 1.5 kre
338 1.5 kre atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \
339 1.5 kre 'eval "if done"; printf %s status=$?'
340 1.5 kre
341 1.5 kre atf_check -s exit:0 -e not-empty -o 'match:status=[1-9]' \
342 1.5 kre ${TEST_SH} -c \
343 1.5 kre 'command eval "if done"; printf %s status=$?'
344 1.5 kre
345 1.5 kre atf_check -s not-exit:0 -e not-empty \
346 1.5 kre -o 'match:status=[1-9]' -o 'not-match:[XY]' ${TEST_SH} -c \
347 1.5 kre 'command eval "printf X; if done; printf Y"
348 1.5 kre S=$?; printf %s status=$S; exit $S'
349 1.5 kre
350 1.5 kre # whether 'X' is output here is (or should be) unspecified.
351 1.5 kre atf_check -s not-exit:0 -e not-empty \
352 1.5 kre -o 'match:status=[1-9]' -o 'not-match:Y' ${TEST_SH} -c \
353 1.5 kre 'command eval "printf X
354 1.5 kre if done
355 1.5 kre printf Y"
356 1.5 kre S=$?; printf %s status=$S; exit $S'
357 1.5 kre
358 1.5 kre if is_netbsd_sh
359 1.5 kre then
360 1.5 kre # but on NetBSD we expect that X to appear...
361 1.5 kre atf_check -s not-exit:0 -e not-empty -o 'match:X' \
362 1.5 kre -o 'match:status=[1-9]' -o 'not-match:Y' ${TEST_SH} -c \
363 1.5 kre 'command eval "printf X
364 1.5 kre if done
365 1.5 kre printf Y"
366 1.5 kre S=$?; printf %s status=$S; exit $S'
367 1.5 kre fi
368 1.1 kre }
369 1.1 kre
370 1.1 kre atf_test_case exec
371 1.1 kre exec_head() {
372 1.1 kre atf_set "descr" "Tests the shell special builtin 'exec'"
373 1.1 kre }
374 1.1 kre exec_body() {
375 1.1 kre have_builtin exec || return 0
376 1.1 kre
377 1.1 kre atf_check -s exit:0 -e empty -o inline:OK ${TEST_SH} -c \
378 1.1 kre 'exec printf OK; printf BROKEN; exit 3'
379 1.1 kre atf_check -s exit:3 -e empty -o inline:OKOK ${TEST_SH} -c \
380 1.1 kre '(exec printf OK); printf OK; exit 3'
381 1.1 kre }
382 1.1 kre
383 1.1 kre atf_test_case export
384 1.1 kre export_head() {
385 1.1 kre atf_set "descr" "Tests the shell builtin 'export'"
386 1.1 kre }
387 1.1 kre export_body() {
388 1.1 kre have_builtin export || return 0
389 1.1 kre
390 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'export VAR'
391 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'export VAR=abc'
392 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'export V A R'
393 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
394 1.1 kre 'export V A=1 R=2'
395 1.1 kre
396 1.1 kre atf_require_prog printenv
397 1.1 kre
398 1.1 kre atf_check -s exit:1 -e empty -o empty ${TEST_SH} -c \
399 1.1 kre 'unset VAR || exit 7; export VAR; printenv VAR'
400 1.1 kre atf_check -s exit:0 -e empty -o inline:\\n ${TEST_SH} -c \
401 1.1 kre 'unset VAR || exit 7; export VAR=; printenv VAR'
402 1.1 kre atf_check -s exit:0 -e empty -o inline:\\n ${TEST_SH} -c \
403 1.1 kre 'unset VAR || exit 7; VAR=; export VAR; printenv VAR'
404 1.1 kre atf_check -s exit:0 -e empty -o inline:\\n ${TEST_SH} -c \
405 1.1 kre 'unset VAR || exit 7; export VAR; VAR=; printenv VAR'
406 1.1 kre atf_check -s exit:0 -e empty -o inline:XYZ\\n ${TEST_SH} -c \
407 1.1 kre 'unset VAR || exit 7; export VAR=XYZ; printenv VAR'
408 1.1 kre atf_check -s exit:0 -e empty -o inline:ABC\\n ${TEST_SH} -c \
409 1.1 kre 'VAR=ABC; export VAR; printenv VAR'
410 1.1 kre atf_check -s exit:0 -e empty -o inline:ABC\\n ${TEST_SH} -c \
411 1.1 kre 'unset VAR || exit 7; export VAR; VAR=ABC; printenv VAR'
412 1.1 kre atf_check -s exit:0 -e empty -o inline:ABC\\nXYZ\\n ${TEST_SH} -c \
413 1.1 kre 'VAR=ABC; export VAR; printenv VAR; VAR=XYZ; printenv VAR'
414 1.1 kre atf_check -s exit:0 -e empty -o inline:ABC\\nXYZ\\n ${TEST_SH} -c \
415 1.1 kre 'unset VAR || exit 7; export VAR;
416 1.1 kre VAR=ABC; printenv VAR; VAR=XYZ; printenv VAR'
417 1.1 kre
418 1.3 kre # don't check VAR=value, some shells provide meaningless quoting...
419 1.3 kre atf_check -s exit:0 -e empty -o match:VAR= -o match:foobar \
420 1.3 kre ${TEST_SH} -c \
421 1.3 kre 'VAR=foobar ; export VAR ; export -p'
422 1.3 kre atf_check -s exit:0 -e empty -o match:VAR= -o match:foobar \
423 1.3 kre ${TEST_SH} -c \
424 1.3 kre 'export VAR=foobar ; export -p'
425 1.3 kre atf_check -s exit:0 -e empty -o match:VAR\$ ${TEST_SH} -c \
426 1.3 kre 'unset VAR ; export VAR ; export -p'
427 1.3 kre atf_check -s exit:0 -e empty -o not-match:VAR ${TEST_SH} -c \
428 1.3 kre 'export VAR ; unset VAR ; export -p'
429 1.3 kre atf_check -s exit:0 -e empty -o not-match:VAR -o not-match:foobar \
430 1.3 kre ${TEST_SH} -c \
431 1.3 kre 'VAR=foobar; export VAR ; unset VAR ; export -p'
432 1.3 kre
433 1.3 kre atf_check -s exit:0 -e empty -o match:VAR= -o match:FOUND=foobar \
434 1.3 kre ${TEST_SH} -c \
435 1.3 kre 'export VAR=foobar; V=$(export -p);
436 1.3 kre unset VAR; eval "$V"; export -p;
437 1.3 kre printf %s\\n FOUND=${VAR-unset}'
438 1.3 kre atf_check -s exit:0 -e empty -o match:VAR -o match:FOUND=unset \
439 1.3 kre ${TEST_SH} -c \
440 1.3 kre 'export VAR; V=$(export -p);
441 1.3 kre unset VAR; eval "$V"; export -p;
442 1.3 kre printf %s\\n FOUND=${VAR-unset}'
443 1.3 kre
444 1.1 kre atf_check -s exit:1 -e empty -o inline:ABC\\nXYZ\\n ${TEST_SH} -c \
445 1.1 kre 'VAR=ABC; export VAR; printenv VAR; VAR=XYZ; printenv VAR;
446 1.1 kre unset VAR; printenv VAR; VAR=PQR; printenv VAR'
447 1.1 kre atf_check -s exit:0 -e empty -o inline:ABC\\nXYZ\\nVAR=unset\\nMNO\\n \
448 1.1 kre ${TEST_SH} -c \
449 1.1 kre 'VAR=ABC; export VAR; printenv VAR; VAR=XYZ; printenv VAR;
450 1.1 kre unset VAR; printf %s\\n "VAR=${VAR-unset}"; printenv VAR;
451 1.1 kre VAR=PQR; printenv VAR; VAR=MNO; export VAR; printenv VAR'
452 1.1 kre }
453 1.1 kre
454 1.1 kre atf_test_case export_nbsd
455 1.1 kre export_nbsd_head() {
456 1.1 kre atf_set "descr" "Tests NetBSD extensions to the shell builtin 'export'"
457 1.1 kre }
458 1.1 kre export_nbsd_body() {
459 1.1 kre have_builtin "export" "" "" "-n foo" ' -n' || return 0
460 1.1 kre
461 1.1 kre atf_require_prog printenv
462 1.1 kre
463 1.1 kre atf_check -s exit:1 -e empty -o inline:ABC\\nXYZ\\n ${TEST_SH} -c \
464 1.1 kre 'VAR=ABC; export VAR; printenv VAR; VAR=XYZ; printenv VAR;
465 1.1 kre export -n VAR; printenv VAR; VAR=PQR; printenv VAR'
466 1.1 kre
467 1.1 kre atf_check -s exit:0 -e empty -o inline:ABC\\nXYZ\\nVAR=XYZ\\nMNO\\n \
468 1.1 kre ${TEST_SH} -c \
469 1.1 kre 'VAR=ABC; export VAR; printenv VAR; VAR=XYZ; printenv VAR;
470 1.1 kre export -n VAR; printf %s\\n "VAR=${VAR-unset}"; printenv VAR;
471 1.1 kre VAR=PQR; printenv VAR; VAR=MNO; export VAR; printenv VAR'
472 1.1 kre
473 1.1 kre have_builtin "export" "" "" -x ' -x' || return 0
474 1.1 kre
475 1.1 kre atf_check -s exit:1 -e empty -o empty ${TEST_SH} -c \
476 1.1 kre 'export VAR=exported; export -x VAR; printenv VAR'
477 1.1 kre atf_check -s exit:1 -e empty -o empty ${TEST_SH} -c \
478 1.1 kre 'export VAR=exported; export -x VAR; VAR=local; printenv VAR'
479 1.1 kre atf_check -s exit:0 -e empty -o inline:once\\nx\\n ${TEST_SH} -c \
480 1.1 kre 'export VAR=exported
481 1.1 kre export -x VAR
482 1.1 kre VAR=once printenv VAR
483 1.1 kre printenv VAR || printf %s\\n x'
484 1.1 kre
485 1.1 kre atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \
486 1.1 kre 'export VAR=exported; export -x VAR; export VAR=FOO'
487 1.4 kre
488 1.4 kre have_builtin export '' 'export VAR;' '-q VAR' ' -q' || return 0
489 1.4 kre
490 1.4 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
491 1.4 kre 'unset VAR; VAR=set; export -q VAR'
492 1.4 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
493 1.4 kre 'export VAR=set; export -q VAR'
494 1.4 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
495 1.4 kre 'VAR=set; RW=set; export -q VAR RW'
496 1.4 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
497 1.4 kre 'VAR=set; export RO=set; export -q VAR RO'
498 1.4 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
499 1.4 kre 'export VAR=set RO=set; export -q VAR RO'
500 1.4 kre
501 1.4 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
502 1.4 kre 'unset VAR; export -q VAR'
503 1.4 kre # next one is the same as the have_builtin test, so "cannot" fail...
504 1.4 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
505 1.4 kre 'unset VAR; export VAR; export -q VAR'
506 1.4 kre
507 1.4 kre # if we have -q we should also have -p var...
508 1.4 kre # What's more, we are testing NetBSD sh, so we know output format.
509 1.4 kre
510 1.4 kre atf_check -s exit:0 -e empty -o match:VAR=foobar \
511 1.4 kre ${TEST_SH} -c \
512 1.4 kre 'VAR=foobar ; export VAR ; export -p VAR'
513 1.4 kre atf_check -s exit:0 -e empty -o inline:1 \
514 1.4 kre ${TEST_SH} -c \
515 1.4 kre 'VAR=foobar ; export VAR ;
516 1.4 kre printf %d $(export -p VAR | wc -l)'
517 1.4 kre atf_check -s exit:0 -e empty \
518 1.4 kre -o inline:'export VAR=foobar\nexport OTHER\n' \
519 1.4 kre ${TEST_SH} -c \
520 1.4 kre 'VAR=foobar; export VAR OTHER; export -p VAR OTHER'
521 1.4 kre atf_check -s exit:0 -e empty \
522 1.4 kre -o inline:'export A=aaa\nexport B\nexport D='"''"'\n' \
523 1.4 kre ${TEST_SH} -c \
524 1.4 kre 'A=aaa D= C=foo; unset B; export A B D;
525 1.4 kre export -p A B C D'
526 1.1 kre }
527 1.1 kre
528 1.1 kre atf_test_case getopts
529 1.1 kre getopts_head() {
530 1.1 kre atf_set "descr" "Tests the shell builtin 'getopts'"
531 1.1 kre }
532 1.1 kre getopts_body() {
533 1.1 kre have_builtin getopts "" "f() {" "a x; }; f -a" || return 0
534 1.1 kre }
535 1.1 kre
536 1.1 kre atf_test_case jobs
537 1.1 kre jobs_head() {
538 1.1 kre atf_set "descr" "Tests the shell builting 'jobs' command"
539 1.1 kre }
540 1.1 kre jobs_body() {
541 1.1 kre have_builtin jobs || return 0
542 1.1 kre
543 1.1 kre atf_require_prog sleep
544 1.1 kre
545 1.1 kre # note that POSIX requires that we reference $! otherwise
546 1.1 kre # the shell is not required to remember the process...
547 1.1 kre
548 1.1 kre atf_check -s exit:0 -e empty -o match:sleep -o match:Running \
549 1.1 kre ${TEST_SH} -c 'sleep 1 & P=$!; jobs; wait'
550 1.1 kre atf_check -s exit:0 -e empty -o match:sleep -o match:Done \
551 1.1 kre ${TEST_SH} -c 'sleep 1 & P=$!; sleep 2; jobs; wait'
552 1.1 kre }
553 1.1 kre
554 1.1 kre atf_test_case read
555 1.1 kre read_head() {
556 1.1 kre atf_set "descr" "Tests the shell builtin read command"
557 1.1 kre }
558 1.1 kre read_body() {
559 1.1 kre have_builtin read "" "echo x|" "var" || return 0
560 1.1 kre }
561 1.1 kre
562 1.1 kre atf_test_case readonly
563 1.1 kre readonly_head() {
564 1.1 kre atf_set "descr" "Tests the shell builtin 'readonly'"
565 1.1 kre }
566 1.1 kre readonly_body() {
567 1.1 kre have_builtin readonly || return 0
568 1.1 kre
569 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'readonly VAR'
570 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'readonly VAR=abc'
571 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'readonly V A R'
572 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c 'readonly V A=1 R=2'
573 1.1 kre
574 1.1 kre atf_check -s exit:0 -e empty -o inline:unset ${TEST_SH} -c \
575 1.1 kre 'unset VAR; readonly VAR; printf %s ${VAR-unset}'
576 1.1 kre atf_check -s exit:0 -e empty -o inline:set ${TEST_SH} -c \
577 1.1 kre 'unset VAR; readonly VAR=set; printf %s ${VAR-unset}'
578 1.3 kre atf_check -s exit:0 -e empty -o inline:set ${TEST_SH} -c \
579 1.3 kre 'VAR=initial; readonly VAR=set; printf %s ${VAR-unset}'
580 1.1 kre atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \
581 1.1 kre 'readonly VAR=initial; VAR=new; printf %s "${VAR}"'
582 1.1 kre
583 1.3 kre # don't check VAR=value, some shells provide meaningless quoting...
584 1.3 kre atf_check -s exit:0 -e empty -o match:VAR= -o match:foobar \
585 1.3 kre ${TEST_SH} -c \
586 1.3 kre 'VAR=foobar ; readonly VAR ; readonly -p'
587 1.3 kre atf_check -s exit:0 -e empty -o match:VAR= -o match:foobar \
588 1.3 kre ${TEST_SH} -c \
589 1.3 kre 'readonly VAR=foobar ; readonly -p'
590 1.3 kre atf_check -s exit:0 -e empty -o match:VAR= -o match:foobar \
591 1.3 kre -o not-match:badvalue ${TEST_SH} -c \
592 1.3 kre 'VAR=badvalue; readonly VAR=foobar ; readonly -p'
593 1.3 kre atf_check -s exit:0 -e empty -o match:VAR\$ ${TEST_SH} -c \
594 1.3 kre 'unset VAR ; readonly VAR ; readonly -p'
595 1.3 kre
596 1.3 kre # checking that readonly -p works (to reset stuff) is a pain...
597 1.3 kre # particularly since not all shells say "readonly..." by default
598 1.3 kre atf_check -s exit:0 -e empty -o match:MYVAR= -o match:FOUND=foobar \
599 1.3 kre ${TEST_SH} -c \
600 1.3 kre 'V=$(readonly MYVAR=foobar; readonly -p | grep " MYVAR")
601 1.3 kre unset MYVAR; eval "$V"; readonly -p;
602 1.3 kre printf %s\\n FOUND=${MYVAR-unset}'
603 1.3 kre atf_check -s exit:0 -e empty -o match:MYVAR\$ -o match:FOUND=unset \
604 1.3 kre ${TEST_SH} -c \
605 1.3 kre 'V=$(readonly MYVAR; readonly -p | grep " MYVAR")
606 1.3 kre unset MYVAR; eval "$V"; readonly -p;
607 1.3 kre printf %s\\n "FOUND=${MYVAR-unset}"'
608 1.3 kre atf_check -s exit:0 -e empty -o match:MYVAR= -o match:FOUND=empty \
609 1.3 kre ${TEST_SH} -c \
610 1.3 kre 'V=$(readonly MYVAR=; readonly -p | grep " MYVAR")
611 1.3 kre unset VAR; eval "$V"; readonly -p;
612 1.3 kre printf %s\\n "FOUND=${MYVAR-unset&}${MYVAR:-empty}"'
613 1.3 kre
614 1.1 kre # don't test stderr, some shells inist on generating a message for an
615 1.1 kre # unset of a readonly var (rather than simply having unset make $?=1)
616 1.1 kre
617 1.1 kre atf_check -s not-exit:0 -e empty -o empty ${TEST_SH} -c \
618 1.1 kre 'unset VAR; readonly VAR=set;
619 1.1 kre unset VAR 2>/dev/null && printf %s ${VAR:-XX}'
620 1.1 kre atf_check -s not-exit:0 -e ignore -o empty ${TEST_SH} -c \
621 1.1 kre 'unset VAR; readonly VAR=set; unset VAR && printf %s ${VAR:-XX}'
622 1.1 kre atf_check -s exit:0 -e ignore -o inline:set ${TEST_SH} -c \
623 1.1 kre 'unset VAR; readonly VAR=set; unset VAR; printf %s ${VAR-unset}'
624 1.1 kre }
625 1.1 kre
626 1.4 kre atf_test_case readonly_nbsd
627 1.4 kre readonly_nbsd_head() {
628 1.4 kre atf_set "descr" "Tests NetBSD extensions to 'readonly'"
629 1.4 kre }
630 1.4 kre readonly_nbsd_body() {
631 1.4 kre have_builtin readonly '' 'readonly VAR;' '-q VAR' ' -q' || return 0
632 1.4 kre
633 1.4 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
634 1.4 kre 'VAR=set; readonly -q VAR'
635 1.4 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
636 1.4 kre 'readonly VAR=set; readonly -q VAR'
637 1.4 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
638 1.4 kre 'VAR=set; RW=set; readonly -q VAR RW'
639 1.4 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
640 1.4 kre 'VAR=set; readonly RO=set; readonly -q VAR RO'
641 1.4 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
642 1.4 kre 'readonly VAR=set RO=set; readonly -q VAR RO'
643 1.4 kre
644 1.4 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
645 1.4 kre 'unset VAR; readonly -q VAR'
646 1.4 kre # next one is the same as the have_builtin test, so "cannot" fail...
647 1.4 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
648 1.4 kre 'unset VAR; readonly VAR; readonly -q VAR'
649 1.4 kre
650 1.4 kre # if we have -q we should also have -p var...
651 1.4 kre # What's more, we are testing NetBSD sh, so we know output format.
652 1.4 kre
653 1.4 kre atf_check -s exit:0 -e empty -o match:VAR=foobar \
654 1.4 kre ${TEST_SH} -c \
655 1.4 kre 'VAR=foobar ; readonly VAR ; readonly -p VAR'
656 1.4 kre atf_check -s exit:0 -e empty -o inline:1 \
657 1.4 kre ${TEST_SH} -c \
658 1.4 kre 'VAR=foobar ; readonly VAR ;
659 1.4 kre printf %d $(readonly -p VAR | wc -l)'
660 1.4 kre atf_check -s exit:0 -e empty \
661 1.4 kre -o inline:'readonly VAR=foobar\nreadonly OTHER\n' \
662 1.4 kre ${TEST_SH} -c \
663 1.4 kre 'VAR=foobar; readonly VAR OTHER; readonly -p VAR OTHER'
664 1.4 kre atf_check -s exit:0 -e empty \
665 1.4 kre -o inline:'readonly A=aaa\nreadonly B\nreadonly D='"''"'\n' \
666 1.4 kre ${TEST_SH} -c \
667 1.4 kre 'A=aaa D= C=foo; unset B; readonly A B D;
668 1.4 kre readonly -p A B C D'
669 1.4 kre }
670 1.4 kre
671 1.1 kre atf_test_case cd_pwd
672 1.1 kre cd_pwd_head() {
673 1.1 kre atf_set "descr" "Tests the shell builtins 'cd' & 'pwd'"
674 1.1 kre }
675 1.1 kre cd_pwd_body() {
676 1.1 kre have_builtin cd "" "HOME=/;" || return 0
677 1.1 kre have_builtin pwd || return 0
678 1.1 kre }
679 1.1 kre
680 1.1 kre atf_test_case true_false
681 1.1 kre true_false_head() {
682 1.1 kre atf_set "descr" "Tests the 'true' and 'false' shell builtin commands"
683 1.1 kre }
684 1.1 kre true_false_body() {
685 1.1 kre have_builtin true || return 0
686 1.1 kre
687 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c true
688 1.1 kre
689 1.1 kre # true is not a special builtin, so errors do not cause exit
690 1.1 kre # but we should still get an error from the broken redirect
691 1.1 kre # and the exit status of true should be false...
692 1.1 kre
693 1.1 kre atf_check -s exit:0 -e not-empty -o inline:OK ${TEST_SH} -c \
694 1.1 kre "true >/foo/bar && printf %s NOT-; printf %s OK"
695 1.1 kre
696 1.1 kre # and var-assigns should not affect the current sh env
697 1.1 kre
698 1.1 kre atf_check -s exit:0 -e empty -o inline:IS-OK ${TEST_SH} -c \
699 1.1 kre 'X=OK; X=BROKEN true && printf %s IS-; printf %s "${X}"'
700 1.1 kre
701 1.1 kre have_builtin false "" ! || return 0
702 1.1 kre
703 1.1 kre atf_check -s exit:1 -e empty -o empty ${TEST_SH} -c false
704 1.1 kre }
705 1.1 kre
706 1.1 kre atf_test_case type
707 1.1 kre type_head() {
708 1.1 kre atf_set "descr" "Tests the sh builtin 'type' command"
709 1.1 kre }
710 1.1 kre type_body() {
711 1.1 kre have_builtin type "" "" type || return 0
712 1.1 kre }
713 1.1 kre
714 1.1 kre # This currently has its own t_ulimit - either merge that here,
715 1.1 kre # or delete this one and keep that... ulimit -n is also tested in
716 1.1 kre # the t_redir tests, as that affects the shell's use of file descriptors
717 1.1 kre atf_test_case ulimit
718 1.1 kre ulimit_head() {
719 1.1 kre atf_set "descr" "Tests the sh builtin 'ulimit'"
720 1.1 kre }
721 1.1 kre ulimit_body() {
722 1.1 kre have_builtin ulimit || return 0
723 1.1 kre }
724 1.1 kre
725 1.1 kre atf_test_case umask
726 1.1 kre umask_head() {
727 1.1 kre atf_set "descr" "Tests the sh builtin 'umask'"
728 1.1 kre }
729 1.1 kre umask_body() {
730 1.1 kre have_builtin umask || return 0
731 1.1 kre
732 1.1 kre atf_require_prog touch
733 1.1 kre atf_require_prog stat
734 1.1 kre atf_require_prog rm
735 1.1 kre atf_require_prog chmod
736 1.1 kre
737 1.1 kre reset umask
738 1.1 kre
739 1.1 kre # 8 octal digits
740 1.1 kre for M in 0 1 2 3 4 5 6 7
741 1.1 kre do
742 1.1 kre # Test numbers start: 1 25 49 73 97 121 145 169
743 1.1 kre
744 1.1 kre # 8 combinations of each to test (64 inner loops)
745 1.1 kre # 3 tests in each loop, hence 192 subtests in all
746 1.1 kre
747 1.1 kre # Test numbers from loop above, plus (below) and the next 2
748 1.1 kre #+ 1 4 7 10 13
749 1.1 kre for T in "0${M}" "00${M}" "0${M}0" "0${M}00" "0${M}${M}" \
750 1.1 kre "0${M}${M}0" "0${M}${M}${M}" "0${M}0${M}"
751 1.1 kre #+ 16 19 22
752 1.1 kre do
753 1.1 kre # umask turns bits off, calculate which bits will be on...
754 1.1 kre
755 1.1 kre D=$(( 0777 & ~ T )) # for directories
756 1.1 kre F=$(( $D & ~ 0111 )) # and files with no 'x' bits
757 1.1 kre
758 1.1 kre # Note: $(( )) always produces decimal, so we test that format
759 1.1 kre # (see '%d' in printf of stat result)
760 1.1 kre
761 1.1 kre # need chmod or we might have no perm to rmdir TD
762 1.1 kre { chmod +rwx TF TFT TD; rm -fr TF TFT TD; } 2>/dev/null || :
763 1.1 kre
764 1.1 kre # check that the umask applies to files created by the shell
765 1.1 kre check \
766 1.1 kre "umask $T; > TF; printf %d \$(stat -nf %#Lp TF)" \
767 1.1 kre "$F" 0 "$F is $(printf %#o $F)" # 1 4 7 10 ...
768 1.1 kre
769 1.1 kre # and to files created by commands that the shell runs
770 1.1 kre check \
771 1.1 kre "umask $T; touch TFT; printf %d \$(stat -nf %#Lp TFT)" \
772 1.1 kre "$F" 0 "$F is $(printf %#o $F)" # 2 5 8 11 ...
773 1.1 kre
774 1.1 kre # and to directories created b ... (directories keep 'x')
775 1.1 kre check \
776 1.1 kre "umask $T; mkdir TD; printf %d \$(stat -nf %#Lp TD)" \
777 1.1 kre "$D" 0 "$D is $(printf %#o $D)" # 3 6 9 12 ...
778 1.1 kre done
779 1.1 kre done
780 1.1 kre
781 1.1 kre # Now add a few more tests with less regular u/g/m masks
782 1.1 kre # In here, include tests where umask value has no leading '0'
783 1.1 kre
784 1.1 kre # 10 loops, the same 3 tests in each loop, 30 more subtests
785 1.1 kre # from 193 .. 222
786 1.1 kre
787 1.1 kre # 193 196 199 202 205 208 211 214 217 220
788 1.1 kre for T in 013 047 722 0772 027 123 421 0124 0513 067
789 1.1 kre do
790 1.1 kre D=$(( 0777 & ~ 0$T ))
791 1.1 kre F=$(( $D & ~ 0111 ))
792 1.1 kre
793 1.1 kre { chmod +rwx TF TFT TD; rm -fr TF TFT TD; } 2>/dev/null || :
794 1.1 kre
795 1.1 kre check \
796 1.1 kre "umask $T; > TF; printf %d \$(stat -nf %#Lp TF)" \
797 1.1 kre "$F" 0 "$F is $(printf %#o $F)" # +0
798 1.1 kre
799 1.1 kre check \
800 1.1 kre "umask $T; touch TFT; printf %d \$(stat -nf %#Lp TFT)" \
801 1.1 kre "$F" 0 "$F is $(printf %#o $F)" # +1
802 1.1 kre
803 1.1 kre check \
804 1.1 kre "umask $T; mkdir TD; printf %d \$(stat -nf %#Lp TD)" \
805 1.1 kre "$D" 0 "$D is $(printf %#o $D)" # +2
806 1.1 kre done
807 1.1 kre
808 1.1 kre results
809 1.1 kre }
810 1.1 kre
811 1.1 kre atf_test_case unset
812 1.1 kre unset_head() {
813 1.1 kre atf_set "descr" "Tests the sh builtin 'unset'"
814 1.1 kre }
815 1.1 kre unset_body() {
816 1.1 kre have_builtin unset || return 0
817 1.1 kre }
818 1.1 kre
819 1.1 kre atf_test_case hash
820 1.1 kre hash_head() {
821 1.1 kre atf_set "descr" "Tests the sh builtin 'hash' (ash extension)"
822 1.1 kre }
823 1.1 kre hash_body() {
824 1.1 kre have_builtin hash || return 0
825 1.1 kre }
826 1.1 kre
827 1.1 kre atf_test_case jobid
828 1.1 kre jobid_head() {
829 1.1 kre atf_set "descr" "Tests sh builtin 'jobid' (NetBSD extension)"
830 1.1 kre }
831 1.1 kre jobid_body() {
832 1.1 kre
833 1.1 kre # have_builtin jobid || return 0 No simple jobid command test
834 1.1 kre $TEST_SH -c '(exit 0)& jobid $!' >/dev/null 2>&1 || {
835 1.1 kre atf_skip "${TEST_SH} has no 'jobid' built-in"
836 1.1 kre return 0
837 1.1 kre }
838 1.1 kre }
839 1.1 kre
840 1.1 kre atf_test_case let
841 1.1 kre let_head() {
842 1.1 kre atf_set "descr" "Tests the sh builtin 'let' (common extension from ksh)"
843 1.1 kre }
844 1.1 kre let_body() {
845 1.1 kre have_builtin let "" "" 1 || return 0
846 1.1 kre }
847 1.1 kre
848 1.1 kre atf_test_case local
849 1.1 kre local_head() {
850 1.1 kre atf_set "descr" "Tests the shell builtin 'local' (common extension)"
851 1.1 kre }
852 1.1 kre local_body() {
853 1.1 kre have_builtin local "" "f () {" "X; }; f" || return 0
854 1.1 kre }
855 1.1 kre
856 1.1 kre atf_test_case setvar
857 1.1 kre setvar_head() {
858 1.1 kre atf_set "descr" "Tests the shell builtin 'setvar' (BSD extension)"
859 1.1 kre }
860 1.1 kre setvar_body() {
861 1.1 kre have_builtin setvar || return 0
862 1.1 kre
863 1.1 kre atf_check -s exit:0 -e empty -o inline:foo ${TEST_SH} -c \
864 1.1 kre 'unset PQ && setvar PQ foo; printf %s "${PQ-not set}"'
865 1.1 kre atf_check -s exit:0 -e empty -o inline:abcd ${TEST_SH} -c \
866 1.1 kre 'for x in a b c d; do setvar "$x" "$x"; done;
867 1.1 kre printf %s "$a$b$c$d"'
868 1.1 kre atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
869 1.1 kre 'a=1; b=2; c=3; d=4
870 1.1 kre for x in a b c d; do setvar "$x" ""; done;
871 1.1 kre printf %s "$a$b$c$d"'
872 1.1 kre }
873 1.1 kre
874 1.1 kre atf_test_case fdflags
875 1.1 kre fdflags_head() {
876 1.1 kre atf_set "descr" \
877 1.1 kre "Tests basic operation of sh builtin 'fdflags' (NetBSD extension)"
878 1.1 kre }
879 1.1 kre fdflags_body() {
880 1.1 kre have_builtin fdflags || return 0
881 1.1 kre }
882 1.1 kre
883 1.1 kre atf_test_case fdflags__s
884 1.1 kre fdflags__s_head() {
885 1.1 kre atf_set "descr" "Checks setting/clearing flags on file descriptors"
886 1.1 kre }
887 1.1 kre fdflags__s_body() {
888 1.1 kre have_builtin fdflags || return 0
889 1.1 kre }
890 1.1 kre
891 1.1 kre atf_test_case fdflags__v
892 1.1 kre fdflags__v_head() {
893 1.1 kre atf_set "descr" "Checks verbose operation of fdflags"
894 1.1 kre }
895 1.1 kre fdflags__v_body() {
896 1.1 kre have_builtin fdflags || return 0
897 1.1 kre }
898 1.1 kre
899 1.1 kre atf_test_case fdflags__v_s
900 1.1 kre fdflags__v_s_head() {
901 1.1 kre atf_set "descr" "tests verbose operation of fdflags -s"
902 1.1 kre }
903 1.1 kre fdflags__v_s_body() {
904 1.1 kre have_builtin fdflags || return 0
905 1.1 kre }
906 1.1 kre
907 1.1 kre atf_test_case fdflags_multiple_fd
908 1.1 kre fdflags_multiple_fd_head() {
909 1.1 kre atf_set "descr" "Checks operation of fdflags with more than one fd"
910 1.1 kre }
911 1.1 kre fdflags_multiple_fd_body() {
912 1.1 kre have_builtin fdflags || return 0
913 1.1 kre }
914 1.1 kre
915 1.1 kre atf_test_case fdflags_one_flag_at_a_time
916 1.1 kre fdflags_one_flag_at_a_time_head() {
917 1.1 kre atf_set "descr" "Tests all possible fdflags flags, and combinations"
918 1.1 kre }
919 1.1 kre fdflags_one_flag_at_a_time_body() {
920 1.1 kre have_builtin fdflags || return 0
921 1.1 kre }
922 1.1 kre
923 1.1 kre atf_test_case fdflags_save_restore
924 1.1 kre fdflags_save_restore_head() {
925 1.1 kre atf_set "descr" 'Verify that fd flags can be saved and restored'
926 1.1 kre }
927 1.1 kre fdflags_save_restore_body() {
928 1.1 kre have_builtin fdflags || return 0
929 1.1 kre }
930 1.1 kre
931 1.1 kre atf_test_case fdflags_names_abbreviated
932 1.1 kre fdflags_names_abbreviated_head() {
933 1.1 kre atf_set "descr" 'Tests using abbreviated names for fdflags'
934 1.1 kre }
935 1.1 kre fdflags_names_abbreviated_body() {
936 1.1 kre have_builtin fdflags || return 0
937 1.1 kre }
938 1.1 kre
939 1.1 kre atf_test_case fdflags_xx_errors
940 1.1 kre fdflags_xx_errors_head() {
941 1.1 kre atf_set "descr" 'Check various erroneous fdflags uses'
942 1.1 kre }
943 1.1 kre fdflags_xx_errors_body() {
944 1.1 kre have_builtin fdflags || return 0
945 1.1 kre }
946 1.1 kre
947 1.1 kre
948 1.1 kre atf_init_test_cases() {
949 1.1 kre
950 1.1 kre # "standard" builtin commands in sh
951 1.1 kre
952 1.1 kre # no tests of the "very special" (almost syntax) builtins
953 1.1 kre # (break/continue/return) - they're tested enough elsewhere
954 1.1 kre
955 1.1 kre atf_add_test_case cd_pwd
956 1.1 kre atf_add_test_case colon
957 1.1 kre atf_add_test_case echo
958 1.1 kre atf_add_test_case eval
959 1.1 kre atf_add_test_case exec
960 1.1 kre atf_add_test_case export
961 1.1 kre atf_add_test_case getopts
962 1.1 kre atf_add_test_case jobs
963 1.1 kre atf_add_test_case read
964 1.1 kre atf_add_test_case readonly
965 1.1 kre atf_add_test_case true_false
966 1.1 kre atf_add_test_case type
967 1.1 kre atf_add_test_case ulimit
968 1.1 kre atf_add_test_case umask
969 1.1 kre atf_add_test_case unset
970 1.1 kre
971 1.1 kre # exit/wait/set/shift/trap/alias/unalias/. should have their own tests
972 1.1 kre # fc/times/fg/bg/% are too messy to contemplate for now
973 1.1 kre # command ?? (probably should have some tests)
974 1.1 kre
975 1.1 kre # Note that builtin versions of, printf, kill, ... are tested separately
976 1.1 kre # (these are all "optional" builtins)
977 1.1 kre # (echo is tested here because NetBSD sh builtin echo and /bin/echo
978 1.1 kre # are different)
979 1.1 kre
980 1.1 kre atf_add_test_case export_nbsd
981 1.1 kre atf_add_test_case hash
982 1.1 kre atf_add_test_case jobid
983 1.1 kre atf_add_test_case let
984 1.1 kre atf_add_test_case local
985 1.4 kre atf_add_test_case readonly_nbsd
986 1.1 kre atf_add_test_case setvar
987 1.1 kre # inputrc should probably be tested in libedit tests (somehow)
988 1.1 kre
989 1.1 kre # fdflags has a bunch of test cases
990 1.1 kre
991 1.1 kre # Always run one test, so we get at least "skipped" result
992 1.1 kre atf_add_test_case fdflags
993 1.1 kre
994 1.1 kre # but no need to say "skipped" lots more times...
995 1.1 kre have_builtin fdflags available && {
996 1.1 kre atf_add_test_case fdflags__s
997 1.1 kre atf_add_test_case fdflags__v
998 1.1 kre atf_add_test_case fdflags__v_s
999 1.1 kre atf_add_test_case fdflags_multiple_fd
1000 1.1 kre atf_add_test_case fdflags_names_abbreviated
1001 1.1 kre atf_add_test_case fdflags_one_flag_at_a_time
1002 1.1 kre atf_add_test_case fdflags_save_restore
1003 1.1 kre atf_add_test_case fdflags_xx_errors
1004 1.1 kre }
1005 1.1 kre return 0
1006 1.1 kre }
1007