]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
cf95bc1d ZJS |
2 | |
3 | #include "env-file.h" | |
4 | #include "fd-util.h" | |
55f99c26 | 5 | #include "fileio.h" |
cf95bc1d ZJS |
6 | #include "fs-util.h" |
7 | #include "macro.h" | |
8 | #include "strv.h" | |
9 | #include "tests.h" | |
10 | #include "tmpfile-util.h" | |
11 | ||
25407ad2 ZJS |
12 | /* In case of repeating keys, later entries win. */ |
13 | ||
cf95bc1d | 14 | #define env_file_1 \ |
25407ad2 ZJS |
15 | "a=a\n" \ |
16 | "a=b\n" \ | |
17 | "a=b\n" \ | |
cf95bc1d ZJS |
18 | "a=a\n" \ |
19 | "b=b\\\n" \ | |
20 | "c\n" \ | |
e9e982a2 ZJS |
21 | "d= d\\\n" \ |
22 | "e \\\n" \ | |
23 | "f \n" \ | |
cf95bc1d | 24 | "g=g\\ \n" \ |
e503019b | 25 | "h= ąęół\\ śćńźżμ \n" \ |
cf95bc1d ZJS |
26 | "i=i\\" |
27 | ||
28 | #define env_file_2 \ | |
29 | "a=a\\\n" | |
30 | ||
31 | #define env_file_3 \ | |
32 | "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \ | |
33 | "#--nouser-config \\\n" \ | |
cd93ec5e | 34 | "normal1=line\\\n" \ |
35 | "111\n" \ | |
e9e982a2 | 36 | ";normal=ignored \\\n" \ |
cd93ec5e | 37 | "normal2=line222\n" \ |
e9e982a2 ZJS |
38 | "normal ignored \\\n" |
39 | ||
40 | #define env_file_4 \ | |
41 | "# Generated\n" \ | |
42 | "\n" \ | |
43 | "HWMON_MODULES=\"coretemp f71882fg\"\n" \ | |
44 | "\n" \ | |
45 | "# For compatibility reasons\n" \ | |
46 | "\n" \ | |
47 | "MODULE_0=coretemp\n" \ | |
48 | "MODULE_1=f71882fg" | |
cf95bc1d ZJS |
49 | |
50 | #define env_file_5 \ | |
e9e982a2 | 51 | "a=\n" \ |
cf95bc1d ZJS |
52 | "b=" |
53 | ||
e9e982a2 ZJS |
54 | #define env_file_6 \ |
55 | "a=\\ \\n \\t \\x \\y \\' \n" \ | |
56 | "b= \\$' \n" \ | |
57 | "c= ' \\n\\t\\$\\`\\\\\n" \ | |
58 | "' \n" \ | |
59 | "d= \" \\n\\t\\$\\`\\\\\n" \ | |
60 | "\" \n" | |
61 | ||
4f7452a8 | 62 | TEST(load_env_file_1) { |
cf95bc1d | 63 | _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; |
367c47c8 | 64 | assert_se(write_tmpfile(name, env_file_1) == 0); |
cf95bc1d | 65 | |
367c47c8 ZJS |
66 | _cleanup_strv_free_ char **data = NULL; |
67 | assert_se(load_env_file(NULL, name, &data) == 0); | |
cf95bc1d ZJS |
68 | assert_se(streq(data[0], "a=a")); |
69 | assert_se(streq(data[1], "b=bc")); | |
e9e982a2 | 70 | assert_se(streq(data[2], "d=de f")); |
cf95bc1d | 71 | assert_se(streq(data[3], "g=g ")); |
e503019b | 72 | assert_se(streq(data[4], "h=ąęół śćńźżμ")); |
cf95bc1d ZJS |
73 | assert_se(streq(data[5], "i=i")); |
74 | assert_se(data[6] == NULL); | |
75 | } | |
76 | ||
4f7452a8 | 77 | TEST(load_env_file_2) { |
cf95bc1d | 78 | _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; |
367c47c8 | 79 | assert_se(write_tmpfile(name, env_file_2) == 0); |
cf95bc1d | 80 | |
367c47c8 ZJS |
81 | _cleanup_strv_free_ char **data = NULL; |
82 | assert_se(load_env_file(NULL, name, &data) == 0); | |
cf95bc1d ZJS |
83 | assert_se(streq(data[0], "a=a")); |
84 | assert_se(data[1] == NULL); | |
85 | } | |
86 | ||
4f7452a8 | 87 | TEST(load_env_file_3) { |
cf95bc1d | 88 | _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; |
367c47c8 | 89 | assert_se(write_tmpfile(name, env_file_3) == 0); |
cf95bc1d | 90 | |
367c47c8 ZJS |
91 | _cleanup_strv_free_ char **data = NULL; |
92 | assert_se(load_env_file(NULL, name, &data) == 0); | |
cd93ec5e | 93 | assert_se(streq(data[0], "normal1=line111")); |
94 | assert_se(streq(data[1], "normal2=line222")); | |
95 | assert_se(data[2] == NULL); | |
cf95bc1d ZJS |
96 | } |
97 | ||
4f7452a8 | 98 | TEST(load_env_file_4) { |
cf95bc1d | 99 | _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; |
367c47c8 | 100 | assert_se(write_tmpfile(name, env_file_4) == 0); |
cf95bc1d | 101 | |
367c47c8 ZJS |
102 | _cleanup_strv_free_ char **data = NULL; |
103 | assert_se(load_env_file(NULL, name, &data) == 0); | |
cf95bc1d ZJS |
104 | assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg")); |
105 | assert_se(streq(data[1], "MODULE_0=coretemp")); | |
106 | assert_se(streq(data[2], "MODULE_1=f71882fg")); | |
107 | assert_se(data[3] == NULL); | |
108 | } | |
109 | ||
4f7452a8 | 110 | TEST(load_env_file_5) { |
cf95bc1d | 111 | _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; |
367c47c8 | 112 | assert_se(write_tmpfile(name, env_file_5) == 0); |
cf95bc1d | 113 | |
367c47c8 ZJS |
114 | _cleanup_strv_free_ char **data = NULL; |
115 | assert_se(load_env_file(NULL, name, &data) == 0); | |
cf95bc1d ZJS |
116 | assert_se(streq(data[0], "a=")); |
117 | assert_se(streq(data[1], "b=")); | |
118 | assert_se(data[2] == NULL); | |
119 | } | |
120 | ||
e9e982a2 | 121 | TEST(load_env_file_6) { |
e9e982a2 | 122 | _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; |
367c47c8 | 123 | assert_se(write_tmpfile(name, env_file_6) == 0); |
e9e982a2 | 124 | |
367c47c8 ZJS |
125 | _cleanup_strv_free_ char **data = NULL; |
126 | assert_se(load_env_file(NULL, name, &data) == 0); | |
e9e982a2 ZJS |
127 | assert_se(streq(data[0], "a= n t x y '")); |
128 | assert_se(streq(data[1], "b=$'")); | |
129 | assert_se(streq(data[2], "c= \\n\\t\\$\\`\\\\\n")); | |
130 | assert_se(streq(data[3], "d= \\n\\t$`\\\n")); | |
131 | assert_se(data[4] == NULL); | |
132 | } | |
133 | ||
841834d9 FS |
134 | TEST(load_env_file_invalid_utf8) { |
135 | /* Test out a couple of assignments where the key/value has an invalid | |
136 | * UTF-8 character ("noncharacter") | |
137 | * | |
138 | * See: https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Non-characters | |
139 | */ | |
140 | FOREACH_STRING(s, | |
141 | "fo\ufffeo=bar", | |
142 | "foo=b\uffffar", | |
143 | "baz=hello world\ufffe") { | |
144 | _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; | |
145 | assert_se(write_tmpfile(name, s) == 0); | |
146 | ||
147 | _cleanup_strv_free_ char **data = NULL; | |
148 | assert_se(load_env_file(NULL, name, &data) == -EINVAL); | |
149 | assert_se(!data); | |
150 | } | |
151 | } | |
152 | ||
4f7452a8 | 153 | TEST(write_and_load_env_file) { |
55f99c26 LP |
154 | /* Make sure that our writer, parser and the shell agree on what our env var files mean */ |
155 | ||
156 | FOREACH_STRING(v, | |
157 | "obbardc-laptop", | |
158 | "obbardc\\-laptop", | |
159 | "obbardc-lap\\top", | |
160 | "obbardc-lap\\top", | |
161 | "obbardc-lap\\\\top", | |
162 | "double\"quote", | |
163 | "single\'quote", | |
164 | "dollar$dollar", | |
165 | "newline\nnewline") { | |
166 | _cleanup_(unlink_and_freep) char *p = NULL; | |
167 | _cleanup_strv_free_ char **l = NULL; | |
168 | _cleanup_free_ char *j = NULL, *w = NULL, *cmd = NULL, *from_shell = NULL; | |
649bde89 | 169 | _cleanup_pclose_ FILE *f = NULL; |
55f99c26 LP |
170 | size_t sz; |
171 | ||
172 | assert_se(tempfn_random_child(NULL, NULL, &p) >= 0); | |
173 | ||
174 | assert_se(j = strjoin("TEST=", v)); | |
f155cb6d | 175 | assert_se(write_env_file(AT_FDCWD, p, STRV_MAKE("# header 1", "", "# header 2"), STRV_MAKE(j)) >= 0); |
55f99c26 LP |
176 | |
177 | assert_se(cmd = strjoin(". ", p, " && /bin/echo -n \"$TEST\"")); | |
178 | assert_se(f = popen(cmd, "re")); | |
179 | assert_se(read_full_stream(f, &from_shell, &sz) >= 0); | |
180 | assert_se(sz == strlen(v)); | |
181 | assert_se(streq(from_shell, v)); | |
182 | ||
183 | assert_se(load_env_file(NULL, p, &l) >= 0); | |
184 | assert_se(strv_equal(l, STRV_MAKE(j))); | |
185 | ||
186 | assert_se(parse_env_file(NULL, p, "TEST", &w) >= 0); | |
187 | assert_se(streq_ptr(w, v)); | |
188 | } | |
189 | } | |
190 | ||
4f7452a8 | 191 | DEFINE_TEST_MAIN(LOG_INFO); |