chiark / gitweb /
eb4fbc91d2dcd2dc50463185ccc99d78c78ca1fd
[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 = mkstemp(p);
45         assert_se(fd >= 0);
46         close(fd);
47
48         fd = mkostemp(t, 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(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(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 = mkstemp(p);
158         assert_se(fd >= 0);
159         close(fd);
160
161         fd = mkostemp(t, 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(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(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(t, 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 int main(int argc, char *argv[]) {
294         log_parse_environment();
295         log_open();
296
297         test_parse_env_file();
298         test_parse_multiline_env_file();
299         test_executable_is_script();
300         test_status_field();
301         test_capeff();
302
303         return 0;
304 }