chiark / gitweb /
conf-parser: distinguish between multiple sections with the same name
[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         assert_se(mktemp(p));
45
46         fd = mkostemp(t, O_CLOEXEC);
47         assert_se(fd >= 0);
48
49         f = fdopen(fd, "w");
50         assert_se(f);
51
52         fputs("one=BAR   \n"
53               "# comment\n"
54               " # comment \n"
55               " ; comment \n"
56               "  two   =   bar    \n"
57               "invalid line\n"
58               "invalid line #comment\n"
59               "three = \"333\n"
60               "xxxx\"\n"
61               "four = \'44\\\"44\'\n"
62               "five = \'55\\\'55\' \"FIVE\" cinco   \n"
63               "six = seis sechs\\\n"
64               " sis\n"
65               "seven=\"sevenval\" #nocomment\n"
66               "eight=eightval #nocomment\n"
67               "export nine=nineval\n"
68               "ten=", f);
69
70         fflush(f);
71         fclose(f);
72
73         r = load_env_file(t, NULL, &a);
74         assert_se(r >= 0);
75
76         STRV_FOREACH(i, a)
77                 log_info("Got: <%s>", *i);
78
79         assert_se(streq(a[0], "one=BAR"));
80         assert_se(streq(a[1], "two=bar"));
81         assert_se(streq(a[2], "three=333\nxxxx"));
82         assert_se(streq(a[3], "four=44\"44"));
83         assert_se(streq(a[4], "five=55\'55FIVEcinco"));
84         assert_se(streq(a[5], "six=seis sechs sis"));
85         assert_se(streq(a[6], "seven=sevenval#nocomment"));
86         assert_se(streq(a[7], "eight=eightval #nocomment"));
87         assert_se(streq(a[8], "export nine=nineval"));
88         assert_se(streq(a[9], "ten="));
89         assert_se(a[10] == NULL);
90
91         strv_env_clean_log(a, "test");
92
93         k = 0;
94         STRV_FOREACH(i, b) {
95                 log_info("Got2: <%s>", *i);
96                 assert_se(streq(*i, a[k++]));
97         }
98
99         r = parse_env_file(
100                         t, NULL,
101                        "one", &one,
102                        "two", &two,
103                        "three", &three,
104                        "four", &four,
105                        "five", &five,
106                        "six", &six,
107                        "seven", &seven,
108                        "eight", &eight,
109                        "export nine", &nine,
110                        "ten", &ten,
111                        NULL);
112
113         assert_se(r >= 0);
114
115         log_info("one=[%s]", strna(one));
116         log_info("two=[%s]", strna(two));
117         log_info("three=[%s]", strna(three));
118         log_info("four=[%s]", strna(four));
119         log_info("five=[%s]", strna(five));
120         log_info("six=[%s]", strna(six));
121         log_info("seven=[%s]", strna(seven));
122         log_info("eight=[%s]", strna(eight));
123         log_info("export nine=[%s]", strna(nine));
124         log_info("ten=[%s]", strna(nine));
125
126         assert_se(streq(one, "BAR"));
127         assert_se(streq(two, "bar"));
128         assert_se(streq(three, "333\nxxxx"));
129         assert_se(streq(four, "44\"44"));
130         assert_se(streq(five, "55\'55FIVEcinco"));
131         assert_se(streq(six, "seis sechs sis"));
132         assert_se(streq(seven, "sevenval#nocomment"));
133         assert_se(streq(eight, "eightval #nocomment"));
134         assert_se(streq(nine, "nineval"));
135         assert_se(ten == NULL);
136
137         r = write_env_file(p, a);
138         assert_se(r >= 0);
139
140         r = load_env_file(p, NULL, &b);
141         assert_se(r >= 0);
142
143         unlink(t);
144         unlink(p);
145 }
146
147 static void test_parse_multiline_env_file(void) {
148         char    t[] = "/tmp/test-fileio-in-XXXXXX",
149                 p[] = "/tmp/test-fileio-out-XXXXXX";
150         int fd, r;
151         FILE *f;
152         _cleanup_strv_free_ char **a = NULL, **b = NULL;
153         char **i;
154
155         assert_se(mktemp(p));
156
157         fd = mkostemp(t, O_CLOEXEC);
158         assert_se(fd >= 0);
159
160         f = fdopen(fd, "w");
161         assert_se(f);
162
163         fputs("one=BAR\\\n"
164               "    VAR\\\n"
165               "\tGAR\n"
166               "#comment\n"
167               "two=\"bar\\\n"
168               "    var\\\n"
169               "\tgar\"\n"
170               "#comment\n"
171               "tri=\"bar \\\n"
172               "    var \\\n"
173               "\tgar \"\n", f);
174
175         fflush(f);
176         fclose(f);
177
178         r = load_env_file(t, NULL, &a);
179         assert_se(r >= 0);
180
181         STRV_FOREACH(i, a)
182                 log_info("Got: <%s>", *i);
183
184         assert_se(streq(a[0], "one=BAR    VAR\tGAR"));
185         assert_se(streq(a[1], "two=bar    var\tgar"));
186         assert_se(streq(a[2], "tri=bar     var \tgar "));
187         assert_se(a[3] == NULL);
188
189         r = write_env_file(p, a);
190         assert_se(r >= 0);
191
192         r = load_env_file(p, NULL, &b);
193         assert_se(r >= 0);
194
195         unlink(t);
196         unlink(p);
197 }
198
199
200 static void test_executable_is_script(void) {
201         char t[] = "/tmp/test-executable-XXXXXX";
202         int fd, r;
203         FILE *f;
204         char *command;
205
206         fd = mkostemp(t, O_CLOEXEC);
207         assert_se(fd >= 0);
208
209         f = fdopen(fd, "w");
210         assert_se(f);
211
212         fputs("#! /bin/script -a -b \ngoo goo", f);
213         fflush(f);
214
215         r = executable_is_script(t, &command);
216         assert_se(r > 0);
217         assert_se(streq(command, "/bin/script"));
218         free(command);
219
220         r = executable_is_script("/bin/sh", &command);
221         assert_se(r == 0);
222
223         r = executable_is_script("/usr/bin/yum", &command);
224         assert_se(r > 0 || r == -ENOENT);
225         if (r > 0) {
226                 assert_se(startswith(command, "/"));
227                 free(command);
228         }
229
230         fclose(f);
231         unlink(t);
232 }
233
234 static void test_status_field(void) {
235         _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
236         unsigned long long total = 0, buffers = 0;
237         int r;
238
239         assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0);
240         puts(t);
241         assert_se(streq(t, "1"));
242
243         r = get_status_field("/proc/meminfo", "MemTotal:", &p);
244         if (r != -ENOENT) {
245                 assert(r == 0);
246                 puts(p);
247                 assert_se(safe_atollu(p, &total) == 0);
248         }
249
250         r = get_status_field("/proc/meminfo", "\nBuffers:", &s);
251         if (r != -ENOENT) {
252                 assert(r == 0);
253                 puts(s);
254                 assert_se(safe_atollu(s, &buffers) == 0);
255         }
256
257         if (p && t)
258                 assert(buffers < total);
259
260         /* Seccomp should be a good test for field full of zeros. */
261         r = get_status_field("/proc/meminfo", "\nSeccomp:", &z);
262         if (r != -ENOENT) {
263                 assert(r == 0);
264                 puts(z);
265                 assert_se(safe_atollu(z, &buffers) == 0);
266         }
267 }
268
269 static void test_capeff(void) {
270         int pid, p;
271
272         for (pid = 0; pid < 2; pid++) {
273                 _cleanup_free_ char *capeff = NULL;
274                 int r;
275
276                 r = get_process_capeff(0, &capeff);
277                 log_info("capeff: '%s' (r=%d)", capeff, r);
278
279                 if (r == -ENOENT || r == -EPERM)
280                         return;
281
282                 assert(r == 0);
283                 assert(*capeff);
284                 p = capeff[strspn(capeff, DIGITS "abcdefABCDEF")];
285                 assert(!p || isspace(p));
286         }
287 }
288
289 int main(int argc, char *argv[]) {
290         log_parse_environment();
291         log_open();
292
293         test_parse_env_file();
294         test_parse_multiline_env_file();
295         test_executable_is_script();
296         test_status_field();
297         test_capeff();
298
299         return 0;
300 }