Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include "escape.h"
4 : : #include "fd-util.h"
5 : : #include "fileio.h"
6 : : #include "fs-util.h"
7 : : #include "log.h"
8 : : #include "serialize.h"
9 : : #include "strv.h"
10 : : #include "tests.h"
11 : : #include "tmpfile-util.h"
12 : :
13 : : char long_string[LONG_LINE_MAX+1];
14 : :
15 : 4 : static void test_serialize_item(void) {
16 : 4 : _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
17 : 4 : _cleanup_fclose_ FILE *f = NULL;
18 : :
19 [ - + ]: 4 : assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
20 [ + - ]: 4 : log_info("/* %s (%s) */", __func__, fn);
21 : :
22 [ - + ]: 4 : assert_se(serialize_item(f, "a", NULL) == 0);
23 [ - + ]: 4 : assert_se(serialize_item(f, "a", "bbb") == 1);
24 [ - + ]: 4 : assert_se(serialize_item(f, "a", "bbb") == 1);
25 [ - + ]: 4 : assert_se(serialize_item(f, "a", long_string) == -EINVAL);
26 [ - + ]: 4 : assert_se(serialize_item(f, long_string, "a") == -EINVAL);
27 [ - + ]: 4 : assert_se(serialize_item(f, long_string, long_string) == -EINVAL);
28 : :
29 : 4 : rewind(f);
30 : :
31 : 4 : _cleanup_free_ char *line1 = NULL, *line2 = NULL, *line3 = NULL;
32 [ - + ]: 4 : assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0);
33 [ - + ]: 4 : assert_se(streq(line1, "a=bbb"));
34 [ - + ]: 4 : assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0);
35 [ - + ]: 4 : assert_se(streq(line2, "a=bbb"));
36 [ - + ]: 4 : assert_se(read_line(f, LONG_LINE_MAX, &line3) == 0);
37 [ - + ]: 4 : assert_se(streq(line3, ""));
38 : 4 : }
39 : :
40 : 4 : static void test_serialize_item_escaped(void) {
41 : 4 : _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
42 : 4 : _cleanup_fclose_ FILE *f = NULL;
43 : :
44 [ - + ]: 4 : assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
45 [ + - ]: 4 : log_info("/* %s (%s) */", __func__, fn);
46 : :
47 [ - + ]: 4 : assert_se(serialize_item_escaped(f, "a", NULL) == 0);
48 [ - + ]: 4 : assert_se(serialize_item_escaped(f, "a", "bbb") == 1);
49 [ - + ]: 4 : assert_se(serialize_item_escaped(f, "a", "bbb") == 1);
50 [ - + ]: 4 : assert_se(serialize_item_escaped(f, "a", long_string) == -EINVAL);
51 [ - + ]: 4 : assert_se(serialize_item_escaped(f, long_string, "a") == -EINVAL);
52 [ - + ]: 4 : assert_se(serialize_item_escaped(f, long_string, long_string) == -EINVAL);
53 : :
54 : 4 : rewind(f);
55 : :
56 : 4 : _cleanup_free_ char *line1 = NULL, *line2 = NULL, *line3 = NULL;
57 [ - + ]: 4 : assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0);
58 [ - + ]: 4 : assert_se(streq(line1, "a=bbb"));
59 [ - + ]: 4 : assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0);
60 [ - + ]: 4 : assert_se(streq(line2, "a=bbb"));
61 [ - + ]: 4 : assert_se(read_line(f, LONG_LINE_MAX, &line3) == 0);
62 [ - + ]: 4 : assert_se(streq(line3, ""));
63 : 4 : }
64 : :
65 : 4 : static void test_serialize_usec(void) {
66 : 4 : _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
67 : 4 : _cleanup_fclose_ FILE *f = NULL;
68 : :
69 [ - + ]: 4 : assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
70 [ + - ]: 4 : log_info("/* %s (%s) */", __func__, fn);
71 : :
72 [ - + ]: 4 : assert_se(serialize_usec(f, "usec1", USEC_INFINITY) == 0);
73 [ - + ]: 4 : assert_se(serialize_usec(f, "usec2", 0) == 1);
74 [ - + ]: 4 : assert_se(serialize_usec(f, "usec3", USEC_INFINITY-1) == 1);
75 : :
76 : 4 : rewind(f);
77 : :
78 : 4 : _cleanup_free_ char *line1 = NULL, *line2 = NULL;
79 : : usec_t x;
80 : :
81 [ - + ]: 4 : assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0);
82 [ - + ]: 4 : assert_se(streq(line1, "usec2=0"));
83 [ - + ]: 4 : assert_se(deserialize_usec(line1 + 6, &x) == 0);
84 [ - + ]: 4 : assert_se(x == 0);
85 : :
86 [ - + ]: 4 : assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0);
87 [ - + ]: 4 : assert_se(startswith(line2, "usec3="));
88 [ - + ]: 4 : assert_se(deserialize_usec(line2 + 6, &x) == 0);
89 [ - + ]: 4 : assert_se(x == USEC_INFINITY-1);
90 : 4 : }
91 : :
92 : 4 : static void test_serialize_strv(void) {
93 : 4 : _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
94 : 4 : _cleanup_fclose_ FILE *f = NULL;
95 : :
96 : 4 : char **strv = STRV_MAKE("a", "b", "foo foo",
97 : : "nasty1 \"",
98 : : "\"nasty2 ",
99 : : "nasty3 '",
100 : : "\"nasty4 \"",
101 : : "nasty5\n",
102 : : "\nnasty5\nfoo=bar",
103 : : "\nnasty5\nfoo=bar");
104 : :
105 [ - + ]: 4 : assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
106 [ + - ]: 4 : log_info("/* %s (%s) */", __func__, fn);
107 : :
108 [ - + ]: 4 : assert_se(serialize_strv(f, "strv1", NULL) == 0);
109 [ - + ]: 4 : assert_se(serialize_strv(f, "strv2", STRV_MAKE_EMPTY) == 0);
110 [ - + ]: 4 : assert_se(serialize_strv(f, "strv3", strv) == 1);
111 [ - + ]: 4 : assert_se(serialize_strv(f, "strv4", STRV_MAKE(long_string)) == -EINVAL);
112 : :
113 : 4 : rewind(f);
114 : :
115 : 8 : _cleanup_strv_free_ char **strv2 = NULL;
116 : 40 : for (;;) {
117 [ + + ]: 44 : _cleanup_free_ char *line = NULL;
118 : : int r;
119 : :
120 : 44 : r = read_line(f, LONG_LINE_MAX, &line);
121 [ + + ]: 44 : if (r == 0)
122 : 4 : break;
123 [ - + ]: 40 : assert_se(r > 0);
124 : :
125 : 40 : const char *t = startswith(line, "strv3=");
126 [ - + ]: 40 : assert_se(t);
127 : :
128 : : char *un;
129 [ - + ]: 40 : assert_se(cunescape(t, 0, &un) >= 0);
130 [ - + ]: 40 : assert_se(strv_consume(&strv2, un) >= 0);
131 : : }
132 : :
133 [ - + ]: 4 : assert_se(strv_equal(strv, strv2));
134 : 4 : }
135 : :
136 : 4 : static void test_deserialize_environment(void) {
137 : 4 : _cleanup_strv_free_ char **env;
138 : :
139 [ + - ]: 4 : log_info("/* %s */", __func__);
140 : :
141 [ - + ]: 4 : assert_se(env = strv_new("A=1"));
142 : :
143 [ - + ]: 4 : assert_se(deserialize_environment("B=2", &env) >= 0);
144 [ - + ]: 4 : assert_se(deserialize_environment("FOO%%=a\\177b\\nc\\td e", &env) >= 0);
145 : :
146 [ - + ]: 4 : assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2", "FOO%%=a\177b\nc\td e")));
147 : :
148 [ - + ]: 4 : assert_se(deserialize_environment("foo\\", &env) < 0);
149 [ - + ]: 4 : assert_se(deserialize_environment("bar\\_baz", &env) < 0);
150 : 4 : }
151 : :
152 : 4 : static void test_serialize_environment(void) {
153 : 4 : _cleanup_strv_free_ char **env = NULL, **env2 = NULL;
154 : 4 : _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-env-util.XXXXXXX";
155 : 4 : _cleanup_fclose_ FILE *f = NULL;
156 : : int r;
157 : :
158 [ - + ]: 4 : assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
159 [ + - ]: 4 : log_info("/* %s (%s) */", __func__, fn);
160 : :
161 [ - + ]: 4 : assert_se(env = strv_new("A=1",
162 : : "B=2",
163 : : "C=ąęółń",
164 : : "D=D=a\\x0Ab",
165 : : "FOO%%=a\177b\nc\td e"));
166 : :
167 [ - + ]: 4 : assert_se(serialize_strv(f, "env", env) == 1);
168 [ - + ]: 4 : assert_se(fflush_and_check(f) == 0);
169 : :
170 : 4 : rewind(f);
171 : :
172 : 20 : for (;;) {
173 [ + + ]: 24 : _cleanup_free_ char *line = NULL;
174 : : const char *l;
175 : :
176 : 24 : r = read_line(f, LONG_LINE_MAX, &line);
177 [ - + ]: 24 : assert_se(r >= 0);
178 : :
179 [ + + ]: 24 : if (r == 0)
180 : 4 : break;
181 : :
182 : 20 : l = strstrip(line);
183 : :
184 [ - + ]: 20 : assert_se(startswith(l, "env="));
185 : :
186 : 20 : r = deserialize_environment(l+4, &env2);
187 [ - + ]: 20 : assert_se(r >= 0);
188 : : }
189 [ - + ]: 4 : assert_se(feof(f));
190 : :
191 [ - + ]: 4 : assert_se(strv_equal(env, env2));
192 : 4 : }
193 : :
194 : 4 : int main(int argc, char *argv[]) {
195 : 4 : test_setup_logging(LOG_INFO);
196 : :
197 : 4 : memset(long_string, 'x', sizeof(long_string)-1);
198 : 4 : char_array_0(long_string);
199 : :
200 : 4 : test_serialize_item();
201 : 4 : test_serialize_item_escaped();
202 : 4 : test_serialize_usec();
203 : 4 : test_serialize_strv();
204 : 4 : test_deserialize_environment();
205 : 4 : test_serialize_environment();
206 : :
207 : 4 : return EXIT_SUCCESS;
208 : : }
|