xref: /titanic_41/usr/src/lib/libshell/common/tests/variables.sh (revision 67e3a03ed4a2813074d36330f062ed6e593a4937)
1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#           Copyright (c) 1982-2007 AT&T Knowledge Ventures            #
5#                      and is licensed under the                       #
6#                  Common Public License, Version 1.0                  #
7#                      by AT&T Knowledge Ventures                      #
8#                                                                      #
9#                A copy of the License is available at                 #
10#            http://www.opensource.org/licenses/cpl1.0.txt             #
11#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
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# RANDOM
31if	(( RANDOM==RANDOM || $RANDOM==$RANDOM ))
32then	err_exit RANDOM variable not working
33fi
34# SECONDS
35sleep 3
36if	(( SECONDS < 2 ))
37then	err_exit SECONDS variable not working
38fi
39# _
40set abc def
41if	[[ $_ != def ]]
42then	err_exit _ variable not working
43fi
44# ERRNO
45#set abc def
46#rm -f foobar#
47#ERRNO=
48#2> /dev/null < foobar#
49#if	(( ERRNO == 0 ))
50#then	err_exit ERRNO variable not working
51#fi
52# PWD
53if	[[ !  $PWD -ef . ]]
54then	err_exit PWD variable not working
55fi
56# PPID
57if	[[ $($SHELL -c 'print $PPID')  != $$ ]]
58then	err_exit PPID variable not working
59fi
60# OLDPWD
61old=$PWD
62cd /
63if	[[ $OLDPWD != $old ]]
64then	err_exit OLDPWD variable not working
65fi
66cd $old || err_exit cd failed
67# REPLY
68read <<-!
69	foobar
70	!
71if	[[ $REPLY != foobar ]]
72then	err_exit REPLY variable not working
73fi
74integer save=$LINENO
75# LINENO
76LINENO=10
77#
78#  These lines intentionally left blank
79#
80if	(( LINENO != 13))
81then	err_exit LINENO variable not working
82fi
83LINENO=save+10
84IFS=:
85x=a::b::c
86if	[[ $x != a::b::c ]]
87then	err_exit "Word splitting on constants"
88fi
89set -- $x
90if	[[ $# != 5 ]]
91then	err_exit ":: doesn't separate null arguments "
92fi
93set x
94if	x$1=0 2> /dev/null
95then	err_exit "x\$1=value treated as an assignment"
96fi
97# check for attributes across subshells
98typeset -i x=3
99y=1/0
100if	( typeset x=y) 2> /dev/null
101then	print -u2 "attributes not passed to subshells"
102fi
103unset x
104function x.set
105{
106	nameref foo=${.sh.name}.save
107	foo=${.sh.value}
108	.sh.value=$0
109}
110x=bar
111if	[[ $x != x.set ]]
112then	err_exit 'x.set does not override assignment'
113fi
114x.get()
115{
116	nameref foo=${.sh.name}.save
117	.sh.value=$foo
118}
119
120if	[[ $x != bar ]]
121then	err_exit 'x.get does not work correctly'
122fi
123typeset +n foo
124unset foo
125foo=bar
126(
127	unset foo
128	set +u
129	if	[[ $foo != '' ]]
130	then	err_exit '$foo not null after unset in subsehll'
131	fi
132)
133if	[[ $foo != bar ]]
134then	err_exit 'unset foo in subshell produces side effect '
135fi
136unset foo
137if	[[ $( { : ${foo?hi there} ; } 2>&1) != *'hi there' ]]
138then	err_exit '${foo?hi there} with foo unset does not print hi there on 2'
139fi
140x=$0
141set foobar
142if	[[ ${@:0} != "$x foobar" ]]
143then	err_exit '${@:0} not expanding correctly'
144fi
145set --
146if	[[ ${*:0:1} != "$0" ]]
147then	err_exit '${@:0} not expanding correctly'
148fi
149ACCESS=0
150function COUNT.set
151{
152        (( ACCESS++ ))
153}
154COUNT=0
155(( COUNT++ ))
156if	(( COUNT != 1 || ACCESS!=2 ))
157then	err_exit " set discipline failure COUNT=$COUNT ACCESS=$ACCESS"
158fi
159LANG=C > /dev/null 2>&1
160if	[[ $LANG != C ]]
161then	err_exit "C locale not working"
162fi
163unset RANDOM
164unset -n foo
165foo=junk
166function foo.get
167{
168	.sh.value=stuff
169	unset -f foo.get
170}
171if	[[ $foo != stuff ]]
172then	err_exit "foo.get discipline not working"
173fi
174if	[[ $foo != junk ]]
175then	err_exit "foo.get discipline not working after unset"
176fi
177# special variables
178set -- 1 2 3 4 5 6 7 8 9 10
179sleep 1000 &
180if	[[ $(print -r -- ${#10}) != 2 ]]
181then	err_exit '${#10}, where ${10}=10 not working'
182fi
183for i in @ '*' ! '#' - '?' '$'
184do	false
185	eval foo='$'$i bar='$'{$i}
186	if	[[ ${foo} != "${bar}" ]]
187	then	err_exit "\$$i not equal to \${$i}"
188	fi
189	command eval bar='$'{$i%?} 2> /dev/null || err_exit "\${$i%?} gives syntax error"
190	if	[[ $i != [@*] && ${foo%?} != "$bar"  ]]
191	then	err_exit "\${$i%?} not correct"
192	fi
193	command eval bar='$'{$i#?} 2> /dev/null || err_exit "\${$i#?} gives syntax error"
194	if	[[ $i != [@*] && ${foo#?} != "$bar"  ]]
195	then	err_exit "\${$i#?} not correct"
196	fi
197	command eval foo='$'{$i} bar='$'{#$i} || err_exit "\${#$i} gives synta
198x error"
199	if	[[ $i != @([@*]) && ${#foo} != "$bar" ]]
200	then	err_exit "\${#$i} not correct"
201	fi
202done
203kill $!
204unset x
205CDPATH=/
206x=$(cd tmp)
207if	[[ $x != /tmp ]]
208then	err_exit 'CDPATH does not display new directory'
209fi
210mkdir /tmp/ksh$$
211CDPATH=/:
212x=$(cd /tmp;cd ksh$$)
213if	[[ $x ]]
214then	err_exit 'CDPATH displays new directory when not used'
215fi
216x=$(cd tmp/ksh$$)
217if	[[ $x != /tmp/ksh$$ ]]
218then	err_exit "CDPATH tmp/ksh$$ does not display new directory"
219fi
220cd /
221rm -rf /tmp/ksh$$
222TMOUT=100
223(TMOUT=20)
224if	(( TMOUT !=100 ))
225then	err_exit 'setting TMOUT in subshell affects parent'
226fi
227unset y
228function setdisc # var
229{
230        eval function $1.get'
231        {
232                .sh.value=good
233        }
234        '
235}
236y=bad
237setdisc y
238if	[[ $y != good ]]
239then	err_exit 'setdisc function not working'
240fi
241integer x=$LINENO
242: $'\
243'
244if	(( LINENO != x+3  ))
245then	err_exit '\<newline> gets linenumber count wrong'
246fi
247set --
248set -- "${@-}"
249if	(( $# !=1 ))
250then	err_exit	'"${@-}" not expanding to null string'
251fi
252for i in : % + / 3b '**' '***' '@@' '{' '[' '}' !!  '*a' '@a' '$foo'
253do      (eval : \${"$i"} 2> /dev/null) && err_exit "\${$i} not an syntax error"
254done
255unset IFS
256( IFS='  ' ; read -r a b c <<-!
257	x  y z
258	!
259	if	[[ $b ]]
260	then	err_exit 'IFS="  " not causing adjacent space to be null string'
261	fi
262)
263read -r a b c <<-!
264x  y z
265!
266if	[[ $b != y ]]
267then	err_exit 'IFS not restored after subshell'
268fi
269
270# The next part generates 3428 IFS set/read tests.
271
272unset IFS x
273function split
274{
275	i=$1 s=$2 r=$3
276	IFS=': '
277	set -- $i
278	IFS=' '
279	g="[$#]"
280	while	:
281	do	case $# in
282		0)	break ;;
283		esac
284		g="$g($1)"
285		shift
286	done
287	case "$g" in
288	"$s")	;;
289	*)	err_exit "IFS=': '; set -- '$i'; expected '$s' got '$g'" ;;
290	esac
291	print "$i" | IFS=": " read arg rem; g="($arg)($rem)"
292	case "$g" in
293	"$r")	;;
294	*)	err_exit "IFS=': '; read '$i'; expected '$r' got '$g'" ;;
295	esac
296}
297for str in 	\
298	'-'	\
299	'a'	\
300	'- -'	\
301	'- a'	\
302	'a -'	\
303	'a b'	\
304	'- - -'	\
305	'- - a'	\
306	'- a -'	\
307	'- a b'	\
308	'a - -'	\
309	'a - b'	\
310	'a b -'	\
311	'a b c'
312do
313	IFS=' '
314	set x $str
315	shift
316	case $# in
317	0)	continue ;;
318	esac
319	f1=$1
320	case $f1 in
321	'-')	f1='' ;;
322	esac
323	shift
324	case $# in
325	0)	for d0 in '' ' '
326		do
327			for d1 in '' ' ' ':' ' :' ': ' ' : '
328			do
329				case $f1$d1 in
330				'')	split "$d0$f1$d1" "[0]" "()()" ;;
331				' ')	;;
332				*)	split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;;
333				esac
334			done
335		done
336		continue
337		;;
338	esac
339	f2=$1
340	case $f2 in
341	'-')	f2='' ;;
342	esac
343	shift
344	case $# in
345	0)	for d0 in '' ' '
346		do
347			for d1 in ' ' ':' ' :' ': ' ' : '
348			do
349				case ' ' in
350				$f1$d1|$d1$f2)	continue ;;
351				esac
352				for d2 in '' ' ' ':' ' :' ': ' ' : '
353				do
354					case $f2$d2 in
355					'')	split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;;
356					' ')	;;
357					*)	split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;;
358					esac
359				done
360			done
361		done
362		continue
363		;;
364	esac
365	f3=$1
366	case $f3 in
367	'-')	f3='' ;;
368	esac
369	shift
370	case $# in
371	0)	for d0 in '' ' '
372		do
373			for d1 in ':' ' :' ': ' ' : '
374			do
375				case ' ' in
376				$f1$d1|$d1$f2)	continue ;;
377				esac
378				for d2 in ' ' ':' ' :' ': ' ' : '
379				do
380					case $f2$d2 in
381					' ')	continue ;;
382					esac
383					case ' ' in
384					$f2$d2|$d2$f3)	continue ;;
385					esac
386					for d3 in '' ' ' ':' ' :' ': ' ' : '
387					do
388						case $f3$d3 in
389						'')	split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;;
390						' ')	;;
391						*)	x=$f2$d2$f3$d3
392							x=${x#' '}
393							x=${x%' '}
394							split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)"
395							;;
396						esac
397					done
398				done
399			done
400		done
401		continue
402		;;
403	esac
404done
405unset IFS
406
407if	[[ $( (print ${12345:?}) 2>&1) != *12345* ]]
408then	err_exit 'Incorrect error message with ${12345?}'
409fi
410unset foobar
411if	[[ $( (print ${foobar:?}) 2>&1) != *foobar* ]]
412then	err_exit 'Incorrect error message with ${foobar?}'
413fi
414unset bar
415if	[[ $( (print ${bar:?bam}) 2>&1) != *bar*bam* ]]
416then	err_exit 'Incorrect error message with ${foobar?}'
417fi
418{ $SHELL -c '
419function foo
420{
421	typeset SECONDS=0
422	sleep 1.5
423	print $SECONDS
424
425}
426x=$(foo)
427(( x >1 && x < 2 ))
428'
429} 2> /dev/null   || err_exit 'SECONDS not working in function'
430trap 'rm -f /tmp/script$$ /tmp/out$$' EXIT
431cat > /tmp/script$$ <<-\!
432	posixfun()
433	{
434		unset x
435	 	nameref x=$1
436	 	print  -r -- "$x"
437	}
438	function fun
439	{
440	 	nameref x=$1
441	 	print  -r -- "$x"
442	}
443	if	[[ $1 ]]
444	then	file=${.sh.file}
445	else	print -r -- "${.sh.file}"
446	fi
447!
448chmod +x /tmp/script$$
449. /tmp/script$$  1
450[[ $file == /tmp/script$$ ]] || err_exit ".sh.file not working for dot scripts"
451[[ $($SHELL /tmp/script$$) == /tmp/script$$ ]] || err_exit ".sh.file not working for scripts"
452[[ $(posixfun .sh.file) == /tmp/script$$ ]] || err_exit ".sh.file not working for posix functions"
453[[ $(fun .sh.file) == /tmp/script$$ ]] || err_exit ".sh.file not working for functions"
454[[ $(posixfun .sh.fun) == posixfun ]] || err_exit ".sh.fun not working for posix functions"
455[[ $(fun .sh.fun) == fun ]] || err_exit ".sh.fun not working for functions"
456[[ $(posixfun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for posix functions"
457[[ $(fun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for functions"
458(
459    [[ $(posixfun .sh.subshell) == 2 ]]  || err_exit ".sh.subshell not working for posix functions in subshells"
460    [[ $(fun .sh.subshell) == 2 ]]  || err_exit ".sh.subshell not working for functions in subshells"
461    (( .sh.subshell == 1 )) || err_exit ".sh.subshell not working in a subshell"
462)
463TIMEFORMAT='this is a test'
464[[ $({ { time :;} 2>&1;}) == "$TIMEFORMAT" ]] || err_exit 'TIMEFORMAT not working'
465: ${.sh.version}
466[[ $(alias integer) == *.sh.* ]] && err_exit '.sh. prefixed to alias name'
467: ${.sh.version}
468[[ $(whence rm) == *.sh.* ]] && err_exit '.sh. prefixed to tracked alias name'
469: ${.sh.version}
470[[ $(cd /bin;env | grep PWD) == *.sh.* ]] && err_exit '.sh. prefixed to PWD'
471# unset discipline bug fix
472dave=dave
473function dave.unset
474{
475    unset dave
476}
477unset dave
478[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed'
479print 'print ${VAR}' >  /tmp/script$$
480VAR=foo /tmp/script$$ > /tmp/out$$
481[[ $(</tmp/out$$) == foo ]] || err_exit 'environment variables not passed to scripts'
482(
483	unset dave
484	function  dave.append
485	{
486		.sh.value+=$dave
487		dave=
488	}
489	dave=foo; dave+=bar
490	[[ $dave == barfoo ]] || exit 2
491) 2> /dev/null
492case $? in
4930)	 ;;
4941)	 err_exit 'append discipline not implemented';;
495*)	 err_exit 'append discipline not working';;
496esac
497.sh.foobar=hello
498{
499	function .sh.foobar.get
500	{
501		.sh.value=world
502	}
503} 2> /dev/null || err_exit "Can't add get discipline to .sh.foobar"
504[[ ${.sh.foobar} == world ]]  || err_exit 'get discipline for .sh.foobar not working'
505x='a|b'
506IFS='|'
507set -- $x
508[[ $2 == b ]] || err_exit '$2 should be b after set'
509exec 3>&2 2> /dev/null
510set -x
511( IFS= ) 2> /dev/null
512set +x
513exec 2>&3-
514set -- $x
515[[ $2 == b ]] || err_exit '$2 should be b after subshell'
516: & pid=$!
517( : & )
518[[ $pid == $! ]] || err_exit '$! value not preserved across subshells'
519unset foo
520typeset -A foo
521function foo.set
522{
523	case ${.sh.subscript} in
524	bar)	if	((.sh.value > 1 ))
525	        then	.sh.value=5
526			foo[barrier_hit]=yes
527		fi
528		;;
529	barrier_hit)
530		if	[[ ${.sh.value} = yes ]]
531		then	foo[barrier_not_hit]=no
532		else	foo[barrier_not_hit]=yes
533		fi
534		;;
535	esac
536}
537foo[barrier_hit]=no
538foo[bar]=1
539(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1'
540[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no'
541[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes'
542foo[barrier_hit]=no
543foo[bar]=2
544(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5'
545[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes'
546[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no'
547unset x
548typeset -i x
549function x.set
550{
551	typeset sub=${.sh.subscript}
552	(( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value ))
553}
554x[0]=0 x[1]=1 x[2]=2 x[3]=3
555[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly'
556((SECONDS=3*4))
557(( SECONDS < 12 || SECONDS > 12.1 )) &&  err_exit "SECONDS is $SECONDS and should be close to 12"
558exit $((Errors))
559