1 #!/bin/bash
2 #
3 # Tests for builtins having to do with variables: export, readonly, unset, etc.
4 #
5 # Also see assign.test.sh.
6
7 ### Export sets a global variable
8 # Even after you do export -n, it still exists.
9 f() { export GLOBAL=X; }
10 f
11 echo $GLOBAL
12 printenv.py GLOBAL
13 # stdout-json: "X\nX\n"
14
15 ### Export sets a global variable that persists after export -n
16 f() { export GLOBAL=X; }
17 f
18 echo $GLOBAL
19 printenv.py GLOBAL
20 export -n GLOBAL
21 echo $GLOBAL
22 printenv.py GLOBAL
23 # stdout-json: "X\nX\nX\nNone\n"
24 # N-I mksh/dash stdout-json: "X\nX\n"
25 # N-I mksh status: 1
26 # N-I dash status: 2
27
28 ### Export a global variable and unset it
29 f() { export GLOBAL=X; }
30 f
31 echo $GLOBAL
32 printenv.py GLOBAL
33 unset GLOBAL
34 echo $GLOBAL
35 printenv.py GLOBAL
36 # stdout-json: "X\nX\n\nNone\n"
37
38 ### Export existing global variables
39 G1=g1
40 G2=g2
41 export G1 G2
42 printenv.py G1 G2
43 # stdout-json: "g1\ng2\n"
44
45 ### Export existing local variable
46 f() {
47 local L1=local1
48 export L1
49 printenv.py L1
50 }
51 f
52 printenv.py L1
53 # stdout-json: "local1\nNone\n"
54
55 ### Export a local that shadows a global
56 V=global
57 f() {
58 local V=local1
59 export V
60 printenv.py V
61 }
62 f
63 printenv.py V # exported local out of scope; global isn't exported yet
64 export V
65 printenv.py V # now it's exported
66 # stdout-json: "local1\nNone\nglobal\n"
67
68 ### Export a variable before defining it
69 export U
70 U=u
71 printenv.py U
72 # stdout: u
73
74 ### Exporting a parent func variable (dynamic scope)
75 # The algorithm is to walk up the stack and export that one.
76 inner() {
77 export outer_var
78 echo "inner: $outer_var"
79 printenv.py outer_var
80 }
81 outer() {
82 local outer_var=X
83 echo "before inner"
84 printenv.py outer_var
85 inner
86 echo "after inner"
87 printenv.py outer_var
88 }
89 outer
90 # stdout-json: "before inner\nNone\ninner: X\nX\nafter inner\nX\n"
91
92 ### Dependent export setting
93 # FOO is not respected here either.
94 export FOO=foo v=$(printenv.py FOO)
95 echo "v=$v"
96 # stdout: v=None
97
98 ### Exporting a variable doesn't change it
99 old=$PATH
100 export PATH
101 new=$PATH
102 test "$old" = "$new" && echo "not changed"
103 # stdout: not changed
104
105 ### Unset a variable
106 foo=bar
107 echo foo=$foo
108 unset foo
109 echo foo=$foo
110 # stdout-json: "foo=bar\nfoo=\n"
111
112 ### Unset exit status
113 V=123
114 unset V
115 echo status=$?
116 # stdout: status=0
117
118 ### Unset nonexistent variable
119 unset ZZZ
120 echo status=$?
121 # stdout: status=0
122
123 ### Unset readonly variable
124 # dash aborts the whole program
125 readonly R=foo
126 unset R
127 echo status=$?
128 # stdout-json: "status=1\n"
129 # OK dash status: 2
130 # OK dash stdout-json: ""
131
132 ### Unset a function without -f
133 f() {
134 echo foo
135 }
136 f
137 unset f
138 f
139 # stdout: foo
140 # status: 127
141 # N-I dash/mksh status: 0
142 # N-I dash/mksh stdout-json: "foo\nfoo\n"
143
144 ### Unset has dynamic scope
145 f() {
146 unset foo
147 }
148 foo=bar
149 echo foo=$foo
150 f
151 echo foo=$foo
152 # stdout-json: "foo=bar\nfoo=\n"
153
154 ### Unset -v
155 foo() {
156 echo "function foo"
157 }
158 foo=bar
159 unset -v foo
160 echo foo=$foo
161 foo
162 # stdout-json: "foo=\nfunction foo\n"
163
164 ### Unset -f
165 foo() {
166 echo "function foo"
167 }
168 foo=bar
169 unset -f foo
170 echo foo=$foo
171 foo
172 echo status=$?
173 # stdout-json: "foo=bar\nstatus=127\n"