]> git.proxmox.com Git - systemd.git/blob - src/test/test-env-util.c
New upstream version 249~rc1
[systemd.git] / src / test / test-env-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "env-util.h"
4 #include "fd-util.h"
5 #include "fileio.h"
6 #include "fs-util.h"
7 #include "parse-util.h"
8 #include "process-util.h"
9 #include "serialize.h"
10 #include "string-util.h"
11 #include "strv.h"
12 #include "tests.h"
13 #include "util.h"
14
15 static void test_strv_env_delete(void) {
16 log_info("/* %s */", __func__);
17
18 _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
19
20 a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
21 assert_se(a);
22
23 b = strv_new("PIEP", "FOO");
24 assert_se(b);
25
26 c = strv_new("SCHLUMPF");
27 assert_se(c);
28
29 d = strv_env_delete(a, 2, b, c);
30 assert_se(d);
31
32 assert_se(streq(d[0], "WALDO=WALDO"));
33 assert_se(streq(d[1], "WALDO="));
34 assert_se(strv_length(d) == 2);
35 }
36
37 static void test_strv_env_get(void) {
38 log_info("/* %s */", __func__);
39
40 char **l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
41
42 assert_se(streq(strv_env_get(l, "ONE_OR_TWO"), "2"));
43 assert_se(streq(strv_env_get(l, "THREE"), "3"));
44 assert_se(streq(strv_env_get(l, "FOUR"), "4"));
45 }
46
47 static void test_strv_env_pairs_get(void) {
48 log_info("/* %s */", __func__);
49
50 char **l = STRV_MAKE("ONE_OR_TWO", "1", "THREE", "3", "ONE_OR_TWO", "2", "FOUR", "4", "FIVE", "5", "SIX", "FIVE", "SEVEN", "7");
51
52 assert_se(streq(strv_env_pairs_get(l, "ONE_OR_TWO"), "2"));
53 assert_se(streq(strv_env_pairs_get(l, "THREE"), "3"));
54 assert_se(streq(strv_env_pairs_get(l, "FOUR"), "4"));
55 assert_se(streq(strv_env_pairs_get(l, "FIVE"), "5"));
56 }
57
58 static void test_strv_env_unset(void) {
59 log_info("/* %s */", __func__);
60
61 _cleanup_strv_free_ char **l = NULL;
62
63 l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
64 assert_se(l);
65
66 assert_se(strv_env_unset(l, "SCHLUMPF") == l);
67
68 assert_se(streq(l[0], "PIEP"));
69 assert_se(streq(l[1], "NANANANA=YES"));
70 assert_se(strv_length(l) == 2);
71 }
72
73 static void test_strv_env_merge(void) {
74 log_info("/* %s */", __func__);
75
76 _cleanup_strv_free_ char **a = NULL, **b = NULL, **r = NULL;
77
78 a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
79 assert_se(a);
80
81 b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES");
82 assert_se(b);
83
84 r = strv_env_merge(2, a, b);
85 assert_se(r);
86 assert_se(streq(r[0], "FOO="));
87 assert_se(streq(r[1], "WALDO="));
88 assert_se(streq(r[2], "PIEP"));
89 assert_se(streq(r[3], "SCHLUMPF=SMURFF"));
90 assert_se(streq(r[4], "PIEP="));
91 assert_se(streq(r[5], "NANANANA=YES"));
92 assert_se(strv_length(r) == 6);
93
94 assert_se(strv_env_clean(r) == r);
95 assert_se(streq(r[0], "FOO="));
96 assert_se(streq(r[1], "WALDO="));
97 assert_se(streq(r[2], "SCHLUMPF=SMURFF"));
98 assert_se(streq(r[3], "PIEP="));
99 assert_se(streq(r[4], "NANANANA=YES"));
100 assert_se(strv_length(r) == 5);
101 }
102
103 static void test_strv_env_replace_strdup(void) {
104 log_info("/* %s */", __func__);
105
106 _cleanup_strv_free_ char **a = NULL;
107
108 assert_se(strv_env_replace_strdup(&a, "a=a") == 1);
109 assert_se(strv_env_replace_strdup(&a, "b=b") == 1);
110 assert_se(strv_env_replace_strdup(&a, "a=A") == 0);
111
112 assert_se(strv_length(a) == 2);
113 strv_sort(a);
114 assert_se(streq(a[0], "a=A"));
115 assert_se(streq(a[1], "b=b"));
116 }
117
118 static void test_strv_env_assign(void) {
119 log_info("/* %s */", __func__);
120
121 _cleanup_strv_free_ char **a = NULL;
122
123 assert_se(strv_env_assign(&a, "a", "a") == 1);
124 assert_se(strv_env_assign(&a, "b", "b") == 1);
125 assert_se(strv_env_assign(&a, "a", "A") == 0);
126 assert_se(strv_env_assign(&a, "b", NULL) == 0);
127
128 assert_se(strv_env_assign(&a, "a=", "B") == -EINVAL);
129
130 assert_se(strv_length(a) == 1);
131 assert_se(streq(a[0], "a=A"));
132 }
133
134 static void test_env_strv_get_n(void) {
135 log_info("/* %s */", __func__);
136
137 const char *_env[] = {
138 "FOO=NO NO NO",
139 "FOO=BAR BAR",
140 "BAR=waldo",
141 "PATH=unset",
142 NULL
143 };
144 char **env = (char**) _env;
145
146 assert_se(streq(strv_env_get_n(env, "FOO__", 3, 0), "BAR BAR"));
147 assert_se(streq(strv_env_get_n(env, "FOO__", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR"));
148 assert_se(streq(strv_env_get_n(env, "FOO", 3, 0), "BAR BAR"));
149 assert_se(streq(strv_env_get_n(env, "FOO", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR"));
150
151 assert_se(streq(strv_env_get_n(env, "PATH__", 4, 0), "unset"));
152 assert_se(streq(strv_env_get_n(env, "PATH", 4, 0), "unset"));
153 assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset"));
154 assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset"));
155
156 env[3] = NULL; /* kill our $PATH */
157
158 assert_se(!strv_env_get_n(env, "PATH__", 4, 0));
159 assert_se(!strv_env_get_n(env, "PATH", 4, 0));
160 assert_se(streq_ptr(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT),
161 getenv("PATH")));
162 assert_se(streq_ptr(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT),
163 getenv("PATH")));
164 }
165
166 static void test_replace_env(bool braceless) {
167 log_info("/* %s(braceless=%s) */", __func__, yes_no(braceless));
168
169 const char *env[] = {
170 "FOO=BAR BAR",
171 "BAR=waldo",
172 NULL
173 };
174 _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL;
175 unsigned flags = REPLACE_ENV_ALLOW_BRACELESS*braceless;
176
177 t = replace_env("FOO=$FOO=${FOO}", (char**) env, flags);
178 assert_se(streq(t, braceless ? "FOO=BAR BAR=BAR BAR" : "FOO=$FOO=BAR BAR"));
179
180 s = replace_env("BAR=$BAR=${BAR}", (char**) env, flags);
181 assert_se(streq(s, braceless ? "BAR=waldo=waldo" : "BAR=$BAR=waldo"));
182
183 q = replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env, flags);
184 assert_se(streq(q, braceless ? "BARBAR==" : "BARBAR=$BARBAR="));
185
186 r = replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env, flags);
187 assert_se(streq(r, braceless ? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo"));
188
189 p = replace_env("${BAR}$BAR$BAR", (char**) env, flags);
190 assert_se(streq(p, braceless ? "waldowaldowaldo" : "waldo$BAR$BAR"));
191 }
192
193 static void test_replace_env2(bool extended) {
194 log_info("/* %s(extended=%s) */", __func__, yes_no(extended));
195
196 const char *env[] = {
197 "FOO=foo",
198 "BAR=bar",
199 NULL
200 };
201 _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL, *x = NULL;
202 unsigned flags = REPLACE_ENV_ALLOW_EXTENDED*extended;
203
204 t = replace_env("FOO=${FOO:-${BAR}}", (char**) env, flags);
205 assert_se(streq(t, extended ? "FOO=foo" : "FOO=${FOO:-bar}"));
206
207 s = replace_env("BAR=${XXX:-${BAR}}", (char**) env, flags);
208 assert_se(streq(s, extended ? "BAR=bar" : "BAR=${XXX:-bar}"));
209
210 q = replace_env("XXX=${XXX:+${BAR}}", (char**) env, flags);
211 assert_se(streq(q, extended ? "XXX=" : "XXX=${XXX:+bar}"));
212
213 r = replace_env("FOO=${FOO:+${BAR}}", (char**) env, flags);
214 assert_se(streq(r, extended ? "FOO=bar" : "FOO=${FOO:+bar}"));
215
216 p = replace_env("FOO=${FOO:-${BAR}post}", (char**) env, flags);
217 assert_se(streq(p, extended ? "FOO=foo" : "FOO=${FOO:-barpost}"));
218
219 x = replace_env("XXX=${XXX:+${BAR}post}", (char**) env, flags);
220 assert_se(streq(x, extended ? "XXX=" : "XXX=${XXX:+barpost}"));
221 }
222
223 static void test_replace_env_argv(void) {
224 log_info("/* %s */", __func__);
225
226 const char *env[] = {
227 "FOO=BAR BAR",
228 "BAR=waldo",
229 NULL
230 };
231 const char *line[] = {
232 "FOO$FOO",
233 "FOO$FOOFOO",
234 "FOO${FOO}$FOO",
235 "FOO${FOO}",
236 "${FOO}",
237 "$FOO",
238 "$FOO$FOO",
239 "${FOO}${BAR}",
240 "${FOO",
241 "FOO$$${FOO}",
242 "$$FOO${FOO}",
243 "${FOO:-${BAR}}",
244 "${QUUX:-${FOO}}",
245 "${FOO:+${BAR}}",
246 "${QUUX:+${BAR}}",
247 "${FOO:+|${BAR}|}}",
248 "${FOO:+|${BAR}{|}",
249 NULL
250 };
251 _cleanup_strv_free_ char **r = NULL;
252
253 r = replace_env_argv((char**) line, (char**) env);
254 assert_se(r);
255 assert_se(streq(r[0], "FOO$FOO"));
256 assert_se(streq(r[1], "FOO$FOOFOO"));
257 assert_se(streq(r[2], "FOOBAR BAR$FOO"));
258 assert_se(streq(r[3], "FOOBAR BAR"));
259 assert_se(streq(r[4], "BAR BAR"));
260 assert_se(streq(r[5], "BAR"));
261 assert_se(streq(r[6], "BAR"));
262 assert_se(streq(r[7], "BAR BARwaldo"));
263 assert_se(streq(r[8], "${FOO"));
264 assert_se(streq(r[9], "FOO$BAR BAR"));
265 assert_se(streq(r[10], "$FOOBAR BAR"));
266 assert_se(streq(r[11], "${FOO:-waldo}"));
267 assert_se(streq(r[12], "${QUUX:-BAR BAR}"));
268 assert_se(streq(r[13], "${FOO:+waldo}"));
269 assert_se(streq(r[14], "${QUUX:+waldo}"));
270 assert_se(streq(r[15], "${FOO:+|waldo|}}"));
271 assert_se(streq(r[16], "${FOO:+|waldo{|}"));
272 assert_se(strv_length(r) == 17);
273 }
274
275 static void test_env_clean(void) {
276 log_info("/* %s */", __func__);
277
278 _cleanup_strv_free_ char **e = strv_new("FOOBAR=WALDO",
279 "FOOBAR=WALDO",
280 "FOOBAR",
281 "F",
282 "X=",
283 "F=F",
284 "=",
285 "=F",
286 "",
287 "0000=000",
288 "äöüß=abcd",
289 "abcd=äöüß",
290 "xyz\n=xyz",
291 "xyz=xyz\n",
292 "another=one",
293 "another=final one",
294 "CRLF=\r\n",
295 "LESS_TERMCAP_mb=\x1b[01;31m",
296 "BASH_FUNC_foo%%=() { echo foo\n}");
297 assert_se(e);
298 assert_se(!strv_env_is_valid(e));
299 assert_se(strv_env_clean(e) == e);
300 assert_se(strv_env_is_valid(e));
301
302 assert_se(streq(e[0], "FOOBAR=WALDO"));
303 assert_se(streq(e[1], "X="));
304 assert_se(streq(e[2], "F=F"));
305 assert_se(streq(e[3], "abcd=äöüß"));
306 assert_se(streq(e[4], "xyz=xyz\n"));
307 assert_se(streq(e[5], "another=final one"));
308 assert_se(streq(e[6], "CRLF=\r\n"));
309 assert_se(streq(e[7], "LESS_TERMCAP_mb=\x1b[01;31m"));
310 assert_se(e[8] == NULL);
311 }
312
313 static void test_env_name_is_valid(void) {
314 log_info("/* %s */", __func__);
315
316 assert_se(env_name_is_valid("test"));
317
318 assert_se(!env_name_is_valid(NULL));
319 assert_se(!env_name_is_valid(""));
320 assert_se(!env_name_is_valid("xxx\a"));
321 assert_se(!env_name_is_valid("xxx\007b"));
322 assert_se(!env_name_is_valid("\007\009"));
323 assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
324 assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
325 }
326
327 static void test_env_value_is_valid(void) {
328 log_info("/* %s */", __func__);
329
330 assert_se(env_value_is_valid(""));
331 assert_se(env_value_is_valid("głąb kapuściany"));
332 assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
333 assert_se(env_value_is_valid("tab\tcharacter"));
334 assert_se(env_value_is_valid("new\nline"));
335 assert_se(env_value_is_valid("Show this?\rNope. Show that!"));
336 assert_se(env_value_is_valid("new DOS\r\nline"));
337
338 assert_se(!env_value_is_valid("\xc5")); /* A truncated utf-8-encoded "ł".
339 * We currently disallow that. */
340 }
341
342 static void test_env_assignment_is_valid(void) {
343 log_info("/* %s */", __func__);
344
345 assert_se(env_assignment_is_valid("a="));
346 assert_se(env_assignment_is_valid("b=głąb kapuściany"));
347 assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
348 assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
349 assert_se(env_assignment_is_valid("f=tab\tcharacter"));
350 assert_se(env_assignment_is_valid("g=new\nline"));
351
352 assert_se(!env_assignment_is_valid("="));
353 assert_se(!env_assignment_is_valid("a b="));
354 assert_se(!env_assignment_is_valid("a ="));
355 assert_se(!env_assignment_is_valid(" b="));
356 /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
357 assert_se(!env_assignment_is_valid("a.b="));
358 assert_se(!env_assignment_is_valid("a-b="));
359 assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
360 assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
361 assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
362 }
363
364 static void test_putenv_dup(void) {
365 log_info("/* %s */", __func__);
366
367 assert_se(putenv_dup("A=a1", true) == 0);
368 assert_se(streq_ptr(getenv("A"), "a1"));
369 assert_se(putenv_dup("A=a1", true) == 0);
370 assert_se(streq_ptr(getenv("A"), "a1"));
371 assert_se(putenv_dup("A=a2", false) == 0);
372 assert_se(streq_ptr(getenv("A"), "a1"));
373 assert_se(putenv_dup("A=a2", true) == 0);
374 assert_se(streq_ptr(getenv("A"), "a2"));
375 }
376
377 static void test_setenv_systemd_exec_pid(void) {
378 _cleanup_free_ char *saved = NULL;
379 const char *e;
380 pid_t p;
381
382 log_info("/* %s */", __func__);
383
384 e = getenv("SYSTEMD_EXEC_PID");
385 if (e)
386 assert_se(saved = strdup(e));
387
388 assert_se(unsetenv("SYSTEMD_EXEC_PID") >= 0);
389 assert_se(setenv_systemd_exec_pid(true) == 0);
390 assert_se(!getenv("SYSTEMD_EXEC_PID"));
391
392 assert_se(setenv("SYSTEMD_EXEC_PID", "*", 1) >= 0);
393 assert_se(setenv_systemd_exec_pid(true) == 0);
394 assert_se(e = getenv("SYSTEMD_EXEC_PID"));
395 assert_se(streq(e, "*"));
396
397 assert_se(setenv("SYSTEMD_EXEC_PID", "123abc", 1) >= 0);
398 assert_se(setenv_systemd_exec_pid(true) == 1);
399 assert_se(e = getenv("SYSTEMD_EXEC_PID"));
400 assert_se(parse_pid(e, &p) >= 0);
401 assert_se(p == getpid_cached());
402
403 assert_se(unsetenv("SYSTEMD_EXEC_PID") >= 0);
404 assert_se(setenv_systemd_exec_pid(false) == 1);
405 assert_se(e = getenv("SYSTEMD_EXEC_PID"));
406 assert_se(parse_pid(e, &p) >= 0);
407 assert_se(p == getpid_cached());
408
409 assert_se(set_unset_env("SYSTEMD_EXEC_PID", saved, 1) >= 0);
410 }
411
412 int main(int argc, char *argv[]) {
413 test_setup_logging(LOG_DEBUG);
414
415 test_strv_env_delete();
416 test_strv_env_get();
417 test_strv_env_pairs_get();
418 test_strv_env_unset();
419 test_strv_env_merge();
420 test_strv_env_replace_strdup();
421 test_strv_env_assign();
422 test_env_strv_get_n();
423 test_replace_env(false);
424 test_replace_env(true);
425 test_replace_env2(false);
426 test_replace_env2(true);
427 test_replace_env_argv();
428 test_env_clean();
429 test_env_name_is_valid();
430 test_env_value_is_valid();
431 test_env_assignment_is_valid();
432 test_putenv_dup();
433 test_setenv_systemd_exec_pid();
434
435 return 0;
436 }