1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1982-2012 AT&T Intellectual Property          #
5#                      and is licensed under the                       #
6#                 Eclipse Public License, Version 1.0                  #
7#                    by AT&T Intellectual Property                     #
8#                                                                      #
9#                A copy of the License is available at                 #
10#          http://www.eclipse.org/org/documents/epl-v10.html           #
11#         (with md5 checksum b35adb5213ca9657e911e9befb180842)         #
12#                                                                      #
13#              Information and Software Systems Research               #
14#                            AT&T Research                             #
15#                           Florham Park NJ                            #
16#                                                                      #
17#                  David Korn <dgk@research.att.com>                   #
18#                                                                      #
19########################################################################
20function err_exit
21{
22	print -u2 -n "\t"
23	print -u2 -r ${Command}[$1]: "${@:2}"
24	let Errors+=1
25}
26alias err_exit='err_exit $LINENO'
27
28Command=${0##*/}
29integer Errors=0
30
31tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
32trap "cd /; rm -rf $tmp" EXIT
33
34null=''
35if	[[ ! -z $null ]]
36then	err_exit "-z: null string should be of zero length"
37fi
38file=$tmp/original
39newer_file=$tmp/newer
40if	[[ -z $file ]]
41then	err_exit "-z: $file string should not be of zero length"
42fi
43if	[[ -a $file ]]
44then	err_exit "-a: $file shouldn't exist"
45fi
46if	[[ -e $file ]]
47then	err_exit "-e: $file shouldn't exist"
48fi
49> $file
50if	[[ ! -a $file ]]
51then	err_exit "-a: $file should exist"
52fi
53if	[[ ! -e $file ]]
54then	err_exit "-e: $file should exist"
55fi
56chmod 777 $file
57if	[[ ! -r $file ]]
58then	err_exit "-r: $file should be readable"
59fi
60if	[[ ! -w $file ]]
61then	err_exit "-w: $file should be writable"
62fi
63if	[[ ! -w $file ]]
64then	err_exit "-x: $file should be executable"
65fi
66if	[[ ! -w $file || ! -r $file ]]
67then	err_exit "-rw: $file should be readable/writable"
68fi
69if	[[ -s $file ]]
70then	err_exit "-s: $file should be of zero size"
71fi
72if	[[ ! -f $file ]]
73then	err_exit "-f: $file should be an ordinary file"
74fi
75if	[[  -d $file ]]
76then	err_exit "-f: $file should not be a directory file"
77fi
78if	[[  ! -d . ]]
79then	err_exit "-d: . should not be a directory file"
80fi
81if	[[  -f /dev/null ]]
82then	err_exit "-f: /dev/null  should not be an ordinary file"
83fi
84chmod 000 $file
85if	[[ -r $file ]]
86then	err_exit "-r: $file should not be readable"
87fi
88if	[[ ! -O $file ]]
89then	err_exit "-r: $file should be owned by me"
90fi
91if	[[ -w $file ]]
92then	err_exit "-w: $file should not be writable"
93fi
94if	[[ -w $file ]]
95then	err_exit "-x: $file should not be executable"
96fi
97if	[[ -w $file || -r $file ]]
98then	err_exit "-rw: $file should not be readable/writable"
99fi
100if	[[   -z x &&  -z x || ! -z x ]]
101then	:
102else	err_exit " wrong precedence"
103fi
104if	[[   -z x &&  (-z x || ! -z x) ]]
105then	err_exit " () grouping not working"
106fi
107if	[[ foo < bar ]]
108then	err_exit "foo comes before bar"
109fi
110[[ . -ef $(pwd) ]] || err_exit ". is not $PWD"
111set -o allexport
112[[ -o allexport ]] || err_exit '-o: did not set allexport option'
113if	[[ -n  $null ]]
114then	err_exit "'$null' has non-zero length"
115fi
116if	[[ ! -r /dev/fd/0 ]]
117then	err_exit "/dev/fd/0 not open for reading"
118fi
119if	[[ ! -w /dev/fd/2 ]]
120then	err_exit "/dev/fd/2 not open for writing"
121fi
122sleep 1
123> $newer_file
124if	[[ ! $file -ot $newer_file ]]
125then	err_exit "$file should be older than $newer_file"
126fi
127if	[[ $file -nt $newer_file ]]
128then	err_exit "$newer_file should be newer than $file"
129fi
130if	[[ $file != $tmp/* ]]
131then	err_exit "$file should match $tmp/*"
132fi
133if	[[ $file == $tmp'/*' ]]
134then	err_exit "$file should not equal $tmp'/*'"
135fi
136[[ ! ( ! -z $null && ! -z x) ]]	|| err_exit "negation and grouping"
137[[ -z '' || -z '' || -z '' ]]	|| err_exit "three ors not working"
138[[ -z '' &&  -z '' && -z '' ]]	|| err_exit "three ors not working"
139(exit 8)
140if	[[ $? -ne 8 || $? -ne 8 ]]
141then	err_exit 'value $? within [[...]]'
142fi
143x='(x'
144if	[[ '(x' != '('* ]]
145then	err_exit " '(x' does not match '('* within [[...]]"
146fi
147if	[[ '(x' != "("* ]]
148then	err_exit ' "(x" does not match "("* within [[...]]'
149fi
150if	[[ '(x' != \(* ]]
151then	err_exit ' "(x" does not match \(* within [[...]]'
152fi
153if	[[ 'x(' != *'(' ]]
154then	err_exit " 'x(' does not match '('* within [[...]]"
155fi
156if	[[ 'x&' != *'&' ]]
157then	err_exit " 'x&' does not match '&'* within [[...]]"
158fi
159if	[[ 'xy' == *'*' ]]
160then	err_exit " 'xy' matches *'*' within [[...]]"
161fi
162if	[[ 3 > 4 ]]
163then	err_exit '3 < 4'
164fi
165if	[[ 4 < 3 ]]
166then	err_exit '3 > 4'
167fi
168if	[[ 3x > 4x ]]
169then	err_exit '3x < 4x'
170fi
171x='@(bin|dev|?)'
172cd /
173if	[[ $(print $x) != "$x" ]]
174then	err_exit 'extended pattern matching on command arguments'
175fi
176if	[[ dev != $x ]]
177then	err_exit 'extended pattern matching not working on variables'
178fi
179if	[[ -u $SHELL ]]
180then	err_exit "setuid on $SHELL"
181fi
182if	[[ -g $SHELL ]]
183then	err_exit "setgid on $SHELL"
184fi
185test -d .  -a '(' ! -f . ')' || err_exit 'test not working'
186if	[[ '!' != ! ]]
187then	err_exit 'quoting unary operator not working'
188fi
189test \( -n x \) -o \( -n y \) 2> /dev/null || err_exit 'test ( -n x ) -o ( -n y) not working'
190test \( -n x \) -o -n y 2> /dev/null || err_exit 'test ( -n x ) -o -n y not working'
191chmod 600 $file
192exec 4> $file
193print -u4 foobar
194if	[[ ! -s $file ]]
195then	err_exit "-s: $file should be non-zero"
196fi
197exec 4>&-
198if	[[ 011 -ne 11 ]]
199then	err_exit "leading zeros in arithmetic compares not ignored"
200fi
201{
202	set -x
203	[[ foo > bar ]]
204} 2> /dev/null || { set +x; err_exit "foo<bar with -x enabled" ;}
205set +x
206(
207	eval "[[ (a) ]]"
208) 2> /dev/null || err_exit "[[ (a) ]] not working"
209> $file
210chmod 4755 "$file"
211if	test -u $file && test ! -u $file
212then	err_exit "test ! -u suidfile not working"
213fi
214for i in '(' ')' '[' ']'
215do	[[ $i == $i ]] || err_exit "[[ $i != $i ]]"
216done
217(
218	[[ aaaa == {4}(a) ]] || err_exit 'aaaa != {4}(a)'
219	[[ aaaa == {2,5}(a) ]] || err_exit 'aaaa != {2,4}(a)'
220	[[ abcdcdabcd == {3,6}(ab|cd) ]] || err_exit 'abcdcdabcd == {3,4}(ab|cd)'
221	[[ abcdcdabcde == {5}(ab|cd)e ]] || err_exit 'abcdcdabcd == {5}(ab|cd)e'
222) || err_exit 'errors with {..}(...) patterns'
223[[ D290.2003.02.16.temp == D290.+(2003.02.16).temp* ]] || err_exit 'pattern match bug with +(...)'
224rm -rf $file
225{
226[[ -N $file ]] && err_exit 'test -N $tmp/*: st_mtime>st_atime after creat'
227sleep 2
228print 'hello world'
229[[ -N $file ]] || err_exit 'test -N $tmp/*: st_mtime<=st_atime after write'
230sleep 2
231read
232[[ -N $file ]] && err_exit 'test -N $tmp/*: st_mtime>st_atime after read'
233} > $file < $file
234if	rm -rf "$file" && ln -s / "$file"
235then	[[ -L "$file" ]] || err_exit '-L not working'
236	[[ -L "$file"/ ]] && err_exit '-L with file/ not working'
237fi
238$SHELL -c 't=1234567890; [[ $t == @({10}(\d)) ]]' 2> /dev/null || err_exit ' @({10}(\d)) pattern not working'
239$SHELL -c '[[ att_ == ~(E)(att|cus)_.* ]]' 2> /dev/null || err_exit ' ~(E)(att|cus)_* pattern not working'
240$SHELL -c '[[ att_ =~ (att|cus)_.* ]]' 2> /dev/null || err_exit ' =~ ere not working'
241$SHELL -c '[[ abc =~ a(b)c ]]' 2> /dev/null || err_exit '[[ abc =~ a(b)c ]] fails'
242$SHELL -xc '[[ abc =~  \babc\b ]]' 2> /dev/null || err_exit '[[ abc =~ \babc\b ]] fails'
243[[ abc == ~(E)\babc\b ]] || err_exit '\b not preserved for ere when not in ()'
244[[ abc == ~(iEi)\babc\b ]] || err_exit '\b not preserved for ~(iEi) when not in ()'
245
246e=$($SHELL -c '[ -z "" -a -z "" ]' 2>&1)
247[[ $e ]] && err_exit "[ ... ] compatibility check failed -- $e"
248i=hell
249[[ hell0 == $i[0] ]]  ||  err_exit 'pattern $i[0] interpreded as array ref'
250test '(' = ')' && err_exit '"test ( = )" should not be true'
251[[ $($SHELL -c 'case  F in ~(Eilr)[a-z0-9#]) print ok;;esac' 2> /dev/null) == ok ]] || err_exit '~(Eilr) not working in case command'
252[[ $($SHELL -c "case  Q in ~(Fi)q |  \$'\E') print ok;;esac" 2> /dev/null) == ok ]] || err_exit '~(Fi)q | \E  not working in case command'
253
254for l in C en_US.ISO8859-15
255do	[[ $($SHELL -c "LC_COLLATE=$l" 2>&1) ]] && continue
256	export LC_COLLATE=$l
257	set -- \
258		'A'   0 1 1   0 1 1      1 0 0   1 0 0   \
259		'Z'   0 1 1   0 1 1      1 0 0   1 0 0   \
260		'/'   0 0 0   0 0 0      1 1 1   1 1 1   \
261		'.'   0 0 0   0 0 0      1 1 1   1 1 1   \
262		'_'   0 0 0   0 0 0      1 1 1   1 1 1   \
263		'-'   1 1 1   1 1 1      0 0 0   0 0 0   \
264		'%'   0 0 0   0 0 0      1 1 1   1 1 1   \
265		'@'   0 0 0   0 0 0      1 1 1   1 1 1   \
266		'!'   0 0 0   0 0 0      1 1 1   1 1 1   \
267		'^'   0 0 0   0 0 0      1 1 1   1 1 1   \
268		# retain this line #
269	while	(( $# >= 13 ))
270	do	c=$1
271		shift
272		for p in \
273			'[![.-.]]' \
274			'[![.-.][:upper:]]' \
275			'[![.-.]A-Z]' \
276			'[!-]' \
277			'[!-[:upper:]]' \
278			'[!-A-Z]' \
279			'[[.-.]]' \
280			'[[.-.][:upper:]]' \
281			'[[.-.]A-Z]' \
282			'[-]' \
283			'[-[:upper:]]' \
284			'[-A-Z]' \
285			# retain this line #
286		do	e=$1
287			shift
288			[[ $c == $p ]]
289			g=$?
290			[[ $g == $e ]] || err_exit "[[ '$c' == $p ]] for LC_COLLATE=$l failed -- expected $e, got $g"
291		done
292	done
293done
294integer n
295if	( : < /dev/tty ) 2>/dev/null && exec {n}< /dev/tty
296then	[[ -t  $n ]] || err_exit "[[ -t  n ]] fails when n > 9"
297fi
298foo=([1]=a [2]=b [3]=c)
299[[ -v foo[1] ]] ||  err_exit 'foo[1] should be set'
300[[ ${foo[1]+x} ]] ||  err_exit '${foo[1]+x} should be x'
301[[ ${foo[@]+x} ]] ||  err_exit '${foo[@]+x} should be x'
302unset foo[1]
303[[ -v foo[1] ]] && err_exit 'foo[1] should not be set'
304[[ ${foo[1]+x} ]] &&  err_exit '${foo[1]+x} should be empty'
305bar=(a b c)
306[[ -v bar[1] ]]  || err_exit 'bar[1] should be set'
307[[ ${bar[1]+x} ]] ||  err_exit '${foo[1]+x} should be x'
308unset bar[1]
309[[ ${bar[1]+x} ]] &&  err_exit '${foo[1]+x} should be empty'
310[[ -v bar ]] || err_exit 'bar should be set'
311[[ -v bar[1] ]] && err_exit 'bar[1] should not be set'
312integer z=( 1 2 4)
313[[ -v z[1] ]] || err_exit 'z[1] should be set'
314unset z[1]
315[[ -v z[1] ]] && err_exit 'z[1] should not be set'
316typeset -si y=( 1 2 4)
317[[ -v y[6] ]] && err_exit 'y[6] should not be set'
318[[ -v y[1] ]] ||  err_exit  'y[1] should be set'
319unset y[1]
320[[ -v y[1] ]] && err_exit 'y[1] should not be set'
321x=abc
322[[ -v x[0] ]] || err_exit  'x[0] should be set'
323[[ ${x[0]+x} ]] || err_exit print  '${x[0]+x} should be x'
324[[ -v x[3] ]] && err_exit 'x[3] should not be set'
325[[ ${x[3]+x} ]] && err_exit  '${x[0]+x} should be Empty'
326unset x
327[[ ${x[@]+x} ]] && err_exit  '${x[@]+x} should be Empty'
328unset x y z foo bar
329
330{ x=$($SHELL -c '[[ (( $# -eq 0 )) ]] && print ok') 2> /dev/null;}
331[[ $x == ok ]] || err_exit '((...)) inside [[...]] not treated as nested ()'
332
333[[ -e /dev/fd/ ]] || err_exit '/dev/fd/ does not exits'
334[[ -e /dev/tcp/ ]] || err_exit '/dev/tcp/ does not exist'
335[[ -e /dev/udp/ ]] || err_exit '/dev/udp/ does not exist'
336[[ -e /dev/xxx/ ]] &&  err_exit '/dev/xxx/ exists'
337
338$SHELL 2> /dev/null -c '[[(-n foo)]]' || err_exit '[[(-n foo)]] should not require space in front of ('
339
340$SHELL 2> /dev/null -c '[[ "]" == ~(E)[]] ]]' || err_exit 'pattern "~(E)[]]" does not match "]"'
341
342unset var
343[[ -v var ]] &&  err_exit '[[ -v var ]] should be false after unset var'
344float var
345[[ -v var ]]  ||  err_exit '[[ -v var ]] should be true after float var'
346unset var
347[[ -v var ]] &&  err_exit '[[ -v var ]] should be false after unset var again'
348
349test ! ! ! 2> /dev/null || err_exit 'test ! ! ! should return 0'
350test ! ! x 2> /dev/null || err_exit 'test ! ! x should return 0'
351test ! ! '' 2> /dev/null && err_exit 'test ! ! "" should return non-zero'
352
353exit $((Errors<125?Errors:125))
354