]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-env-util.c
d45f210689a42065a9735150f4703579cc7c2c34
[thirdparty/systemd.git] / src / test / test-env-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <stdlib.h>
4 #include <unistd.h>
5
6 #include "env-util.h"
7 #include "parse-util.h"
8 #include "process-util.h"
9 #include "strv.h"
10 #include "tests.h"
11
12 TEST(strv_env_delete) {
13 _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
14
15 a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
16 assert_se(a);
17
18 b = strv_new("PIEP", "FOO");
19 assert_se(b);
20
21 c = strv_new("SCHLUMPF");
22 assert_se(c);
23
24 d = strv_env_delete(a, 2, b, c);
25 assert_se(d);
26
27 ASSERT_STREQ(d[0], "WALDO=WALDO");
28 ASSERT_STREQ(d[1], "WALDO=");
29 assert_se(strv_length(d) == 2);
30 }
31
32 TEST(strv_env_get) {
33 char **l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
34
35 ASSERT_STREQ(strv_env_get(l, "ONE_OR_TWO"), "2");
36 ASSERT_STREQ(strv_env_get(l, "THREE"), "3");
37 ASSERT_STREQ(strv_env_get(l, "FOUR"), "4");
38 }
39
40 TEST(strv_env_pairs_get) {
41 char **l = STRV_MAKE("ONE_OR_TWO", "1", "THREE", "3", "ONE_OR_TWO", "2", "FOUR", "4", "FIVE", "5", "SIX", "FIVE", "SEVEN", "7");
42
43 ASSERT_STREQ(strv_env_pairs_get(l, "ONE_OR_TWO"), "2");
44 ASSERT_STREQ(strv_env_pairs_get(l, "THREE"), "3");
45 ASSERT_STREQ(strv_env_pairs_get(l, "FOUR"), "4");
46 ASSERT_STREQ(strv_env_pairs_get(l, "FIVE"), "5");
47 }
48
49 TEST(strv_env_unset) {
50 _cleanup_strv_free_ char **l = NULL;
51
52 l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
53 assert_se(l);
54
55 assert_se(strv_env_unset(l, "SCHLUMPF") == l);
56
57 ASSERT_STREQ(l[0], "PIEP");
58 ASSERT_STREQ(l[1], "NANANANA=YES");
59 assert_se(strv_length(l) == 2);
60 }
61
62 TEST(strv_env_merge) {
63 char **a = STRV_MAKE("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", "EQ===");
64 char **b = STRV_MAKE("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES");
65
66 _cleanup_strv_free_ char **r = strv_env_merge(NULL, a, NULL, b, NULL, a, b, b, NULL);
67 assert_se(r);
68 ASSERT_STREQ(r[0], "FOO=");
69 ASSERT_STREQ(r[1], "WALDO=");
70 ASSERT_STREQ(r[2], "PIEP");
71 ASSERT_STREQ(r[3], "SCHLUMPF=SMURFF");
72 ASSERT_STREQ(r[4], "EQ===");
73 ASSERT_STREQ(r[5], "PIEP=");
74 ASSERT_STREQ(r[6], "NANANANA=YES");
75 assert_se(strv_length(r) == 7);
76
77 assert_se(strv_env_clean(r) == r);
78 ASSERT_STREQ(r[0], "FOO=");
79 ASSERT_STREQ(r[1], "WALDO=");
80 ASSERT_STREQ(r[2], "SCHLUMPF=SMURFF");
81 ASSERT_STREQ(r[3], "EQ===");
82 ASSERT_STREQ(r[4], "PIEP=");
83 ASSERT_STREQ(r[5], "NANANANA=YES");
84 assert_se(strv_length(r) == 6);
85 }
86
87 TEST(strv_env_replace_strdup) {
88 _cleanup_strv_free_ char **a = NULL;
89
90 assert_se(strv_env_replace_strdup(&a, "a=a") == 1);
91 assert_se(strv_env_replace_strdup(&a, "b=b") == 1);
92 assert_se(strv_env_replace_strdup(&a, "a=A") == 0);
93 assert_se(strv_env_replace_strdup(&a, "c") == -EINVAL);
94
95 assert_se(strv_length(a) == 2);
96 strv_sort(a);
97 ASSERT_STREQ(a[0], "a=A");
98 ASSERT_STREQ(a[1], "b=b");
99 }
100
101 TEST(strv_env_replace_strdup_passthrough) {
102 _cleanup_strv_free_ char **a = NULL;
103
104 assert_se(putenv((char*) "a=a") == 0);
105 assert_se(putenv((char*) "b=") == 0);
106 assert_se(unsetenv("c") == 0);
107
108 assert_se(strv_env_replace_strdup_passthrough(&a, "a") == 1);
109 assert_se(strv_env_replace_strdup_passthrough(&a, "b") == 1);
110 assert_se(strv_env_replace_strdup_passthrough(&a, "c") == 1);
111 assert_se(strv_env_replace_strdup_passthrough(&a, "a") == 0);
112 assert_se(strv_env_replace_strdup_passthrough(&a, "$a") == -EINVAL);
113
114 assert_se(strv_length(a) == 3);
115 ASSERT_STREQ(a[0], "a=a");
116 ASSERT_STREQ(a[1], "b=");
117 ASSERT_STREQ(a[2], "c=");
118 }
119
120 TEST(strv_env_assign) {
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_STREQ(a[0], "a=A");
132 }
133
134 TEST(strv_env_assignf) {
135 _cleanup_strv_free_ char **a = NULL;
136
137 assert_se(strv_env_assignf(&a, "a", "a") > 0);
138 assert_se(strv_env_assignf(&a, "a", "%c", 'a') == 0);
139
140 assert_se(strv_env_assignf(&a, "c", "xxx%iyyy", 5) > 0);
141 assert_se(strv_length(a) == 2);
142 assert_se(strv_equal(a, STRV_MAKE("a=a", "c=xxx5yyy")));
143 assert_se(strv_env_assignf(&a, "c", NULL) == 0);
144
145 assert_se(strv_env_assignf(&a, "b", "b") > 0);
146 assert_se(strv_env_assignf(&a, "a", "A") == 0);
147 assert_se(strv_env_assignf(&a, "b", NULL) == 0);
148
149 assert_se(strv_env_assignf(&a, "a=", "B") == -EINVAL);
150
151 assert_se(strv_length(a) == 1);
152 ASSERT_STREQ(a[0], "a=A");
153 }
154
155 TEST(strv_env_assign_many) {
156 _cleanup_strv_free_ char **a = NULL;
157
158 assert_se(strv_env_assign_many(&a, "a", "a", "b", "b") >= 0);
159
160 assert_se(strv_length(a) == 2);
161 assert_se(strv_contains(a, "a=a"));
162 assert_se(strv_contains(a, "b=b"));
163
164 assert_se(strv_env_assign_many(&a, "a", "A", "b", "b", "c", "c") >= 0);
165 assert_se(strv_length(a) == 3);
166 assert_se(strv_contains(a, "a=A"));
167 assert_se(strv_contains(a, "b=b"));
168 assert_se(strv_contains(a, "c=c"));
169
170 assert_se(strv_env_assign_many(&a, "b", NULL, "c", "C") >= 0);
171 assert_se(strv_length(a) == 2);
172 assert_se(strv_contains(a, "a=A"));
173 assert_se(strv_contains(a, "c=C"));
174
175 assert_se(strv_env_assign_many(&a, "a=", "B") == -EINVAL);
176 assert_se(strv_length(a) == 2);
177 assert_se(strv_contains(a, "a=A"));
178 assert_se(strv_contains(a, "c=C"));
179 }
180
181 TEST(env_strv_get_n) {
182 const char *_env[] = {
183 "FOO=NO NO NO",
184 "FOO=BAR BAR",
185 "BAR=waldo",
186 "PATH=unset",
187 NULL
188 };
189 char **env = (char**) _env;
190
191 ASSERT_STREQ(strv_env_get_n(env, "FOO__", 3, 0), "BAR BAR");
192 ASSERT_STREQ(strv_env_get_n(env, "FOO__", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR");
193 ASSERT_STREQ(strv_env_get_n(env, "FOO", 3, 0), "BAR BAR");
194 ASSERT_STREQ(strv_env_get_n(env, "FOO", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR");
195
196 ASSERT_STREQ(strv_env_get_n(env, "PATH__", 4, 0), "unset");
197 ASSERT_STREQ(strv_env_get_n(env, "PATH", 4, 0), "unset");
198 ASSERT_STREQ(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset");
199 ASSERT_STREQ(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset");
200
201 env[3] = NULL; /* kill our $PATH */
202
203 assert_se(!strv_env_get_n(env, "PATH__", 4, 0));
204 assert_se(!strv_env_get_n(env, "PATH", 4, 0));
205 assert_se(streq_ptr(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT),
206 getenv("PATH")));
207 assert_se(streq_ptr(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT),
208 getenv("PATH")));
209 }
210
211 static void test_replace_env1(bool braceless) {
212 log_info("/* %s(braceless=%s) */", __func__, yes_no(braceless));
213
214 const char *env[] = {
215 "FOO=BAR BAR",
216 "BAR=waldo",
217 NULL
218 };
219 _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL;
220 unsigned flags = REPLACE_ENV_ALLOW_BRACELESS*braceless;
221
222 assert_se(replace_env("FOO=$FOO=${FOO}", (char**) env, flags, &t) >= 0);
223 ASSERT_STREQ(t, braceless ? "FOO=BAR BAR=BAR BAR" : "FOO=$FOO=BAR BAR");
224
225 assert_se(replace_env("BAR=$BAR=${BAR}", (char**) env, flags, &s) >= 0);
226 ASSERT_STREQ(s, braceless ? "BAR=waldo=waldo" : "BAR=$BAR=waldo");
227
228 assert_se(replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env, flags, &q) >= 0);
229 ASSERT_STREQ(q, braceless ? "BARBAR==" : "BARBAR=$BARBAR=");
230
231 assert_se(replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env, flags, &r) >= 0);
232 ASSERT_STREQ(r, braceless ? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo");
233
234 assert_se(replace_env("${BAR}$BAR$BAR", (char**) env, flags, &p) >= 0);
235 ASSERT_STREQ(p, braceless ? "waldowaldowaldo" : "waldo$BAR$BAR");
236 }
237
238 static void test_replace_env2(bool extended) {
239 log_info("/* %s(extended=%s) */", __func__, yes_no(extended));
240
241 const char *env[] = {
242 "FOO=foo",
243 "BAR=bar",
244 NULL
245 };
246 _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL, *x = NULL, *y = NULL;
247 unsigned flags = REPLACE_ENV_ALLOW_EXTENDED*extended;
248
249 assert_se(replace_env("FOO=${FOO:-${BAR}}", (char**) env, flags, &t) >= 0);
250 ASSERT_STREQ(t, extended ? "FOO=foo" : "FOO=${FOO:-bar}");
251
252 assert_se(replace_env("BAR=${XXX:-${BAR}}", (char**) env, flags, &s) >= 0);
253 ASSERT_STREQ(s, extended ? "BAR=bar" : "BAR=${XXX:-bar}");
254
255 assert_se(replace_env("XXX=${XXX:+${BAR}}", (char**) env, flags, &q) >= 0);
256 ASSERT_STREQ(q, extended ? "XXX=" : "XXX=${XXX:+bar}");
257
258 assert_se(replace_env("FOO=${FOO:+${BAR}}", (char**) env, flags, &r) >= 0);
259 ASSERT_STREQ(r, extended ? "FOO=bar" : "FOO=${FOO:+bar}");
260
261 assert_se(replace_env("FOO=${FOO:-${BAR}post}", (char**) env, flags, &p) >= 0);
262 ASSERT_STREQ(p, extended ? "FOO=foo" : "FOO=${FOO:-barpost}");
263
264 assert_se(replace_env("XXX=${XXX:+${BAR}post}", (char**) env, flags, &x) >= 0);
265 ASSERT_STREQ(x, extended ? "XXX=" : "XXX=${XXX:+barpost}");
266
267 assert_se(replace_env("FOO=${FOO}between${BAR:-baz}", (char**) env, flags, &y) >= 0);
268 ASSERT_STREQ(y, extended ? "FOO=foobetweenbar" : "FOO=foobetween${BAR:-baz}");
269 }
270
271 TEST(replace_env) {
272 test_replace_env1(false);
273 test_replace_env1(true);
274 test_replace_env2(false);
275 test_replace_env2(true);
276 }
277
278 TEST(replace_env_argv) {
279 const char *env[] = {
280 "FOO=BAR BAR",
281 "BAR=waldo",
282 NULL
283 };
284 const char *line[] = {
285 "FOO$FOO",
286 "FOO$FOOFOO",
287 "FOO${FOO}$FOO",
288 "FOO${FOO}",
289 "${FOO}",
290 "$FOO",
291 "$FOO$FOO",
292 "${FOO}${BAR}",
293 "${FOO",
294 "FOO$$${FOO}",
295 "$$FOO${FOO}",
296 "${FOO:-${BAR}}",
297 "${QUUX:-${FOO}}",
298 "${FOO:+${BAR}}",
299 "${QUUX:+${BAR}}",
300 "${FOO:+|${BAR}|}}",
301 "${FOO:+|${BAR}{|}",
302 NULL
303 };
304 _cleanup_strv_free_ char **r = NULL;
305
306 assert_se(replace_env_argv((char**) line, (char**) env, &r, NULL, NULL) >= 0);
307 assert_se(r);
308 ASSERT_STREQ(r[0], "FOO$FOO");
309 ASSERT_STREQ(r[1], "FOO$FOOFOO");
310 ASSERT_STREQ(r[2], "FOOBAR BAR$FOO");
311 ASSERT_STREQ(r[3], "FOOBAR BAR");
312 ASSERT_STREQ(r[4], "BAR BAR");
313 ASSERT_STREQ(r[5], "BAR");
314 ASSERT_STREQ(r[6], "BAR");
315 ASSERT_STREQ(r[7], "BAR BARwaldo");
316 ASSERT_STREQ(r[8], "${FOO");
317 ASSERT_STREQ(r[9], "FOO$BAR BAR");
318 ASSERT_STREQ(r[10], "$FOOBAR BAR");
319 ASSERT_STREQ(r[11], "${FOO:-waldo}");
320 ASSERT_STREQ(r[12], "${QUUX:-BAR BAR}");
321 ASSERT_STREQ(r[13], "${FOO:+waldo}");
322 ASSERT_STREQ(r[14], "${QUUX:+waldo}");
323 ASSERT_STREQ(r[15], "${FOO:+|waldo|}}");
324 ASSERT_STREQ(r[16], "${FOO:+|waldo{|}");
325 assert_se(strv_length(r) == 17);
326 }
327
328 TEST(replace_env_argv_bad) {
329
330 const char *env[] = {
331 "FOO=BAR BAR",
332 "BAR=waldo",
333 NULL
334 };
335
336 const char *line[] = {
337 "$FOO",
338 "A${FOO}B",
339 "a${~}${%}b",
340 "x${}y",
341 "$UNSET2",
342 "z${UNSET3}z${UNSET1}z",
343 "piff${UNSET2}piff",
344 NULL
345 };
346
347 _cleanup_strv_free_ char **bad = NULL, **unset = NULL, **replaced = NULL;
348
349 assert_se(replace_env_argv((char**) line, (char**) env, &replaced, &unset, &bad) >= 0);
350
351 assert_se(strv_equal(replaced, STRV_MAKE(
352 "BAR",
353 "BAR",
354 "ABAR BARB",
355 "ab",
356 "xy",
357 "zzz",
358 "piffpiff")));
359
360 assert_se(strv_equal(unset, STRV_MAKE(
361 "UNSET1",
362 "UNSET2",
363 "UNSET3")));
364 assert_se(strv_equal(bad, STRV_MAKE("",
365 "%",
366 "~")));
367 }
368
369 TEST(env_clean) {
370 _cleanup_strv_free_ char **e = strv_new("FOOBAR=WALDO",
371 "FOOBAR=WALDO",
372 "FOOBAR",
373 "F",
374 "X=",
375 "F=F",
376 "=",
377 "=F",
378 "",
379 "0000=000",
380 "äöüß=abcd",
381 "abcd=äöüß",
382 "xyz\n=xyz",
383 "xyz=xyz\n",
384 "another=one",
385 "another=final one",
386 "CRLF=\r\n",
387 "LESS_TERMCAP_mb=\x1b[01;31m",
388 "BASH_FUNC_foo%%=() { echo foo\n}");
389 assert_se(e);
390 assert_se(!strv_env_is_valid(e));
391 assert_se(strv_env_clean(e) == e);
392 assert_se(strv_env_is_valid(e));
393
394 ASSERT_STREQ(e[0], "FOOBAR=WALDO");
395 ASSERT_STREQ(e[1], "X=");
396 ASSERT_STREQ(e[2], "F=F");
397 ASSERT_STREQ(e[3], "abcd=äöüß");
398 ASSERT_STREQ(e[4], "xyz=xyz\n");
399 ASSERT_STREQ(e[5], "another=final one");
400 ASSERT_STREQ(e[6], "CRLF=\r\n");
401 ASSERT_STREQ(e[7], "LESS_TERMCAP_mb=\x1b[01;31m");
402 ASSERT_NULL(e[8]);
403 }
404
405 TEST(env_name_is_valid) {
406 assert_se(env_name_is_valid("test"));
407
408 assert_se(!env_name_is_valid(NULL));
409 assert_se(!env_name_is_valid(""));
410 assert_se(!env_name_is_valid("xxx\a"));
411 assert_se(!env_name_is_valid("xxx\007b"));
412 assert_se(!env_name_is_valid("\007\009"));
413 assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
414 assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
415 }
416
417 TEST(env_value_is_valid) {
418 assert_se(env_value_is_valid(""));
419 assert_se(env_value_is_valid("głąb kapuściany"));
420 assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
421 assert_se(env_value_is_valid("tab\tcharacter"));
422 assert_se(env_value_is_valid("new\nline"));
423 assert_se(env_value_is_valid("Show this?\rNope. Show that!"));
424 assert_se(env_value_is_valid("new DOS\r\nline"));
425
426 assert_se(!env_value_is_valid("\xc5")); /* A truncated utf-8-encoded "ł".
427 * We currently disallow that. */
428 }
429
430 TEST(env_assignment_is_valid) {
431 assert_se(env_assignment_is_valid("a="));
432 assert_se(env_assignment_is_valid("b=głąb kapuściany"));
433 assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
434 assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
435 assert_se(env_assignment_is_valid("f=tab\tcharacter"));
436 assert_se(env_assignment_is_valid("g=new\nline"));
437
438 assert_se(!env_assignment_is_valid("="));
439 assert_se(!env_assignment_is_valid("a b="));
440 assert_se(!env_assignment_is_valid("a ="));
441 assert_se(!env_assignment_is_valid(" b="));
442 /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
443 assert_se(!env_assignment_is_valid("a.b="));
444 assert_se(!env_assignment_is_valid("a-b="));
445 assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
446 assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
447 assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
448 }
449
450 TEST(putenv_dup) {
451 assert_se(putenv_dup("A=a1", true) == 0);
452 ASSERT_STREQ(getenv("A"), "a1");
453 assert_se(putenv_dup("A=a1", true) == 0);
454 ASSERT_STREQ(getenv("A"), "a1");
455 assert_se(putenv_dup("A=a2", false) == 0);
456 ASSERT_STREQ(getenv("A"), "a1");
457 assert_se(putenv_dup("A=a2", true) == 0);
458 ASSERT_STREQ(getenv("A"), "a2");
459 }
460
461 TEST(setenv_systemd_exec_pid) {
462 _cleanup_free_ char *saved = NULL;
463 const char *e;
464 pid_t p;
465
466 e = getenv("SYSTEMD_EXEC_PID");
467 if (e)
468 assert_se(saved = strdup(e));
469
470 assert_se(unsetenv("SYSTEMD_EXEC_PID") >= 0);
471 assert_se(setenv_systemd_exec_pid(true) == 0);
472 assert_se(!getenv("SYSTEMD_EXEC_PID"));
473
474 assert_se(setenv("SYSTEMD_EXEC_PID", "*", 1) >= 0);
475 assert_se(setenv_systemd_exec_pid(true) == 0);
476 assert_se(e = getenv("SYSTEMD_EXEC_PID"));
477 ASSERT_STREQ(e, "*");
478
479 assert_se(setenv("SYSTEMD_EXEC_PID", "123abc", 1) >= 0);
480 assert_se(setenv_systemd_exec_pid(true) == 1);
481 assert_se(e = getenv("SYSTEMD_EXEC_PID"));
482 assert_se(parse_pid(e, &p) >= 0);
483 assert_se(p == getpid_cached());
484
485 assert_se(unsetenv("SYSTEMD_EXEC_PID") >= 0);
486 assert_se(setenv_systemd_exec_pid(false) == 1);
487 assert_se(e = getenv("SYSTEMD_EXEC_PID"));
488 assert_se(parse_pid(e, &p) >= 0);
489 assert_se(p == getpid_cached());
490
491 assert_se(set_unset_env("SYSTEMD_EXEC_PID", saved, 1) >= 0);
492 }
493
494 TEST(getenv_steal_erase) {
495 int r;
496
497 r = safe_fork("(sd-getenvstealerase)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
498 if (r == 0) {
499 _cleanup_strv_free_ char **l = NULL;
500
501 /* child */
502
503 assert_se(getenv_steal_erase("thisenvvardefinitelywontexist", NULL) == 0);
504
505 l = strv_new("FOO=BAR", "QUUX=PIFF", "ONE=TWO", "A=B");
506 assert_se(strv_length(l) == 4);
507
508 environ = l;
509
510 STRV_FOREACH(e, environ) {
511 _cleanup_free_ char *n = NULL, *copy1 = NULL, *copy2 = NULL;
512 char *eq;
513
514 eq = strchr(*e, '=');
515 if (!eq)
516 continue;
517
518 n = strndup(*e, eq - *e);
519 assert_se(n);
520
521 copy1 = strdup(eq + 1);
522 assert_se(copy1);
523
524 ASSERT_STREQ(getenv(n), copy1);
525 assert_se(getenv(n) == eq + 1);
526 assert_se(getenv_steal_erase(n, &copy2) > 0);
527 ASSERT_STREQ(copy1, copy2);
528 assert_se(isempty(eq + 1));
529 assert_se(!getenv(n));
530 }
531
532 environ = NULL;
533 l = strv_free(l);
534
535 _exit(EXIT_SUCCESS);
536 }
537
538 assert_se(r > 0);
539 }
540
541 TEST(strv_env_name_is_valid) {
542 assert_se(strv_env_name_is_valid(STRV_MAKE("HOME", "USER", "SHELL", "PATH")));
543 assert_se(!strv_env_name_is_valid(STRV_MAKE("", "PATH", "home", "user", "SHELL")));
544 assert_se(!strv_env_name_is_valid(STRV_MAKE("HOME", "USER", "SHELL", "USER")));
545 }
546
547 TEST(getenv_path_list) {
548 _cleanup_strv_free_ char **path_list = NULL;
549
550 /* Empty paths */
551 FOREACH_STRING(s, "", ":", ":::::", " : ::: :: :") {
552 assert_se(setenv("TEST_GETENV_PATH_LIST", s, 1) >= 0);
553 assert_se(getenv_path_list("TEST_GETENV_PATH_LIST", &path_list) == -EINVAL);
554 assert_se(!path_list);
555 }
556
557 /* Invalid paths */
558 FOREACH_STRING(s, ".", "..", "/../", "/", "/foo/bar/baz/../foo", "foo/bar/baz") {
559 assert_se(setenv("TEST_GETENV_PATH_LIST", s, 1) >= 0);
560 assert_se(getenv_path_list("TEST_GETENV_PATH_LIST", &path_list) == -EINVAL);
561 assert_se(!path_list);
562 }
563
564 /* Valid paths mixed with invalid ones */
565 assert_se(setenv("TEST_GETENV_PATH_LIST", "/foo:/bar/baz:/../:/hello", 1) >= 0);
566 assert_se(getenv_path_list("TEST_GETENV_PATH_LIST", &path_list) == -EINVAL);
567 assert_se(!path_list);
568
569 /* Finally some valid paths */
570 assert_se(setenv("TEST_GETENV_PATH_LIST", "/foo:/bar/baz:/hello/world:/path with spaces:/final", 1) >= 0);
571 assert_se(getenv_path_list("TEST_GETENV_PATH_LIST", &path_list) >= 0);
572 ASSERT_STREQ(path_list[0], "/foo");
573 ASSERT_STREQ(path_list[1], "/bar/baz");
574 ASSERT_STREQ(path_list[2], "/hello/world");
575 ASSERT_STREQ(path_list[3], "/path with spaces");
576 ASSERT_STREQ(path_list[4], "/final");
577 ASSERT_NULL(path_list[5]);
578
579 assert_se(unsetenv("TEST_GETENV_PATH_LIST") >= 0);
580 }
581
582 TEST(strv_env_get_merged) {
583 char **l = STRV_MAKE("ONE", "1", "TWO", "2", "THREE", "3", "FOUR", "4", "FIVE", "5"),
584 **expected = STRV_MAKE("ONE=1", "TWO=2", "THREE=3", "FOUR=4", "FIVE=5");
585 _cleanup_strv_free_ char **m = NULL;
586
587 ASSERT_OK(strv_env_get_merged(NULL, &m));
588 ASSERT_NULL(m);
589 ASSERT_OK(strv_env_get_merged(l, &m));
590 ASSERT_TRUE(strv_equal(m, expected));
591 }
592
593 DEFINE_TEST_MAIN(LOG_DEBUG);