1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "env-file.h"
4 #include "fd-util.h"
5 #include "fileio.h"
6 #include "fs-util.h"
7 #include "macro.h"
8 #include "strv.h"
9 #include "tests.h"
10 #include "tmpfile-util.h"
11
12 /* In case of repeating keys, later entries win. */
13
14 #define env_file_1 \
15 "a=a\n" \
16 "a=b\n" \
17 "a=b\n" \
18 "a=a\n" \
19 "b=b\\\n" \
20 "c\n" \
21 "d= d\\\n" \
22 "e \\\n" \
23 "f \n" \
24 "g=g\\ \n" \
25 "h= ąęół\\ śćńźżµ \n" \
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" \
34 "normal=line \\\n" \
35 ";normal=ignored \\\n" \
36 "normal_ignored \\\n" \
37 "normal ignored \\\n"
38
39 #define env_file_4 \
40 "# Generated\n" \
41 "\n" \
42 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
43 "\n" \
44 "# For compatibility reasons\n" \
45 "\n" \
46 "MODULE_0=coretemp\n" \
47 "MODULE_1=f71882fg"
48
49 #define env_file_5 \
50 "a=\n" \
51 "b="
52
53 #define env_file_6 \
54 "a=\\ \\n \\t \\x \\y \\' \n" \
55 "b= \\$' \n" \
56 "c= ' \\n\\t\\$\\`\\\\\n" \
57 "' \n" \
58 "d= \" \\n\\t\\$\\`\\\\\n" \
59 "\" \n"
60
61
TEST(load_env_file_1)62 TEST(load_env_file_1) {
63 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
64 assert_se(write_tmpfile(name, env_file_1) == 0);
65
66 _cleanup_strv_free_ char **data = NULL;
67 assert_se(load_env_file(NULL, name, &data) == 0);
68 assert_se(streq(data[0], "a=a"));
69 assert_se(streq(data[1], "b=bc"));
70 assert_se(streq(data[2], "d=de f"));
71 assert_se(streq(data[3], "g=g "));
72 assert_se(streq(data[4], "h=ąęół śćńźżµ"));
73 assert_se(streq(data[5], "i=i"));
74 assert_se(data[6] == NULL);
75 }
76
TEST(load_env_file_2)77 TEST(load_env_file_2) {
78 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
79 assert_se(write_tmpfile(name, env_file_2) == 0);
80
81 _cleanup_strv_free_ char **data = NULL;
82 assert_se(load_env_file(NULL, name, &data) == 0);
83 assert_se(streq(data[0], "a=a"));
84 assert_se(data[1] == NULL);
85 }
86
TEST(load_env_file_3)87 TEST(load_env_file_3) {
88 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
89 assert_se(write_tmpfile(name, env_file_3) == 0);
90
91 _cleanup_strv_free_ char **data = NULL;
92 assert_se(load_env_file(NULL, name, &data) == 0);
93 assert_se(data == NULL);
94 }
95
TEST(load_env_file_4)96 TEST(load_env_file_4) {
97 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
98 assert_se(write_tmpfile(name, env_file_4) == 0);
99
100 _cleanup_strv_free_ char **data = NULL;
101 assert_se(load_env_file(NULL, name, &data) == 0);
102 assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
103 assert_se(streq(data[1], "MODULE_0=coretemp"));
104 assert_se(streq(data[2], "MODULE_1=f71882fg"));
105 assert_se(data[3] == NULL);
106 }
107
TEST(load_env_file_5)108 TEST(load_env_file_5) {
109 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
110 assert_se(write_tmpfile(name, env_file_5) == 0);
111
112 _cleanup_strv_free_ char **data = NULL;
113 assert_se(load_env_file(NULL, name, &data) == 0);
114 assert_se(streq(data[0], "a="));
115 assert_se(streq(data[1], "b="));
116 assert_se(data[2] == NULL);
117 }
118
TEST(load_env_file_6)119 TEST(load_env_file_6) {
120 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
121 assert_se(write_tmpfile(name, env_file_6) == 0);
122
123 _cleanup_strv_free_ char **data = NULL;
124 assert_se(load_env_file(NULL, name, &data) == 0);
125 assert_se(streq(data[0], "a= n t x y '"));
126 assert_se(streq(data[1], "b=$'"));
127 assert_se(streq(data[2], "c= \\n\\t\\$\\`\\\\\n"));
128 assert_se(streq(data[3], "d= \\n\\t$`\\\n"));
129 assert_se(data[4] == NULL);
130 }
131
TEST(write_and_load_env_file)132 TEST(write_and_load_env_file) {
133 /* Make sure that our writer, parser and the shell agree on what our env var files mean */
134
135 FOREACH_STRING(v,
136 "obbardc-laptop",
137 "obbardc\\-laptop",
138 "obbardc-lap\\top",
139 "obbardc-lap\\top",
140 "obbardc-lap\\\\top",
141 "double\"quote",
142 "single\'quote",
143 "dollar$dollar",
144 "newline\nnewline") {
145 _cleanup_(unlink_and_freep) char *p = NULL;
146 _cleanup_strv_free_ char **l = NULL;
147 _cleanup_free_ char *j = NULL, *w = NULL, *cmd = NULL, *from_shell = NULL;
148 _cleanup_pclose_ FILE *f = NULL;
149 size_t sz;
150
151 assert_se(tempfn_random_child(NULL, NULL, &p) >= 0);
152
153 assert_se(j = strjoin("TEST=", v));
154 assert_se(write_env_file(p, STRV_MAKE(j)) >= 0);
155
156 assert_se(cmd = strjoin(". ", p, " && /bin/echo -n \"$TEST\""));
157 assert_se(f = popen(cmd, "re"));
158 assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
159 assert_se(sz == strlen(v));
160 assert_se(streq(from_shell, v));
161
162 assert_se(load_env_file(NULL, p, &l) >= 0);
163 assert_se(strv_equal(l, STRV_MAKE(j)));
164
165 assert_se(parse_env_file(NULL, p, "TEST", &w) >= 0);
166 assert_se(streq_ptr(w, v));
167 }
168 }
169
170 DEFINE_TEST_MAIN(LOG_INFO);
171