2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2016 Zbigniew Jędrzejewski-Szmek
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "string-util.h"
28 static void test_strv_env_delete(void) {
29 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
31 a
= strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL
);
34 b
= strv_new("PIEP", "FOO", NULL
);
37 c
= strv_new("SCHLUMPF", NULL
);
40 d
= strv_env_delete(a
, 2, b
, c
);
43 assert_se(streq(d
[0], "WALDO=WALDO"));
44 assert_se(streq(d
[1], "WALDO="));
45 assert_se(strv_length(d
) == 2);
48 static void test_strv_env_get(void) {
51 l
= STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
53 assert_se(streq(strv_env_get(l
, "ONE_OR_TWO"), "2"));
54 assert_se(streq(strv_env_get(l
, "THREE"), "3"));
55 assert_se(streq(strv_env_get(l
, "FOUR"), "4"));
58 static void test_strv_env_unset(void) {
59 _cleanup_strv_free_
char **l
= NULL
;
61 l
= strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL
);
64 assert_se(strv_env_unset(l
, "SCHLUMPF") == l
);
66 assert_se(streq(l
[0], "PIEP"));
67 assert_se(streq(l
[1], "NANANANA=YES"));
68 assert_se(strv_length(l
) == 2);
71 static void test_strv_env_set(void) {
72 _cleanup_strv_free_
char **l
= NULL
, **r
= NULL
;
74 l
= strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL
);
77 r
= strv_env_set(l
, "WALDO=WALDO");
80 assert_se(streq(r
[0], "PIEP"));
81 assert_se(streq(r
[1], "SCHLUMPF=SMURFF"));
82 assert_se(streq(r
[2], "NANANANA=YES"));
83 assert_se(streq(r
[3], "WALDO=WALDO"));
84 assert_se(strv_length(r
) == 4);
87 static void test_strv_env_merge(void) {
88 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **r
= NULL
;
90 a
= strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL
);
93 b
= strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL
);
96 r
= strv_env_merge(2, a
, b
);
98 assert_se(streq(r
[0], "FOO="));
99 assert_se(streq(r
[1], "WALDO="));
100 assert_se(streq(r
[2], "PIEP"));
101 assert_se(streq(r
[3], "SCHLUMPF=SMURFF"));
102 assert_se(streq(r
[4], "PIEP="));
103 assert_se(streq(r
[5], "NANANANA=YES"));
104 assert_se(strv_length(r
) == 6);
106 assert_se(strv_env_clean(r
) == r
);
107 assert_se(streq(r
[0], "FOO="));
108 assert_se(streq(r
[1], "WALDO="));
109 assert_se(streq(r
[2], "SCHLUMPF=SMURFF"));
110 assert_se(streq(r
[3], "PIEP="));
111 assert_se(streq(r
[4], "NANANANA=YES"));
112 assert_se(strv_length(r
) == 5);
115 static void test_env_strv_get_n(void) {
116 const char *_env
[] = {
123 char **env
= (char**) _env
;
125 assert_se(streq(strv_env_get_n(env
, "FOO__", 3, 0), "BAR BAR"));
126 assert_se(streq(strv_env_get_n(env
, "FOO__", 3, REPLACE_ENV_USE_ENVIRONMENT
), "BAR BAR"));
127 assert_se(streq(strv_env_get_n(env
, "FOO", 3, 0), "BAR BAR"));
128 assert_se(streq(strv_env_get_n(env
, "FOO", 3, REPLACE_ENV_USE_ENVIRONMENT
), "BAR BAR"));
130 assert_se(streq(strv_env_get_n(env
, "PATH__", 4, 0), "unset"));
131 assert_se(streq(strv_env_get_n(env
, "PATH", 4, 0), "unset"));
132 assert_se(streq(strv_env_get_n(env
, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT
), "unset"));
133 assert_se(streq(strv_env_get_n(env
, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT
), "unset"));
135 env
[3] = NULL
; /* kill our $PATH */
137 assert_se(!strv_env_get_n(env
, "PATH__", 4, 0));
138 assert_se(!strv_env_get_n(env
, "PATH", 4, 0));
139 assert_se(streq(strv_env_get_n(env
, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT
),
141 assert_se(streq(strv_env_get_n(env
, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT
),
145 static void test_replace_env(bool braceless
) {
146 const char *env
[] = {
151 _cleanup_free_
char *t
= NULL
, *s
= NULL
, *q
= NULL
, *r
= NULL
, *p
= NULL
;
152 unsigned flags
= REPLACE_ENV_ALLOW_BRACELESS
*braceless
;
154 t
= replace_env("FOO=$FOO=${FOO}", (char**) env
, flags
);
155 assert_se(streq(t
, braceless
? "FOO=BAR BAR=BAR BAR" : "FOO=$FOO=BAR BAR"));
157 s
= replace_env("BAR=$BAR=${BAR}", (char**) env
, flags
);
158 assert_se(streq(s
, braceless
? "BAR=waldo=waldo" : "BAR=$BAR=waldo"));
160 q
= replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env
, flags
);
161 assert_se(streq(q
, braceless
? "BARBAR==" : "BARBAR=$BARBAR="));
163 r
= replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env
, flags
);
164 assert_se(streq(r
, braceless
? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo"));
166 p
= replace_env("${BAR}$BAR$BAR", (char**) env
, flags
);
167 assert_se(streq(p
, braceless
? "waldowaldowaldo" : "waldo$BAR$BAR"));
170 static void test_replace_env2(bool extended
) {
171 const char *env
[] = {
176 _cleanup_free_
char *t
= NULL
, *s
= NULL
, *q
= NULL
, *r
= NULL
, *p
= NULL
, *x
= NULL
;
177 unsigned flags
= REPLACE_ENV_ALLOW_EXTENDED
*extended
;
179 t
= replace_env("FOO=${FOO:-${BAR}}", (char**) env
, flags
);
180 assert_se(streq(t
, extended
? "FOO=foo" : "FOO=${FOO:-bar}"));
182 s
= replace_env("BAR=${XXX:-${BAR}}", (char**) env
, flags
);
183 assert_se(streq(s
, extended
? "BAR=bar" : "BAR=${XXX:-bar}"));
185 q
= replace_env("XXX=${XXX:+${BAR}}", (char**) env
, flags
);
186 assert_se(streq(q
, extended
? "XXX=" : "XXX=${XXX:+bar}"));
188 r
= replace_env("FOO=${FOO:+${BAR}}", (char**) env
, flags
);
189 assert_se(streq(r
, extended
? "FOO=bar" : "FOO=${FOO:+bar}"));
191 p
= replace_env("FOO=${FOO:-${BAR}post}", (char**) env
, flags
);
192 assert_se(streq(p
, extended
? "FOO=foo" : "FOO=${FOO:-barpost}"));
194 x
= replace_env("XXX=${XXX:+${BAR}post}", (char**) env
, flags
);
195 assert_se(streq(x
, extended
? "XXX=" : "XXX=${XXX:+barpost}"));
198 static void test_replace_env_argv(void) {
199 const char *env
[] = {
204 const char *line
[] = {
224 _cleanup_strv_free_
char **r
= NULL
;
226 r
= replace_env_argv((char**) line
, (char**) env
);
228 assert_se(streq(r
[0], "FOO$FOO"));
229 assert_se(streq(r
[1], "FOO$FOOFOO"));
230 assert_se(streq(r
[2], "FOOBAR BAR$FOO"));
231 assert_se(streq(r
[3], "FOOBAR BAR"));
232 assert_se(streq(r
[4], "BAR BAR"));
233 assert_se(streq(r
[5], "BAR"));
234 assert_se(streq(r
[6], "BAR"));
235 assert_se(streq(r
[7], "BAR BARwaldo"));
236 assert_se(streq(r
[8], "${FOO"));
237 assert_se(streq(r
[9], "FOO$BAR BAR"));
238 assert_se(streq(r
[10], "$FOOBAR BAR"));
239 assert_se(streq(r
[11], "${FOO:-waldo}"));
240 assert_se(streq(r
[12], "${QUUX:-BAR BAR}"));
241 assert_se(streq(r
[13], "${FOO:+waldo}"));
242 assert_se(streq(r
[14], "${QUUX:+waldo}"));
243 assert_se(streq(r
[15], "${FOO:+|waldo|}}"));
244 assert_se(streq(r
[16], "${FOO:+|waldo{|}"));
245 assert_se(strv_length(r
) == 17);
248 static void test_env_clean(void) {
249 _cleanup_strv_free_
char **e
;
251 e
= strv_new("FOOBAR=WALDO",
269 assert_se(!strv_env_is_valid(e
));
270 assert_se(strv_env_clean(e
) == e
);
271 assert_se(strv_env_is_valid(e
));
273 assert_se(streq(e
[0], "FOOBAR=WALDO"));
274 assert_se(streq(e
[1], "X="));
275 assert_se(streq(e
[2], "F=F"));
276 assert_se(streq(e
[3], "abcd=äöüß"));
277 assert_se(streq(e
[4], "another=final one"));
278 assert_se(e
[5] == NULL
);
281 static void test_env_name_is_valid(void) {
282 assert_se(env_name_is_valid("test"));
284 assert_se(!env_name_is_valid(NULL
));
285 assert_se(!env_name_is_valid(""));
286 assert_se(!env_name_is_valid("xxx\a"));
287 assert_se(!env_name_is_valid("xxx\007b"));
288 assert_se(!env_name_is_valid("\007\009"));
289 assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
290 assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
293 static void test_env_value_is_valid(void) {
294 assert_se(env_value_is_valid(""));
295 assert_se(env_value_is_valid("głąb kapuściany"));
296 assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
299 static void test_env_assignment_is_valid(void) {
300 assert_se(env_assignment_is_valid("a="));
301 assert_se(env_assignment_is_valid("b=głąb kapuściany"));
302 assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
303 assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
305 assert_se(!env_assignment_is_valid("="));
306 assert_se(!env_assignment_is_valid("a b="));
307 assert_se(!env_assignment_is_valid("a ="));
308 assert_se(!env_assignment_is_valid(" b="));
309 /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
310 assert_se(!env_assignment_is_valid("a.b="));
311 assert_se(!env_assignment_is_valid("a-b="));
312 assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
313 assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
314 assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
317 int main(int argc
, char *argv
[]) {
318 test_strv_env_delete();
320 test_strv_env_unset();
322 test_strv_env_merge();
323 test_env_strv_get_n();
324 test_replace_env(false);
325 test_replace_env(true);
326 test_replace_env2(false);
327 test_replace_env2(true);
328 test_replace_env_argv();
330 test_env_name_is_valid();
331 test_env_value_is_valid();
332 test_env_assignment_is_valid();