xref: /netbsd-src/tests/bin/sh/t_shift.sh (revision 2f76de8b9e6d8b5620c5a246613458e2e4bca96f)
1*2f76de8bSkre# $NetBSD: t_shift.sh,v 1.3 2024/09/21 20:48:50 kre Exp $
2e4619cdfSchristos#
3e4619cdfSchristos# Copyright (c) 2016 The NetBSD Foundation, Inc.
4e4619cdfSchristos# All rights reserved.
5e4619cdfSchristos#
6e4619cdfSchristos# Redistribution and use in source and binary forms, with or without
7e4619cdfSchristos# modification, are permitted provided that the following conditions
8e4619cdfSchristos# are met:
9e4619cdfSchristos# 1. Redistributions of source code must retain the above copyright
10e4619cdfSchristos#    notice, this list of conditions and the following disclaimer.
11e4619cdfSchristos# 2. Redistributions in binary form must reproduce the above copyright
12e4619cdfSchristos#    notice, this list of conditions and the following disclaimer in the
13e4619cdfSchristos#    documentation and/or other materials provided with the distribution.
14e4619cdfSchristos#
15e4619cdfSchristos# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16e4619cdfSchristos# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17e4619cdfSchristos# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18e4619cdfSchristos# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19e4619cdfSchristos# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20e4619cdfSchristos# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21e4619cdfSchristos# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22e4619cdfSchristos# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23e4619cdfSchristos# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24e4619cdfSchristos# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25e4619cdfSchristos# POSSIBILITY OF SUCH DAMAGE.
26e4619cdfSchristos#
27e4619cdfSchristos# the implementation of "sh" to test
28e4619cdfSchristos: ${TEST_SH:="/bin/sh"}
29e4619cdfSchristos
30e4619cdfSchristosatf_test_case basic_shift_test
31e4619cdfSchristosbasic_shift_test_head() {
32e4619cdfSchristos	atf_set "descr" "Test correct operation of valid shifts"
33e4619cdfSchristos}
34e4619cdfSchristosbasic_shift_test_body() {
35e4619cdfSchristos
36e4619cdfSchristos	for a in			\
37e4619cdfSchristos	  "one-arg::0:one-arg"		\
38*2f76de8bSkre	  "one-arg:--:0:one-arg"	\
39e4619cdfSchristos	  "one-arg:1:0:one-arg"		\
40*2f76de8bSkre	  "one-arg:-- 1:0:one-arg"	\
41*2f76de8bSkre	  "one-arg:-- 0:1 one-arg"	\
42e4619cdfSchristos	  "a b c::2 b c:a"		\
43e4619cdfSchristos	  "a b c:1:2 b c:a"		\
44e4619cdfSchristos	  "a b c:2:1 c:a:b"		\
45e4619cdfSchristos	  "a b c:3:0:a:b:c"		\
46e4619cdfSchristos	  "a b c:0:3 a b c"		\
47e4619cdfSchristos	  "a b c d e f g h i j k l m n o p:1:15 b c d e f g h i j k l m n o p"\
48e4619cdfSchristos	  "a b c d e f g h i j k l m n o p:9:7 j k l m n o p:a:b:c:g:h:i"     \
49e4619cdfSchristos	  "a b c d e f g h i j k l m n o p:13:3 n o p:a:b:c:d:k:l:m"	      \
50e4619cdfSchristos	  "a b c d e f g h i j k l m n o p:16:0:a:b:c:d:e:f:g:h:i:j:k:l:m:n:o:p"
51e4619cdfSchristos	do
52e4619cdfSchristos		oIFS="${IFS}"
53e4619cdfSchristos		IFS=:; set -- $a
54e4619cdfSchristos		IFS="${oIFS}"
55e4619cdfSchristos
56e4619cdfSchristos		init="$1"; n="$2"; res="$3"; shift 3
57e4619cdfSchristos
58e4619cdfSchristos		not=
59e4619cdfSchristos		for b
60e4619cdfSchristos		do
61e4619cdfSchristos			not="${not} -o not-match:$b"
62e4619cdfSchristos		done
63e4619cdfSchristos
64e4619cdfSchristos		atf_check -s exit:0 -o "match:${res}" ${not} -e empty \
65e4619cdfSchristos			${TEST_SH} -c "set -- ${init}; shift $n;"' echo "$# $*"'
66e4619cdfSchristos	done
67e4619cdfSchristos
68e4619cdfSchristos	atf_check -s exit:0 -o match:complete -o not-match:ERR -e empty \
69e4619cdfSchristos		${TEST_SH} -c \
70e4619cdfSchristos    'set -- a b c d e;while [ $# -gt 0 ];do shift||echo ERR;done;echo complete'
71e4619cdfSchristos}
72e4619cdfSchristos
73*2f76de8bSkreatf_test_case basic_rotate
74*2f76de8bSkrebasic_rotate_head() {
75*2f76de8bSkre	atf_set "descr" "Test correct operation of valid rotates"
76*2f76de8bSkre}
77*2f76de8bSkrebasic_rotate_body() {
78*2f76de8bSkre
79*2f76de8bSkre	for a in			\
80*2f76de8bSkre	  "one-arg:-0:1 one-arg"	\
81*2f76de8bSkre	  "one-arg:-1:1 one-arg"	\
82*2f76de8bSkre	  "one-arg:-- -1:1 one-arg"	\
83*2f76de8bSkre	  "a b c:-1:3 c a b"		\
84*2f76de8bSkre	  "a b c:-2:3 b c a"		\
85*2f76de8bSkre	  "a b c:-3:3 a b c"		\
86*2f76de8bSkre	  "a b c:-- -3:3 a b c"		\
87*2f76de8bSkre	  "a b c:-0:3 a b c"		\
88*2f76de8bSkre	  "a b c d e f g h i j k l m n o:-1:15 o a b c d e f g h i j k l m n" \
89*2f76de8bSkre	  "a b c d e f g h i j k l m n o:-2:15 n o a b c d e f g h i j k l m" \
90*2f76de8bSkre	  "a b c d e f g h i j k l m n o:-9:15 g h i j k l m n o a b c d e f" \
91*2f76de8bSkre	  "a b c d e f g h i j k l m n o:-13:15 c d e f g h i j k l m n o a b" \
92*2f76de8bSkre	  "a b c d e f g h i j k l m n o:-14:15 b c d e f g h i j k l m n o a" \
93*2f76de8bSkre	  "a b c d e f g h i j k l m n o:-15:15 a b c d e f g h i j k l m n o"
94*2f76de8bSkre	do
95*2f76de8bSkre		oIFS="${IFS}"
96*2f76de8bSkre		IFS=:; set -- $a
97*2f76de8bSkre		IFS="${oIFS}"
98*2f76de8bSkre
99*2f76de8bSkre		init="$1"; n="$2"; res="$3"; shift 3
100*2f76de8bSkre
101*2f76de8bSkre		atf_check -s exit:0 -o "match:${res}" -e empty \
102*2f76de8bSkre			${TEST_SH} -c "set -- ${init}; shift $n;"' echo "$# $*"'
103*2f76de8bSkre	done
104*2f76de8bSkre}
105*2f76de8bSkre
106e4619cdfSchristosatf_test_case excessive_shift
107e4619cdfSchristosexcessive_shift_head() {
108e4619cdfSchristos	atf_set "descr" "Test acceptable operation of shift too many"
109e4619cdfSchristos}
110e4619cdfSchristos# In:
111e4619cdfSchristos#
112e4619cdfSchristos#	http://pubs.opengroup.org/onlinepubs/9699919799
113e4619cdfSchristos#		/utilities/V3_chap02.html#tag_18_26_01
114e4619cdfSchristos#
115e4619cdfSchristos# (that URL should be one line, with the /util... immediately after ...9799)
116e4619cdfSchristos#
117e4619cdfSchristos# POSIX says of shift (in the "EXIT STATUS" paragraph):
118e4619cdfSchristos#
119e4619cdfSchristos#  If the n operand is invalid or is greater than "$#", this may be considered
120e4619cdfSchristos#  a syntax error and a non-interactive shell may exit; if the shell does not
121e4619cdfSchristos#  exit in this case, a non-zero exit status shall be returned.
122e4619cdfSchristos#  Otherwise, zero shall be returned.
123e4619cdfSchristos#
124e4619cdfSchristos# NetBSD's sh treats it as an error and exits (if non-interactive, as here),
125e4619cdfSchristos# other shells do not.
126e4619cdfSchristos#
127e4619cdfSchristos# Either behaviour is acceptable - so the test allows for both
128e4619cdfSchristos# (and checks that if the shell does not exit, "shift" returns status != 0)
129e4619cdfSchristos
130e4619cdfSchristosexcessive_shift_body() {
131e4619cdfSchristos	for a in				\
132e4619cdfSchristos		"one-arg:2"			\
133e4619cdfSchristos		"one-arg:4"			\
134e4619cdfSchristos		"one-arg:13"			\
135e4619cdfSchristos		"one two:3"			\
136e4619cdfSchristos		"one two:7"			\
137e4619cdfSchristos		"one two three four five:6"	\
138e4619cdfSchristos		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:16"	\
139e4619cdfSchristos		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:17"	\
140e4619cdfSchristos		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:30"	\
141e4619cdfSchristos		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:9999"
142e4619cdfSchristos	do
143e4619cdfSchristos		oIFS="${IFS}"
144e4619cdfSchristos		IFS=:; set -- $a
145e4619cdfSchristos		IFS="${oIFS}"
146e4619cdfSchristos
147e4619cdfSchristos		atf_check -s not-exit:0 -o match:OK -o not-match:ERR \
148e4619cdfSchristos			-e ignore ${TEST_SH} -c \
149e4619cdfSchristos			"set -- $1 ;"'echo OK:$#-'"$2;shift $2 && echo ERR"
150e4619cdfSchristos	done
151e4619cdfSchristos}
152e4619cdfSchristos
153*2f76de8bSkreatf_test_case excessive_rotate
154*2f76de8bSkreexcessive_rotate_head() {
155*2f76de8bSkre	atf_set "descr" "Test acceptable operation of rotate too many"
156*2f76de8bSkre}
157*2f76de8bSkre
158*2f76de8bSkreexcessive_rotate_body() {
159*2f76de8bSkre	for a in				\
160*2f76de8bSkre		"one-arg:2"			\
161*2f76de8bSkre		"one-arg:4"			\
162*2f76de8bSkre		"one-arg:13"			\
163*2f76de8bSkre		"one two:3"			\
164*2f76de8bSkre		"one two:7"			\
165*2f76de8bSkre		"one two three four five:6"	\
166*2f76de8bSkre		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:16"	\
167*2f76de8bSkre		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:17"	\
168*2f76de8bSkre		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:30"	\
169*2f76de8bSkre		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:9999"
170*2f76de8bSkre	do
171*2f76de8bSkre		oIFS="${IFS}"
172*2f76de8bSkre		IFS=:; set -- $a
173*2f76de8bSkre		IFS="${oIFS}"
174*2f76de8bSkre
175*2f76de8bSkre		atf_check -s not-exit:0 -o match:OK -o not-match:ERR \
176*2f76de8bSkre			-e ignore ${TEST_SH} -c \
177*2f76de8bSkre			"set -- $1 ;echo OK:$#:-$2; shift -$2 && echo ERR"
178*2f76de8bSkre	done
179*2f76de8bSkre}
180*2f76de8bSkre
181e4619cdfSchristosatf_test_case function_shift
182e4619cdfSchristosfunction_shift_head() {
183e4619cdfSchristos	atf_set "descr" "Test that shift in a function does not affect outside"
184e4619cdfSchristos}
185e4619cdfSchristosfunction_shift_body() {
186c8006382Skre	: # later...
187e4619cdfSchristos}
188e4619cdfSchristos
189e4619cdfSchristosatf_test_case non_numeric_shift
190e4619cdfSchristosnon_numeric_shift_head() {
191e4619cdfSchristos	atf_set "descr" "Test that non-numeric args to shift are detected"
192e4619cdfSchristos}
193e4619cdfSchristos
194e4619cdfSchristos# from the DESCRIPTION section at the URL mentioned with the excessive_shift
195e4619cdfSchristos# test:
196e4619cdfSchristos#
197e4619cdfSchristos#	The value n shall be an unsigned decimal integer ...
198e4619cdfSchristos#
199e4619cdfSchristos# That is not hex (octal will be treated as if it were decimal, a leading 0
200e4619cdfSchristos# will simply be ignored - we test for this by giving an "octal" value that
201e4619cdfSchristos# would be OK if parsed as octal, but not if parsed (correctly) as decimal)
202e4619cdfSchristos#
203e4619cdfSchristos# Obviously total trash like roman numerals or alphabetic strings are out.
204e4619cdfSchristos#
205e4619cdfSchristos# Also no signed values (no + or -) and not a string that looks kind of like
206e4619cdfSchristos# a number,  but only if you're generous
207e4619cdfSchristos#
208e4619cdfSchristos# But as the EXIT STATUS section quoted above says, with an invalid 'n'
209e4619cdfSchristos# the shell has the option of exiting, or returning status != 0, so
210e4619cdfSchristos# again this test allows both.
211e4619cdfSchristos
212e4619cdfSchristosnon_numeric_shift_body() {
213e4619cdfSchristos
214e4619cdfSchristos	# there are 9 args set, 010 is 8 if parsed octal, 10 decimal
215*2f76de8bSkre	for a in a I 0x12 010 5V ' ' '' +1 ' 1'
216e4619cdfSchristos	do
217e4619cdfSchristos		atf_check -s not-exit:0 -o empty -e ignore ${TEST_SH} -c \
218e4619cdfSchristos			"set -- a b c d e f g h i; shift '$a' && echo ERROR"
219*2f76de8bSkre		atf_check -s not-exit:0 -o empty -e ignore ${TEST_SH} -c \
220*2f76de8bSkre			"set -- a b c d e f g h i; shift -- '$a' && echo ERROR"
221e4619cdfSchristos	done
222e4619cdfSchristos}
223e4619cdfSchristos
224e4619cdfSchristosatf_test_case too_many_args
225e4619cdfSchristostoo_many_args_head() {
226e4619cdfSchristos	# See PR bin/50896
227e4619cdfSchristos	atf_set "descr" "Test that sh detects invalid extraneous args to shift"
228e4619cdfSchristos}
229e4619cdfSchristos# This is a syntax error, a non-interactive shell (us) must exit $? != 0
230e4619cdfSchristostoo_many_args_body() {
231e4619cdfSchristos	# This tests the bug in PR bin/50896 is fixed
232e4619cdfSchristos
233*2f76de8bSkre	for a in "1 1" "1 0" "1 2 3" "1 foo" "1 --" "-- 1 2" "-1 2"
234e4619cdfSchristos	do
235e4619cdfSchristos		atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
236e4619cdfSchristos			" set -- a b c d; shift ${a} ; echo FAILED "
237e4619cdfSchristos	done
238e4619cdfSchristos}
239e4619cdfSchristos
240e4619cdfSchristosatf_init_test_cases() {
241e4619cdfSchristos	atf_add_test_case basic_shift_test
242e4619cdfSchristos	atf_add_test_case excessive_shift
243e4619cdfSchristos	atf_add_test_case function_shift
244e4619cdfSchristos	atf_add_test_case non_numeric_shift
245e4619cdfSchristos	atf_add_test_case too_many_args
246*2f76de8bSkre	atf_add_test_case basic_rotate
247*2f76de8bSkre	atf_add_test_case excessive_rotate
248e4619cdfSchristos}
249