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