xref: /titanic_41/usr/src/lib/libshell/common/tests/nameref.sh (revision 9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bb)
1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1982-2008 AT&T Intellectual Property          #
5#                      and is licensed under the                       #
6#                  Common Public License, Version 1.0                  #
7#                    by AT&T Intellectual Property                     #
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
30function checkref
31{
32	nameref foo=$1 bar=$2
33	if	[[ $foo !=  $bar ]]
34	then	err_exit "foo=$foo != bar=$bar"
35	fi
36	foo=hello
37	if	[[ $foo !=  $bar ]]
38	then	err_exit "foo=$foo != bar=$bar"
39	fi
40	foo.child=child
41	if	[[ ${foo.child} !=  ${bar.child} ]]
42	then	err_exit "foo.child=${foo.child} != bar=${bar.child}"
43	fi
44}
45
46name=first
47checkref name name
48name.child=second
49checkref name name
50.foo=top
51.foo.bar=next
52checkref .foo.bar .foo.bar
53if	[[ ${.foo.bar} !=  hello ]]
54then	err_exit ".foo.bar=${.foo.bar} != hello"
55fi
56if	[[ ${.foo.bar.child} !=  child ]]
57then	err_exit ".foo.bar.child=${.foo.bar.child} != child"
58fi
59function func1
60{
61        nameref color=$1
62        func2 color
63}
64
65function func2
66{
67        nameref color=$1
68        set -s -- ${!color[@]}
69	print -r -- "$@"
70}
71
72typeset -A color
73color[apple]=red
74color[grape]=purple
75color[banana]=yellow
76if	[[ $(func1 color) != 'apple banana grape' ]]
77then	err_exit "nameref or nameref not working"
78fi
79nameref x=.foo.bar
80if	[[ ${!x} != .foo.bar ]]
81then	err_exit "${!x} not working"
82fi
83typeset +n x $(typeset +n)
84unset x
85nameref x=.foo.bar
86function x.set
87{
88	[[ ${.sh.value} ]] && print hello
89}
90if	[[ $(.foo.bar.set) != $(x.set) ]]
91then	err_exit "function references  not working"
92fi
93if	[[ $(typeset +n) != x ]]
94then	err_exit "typeset +n doesn't list names of reference variables"
95fi
96if	[[ $(typeset -n) != x=.foo.bar ]]
97then	err_exit "typeset +n doesn't list values of reference variables"
98fi
99file=/tmp/shtest$$
100typeset +n foo bar 2> /dev/null
101unset foo bar
102export bar=foo
103nameref foo=bar
104if	[[ $foo != foo ]]
105then	err_exit "value of nameref foo !=  $foo"
106fi
107trap "rm -f $file" EXIT INT
108cat > $file <<\!
109print -r -- $foo
110!
111chmod +x "$file"
112y=$( $file)
113if	[[ $y != '' ]]
114then	err_exit "reference variable not cleared"
115fi
116{
117	command nameref xx=yy
118	command nameref yy=xx
119} 2> /dev/null && err_exit "self reference not detected"
120typeset +n foo bar
121unset foo bar
122set foo
123nameref bar=$1
124foo=hello
125if	[[ $bar !=  hello ]]
126then	err_exit 'nameref of positional paramters outside of function not working'
127fi
128unset foo bar
129bar=123
130function foobar
131{
132	typeset -n foo=bar
133	typeset -n foo=bar
134}
135foobar 2> /dev/null || err_exit 'nameref not unsetting previous reference'
136(
137	nameref short=verylong
138	short=( A=a B=b )
139	if	[[ ${verylong.A} != a ]]
140	then	err_exit 'nameref short to longname compound assignment error'
141	fi
142) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error'
143unset x
144if	[[	$(var1=1 var2=2
145		for i in var1 var2
146		do	nameref x=$i
147			print $x
148		done) != $'1\n2' ]]
149then	err_exit 'for loop nameref optimization error'
150fi
151if	[[	$(typeset -A var1 var2
152		var1[sub1]=1 var2[sub2]=1
153		for i in var1 var2
154		do
155		        typeset -n array=$i
156		        print ${!array[*]}
157		done) != $'sub1\nsub2' ]]
158then 	err_exit 'for loop nameref optimization test2 error'
159fi
160
161unset -n x foo bar
162if	[[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]]
163then	err_exit 'for loop optimization with namerefs not working'
164fi
165if	[[ $(
166	p=(x=(r=3) y=(r=4))
167	for i in x y
168	do	nameref x=p.$i
169		print ${x.r}
170	done
171) != $'3\n4' ]]
172then	err_exit 'nameref optimization error'
173fi
174[[ $(
175unset x y var
176var=(foo=bar)
177for i in y var
178do	typeset -n x=$i
179	if	[[ ${!x.@} ]]
180	then	print ok
181	fi
182	typeset +n x
183done) != ok ]] && err_exit 'invalid for loop optimization of name references'
184function setval # name value
185{
186        nameref arg=$1
187	nameref var=arg.bar
188	var=$2
189}
190foo=( integer bar=0)
191setval foo 5
192(( foo.bar == 5)) || err_exit 'nested nameref not working'
193function selfref
194{
195        typeset -n ps=$1
196        print -r -- "${ps}"
197}
198ps=(a=1 b=2)
199[[ $(selfref ps) == *a=1* ]] ||  err_exit 'local nameref cannot reference global variable of the same name'
200function subref
201{
202	typeset -n foo=$1
203	print -r -- ${foo.a}
204}
205[[ $(subref ps) == 1 ]] ||  err_exit 'local nameref cannot reference global variable child'
206
207function local
208{
209	typeset ps=(typeset -i a=3 b=4)
210	[[ $(subref ps) == 3 ]] ||  err_exit 'local nameref cannot reference caller compound variable'
211}
212local
213unset -f local
214function local
215{
216	qs=(integer  a=3; integer b=4)
217}
218local 2> /dev/null || err_exit 'function local has non-zero exit status'
219[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable'
220unset fun i
221foo=(x=hi)
222function fun
223{
224        nameref i=$1
225        print -r -- "${i.x}"
226}
227i=foo
228[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails'
229unset -n foo bar
230typeset -A foo
231foo[x.y]=(x=3 y=4)
232nameref bar=foo[x.y]
233[[ ${bar.x} == 3 ]] || err_exit 'nameref to subscript containing . fails'
234[[ ${!bar} == 'foo[x.y]' ]] || err_exit '${!var} not correct for nameref to an array instance'
235typeset +n bar
236nameref bar=foo
237[[ ${!bar} == foo ]] || err_exit '${!var} not correct for nameref to array variable'
238$SHELL -c 'function bar { nameref x=foo[++];};typeset -A foo;bar' 2> /dev/null ||err_exit 'nameref of associative array tries to evaluate subscript'
239i=$($SHELL -c 'nameref foo=bar; bar[2]=(x=3 y=4); nameref x=foo[2].y;print -r -- $x' 2> /dev/null)
240[[ $i == 4 ]] || err_exit 'creating reference from subscripted variable whose name is a reference failed'
241[[ $($SHELL 2> /dev/null <<- '+++EOF'
242	function bar
243	{
244	 	nameref x=$1
245	 	print -r -- "$x"
246	}
247	function foo
248	{
249	 	typeset var=( foo=hello)
250	 	bar var
251	}
252	foo
253+++EOF
254) ==  *foo=hello* ]] || err_exit 'unable to display compound variable from name reference of local variable'
255#set -x
256for c in '=' '[' ']' '\' "'" '"' '<' '=' '('
257do	[[ $($SHELL 2> /dev/null <<- ++EOF++
258	x;i=\\$c;typeset -A a; a[\$i]=foo;typeset -n x=a[\$i]; print "\$x"
259	++EOF++
260) != foo ]] && err_exit 'nameref x=[$c] '"not working for c=$c"
261done
262unset -n foo x
263unset foo x
264typeset -A foo
265nameref x=foo[xyz]
266foo[xyz]=ok
267[[ $x == ok ]] || err_exit 'nameref to unset subscript not working'
268function function2
269{
270	nameref v=$1
271	v.x=19 v.y=20
272}
273function function1
274{
275	typeset compound_var=()
276	function2 compound_var
277	printf "x=%d, y=%d\n" compound_var.x compound_var.y
278}
279x="$(function1)"
280[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'"
281typeset +n bar
282unset foo bar
283[[ $(function a
284{
285	for i in  foo bar
286	do	typeset -n v=$i
287		print $v
288	done | cat
289}
290foo=1 bar=2;a) == $'1\n2' ]] 2> /dev/null || err_exit 'nameref in pipeline broken'
291function a
292{
293	typeset -n v=vars.data._1
294	print "${v.a} ${v.b}"
295}
296vars=(data=())
297vars.data._1.a=a.1
298vars.data._1.b=b.1
299[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- '
300exit $((Errors))
301