chiark / gitweb /
test-dhcp6-client: Fix option length
[elogind.git] / src / test / test-fileio.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25
26 #include "util.h"
27 #include "fileio.h"
28 #include "strv.h"
29 #include "env-util.h"
30 #include "def.h"
31 #include "ctype.h"
32
33 static void test_parse_env_file(void) {
34         char    t[] = "/tmp/test-fileio-in-XXXXXX",
35                 p[] = "/tmp/test-fileio-out-XXXXXX";
36         int fd, r;
37         FILE *f;
38         _cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL,
39                         *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL;
40         _cleanup_strv_free_ char **a = NULL, **b = NULL;
41         char **i;
42         unsigned k;
43
44         fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
45         assert_se(fd >= 0);
46         close(fd);
47
48         fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
49         assert_se(fd >= 0);
50
51         f = fdopen(fd, "w");
52         assert_se(f);
53
54         fputs("one=BAR   \n"
55               "# comment\n"
56               " # comment \n"
57               " ; comment \n"
58               "  two   =   bar    \n"
59               "invalid line\n"
60               "invalid line #comment\n"
61               "three = \"333\n"
62               "xxxx\"\n"
63               "four = \'44\\\"44\'\n"
64               "five = \'55\\\'55\' \"FIVE\" cinco   \n"
65               "six = seis sechs\\\n"
66               " sis\n"
67               "seven=\"sevenval\" #nocomment\n"
68               "eight=eightval #nocomment\n"
69               "export nine=nineval\n"
70               "ten=", f);
71
72         fflush(f);
73         fclose(f);
74
75         r = load_env_file(NULL, t, NULL, &a);
76         assert_se(r >= 0);
77
78         STRV_FOREACH(i, a)
79                 log_info("Got: <%s>", *i);
80
81         assert_se(streq_ptr(a[0], "one=BAR"));
82         assert_se(streq_ptr(a[1], "two=bar"));
83         assert_se(streq_ptr(a[2], "three=333\nxxxx"));
84         assert_se(streq_ptr(a[3], "four=44\"44"));
85         assert_se(streq_ptr(a[4], "five=55\'55FIVEcinco"));
86         assert_se(streq_ptr(a[5], "six=seis sechs sis"));
87         assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
88         assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
89         assert_se(streq_ptr(a[8], "export nine=nineval"));
90         assert_se(streq_ptr(a[9], "ten="));
91         assert_se(a[10] == NULL);
92
93         strv_env_clean_log(a, "test");
94
95         k = 0;
96         STRV_FOREACH(i, b) {
97                 log_info("Got2: <%s>", *i);
98                 assert_se(streq(*i, a[k++]));
99         }
100
101         r = parse_env_file(
102                         t, NULL,
103                        "one", &one,
104                        "two", &two,
105                        "three", &three,
106                        "four", &four,
107                        "five", &five,
108                        "six", &six,
109                        "seven", &seven,
110                        "eight", &eight,
111                        "export nine", &nine,
112                        "ten", &ten,
113                        NULL);
114
115         assert_se(r >= 0);
116
117         log_info("one=[%s]", strna(one));
118         log_info("two=[%s]", strna(two));
119         log_info("three=[%s]", strna(three));
120         log_info("four=[%s]", strna(four));
121         log_info("five=[%s]", strna(five));
122         log_info("six=[%s]", strna(six));
123         log_info("seven=[%s]", strna(seven));
124         log_info("eight=[%s]", strna(eight));
125         log_info("export nine=[%s]", strna(nine));
126         log_info("ten=[%s]", strna(nine));
127
128         assert_se(streq(one, "BAR"));
129         assert_se(streq(two, "bar"));
130         assert_se(streq(three, "333\nxxxx"));
131         assert_se(streq(four, "44\"44"));
132         assert_se(streq(five, "55\'55FIVEcinco"));
133         assert_se(streq(six, "seis sechs sis"));
134         assert_se(streq(seven, "sevenval#nocomment"));
135         assert_se(streq(eight, "eightval #nocomment"));
136         assert_se(streq(nine, "nineval"));
137         assert_se(ten == NULL);
138
139         r = write_env_file(p, a);
140         assert_se(r >= 0);
141
142         r = load_env_file(NULL, p, NULL, &b);
143         assert_se(r >= 0);
144
145         unlink(t);
146         unlink(p);
147 }
148
149 static void test_parse_multiline_env_file(void) {
150         char    t[] = "/tmp/test-fileio-in-XXXXXX",
151                 p[] = "/tmp/test-fileio-out-XXXXXX";
152         int fd, r;
153         FILE *f;
154         _cleanup_strv_free_ char **a = NULL, **b = NULL;
155         char **i;
156
157         fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
158         assert_se(fd >= 0);
159         close(fd);
160
161         fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
162         assert_se(fd >= 0);
163
164         f = fdopen(fd, "w");
165         assert_se(f);
166
167         fputs("one=BAR\\\n"
168               "    VAR\\\n"
169               "\tGAR\n"
170               "#comment\n"
171               "two=\"bar\\\n"
172               "    var\\\n"
173               "\tgar\"\n"
174               "#comment\n"
175               "tri=\"bar \\\n"
176               "    var \\\n"
177               "\tgar \"\n", f);
178
179         fflush(f);
180         fclose(f);
181
182         r = load_env_file(NULL, t, NULL, &a);
183         assert_se(r >= 0);
184
185         STRV_FOREACH(i, a)
186                 log_info("Got: <%s>", *i);
187
188         assert_se(streq_ptr(a[0], "one=BAR    VAR\tGAR"));
189         assert_se(streq_ptr(a[1], "two=bar    var\tgar"));
190         assert_se(streq_ptr(a[2], "tri=bar     var \tgar "));
191         assert_se(a[3] == NULL);
192
193         r = write_env_file(p, a);
194         assert_se(r >= 0);
195
196         r = load_env_file(NULL, p, NULL, &b);
197         assert_se(r >= 0);
198
199         unlink(t);
200         unlink(p);
201 }
202
203
204 static void test_executable_is_script(void) {
205         char t[] = "/tmp/test-executable-XXXXXX";
206         int fd, r;
207         FILE *f;
208         char *command;
209
210         fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
211         assert_se(fd >= 0);
212
213         f = fdopen(fd, "w");
214         assert_se(f);
215
216         fputs("#! /bin/script -a -b \ngoo goo", f);
217         fflush(f);
218
219         r = executable_is_script(t, &command);
220         assert_se(r > 0);
221         assert_se(streq(command, "/bin/script"));
222         free(command);
223
224         r = executable_is_script("/bin/sh", &command);
225         assert_se(r == 0);
226
227         r = executable_is_script("/usr/bin/yum", &command);
228         assert_se(r > 0 || r == -ENOENT);
229         if (r > 0) {
230                 assert_se(startswith(command, "/"));
231                 free(command);
232         }
233
234         fclose(f);
235         unlink(t);
236 }
237
238 static void test_status_field(void) {
239         _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
240         unsigned long long total = 0, buffers = 0;
241         int r;
242
243         assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0);
244         puts(t);
245         assert_se(streq(t, "1"));
246
247         r = get_status_field("/proc/meminfo", "MemTotal:", &p);
248         if (r != -ENOENT) {
249                 assert(r == 0);
250                 puts(p);
251                 assert_se(safe_atollu(p, &total) == 0);
252         }
253
254         r = get_status_field("/proc/meminfo", "\nBuffers:", &s);
255         if (r != -ENOENT) {
256                 assert(r == 0);
257                 puts(s);
258                 assert_se(safe_atollu(s, &buffers) == 0);
259         }
260
261         if (p && t)
262                 assert(buffers < total);
263
264         /* Seccomp should be a good test for field full of zeros. */
265         r = get_status_field("/proc/meminfo", "\nSeccomp:", &z);
266         if (r != -ENOENT) {
267                 assert(r == 0);
268                 puts(z);
269                 assert_se(safe_atollu(z, &buffers) == 0);
270         }
271 }
272
273 static void test_capeff(void) {
274         int pid, p;
275
276         for (pid = 0; pid < 2; pid++) {
277                 _cleanup_free_ char *capeff = NULL;
278                 int r;
279
280                 r = get_process_capeff(0, &capeff);
281                 log_info("capeff: '%s' (r=%d)", capeff, r);
282
283                 if (r == -ENOENT || r == -EPERM)
284                         return;
285
286                 assert(r == 0);
287                 assert(*capeff);
288                 p = capeff[strspn(capeff, DIGITS "abcdefABCDEF")];
289                 assert(!p || isspace(p));
290         }
291 }
292
293 static void test_write_string_stream(void) {
294         char fn[] = "/tmp/test-write_string_stream-XXXXXX";
295         _cleanup_fclose_ FILE *f = NULL;
296         int fd;
297         char buf[64];
298
299         fd = mkostemp_safe(fn, O_RDWR);
300         assert_se(fd >= 0);
301
302         f = fdopen(fd, "r");
303         assert_se(f);
304         assert_se(write_string_stream(f, "boohoo") < 0);
305
306         f = fdopen(fd, "r+");
307         assert_se(f);
308
309         assert_se(write_string_stream(f, "boohoo") == 0);
310         rewind(f);
311
312         assert_se(fgets(buf, sizeof(buf), f));
313         assert_se(streq(buf, "boohoo\n"));
314
315         unlink(fn);
316 }
317
318 static void test_write_string_file(void) {
319         char fn[] = "/tmp/test-write_string_file-XXXXXX";
320         int fd;
321         char buf[64] = {0};
322
323         fd = mkostemp_safe(fn, O_RDWR);
324         assert_se(fd >= 0);
325
326         assert_se(write_string_file(fn, "boohoo") == 0);
327
328         assert_se(read(fd, buf, sizeof(buf)));
329         assert_se(streq(buf, "boohoo\n"));
330
331         unlink(fn);
332 }
333
334 static void test_sendfile_full(void) {
335         char in_fn[] = "/tmp/test-sendfile_full-XXXXXX";
336         char out_fn[] = "/tmp/test-sendfile_full-XXXXXX";
337         _cleanup_close_ int in_fd = -1;
338         int out_fd;
339         char text[] = "boohoo\nfoo\n\tbar\n";
340         char buf[64] = {0};
341
342         in_fd = mkostemp_safe(in_fn, O_RDWR);
343         assert_se(in_fd >= 0);
344         out_fd = mkostemp_safe(out_fn, O_RDWR);
345         assert_se(out_fd >= 0);
346
347         assert_se(write_string_file(in_fn, text) == 0);
348         assert_se(sendfile_full(out_fd, "/a/file/which/does/not/exist/i/guess") < 0);
349         assert_se(sendfile_full(out_fd, in_fn) == sizeof(text) - 1);
350         assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
351
352         assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);
353         assert_se(streq(buf, text));
354
355         unlink(in_fn);
356         unlink(out_fn);
357 }
358
359 int main(int argc, char *argv[]) {
360         log_parse_environment();
361         log_open();
362
363         test_parse_env_file();
364         test_parse_multiline_env_file();
365         test_executable_is_script();
366         test_status_field();
367         test_capeff();
368         test_write_string_stream();
369         test_write_string_file();
370         test_sendfile_full();
371
372         return 0;
373 }