Home | History | Annotate | Line # | Download | only in sh
t_shift.sh revision 1.1
      1 # $NetBSD: t_shift.sh,v 1.1 2016/03/08 14:26:26 christos Exp $
      2 #
      3 # Copyright (c) 2016 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_shift_test
     31 basic_shift_test_head() {
     32 	atf_set "descr" "Test correct operation of valid shifts"
     33 }
     34 basic_shift_test_body() {
     35 
     36 	for a in			\
     37 	  "one-arg::0:one-arg"		\
     38 	  "one-arg:1:0:one-arg"		\
     39 	  "one-arg:0:1 one-arg"		\
     40 	  "a b c::2 b c:a"		\
     41 	  "a b c:1:2 b c:a"		\
     42 	  "a b c:2:1 c:a:b"		\
     43 	  "a b c:3:0:a:b:c"		\
     44 	  "a b c:0:3 a b c"		\
     45 	  "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"\
     46 	  "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"     \
     47 	  "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"	      \
     48 	  "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"
     49 	do
     50 		oIFS="${IFS}"
     51 		IFS=:; set -- $a
     52 		IFS="${oIFS}"
     53 
     54 		init="$1"; n="$2"; res="$3"; shift 3
     55 
     56 		not=
     57 		for b
     58 		do
     59 			not="${not} -o not-match:$b"
     60 		done
     61 
     62 		atf_check -s exit:0 -o "match:${res}" ${not} -e empty \
     63 			${TEST_SH} -c "set -- ${init}; shift $n;"' echo "$# $*"'
     64 	done
     65 
     66 	atf_check -s exit:0 -o match:complete -o not-match:ERR -e empty \
     67 		${TEST_SH} -c \
     68     'set -- a b c d e;while [ $# -gt 0 ];do shift||echo ERR;done;echo complete'
     69 }
     70 
     71 atf_test_case excessive_shift
     72 excessive_shift_head() {
     73 	atf_set "descr" "Test acceptable operation of shift too many"
     74 }
     75 # In:
     76 #
     77 #	http://pubs.opengroup.org/onlinepubs/9699919799
     78 #		/utilities/V3_chap02.html#tag_18_26_01
     79 #
     80 # (that URL should be one line, with the /util... immediately after ...9799)
     81 #
     82 # POSIX says of shift (in the "EXIT STATUS" paragraph):
     83 #
     84 #  If the n operand is invalid or is greater than "$#", this may be considered
     85 #  a syntax error and a non-interactive shell may exit; if the shell does not
     86 #  exit in this case, a non-zero exit status shall be returned.
     87 #  Otherwise, zero shall be returned.
     88 #
     89 # NetBSD's sh treats it as an error and exits (if non-interactive, as here),
     90 # other shells do not.
     91 #
     92 # Either behaviour is acceptable - so the test allows for both
     93 # (and checks that if the shell does not exit, "shift" returns status != 0)
     94 
     95 excessive_shift_body() {
     96 	for a in				\
     97 		"one-arg:2"			\
     98 		"one-arg:4"			\
     99 		"one-arg:13"			\
    100 		"one two:3"			\
    101 		"one two:7"			\
    102 		"one two three four five:6"	\
    103 		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:16"	\
    104 		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:17"	\
    105 		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:30"	\
    106 		"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:9999"
    107 	do
    108 		oIFS="${IFS}"
    109 		IFS=:; set -- $a
    110 		IFS="${oIFS}"
    111 
    112 		atf_check -s not-exit:0 -o match:OK -o not-match:ERR \
    113 			-e ignore ${TEST_SH} -c \
    114 			"set -- $1 ;"'echo OK:$#-'"$2;shift $2 && echo ERR"
    115 	done
    116 }
    117 
    118 atf_test_case function_shift
    119 function_shift_head() {
    120 	atf_set "descr" "Test that shift in a function does not affect outside"
    121 }
    122 function_shift_body() {
    123 	# later...
    124 }
    125 
    126 atf_test_case non_numeric_shift
    127 non_numeric_shift_head() {
    128 	atf_set "descr" "Test that non-numeric args to shift are detected"
    129 }
    130 
    131 # from the DESCRIPTION section at the URL mentioned with the excessive_shift
    132 # test:
    133 #
    134 #	The value n shall be an unsigned decimal integer ...
    135 #
    136 # That is not hex (octal will be treated as if it were decimal, a leading 0
    137 # will simply be ignored - we test for this by giving an "octal" value that
    138 # would be OK if parsed as octal, but not if parsed (correctly) as decimal)
    139 #
    140 # Obviously total trash like roman numerals or alphabetic strings are out.
    141 #
    142 # Also no signed values (no + or -) and not a string that looks kind of like
    143 # a number,  but only if you're generous
    144 #
    145 # But as the EXIT STATUS section quoted above says, with an invalid 'n'
    146 # the shell has the option of exiting, or returning status != 0, so
    147 # again this test allows both.
    148 
    149 non_numeric_shift_body() {
    150 
    151 	# there are 9 args set, 010 is 8 if parsed octal, 10 decimal
    152 	for a in a I 0x12 010 5V -1 ' ' '' +1 ' 1'
    153 	do
    154 		atf_check -s not-exit:0 -o empty -e ignore ${TEST_SH} -c \
    155 			"set -- a b c d e f g h i; shift '$a' && echo ERROR"
    156 	done
    157 }
    158 
    159 atf_test_case too_many_args
    160 too_many_args_head() {
    161 	# See PR bin/50896
    162 	atf_set "descr" "Test that sh detects invalid extraneous args to shift"
    163 }
    164 # This is a syntax error, a non-interactive shell (us) must exit $? != 0
    165 too_many_args_body() {
    166 	# This tests the bug in PR bin/50896 is fixed
    167 
    168 	for a in "1 1" "1 0" "1 2 3" "1 foo" "1 --" "-- 1"
    169 	do
    170 		atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    171 			" set -- a b c d; shift ${a} ; echo FAILED "
    172 	done
    173 }
    174 
    175 atf_init_test_cases() {
    176 	atf_add_test_case basic_shift_test
    177 	atf_add_test_case excessive_shift
    178 	atf_add_test_case function_shift
    179 	atf_add_test_case non_numeric_shift
    180 	atf_add_test_case too_many_args
    181 }
    182