1 /*
2 * Copyright © 2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #include "config.h"
27
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <errno.h>
34 #include <unistd.h>
35
36 #include <libweston/config-parser.h>
37
38 #include "shared/helpers.h"
39 #include "zunitc/zunitc.h"
40
41 struct fixture_data {
42 const char *text;
43 struct weston_config *config;
44 };
45
46 static struct weston_config *
load_config(const char * text)47 load_config(const char *text)
48 {
49 struct weston_config *config = NULL;
50 int len = 0;
51 int fd = -1;
52 char file[] = "/tmp/weston-config-parser-test-XXXXXX";
53
54 ZUC_ASSERTG_NOT_NULL(text, out);
55
56 fd = mkstemp(file);
57 ZUC_ASSERTG_NE(-1, fd, out);
58
59 len = write(fd, text, strlen(text));
60 ZUC_ASSERTG_EQ((int)strlen(text), len, out_close);
61
62 config = weston_config_parse(file);
63
64 out_close:
65 close(fd);
66 unlink(file);
67 out:
68 return config;
69 }
70
71 static void *
setup_test_config(void * data)72 setup_test_config(void *data)
73 {
74 struct weston_config *config = load_config(data);
75 ZUC_ASSERTG_NOT_NULL(config, out);
76
77 out:
78 return config;
79 }
80
81 static void *
setup_test_config_failing(void * data)82 setup_test_config_failing(void *data)
83 {
84 struct weston_config *config = load_config(data);
85 ZUC_ASSERTG_NULL(config, err_free);
86
87 return config;
88 err_free:
89 weston_config_destroy(config);
90 return NULL;
91 }
92
93 static void
cleanup_test_config(void * data)94 cleanup_test_config(void *data)
95 {
96 struct weston_config *config = data;
97 ZUC_ASSERT_NOT_NULL(config);
98 weston_config_destroy(config);
99 }
100
101 static struct zuc_fixture config_test_t0 = {
102 .data = "# nothing in this file...\n",
103 .set_up = setup_test_config,
104 .tear_down = cleanup_test_config
105 };
106
107 static struct zuc_fixture config_test_t1 = {
108 .data =
109 "# comment line here...\n"
110 "\n"
111 "[foo]\n"
112 "a=b\n"
113 "name= Roy Batty \n"
114 "\n"
115 "\n"
116 "[bar]\n"
117 "# more comments\n"
118 "number=5252\n"
119 "zero=0\n"
120 "negative=-42\n"
121 "flag=false\n"
122 "\n"
123 "[colors]\n"
124 "none=0x00000000\n"
125 "low=0x11223344\n"
126 "high=0xff00ff00\n"
127 "oct=01234567\n"
128 "dec=12345670\n"
129 "short=1234567\n"
130 "\n"
131 "[stuff]\n"
132 "flag= true \n"
133 "\n"
134 "[bucket]\n"
135 "color=blue \n"
136 "contents=live crabs\n"
137 "pinchy=true\n"
138 "\n"
139 "[bucket]\n"
140 "material=plastic \n"
141 "color=red\n"
142 "contents=sand\n",
143 .set_up = setup_test_config,
144 .tear_down = cleanup_test_config
145 };
146
147 static const char *section_names[] = {
148 "foo", "bar", "colors", "stuff", "bucket", "bucket"
149 };
150
151 /*
152 * Since these next few won't parse, we don't add the tear_down to
153 * attempt cleanup.
154 */
155
156 static struct zuc_fixture config_test_t2 = {
157 .data =
158 "# invalid section...\n"
159 "[this bracket isn't closed\n",
160 .set_up = setup_test_config_failing,
161 };
162
163 static struct zuc_fixture config_test_t3 = {
164 .data =
165 "# line without = ...\n"
166 "[bambam]\n"
167 "this line isn't any kind of valid\n",
168 .set_up = setup_test_config_failing,
169 };
170
171 static struct zuc_fixture config_test_t4 = {
172 .data =
173 "# starting with = ...\n"
174 "[bambam]\n"
175 "=not valid at all\n",
176 .set_up = setup_test_config_failing,
177 };
178
ZUC_TEST_F(config_test_t0,comment_only,data)179 ZUC_TEST_F(config_test_t0, comment_only, data)
180 {
181 struct weston_config *config = data;
182 ZUC_ASSERT_NOT_NULL(config);
183 }
184
185 /** @todo individual t1 tests should have more descriptive names. */
186
ZUC_TEST_F(config_test_t1,test001,data)187 ZUC_TEST_F(config_test_t1, test001, data)
188 {
189 struct weston_config_section *section;
190 struct weston_config *config = data;
191 ZUC_ASSERT_NOT_NULL(config);
192 section = weston_config_get_section(config,
193 "mollusc", NULL, NULL);
194 ZUC_ASSERT_NULL(section);
195 }
196
ZUC_TEST_F(config_test_t1,test002,data)197 ZUC_TEST_F(config_test_t1, test002, data)
198 {
199 char *s;
200 int r;
201 struct weston_config_section *section;
202 struct weston_config *config = data;
203
204 section = weston_config_get_section(config, "foo", NULL, NULL);
205 r = weston_config_section_get_string(section, "a", &s, NULL);
206
207 ZUC_ASSERTG_EQ(0, r, out_free);
208 ZUC_ASSERTG_STREQ("b", s, out_free);
209
210 out_free:
211 free(s);
212 }
213
ZUC_TEST_F(config_test_t1,test003,data)214 ZUC_TEST_F(config_test_t1, test003, data)
215 {
216 char *s;
217 int r;
218 struct weston_config_section *section;
219 struct weston_config *config = data;
220
221 section = weston_config_get_section(config, "foo", NULL, NULL);
222 r = weston_config_section_get_string(section, "b", &s, NULL);
223
224 ZUC_ASSERT_EQ(-1, r);
225 ZUC_ASSERT_EQ(ENOENT, errno);
226 ZUC_ASSERT_NULL(s);
227 }
228
ZUC_TEST_F(config_test_t1,test004,data)229 ZUC_TEST_F(config_test_t1, test004, data)
230 {
231 char *s;
232 int r;
233 struct weston_config_section *section;
234 struct weston_config *config = data;
235
236 section = weston_config_get_section(config, "foo", NULL, NULL);
237 r = weston_config_section_get_string(section, "name", &s, NULL);
238
239 ZUC_ASSERTG_EQ(0, r, out_free);
240 ZUC_ASSERTG_STREQ("Roy Batty", s, out_free);
241
242 out_free:
243 free(s);
244 }
245
ZUC_TEST_F(config_test_t1,test005,data)246 ZUC_TEST_F(config_test_t1, test005, data)
247 {
248 char *s;
249 int r;
250 struct weston_config_section *section;
251 struct weston_config *config = data;
252
253 section = weston_config_get_section(config, "bar", NULL, NULL);
254 r = weston_config_section_get_string(section, "a", &s, "boo");
255
256 ZUC_ASSERTG_EQ(-1, r, out_free);
257 ZUC_ASSERTG_EQ(ENOENT, errno, out_free);
258 ZUC_ASSERTG_STREQ("boo", s, out_free);
259
260 out_free:
261 free(s);
262 }
263
ZUC_TEST_F(config_test_t1,test006,data)264 ZUC_TEST_F(config_test_t1, test006, data)
265 {
266 int r;
267 int32_t n;
268 struct weston_config_section *section;
269 struct weston_config *config = data;
270
271 section = weston_config_get_section(config, "bar", NULL, NULL);
272 r = weston_config_section_get_int(section, "number", &n, 600);
273
274 ZUC_ASSERT_EQ(0, r);
275 ZUC_ASSERT_EQ(5252, n);
276 ZUC_ASSERT_EQ(0, errno);
277 }
278
ZUC_TEST_F(config_test_t1,test007,data)279 ZUC_TEST_F(config_test_t1, test007, data)
280 {
281 int r;
282 int32_t n;
283 struct weston_config_section *section;
284 struct weston_config *config = data;
285
286 section = weston_config_get_section(config, "bar", NULL, NULL);
287 r = weston_config_section_get_int(section, "+++", &n, 700);
288
289 ZUC_ASSERT_EQ(-1, r);
290 ZUC_ASSERT_EQ(ENOENT, errno);
291 ZUC_ASSERT_EQ(700, n);
292 }
293
ZUC_TEST_F(config_test_t1,test008,data)294 ZUC_TEST_F(config_test_t1, test008, data)
295 {
296 int r;
297 uint32_t u;
298 struct weston_config_section *section;
299 struct weston_config *config = data;
300
301 section = weston_config_get_section(config, "bar", NULL, NULL);
302 r = weston_config_section_get_uint(section, "number", &u, 600);
303
304 ZUC_ASSERT_EQ(0, r);
305 ZUC_ASSERT_EQ(5252, u);
306 ZUC_ASSERT_EQ(0, errno);
307 }
308
ZUC_TEST_F(config_test_t1,test009,data)309 ZUC_TEST_F(config_test_t1, test009, data)
310 {
311 int r;
312 uint32_t u;
313 struct weston_config_section *section;
314 struct weston_config *config = data;
315
316 section = weston_config_get_section(config, "bar", NULL, NULL);
317 r = weston_config_section_get_uint(section, "+++", &u, 600);
318 ZUC_ASSERT_EQ(-1, r);
319 ZUC_ASSERT_EQ(ENOENT, errno);
320 ZUC_ASSERT_EQ(600, u);
321 }
322
ZUC_TEST_F(config_test_t1,test010,data)323 ZUC_TEST_F(config_test_t1, test010, data)
324 {
325 int r;
326 bool b;
327 struct weston_config_section *section;
328 struct weston_config *config = data;
329
330 section = weston_config_get_section(config, "bar", NULL, NULL);
331 r = weston_config_section_get_bool(section, "flag", &b, true);
332 ZUC_ASSERT_EQ(0, r);
333 ZUC_ASSERT_EQ(false, b);
334 }
335
ZUC_TEST_F(config_test_t1,test011,data)336 ZUC_TEST_F(config_test_t1, test011, data)
337 {
338 int r;
339 bool b;
340 struct weston_config_section *section;
341 struct weston_config *config = data;
342
343 section = weston_config_get_section(config, "stuff", NULL, NULL);
344 r = weston_config_section_get_bool(section, "flag", &b, false);
345 ZUC_ASSERT_EQ(0, r);
346 ZUC_ASSERT_EQ(true, b);
347 }
348
ZUC_TEST_F(config_test_t1,test012,data)349 ZUC_TEST_F(config_test_t1, test012, data)
350 {
351 int r;
352 bool b;
353 struct weston_config_section *section;
354 struct weston_config *config = data;
355
356 section = weston_config_get_section(config, "stuff", NULL, NULL);
357 r = weston_config_section_get_bool(section, "bonk", &b, false);
358 ZUC_ASSERT_EQ(-1, r);
359 ZUC_ASSERT_EQ(ENOENT, errno);
360 ZUC_ASSERT_EQ(false, b);
361 }
362
ZUC_TEST_F(config_test_t1,test013,data)363 ZUC_TEST_F(config_test_t1, test013, data)
364 {
365 char *s;
366 int r;
367 struct weston_config_section *section;
368 struct weston_config *config = data;
369
370 section = weston_config_get_section(config,
371 "bucket", "color", "blue");
372 r = weston_config_section_get_string(section, "contents", &s, NULL);
373
374 ZUC_ASSERTG_EQ(0, r, out_free);
375 ZUC_ASSERTG_STREQ("live crabs", s, out_free);
376
377 out_free:
378 free(s);
379 }
380
ZUC_TEST_F(config_test_t1,test014,data)381 ZUC_TEST_F(config_test_t1, test014, data)
382 {
383 char *s;
384 int r;
385 struct weston_config_section *section;
386 struct weston_config *config = data;
387
388 section = weston_config_get_section(config,
389 "bucket", "color", "red");
390 r = weston_config_section_get_string(section, "contents", &s, NULL);
391
392 ZUC_ASSERTG_EQ(0, r, out_free);
393 ZUC_ASSERTG_STREQ("sand", s, out_free);
394
395 out_free:
396 free(s);
397 }
398
ZUC_TEST_F(config_test_t1,test015,data)399 ZUC_TEST_F(config_test_t1, test015, data)
400 {
401 char *s;
402 int r;
403 struct weston_config_section *section;
404 struct weston_config *config = data;
405
406 section = weston_config_get_section(config,
407 "bucket", "color", "pink");
408 ZUC_ASSERT_NULL(section);
409 r = weston_config_section_get_string(section, "contents", &s, "eels");
410
411 ZUC_ASSERTG_EQ(-1, r, out_free);
412 ZUC_ASSERTG_EQ(ENOENT, errno, out_free);
413 ZUC_ASSERTG_STREQ("eels", s, out_free);
414
415 out_free:
416 free(s);
417 }
418
ZUC_TEST_F(config_test_t1,test016,data)419 ZUC_TEST_F(config_test_t1, test016, data)
420 {
421 const char *name;
422 int i;
423 struct weston_config_section *section;
424 struct weston_config *config = data;
425
426 section = NULL;
427 i = 0;
428 while (weston_config_next_section(config, §ion, &name))
429 ZUC_ASSERT_STREQ(section_names[i++], name);
430
431 ZUC_ASSERT_EQ(6, i);
432 }
433
ZUC_TEST_F(config_test_t1,test017,data)434 ZUC_TEST_F(config_test_t1, test017, data)
435 {
436 int r;
437 int32_t n;
438 struct weston_config_section *section;
439 struct weston_config *config = data;
440
441 section = weston_config_get_section(config, "bar", NULL, NULL);
442 r = weston_config_section_get_int(section, "zero", &n, 600);
443
444 ZUC_ASSERT_EQ(0, r);
445 ZUC_ASSERT_EQ(0, n);
446 ZUC_ASSERT_EQ(0, errno);
447 }
448
ZUC_TEST_F(config_test_t1,test018,data)449 ZUC_TEST_F(config_test_t1, test018, data)
450 {
451 int r;
452 uint32_t n;
453 struct weston_config_section *section;
454 struct weston_config *config = data;
455
456 section = weston_config_get_section(config, "bar", NULL, NULL);
457 r = weston_config_section_get_uint(section, "zero", &n, 600);
458
459 ZUC_ASSERT_EQ(0, r);
460 ZUC_ASSERT_EQ(0, n);
461 ZUC_ASSERT_EQ(0, errno);
462 }
463
ZUC_TEST_F(config_test_t1,test019,data)464 ZUC_TEST_F(config_test_t1, test019, data)
465 {
466 int r;
467 uint32_t n;
468 struct weston_config_section *section;
469 struct weston_config *config = data;
470
471 section = weston_config_get_section(config, "colors", NULL, NULL);
472 r = weston_config_section_get_color(section, "none", &n, 0xff336699);
473
474 ZUC_ASSERT_EQ(0, r);
475 ZUC_ASSERT_EQ(0x000000, n);
476 ZUC_ASSERT_EQ(0, errno);
477 }
478
ZUC_TEST_F(config_test_t1,test020,data)479 ZUC_TEST_F(config_test_t1, test020, data)
480 {
481 int r;
482 uint32_t n;
483 struct weston_config_section *section;
484 struct weston_config *config = data;
485
486 section = weston_config_get_section(config, "colors", NULL, NULL);
487 r = weston_config_section_get_color(section, "low", &n, 0xff336699);
488
489 ZUC_ASSERT_EQ(0, r);
490 ZUC_ASSERT_EQ(0x11223344, n);
491 ZUC_ASSERT_EQ(0, errno);
492 }
493
ZUC_TEST_F(config_test_t1,test021,data)494 ZUC_TEST_F(config_test_t1, test021, data)
495 {
496 int r;
497 uint32_t n;
498 struct weston_config_section *section;
499 struct weston_config *config = data;
500
501 section = weston_config_get_section(config, "colors", NULL, NULL);
502 r = weston_config_section_get_color(section, "high", &n, 0xff336699);
503
504 ZUC_ASSERT_EQ(0, r);
505 ZUC_ASSERT_EQ(0xff00ff00, n);
506 ZUC_ASSERT_EQ(0, errno);
507 }
508
ZUC_TEST_F(config_test_t1,test022,data)509 ZUC_TEST_F(config_test_t1, test022, data)
510 {
511 int r;
512 uint32_t n;
513 struct weston_config_section *section;
514 struct weston_config *config = data;
515
516 // Treat colors as hex values even if missing the leading 0x
517 section = weston_config_get_section(config, "colors", NULL, NULL);
518 r = weston_config_section_get_color(section, "oct", &n, 0xff336699);
519
520 ZUC_ASSERT_EQ(0, r);
521 ZUC_ASSERT_EQ(0x01234567, n);
522 ZUC_ASSERT_EQ(0, errno);
523 }
524
ZUC_TEST_F(config_test_t1,test023,data)525 ZUC_TEST_F(config_test_t1, test023, data)
526 {
527 int r;
528 uint32_t n;
529 struct weston_config_section *section;
530 struct weston_config *config = data;
531
532 // Treat colors as hex values even if missing the leading 0x
533 section = weston_config_get_section(config, "colors", NULL, NULL);
534 r = weston_config_section_get_color(section, "dec", &n, 0xff336699);
535
536 ZUC_ASSERT_EQ(0, r);
537 ZUC_ASSERT_EQ(0x12345670, n);
538 ZUC_ASSERT_EQ(0, errno);
539 }
540
ZUC_TEST_F(config_test_t1,test024,data)541 ZUC_TEST_F(config_test_t1, test024, data)
542 {
543 int r;
544 uint32_t n;
545 struct weston_config_section *section;
546 struct weston_config *config = data;
547
548 // 7-digit colors are not valid (most likely typos)
549 section = weston_config_get_section(config, "colors", NULL, NULL);
550 r = weston_config_section_get_color(section, "short", &n, 0xff336699);
551
552 ZUC_ASSERT_EQ(-1, r);
553 ZUC_ASSERT_EQ(0xff336699, n);
554 ZUC_ASSERT_EQ(EINVAL, errno);
555 }
556
ZUC_TEST_F(config_test_t1,test025,data)557 ZUC_TEST_F(config_test_t1, test025, data)
558 {
559 int r;
560 uint32_t n;
561 struct weston_config_section *section;
562 struct weston_config *config = data;
563
564 // String color names are unsupported
565 section = weston_config_get_section(config, "bucket", NULL, NULL);
566 r = weston_config_section_get_color(section, "color", &n, 0xff336699);
567
568 ZUC_ASSERT_EQ(-1, r);
569 ZUC_ASSERT_EQ(0xff336699, n);
570 ZUC_ASSERT_EQ(EINVAL, errno);
571 }
572
ZUC_TEST_F(config_test_t1,test026,data)573 ZUC_TEST_F(config_test_t1, test026, data)
574 {
575 int r;
576 int32_t n;
577 struct weston_config_section *section;
578 struct weston_config *config = data;
579
580 section = weston_config_get_section(config, "bar", NULL, NULL);
581 r = weston_config_section_get_int(section, "negative", &n, 600);
582
583 ZUC_ASSERT_EQ(0, r);
584 ZUC_ASSERT_EQ(-42, n);
585 ZUC_ASSERT_EQ(0, errno);
586 }
587
ZUC_TEST_F(config_test_t1,test027,data)588 ZUC_TEST_F(config_test_t1, test027, data)
589 {
590 int r;
591 uint32_t n;
592 struct weston_config_section *section;
593 struct weston_config *config = data;
594
595 section = weston_config_get_section(config, "bar", NULL, NULL);
596 r = weston_config_section_get_uint(section, "negative", &n, 600);
597
598 ZUC_ASSERT_EQ(-1, r);
599 ZUC_ASSERT_EQ(600, n);
600 ZUC_ASSERT_EQ(ERANGE, errno);
601 }
602
ZUC_TEST_F(config_test_t2,doesnt_parse,data)603 ZUC_TEST_F(config_test_t2, doesnt_parse, data)
604 {
605 struct weston_config *config = data;
606 ZUC_ASSERT_NULL(config);
607 }
608
ZUC_TEST_F(config_test_t3,doesnt_parse,data)609 ZUC_TEST_F(config_test_t3, doesnt_parse, data)
610 {
611 struct weston_config *config = data;
612 ZUC_ASSERT_NULL(config);
613 }
614
ZUC_TEST_F(config_test_t4,doesnt_parse,data)615 ZUC_TEST_F(config_test_t4, doesnt_parse, data)
616 {
617 struct weston_config *config = data;
618 ZUC_ASSERT_NULL(config);
619 }
620
ZUC_TEST(config_test,destroy_null)621 ZUC_TEST(config_test, destroy_null)
622 {
623 weston_config_destroy(NULL);
624 ZUC_ASSERT_EQ(0, weston_config_next_section(NULL, NULL, NULL));
625 }
626
ZUC_TEST(config_test,section_from_null)627 ZUC_TEST(config_test, section_from_null)
628 {
629 struct weston_config_section *section;
630 section = weston_config_get_section(NULL, "bucket", NULL, NULL);
631 ZUC_ASSERT_NULL(section);
632 }
633