1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
7 #include "parse-util.h"
8 #include "process-util.h"
10 #include "string-util.h"
15 static void test_strv_env_delete(void) {
16 log_info("/* %s */", __func__
);
18 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
20 a
= strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
23 b
= strv_new("PIEP", "FOO");
26 c
= strv_new("SCHLUMPF");
29 d
= strv_env_delete(a
, 2, b
, c
);
32 assert_se(streq(d
[0], "WALDO=WALDO"));
33 assert_se(streq(d
[1], "WALDO="));
34 assert_se(strv_length(d
) == 2);
37 static void test_strv_env_get(void) {
38 log_info("/* %s */", __func__
);
40 char **l
= STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
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"));
47 static void test_strv_env_pairs_get(void) {
48 log_info("/* %s */", __func__
);
50 char **l
= STRV_MAKE("ONE_OR_TWO", "1", "THREE", "3", "ONE_OR_TWO", "2", "FOUR", "4", "FIVE", "5", "SIX", "FIVE", "SEVEN", "7");
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"));
58 static void test_strv_env_unset(void) {
59 log_info("/* %s */", __func__
);
61 _cleanup_strv_free_
char **l
= NULL
;
63 l
= strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
66 assert_se(strv_env_unset(l
, "SCHLUMPF") == l
);
68 assert_se(streq(l
[0], "PIEP"));
69 assert_se(streq(l
[1], "NANANANA=YES"));
70 assert_se(strv_length(l
) == 2);
73 static void test_strv_env_merge(void) {
74 log_info("/* %s */", __func__
);
76 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **r
= NULL
;
78 a
= strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
81 b
= strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES");
84 r
= strv_env_merge(2, a
, b
);
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);
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);
103 static void test_strv_env_replace_strdup(void) {
104 log_info("/* %s */", __func__
);
106 _cleanup_strv_free_
char **a
= NULL
;
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);
112 assert_se(strv_length(a
) == 2);
114 assert_se(streq(a
[0], "a=A"));
115 assert_se(streq(a
[1], "b=b"));
118 static void test_strv_env_assign(void) {
119 log_info("/* %s */", __func__
);
121 _cleanup_strv_free_
char **a
= NULL
;
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);
128 assert_se(strv_env_assign(&a
, "a=", "B") == -EINVAL
);
130 assert_se(strv_length(a
) == 1);
131 assert_se(streq(a
[0], "a=A"));
134 static void test_env_strv_get_n(void) {
135 log_info("/* %s */", __func__
);
137 const char *_env
[] = {
144 char **env
= (char**) _env
;
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"));
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"));
156 env
[3] = NULL
; /* kill our $PATH */
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
),
162 assert_se(streq_ptr(strv_env_get_n(env
, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT
),
166 static void test_replace_env(bool braceless
) {
167 log_info("/* %s(braceless=%s) */", __func__
, yes_no(braceless
));
169 const char *env
[] = {
174 _cleanup_free_
char *t
= NULL
, *s
= NULL
, *q
= NULL
, *r
= NULL
, *p
= NULL
;
175 unsigned flags
= REPLACE_ENV_ALLOW_BRACELESS
*braceless
;
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"));
180 s
= replace_env("BAR=$BAR=${BAR}", (char**) env
, flags
);
181 assert_se(streq(s
, braceless
? "BAR=waldo=waldo" : "BAR=$BAR=waldo"));
183 q
= replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env
, flags
);
184 assert_se(streq(q
, braceless
? "BARBAR==" : "BARBAR=$BARBAR="));
186 r
= replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env
, flags
);
187 assert_se(streq(r
, braceless
? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo"));
189 p
= replace_env("${BAR}$BAR$BAR", (char**) env
, flags
);
190 assert_se(streq(p
, braceless
? "waldowaldowaldo" : "waldo$BAR$BAR"));
193 static void test_replace_env2(bool extended
) {
194 log_info("/* %s(extended=%s) */", __func__
, yes_no(extended
));
196 const char *env
[] = {
201 _cleanup_free_
char *t
= NULL
, *s
= NULL
, *q
= NULL
, *r
= NULL
, *p
= NULL
, *x
= NULL
;
202 unsigned flags
= REPLACE_ENV_ALLOW_EXTENDED
*extended
;
204 t
= replace_env("FOO=${FOO:-${BAR}}", (char**) env
, flags
);
205 assert_se(streq(t
, extended
? "FOO=foo" : "FOO=${FOO:-bar}"));
207 s
= replace_env("BAR=${XXX:-${BAR}}", (char**) env
, flags
);
208 assert_se(streq(s
, extended
? "BAR=bar" : "BAR=${XXX:-bar}"));
210 q
= replace_env("XXX=${XXX:+${BAR}}", (char**) env
, flags
);
211 assert_se(streq(q
, extended
? "XXX=" : "XXX=${XXX:+bar}"));
213 r
= replace_env("FOO=${FOO:+${BAR}}", (char**) env
, flags
);
214 assert_se(streq(r
, extended
? "FOO=bar" : "FOO=${FOO:+bar}"));
216 p
= replace_env("FOO=${FOO:-${BAR}post}", (char**) env
, flags
);
217 assert_se(streq(p
, extended
? "FOO=foo" : "FOO=${FOO:-barpost}"));
219 x
= replace_env("XXX=${XXX:+${BAR}post}", (char**) env
, flags
);
220 assert_se(streq(x
, extended
? "XXX=" : "XXX=${XXX:+barpost}"));
223 static void test_replace_env_argv(void) {
224 log_info("/* %s */", __func__
);
226 const char *env
[] = {
231 const char *line
[] = {
251 _cleanup_strv_free_
char **r
= NULL
;
253 r
= replace_env_argv((char**) line
, (char**) env
);
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);
275 static void test_env_clean(void) {
276 log_info("/* %s */", __func__
);
278 _cleanup_strv_free_
char **e
= strv_new("FOOBAR=WALDO",
295 "LESS_TERMCAP_mb=\x1b[01;31m",
296 "BASH_FUNC_foo%%=() { echo foo\n}");
298 assert_se(!strv_env_is_valid(e
));
299 assert_se(strv_env_clean(e
) == e
);
300 assert_se(strv_env_is_valid(e
));
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
);
313 static void test_env_name_is_valid(void) {
314 log_info("/* %s */", __func__
);
316 assert_se(env_name_is_valid("test"));
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"));
327 static void test_env_value_is_valid(void) {
328 log_info("/* %s */", __func__
);
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"));
338 assert_se(!env_value_is_valid("\xc5")); /* A truncated utf-8-encoded "ł".
339 * We currently disallow that. */
342 static void test_env_assignment_is_valid(void) {
343 log_info("/* %s */", __func__
);
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"));
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>\""));
364 static void test_putenv_dup(void) {
365 log_info("/* %s */", __func__
);
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"));
377 static void test_setenv_systemd_exec_pid(void) {
378 _cleanup_free_
char *saved
= NULL
;
382 log_info("/* %s */", __func__
);
384 e
= getenv("SYSTEMD_EXEC_PID");
386 assert_se(saved
= strdup(e
));
388 assert_se(unsetenv("SYSTEMD_EXEC_PID") >= 0);
389 assert_se(setenv_systemd_exec_pid(true) == 0);
390 assert_se(!getenv("SYSTEMD_EXEC_PID"));
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
, "*"));
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());
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());
409 assert_se(set_unset_env("SYSTEMD_EXEC_PID", saved
, 1) >= 0);
412 int main(int argc
, char *argv
[]) {
413 test_setup_logging(LOG_DEBUG
);
415 test_strv_env_delete();
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();
429 test_env_name_is_valid();
430 test_env_value_is_valid();
431 test_env_assignment_is_valid();
433 test_setenv_systemd_exec_pid();