1 package expansion
2
3 import (
4 "testing"
5
6 api "k8s.io/kubernetes/pkg/apis/core"
7 )
8
9 func TestMapReference(t *testing.T) {
10 envs := []api.EnvVar{
11 {
12 Name: "FOO",
13 Value: "bar",
14 },
15 {
16 Name: "ZOO",
17 Value: "$(FOO)-1",
18 },
19 {
20 Name: "BLU",
21 Value: "$(ZOO)-2",
22 },
23 }
24
25 declaredEnv := map[string]string{
26 "FOO": "bar",
27 "ZOO": "$(FOO)-1",
28 "BLU": "$(ZOO)-2",
29 }
30
31 serviceEnv := map[string]string{}
32
33 mapping := MappingFuncFor(declaredEnv, serviceEnv)
34
35 for _, env := range envs {
36 declaredEnv[env.Name] = Expand(env.Value, mapping)
37 }
38
39 expectedEnv := map[string]string{
40 "FOO": "bar",
41 "ZOO": "bar-1",
42 "BLU": "bar-1-2",
43 }
44
45 for k, v := range expectedEnv {
46 if e, a := v, declaredEnv[k]; e != a {
47 t.Errorf("Expected %v, got %v", e, a)
48 } else {
49 delete(declaredEnv, k)
50 }
51 }
52
53 if len(declaredEnv) != 0 {
54 t.Errorf("Unexpected keys in declared env: %v", declaredEnv)
55 }
56 }
57
58 func TestMapping(t *testing.T) {
59 context := map[string]string{
60 "VAR_A": "A",
61 "VAR_B": "B",
62 "VAR_C": "C",
63 "VAR_REF": "$(VAR_A)",
64 "VAR_EMPTY": "",
65 }
66 mapping := MappingFuncFor(context)
67
68 doExpansionTest(t, mapping)
69 }
70
71 func TestMappingDual(t *testing.T) {
72 context := map[string]string{
73 "VAR_A": "A",
74 "VAR_EMPTY": "",
75 }
76 context2 := map[string]string{
77 "VAR_B": "B",
78 "VAR_C": "C",
79 "VAR_REF": "$(VAR_A)",
80 }
81 mapping := MappingFuncFor(context, context2)
82
83 doExpansionTest(t, mapping)
84 }
85
86 func doExpansionTest(t *testing.T, mapping func(string) string) {
87 cases := []struct {
88 name string
89 input string
90 expected string
91 }{
92 {
93 name: "whole string",
94 input: "$(VAR_A)",
95 expected: "A",
96 },
97 {
98 name: "repeat",
99 input: "$(VAR_A)-$(VAR_A)",
100 expected: "A-A",
101 },
102 {
103 name: "beginning",
104 input: "$(VAR_A)-1",
105 expected: "A-1",
106 },
107 {
108 name: "middle",
109 input: "___$(VAR_B)___",
110 expected: "___B___",
111 },
112 {
113 name: "end",
114 input: "___$(VAR_C)",
115 expected: "___C",
116 },
117 {
118 name: "compound",
119 input: "$(VAR_A)_$(VAR_B)_$(VAR_C)",
120 expected: "A_B_C",
121 },
122 {
123 name: "escape & expand",
124 input: "$$(VAR_B)_$(VAR_A)",
125 expected: "$(VAR_B)_A",
126 },
127 {
128 name: "compound escape",
129 input: "$$(VAR_A)_$$(VAR_B)",
130 expected: "$(VAR_A)_$(VAR_B)",
131 },
132 {
133 name: "mixed in escapes",
134 input: "f000-$$VAR_A",
135 expected: "f000-$VAR_A",
136 },
137 {
138 name: "backslash escape ignored",
139 input: "foo\\$(VAR_C)bar",
140 expected: "foo\\Cbar",
141 },
142 {
143 name: "backslash escape ignored",
144 input: "foo\\\\$(VAR_C)bar",
145 expected: "foo\\\\Cbar",
146 },
147 {
148 name: "lots of backslashes",
149 input: "foo\\\\\\\\$(VAR_A)bar",
150 expected: "foo\\\\\\\\Abar",
151 },
152 {
153 name: "nested var references",
154 input: "$(VAR_A$(VAR_B))",
155 expected: "$(VAR_A$(VAR_B))",
156 },
157 {
158 name: "nested var references second type",
159 input: "$(VAR_A$(VAR_B)",
160 expected: "$(VAR_A$(VAR_B)",
161 },
162 {
163 name: "value is a reference",
164 input: "$(VAR_REF)",
165 expected: "$(VAR_A)",
166 },
167 {
168 name: "value is a reference x 2",
169 input: "%%$(VAR_REF)--$(VAR_REF)%%",
170 expected: "%%$(VAR_A)--$(VAR_A)%%",
171 },
172 {
173 name: "empty var",
174 input: "foo$(VAR_EMPTY)bar",
175 expected: "foobar",
176 },
177 {
178 name: "unterminated expression",
179 input: "foo$(VAR_Awhoops!",
180 expected: "foo$(VAR_Awhoops!",
181 },
182 {
183 name: "expression without operator",
184 input: "f00__(VAR_A)__",
185 expected: "f00__(VAR_A)__",
186 },
187 {
188 name: "shell special vars pass through",
189 input: "$?_boo_$!",
190 expected: "$?_boo_$!",
191 },
192 {
193 name: "bare operators are ignored",
194 input: "$VAR_A",
195 expected: "$VAR_A",
196 },
197 {
198 name: "undefined vars are passed through",
199 input: "$(VAR_DNE)",
200 expected: "$(VAR_DNE)",
201 },
202 {
203 name: "multiple (even) operators, var undefined",
204 input: "$$$$$$(BIG_MONEY)",
205 expected: "$$$(BIG_MONEY)",
206 },
207 {
208 name: "multiple (even) operators, var defined",
209 input: "$$$$$$(VAR_A)",
210 expected: "$$$(VAR_A)",
211 },
212 {
213 name: "multiple (odd) operators, var undefined",
214 input: "$$$$$$$(GOOD_ODDS)",
215 expected: "$$$$(GOOD_ODDS)",
216 },
217 {
218 name: "multiple (odd) operators, var defined",
219 input: "$$$$$$$(VAR_A)",
220 expected: "$$$A",
221 },
222 {
223 name: "missing open expression",
224 input: "$VAR_A)",
225 expected: "$VAR_A)",
226 },
227 {
228 name: "shell syntax ignored",
229 input: "${VAR_A}",
230 expected: "${VAR_A}",
231 },
232 {
233 name: "trailing incomplete expression not consumed",
234 input: "$(VAR_B)_______$(A",
235 expected: "B_______$(A",
236 },
237 {
238 name: "trailing incomplete expression, no content, is not consumed",
239 input: "$(VAR_C)_______$(",
240 expected: "C_______$(",
241 },
242 {
243 name: "operator at end of input string is preserved",
244 input: "$(VAR_A)foobarzab$",
245 expected: "Afoobarzab$",
246 },
247 {
248 name: "shell escaped incomplete expr",
249 input: "foo-\\$(VAR_A",
250 expected: "foo-\\$(VAR_A",
251 },
252 {
253 name: "lots of $( in middle",
254 input: "--$($($($($--",
255 expected: "--$($($($($--",
256 },
257 {
258 name: "lots of $( in beginning",
259 input: "$($($($($--foo$(",
260 expected: "$($($($($--foo$(",
261 },
262 {
263 name: "lots of $( at end",
264 input: "foo0--$($($($(",
265 expected: "foo0--$($($($(",
266 },
267 {
268 name: "escaped operators in variable names are not escaped",
269 input: "$(foo$$var)",
270 expected: "$(foo$$var)",
271 },
272 {
273 name: "newline not expanded",
274 input: "\n",
275 expected: "\n",
276 },
277 }
278
279 for _, tc := range cases {
280 expanded := Expand(tc.input, mapping)
281 if e, a := tc.expected, expanded; e != a {
282 t.Errorf("%v: expected %q, got %q", tc.name, e, a)
283 }
284 }
285 }
286
View as plain text