1 /* $Id: confparse-t.c 10308 2018-12-02 14:33:59Z iulius $ */
2 /* confparse test suite. */
3
4 #include "config.h"
5 #include "clibrary.h"
6
7 #include "inn/confparse.h"
8 #include "inn/messages.h"
9 #include "inn/vector.h"
10 #include "inn/libinn.h"
11 #include "tap/basic.h"
12 #include "tap/float.h"
13 #include "tap/messages.h"
14
15 /* Given a FILE *, read from that file, putting the results into a newly
16 allocated buffer, until encountering a line consisting solely of "===".
17 Returns the buffer, NULL on end of file, dies on error. */
18 static char *
read_section(FILE * file)19 read_section(FILE *file)
20 {
21 char buf[1024];
22 char *data = NULL;
23 char *status;
24
25 status = fgets(buf, sizeof(buf), file);
26 if (status == NULL)
27 return false;
28 while (1) {
29 if (status == NULL)
30 die("Unexpected end of file while reading tests");
31 if (strcmp(buf, "===\n") == 0)
32 break;
33 if (data == NULL) {
34 data = xstrdup(buf);
35 } else {
36 char *new_data;
37
38 new_data = concat(data, buf, (char *) 0);
39 free(data);
40 data = new_data;
41 }
42 status = fgets(buf, sizeof(buf), file);
43 }
44 return data;
45 }
46
47 /* Read from the given file a configuration file and write it out to
48 config/tmp. Returns true on success, false on end of file, and dies on
49 any error. */
50 static bool
write_test_config(FILE * file)51 write_test_config(FILE *file)
52 {
53 FILE *tmp;
54 char *config;
55
56 config = read_section(file);
57 if (config == NULL)
58 return false;
59 tmp = fopen("config/tmp", "w");
60 if (tmp == NULL)
61 sysdie("Cannot create config/tmp");
62 if (fputs(config, tmp) == EOF)
63 sysdie("Write error while writing to config/tmp");
64 fclose(tmp);
65 free(config);
66 return true;
67 }
68
69 /* Parse a given config file with errors, setting the appropriate error
70 handler for the duration of the parse to save errors into the errors
71 global. Returns the resulting config_group. */
72 static struct config_group *
parse_error_config(const char * filename)73 parse_error_config(const char *filename)
74 {
75 struct config_group *group;
76
77 errors_capture();
78 group = config_parse_file(filename);
79 errors_uncapture();
80 return group;
81 }
82
83 /* Read in a configuration file from the provided FILE *, write it to disk,
84 parse the temporary config file, and return the resulting config_group in
85 the pointer passed as the second parameter. Returns true on success,
86 false on end of file. */
87 static bool
parse_test_config(FILE * file,struct config_group ** group)88 parse_test_config(FILE *file, struct config_group **group)
89 {
90 if (!write_test_config(file))
91 return false;
92 *group = parse_error_config("config/tmp");
93 unlink("config/tmp");
94 return true;
95 }
96
97 /* Test the error test cases in config/errors, ensuring that they all fail
98 to parse and match the expected error messages. Takes the current test
99 count and returns the new test count. */
100 static int
test_errors(int n)101 test_errors(int n)
102 {
103 FILE *errfile;
104 char *expected;
105 struct config_group *group;
106
107 if (symlink(".", "config/link") < 0)
108 sysdie("Cannot create config/link symlink");
109 errfile = fopen("config/errors", "r");
110 if (errfile == NULL)
111 sysdie("Cannot open config/errors");
112 while (parse_test_config(errfile, &group)) {
113 expected = read_section(errfile);
114 if (expected == NULL)
115 die("Unexpected end of file while reading error tests");
116 ok(n++, group == NULL);
117 ok_string(n++, expected, errors);
118 free(expected);
119 if (group != NULL)
120 config_free(group);
121 }
122 fclose(errfile);
123 unlink("config/link");
124 return n;
125 }
126
127 /* Test the warning test cases in config/warnings, ensuring that they all
128 parse successfully and match the expected error messages. Takes the
129 current test count and returns the new test count. */
130 static int
test_warnings(int n)131 test_warnings(int n)
132 {
133 FILE *warnfile;
134 char *expected;
135 struct config_group *group;
136
137 warnfile = fopen("config/warnings", "r");
138 if (warnfile == NULL)
139 sysdie("Cannot open config/warnings");
140 while (parse_test_config(warnfile, &group)) {
141 expected = read_section(warnfile);
142 if (expected == NULL)
143 die("Unexpected end of file while reading error tests");
144 ok(n++, group != NULL);
145 ok_string(n++, expected, errors);
146 free(expected);
147 if (group != NULL)
148 config_free(group);
149 }
150 fclose(warnfile);
151 return n;
152 }
153
154 /* Test the warning test cases in config/warn-bool, ensuring that they all
155 parse successfully and produce the expected error messages when retrieved
156 as bools. Takes the current test count and returns the new test count. */
157 static int
test_warnings_bool(int n)158 test_warnings_bool(int n)
159 {
160 FILE *warnfile;
161 char *expected;
162 struct config_group *group;
163 bool b_value = false;
164
165 warnfile = fopen("config/warn-bool", "r");
166 if (warnfile == NULL)
167 sysdie("Cannot open config/warn-bool");
168 while (parse_test_config(warnfile, &group)) {
169 expected = read_section(warnfile);
170 if (expected == NULL)
171 die("Unexpected end of file while reading error tests");
172 ok(n++, group != NULL);
173 ok(n++, errors == NULL);
174 errors_capture();
175 ok(n++, !config_param_boolean(group, "parameter", &b_value));
176 ok_string(n++, expected, errors);
177 errors_uncapture();
178 free(expected);
179 if (group != NULL)
180 config_free(group);
181 }
182 fclose(warnfile);
183 return n;
184 }
185
186 /* Test the warning test cases in config/warn-int, ensuring that they all
187 parse successfully and produce the expected error messages when retrieved
188 as signed numbers. Takes the current test count and returns the new test
189 count. */
190 static int
test_warnings_int(int n)191 test_warnings_int(int n)
192 {
193 FILE *warnfile;
194 char *expected;
195 struct config_group *group;
196 long l_value = 1;
197
198 warnfile = fopen("config/warn-int", "r");
199 if (warnfile == NULL)
200 sysdie("Cannot open config/warn-int");
201 while (parse_test_config(warnfile, &group)) {
202 expected = read_section(warnfile);
203 if (expected == NULL)
204 die("Unexpected end of file while reading error tests");
205 ok(n++, group != NULL);
206 ok(n++, errors == NULL);
207 errors_capture();
208 ok(n++, !config_param_signed_number(group, "parameter", &l_value));
209 ok_string(n++, expected, errors);
210 errors_uncapture();
211 free(expected);
212 if (group != NULL)
213 config_free(group);
214 }
215 fclose(warnfile);
216 return n;
217 }
218
219 /* Test the warning test cases in config/warn-uint, ensuring that they all
220 parse successfully and produce the expected error messages when retrieved
221 as usigned numbers. Takes the current test count and returns the new test
222 count. */
223 static int
test_warnings_uint(int n)224 test_warnings_uint(int n)
225 {
226 FILE *warnfile;
227 char *expected;
228 struct config_group *group;
229 unsigned long lu_value = 1;
230
231 warnfile = fopen("config/warn-uint", "r");
232 if (warnfile == NULL)
233 sysdie("Cannot open config/warn-uint");
234 while (parse_test_config(warnfile, &group)) {
235 expected = read_section(warnfile);
236 if (expected == NULL)
237 die("Unexpected end of file while reading error tests");
238 ok(n++, group != NULL);
239 ok(n++, errors == NULL);
240 errors_capture();
241 ok(n++, !config_param_unsigned_number(group, "parameter", &lu_value));
242 ok_string(n++, expected, errors);
243 errors_uncapture();
244 free(expected);
245 if (group != NULL)
246 config_free(group);
247 }
248 fclose(warnfile);
249 return n;
250 }
251
252 /* Test the warning test cases in config/warn-real, ensuring that they all
253 parse successfully and produce the expected error messages when retrieved
254 as reals. Takes the current test count and returns the new test count. */
255 static int
test_warnings_real(int n)256 test_warnings_real(int n)
257 {
258 FILE *warnfile;
259 char *expected;
260 struct config_group *group;
261 double d_value;
262
263 warnfile = fopen("config/warn-real", "r");
264 if (warnfile == NULL)
265 sysdie("Cannot open config/warn-real");
266 while (parse_test_config(warnfile, &group)) {
267 expected = read_section(warnfile);
268 if (expected == NULL)
269 die("Unexpected end of file while reading error tests");
270 ok(n++, group != NULL);
271 ok(n++, errors == NULL);
272 errors_capture();
273 ok(n++, !config_param_real(group, "parameter", &d_value));
274 ok_string(n++, expected, errors);
275 errors_uncapture();
276 free(expected);
277 if (group != NULL)
278 config_free(group);
279 }
280 fclose(warnfile);
281 return n;
282 }
283
284 /* Test the warning test cases in config/warn-string, ensuring that they all
285 parse successfully and produce the expected error messages when retrieved
286 as strings. Takes the current test count and returns the new test count. */
287 static int
test_warnings_string(int n)288 test_warnings_string(int n)
289 {
290 FILE *warnfile;
291 char *expected;
292 struct config_group *group;
293 const char *s_value = NULL;
294
295 warnfile = fopen("config/warn-string", "r");
296 if (warnfile == NULL)
297 sysdie("Cannot open config/warn-string");
298 while (parse_test_config(warnfile, &group)) {
299 expected = read_section(warnfile);
300 if (expected == NULL)
301 die("Unexpected end of file while reading error tests");
302 ok(n++, group != NULL);
303 ok(n++, errors == NULL);
304 errors_capture();
305 ok(n++, !config_param_string(group, "parameter", &s_value));
306 ok_string(n++, expected, errors);
307 errors_uncapture();
308 free(expected);
309 if (group != NULL)
310 config_free(group);
311 }
312 fclose(warnfile);
313 return n;
314 }
315
316 /* Test the warning test cases in config/warn-list, ensuring that they all
317 parse successfully and produce the expected error messages when retrieved
318 as lists. Takes the current test count and returns the new test count. */
319 static int
test_warnings_list(int n)320 test_warnings_list(int n)
321 {
322 FILE *warnfile;
323 char *expected;
324 struct config_group *group;
325 const struct vector *v_value = NULL;
326
327 warnfile = fopen("config/warn-list", "r");
328 if (warnfile == NULL)
329 sysdie("Cannot open config/warn-list");
330 while (parse_test_config(warnfile, &group)) {
331 expected = read_section(warnfile);
332 if (expected == NULL)
333 die("Unexpected end of file while reading error tests");
334 ok(n++, group != NULL);
335 ok(n++, errors == NULL);
336 errors_capture();
337 ok(n++, !config_param_list(group, "parameter", &v_value));
338 ok_string(n++, expected, errors);
339 errors_uncapture();
340 free(expected);
341 if (group != NULL)
342 config_free(group);
343 }
344 fclose(warnfile);
345 return n;
346 }
347
348 int
main(void)349 main(void)
350 {
351 struct config_group *group, *subgroup;
352 bool b_value = false;
353 long l_value = 1;
354 double d_value = 1;
355 const char *s_value;
356 const struct vector *v_value;
357 struct vector *vector;
358 char *long_param, *long_value;
359 size_t length;
360 int n;
361 FILE *tmpconfig;
362
363 test_init(373);
364
365 if (access("../data/config/valid", F_OK) == 0) {
366 if (chdir("../data") < 0) {
367 sysbail("cannot chdir to ../data");
368 }
369 } else if (access("data/config/valid", F_OK) == 0) {
370 if (chdir("data") < 0) {
371 sysbail("cannot chdir to data");
372 }
373 } else if (access("tests/data/config/valid", F_OK) == 0) {
374 if (chdir("tests/data") < 0) {
375 sysbail("cannot chdir to tests/data");
376 }
377 }
378 group = config_parse_file("config/valid");
379 ok(1, group != NULL);
380 if (group == NULL)
381 exit(1);
382
383 /* Booleans. */
384 ok(2, config_param_boolean(group, "param1", &b_value));
385 ok(3, b_value);
386 b_value = false;
387 ok(4, config_param_boolean(group, "param2", &b_value));
388 ok(5, b_value);
389 b_value = false;
390 ok(6, config_param_boolean(group, "param3", &b_value));
391 ok(7, b_value);
392 ok(8, config_param_boolean(group, "param4", &b_value));
393 ok(9, !b_value);
394 b_value = true;
395 ok(10, config_param_boolean(group, "param5", &b_value));
396 ok(11, !b_value);
397 b_value = true;
398 ok(12, config_param_boolean(group, "param6", &b_value));
399 ok(13, !b_value);
400
401 /* Integers. */
402 ok(14, config_param_signed_number(group, "int1", &l_value));
403 ok(15, l_value == 0);
404 ok(16, config_param_signed_number(group, "int2", &l_value));
405 ok(17, l_value == -3);
406 ok(18, !config_param_signed_number(group, "int3", &l_value));
407 ok(19, l_value == -3);
408 ok(20, config_param_signed_number(group, "int4", &l_value));
409 ok(21, l_value == 5000);
410 ok(22, config_param_signed_number(group, "int5", &l_value));
411 ok(23, l_value == 2147483647L);
412 ok(24, config_param_signed_number(group, "int6", &l_value));
413 ok(25, l_value == (-2147483647L - 1));
414
415 /* Strings. */
416 ok(26, config_param_string(group, "string1", &s_value));
417 ok_string(27, "foo", s_value);
418 ok(28, config_param_string(group, "string2", &s_value));
419 ok_string(29, "bar", s_value);
420 ok(30, config_param_string(group, "string3", &s_value));
421 ok_string(31, "this is a test", s_value);
422 ok(32, config_param_string(group, "string4", &s_value));
423 ok_string(33, "this is a test", s_value);
424 ok(34, config_param_string(group, "string5", &s_value));
425 ok_string(35, "this is \a\b\f\n\r\t\v a test \' of \" escapes \?\\",
426 s_value);
427 ok(36, config_param_string(group, "string6", &s_value));
428 ok_string(37, "# this is not a comment", s_value);
429 ok(38, config_param_string(group, "string7", &s_value));
430 ok_string(39, "lost \nyet?", s_value);
431
432 config_free(group);
433
434 /* Missing newline. */
435 group = config_parse_file("config/no-newline");
436 ok(40, group != NULL);
437 if (group == NULL)
438 ok_block(41, 2, false);
439 else {
440 ok(41, config_param_string(group, "parameter", &s_value));
441 ok_string(42, "value", s_value);
442 config_free(group);
443 }
444
445 /* Extremely long parameter and value. */
446 tmpconfig = fopen("config/tmp", "w");
447 if (tmpconfig == NULL)
448 sysdie("cannot create config/tmp");
449 long_param = xcalloc(20001, 1);
450 memset(long_param, 'a', 20000);
451 long_value = xcalloc(64 * 1024 + 1, 1);
452 memset(long_value, 'b', 64 * 1024);
453 fprintf(tmpconfig, "%s: \"%s\"; two: %s", long_param, long_value,
454 long_value);
455 fclose(tmpconfig);
456 group = config_parse_file("config/tmp");
457 ok(43, group != NULL);
458 if (group == NULL)
459 ok_block(44, 4, false);
460 else {
461 ok(44, config_param_string(group, long_param, &s_value));
462 ok_string(45, long_value, s_value);
463 ok(46, config_param_string(group, "two", &s_value));
464 ok_string(47, long_value, s_value);
465 config_free(group);
466 }
467 unlink("config/tmp");
468 free(long_param);
469 free(long_value);
470
471 /* Parsing problems exactly on the boundary of a buffer. This test caught
472 a bug in the parser that caused it to miss the colon at the end of a
473 parameter because the colon was the first character read in a new read
474 of the file buffer. */
475 tmpconfig = fopen("config/tmp", "w");
476 if (tmpconfig == NULL)
477 sysdie("cannot create config/tmp");
478 length = 16 * 1024 - strlen(": baz\nfoo:");
479 long_param = xcalloc(length + 1, 1);
480 memset(long_param, 'c', length);
481 fprintf(tmpconfig, "%s: baz\nfoo: bar\n", long_param);
482 fclose(tmpconfig);
483 group = config_parse_file("config/tmp");
484 ok(48, group != NULL);
485 if (group == NULL)
486 ok_block(49, 4, false);
487 else {
488 ok(49, config_param_string(group, long_param, &s_value));
489 ok_string(50, "baz", s_value);
490 ok(51, config_param_string(group, "foo", &s_value));
491 ok_string(52, "bar", s_value);
492 config_free(group);
493 }
494 unlink("config/tmp");
495 free(long_param);
496
497 /* Alternate line endings. */
498 group = config_parse_file("config/line-endings");
499 ok(53, group != NULL);
500 if (group == NULL)
501 exit(1);
502 ok(54, config_param_boolean(group, "param1", &b_value));
503 ok(55, b_value);
504 b_value = false;
505 ok(56, config_param_boolean(group, "param2", &b_value));
506 ok(57, b_value);
507 b_value = false;
508 ok(58, config_param_boolean(group, "param3", &b_value));
509 ok(59, b_value);
510 ok(60, config_param_boolean(group, "param4", &b_value));
511 ok(61, !b_value);
512 ok(62, config_param_signed_number(group, "int1", &l_value));
513 ok(63, l_value == 0);
514 ok(64, config_param_signed_number(group, "int2", &l_value));
515 ok(65, l_value == -3);
516 config_free(group);
517
518 /* Listing parameters. */
519 group = config_parse_file("config/simple");
520 ok(66, group != NULL);
521 if (group == NULL)
522 exit(1);
523 vector = config_params(group);
524 ok_int(67, 2, vector->count);
525 skip(68, "test to be removed when using the new C TAP Harness syntax");
526 if (strcmp(vector->strings[0], "foo") == 0)
527 ok_string(69, "bar", vector->strings[1]);
528 else if (strcmp(vector->strings[0], "bar") == 0)
529 ok_string(69, "foo", vector->strings[1]);
530 else
531 ok(69, false);
532 vector_free(vector);
533 config_free(group);
534
535 /* Lists. */
536 group = config_parse_file("config/lists");
537 ok(70, group != NULL);
538 if (group == NULL)
539 exit(1);
540 ok(71, config_param_list(group, "vector1", &v_value));
541 ok_int(72, 1, v_value->count);
542 ok_string(73, "simple", v_value->strings[0]);
543 ok(74, config_param_list(group, "vector2", &v_value));
544 ok_int(75, 3, v_value->count);
545 ok_string(76, "foo\tbar", v_value->strings[0]);
546 ok_string(77, "baz", v_value->strings[1]);
547 ok_string(78, "# this is not a comment", v_value->strings[2]);
548 ok(79, config_param_list(group, "vector3", &v_value));
549 ok_int(80, 0, v_value->count);
550 ok(81, config_param_list(group, "vector4", &v_value));
551 ok_int(82, 0, v_value->count);
552 ok(83, config_param_list(group, "vector5", &v_value));
553 ok_int(84, 1, v_value->count);
554 ok_string(85, "baz", v_value->strings[0]);
555 ok(86, config_param_list(group, "vector6", &v_value));
556 ok_int(87, 1, v_value->count);
557 ok_string(88, "bar baz", v_value->strings[0]);
558 config_free(group);
559
560 /* Groups. */
561 group = config_parse_file("config/groups");
562 ok(89, group != NULL);
563 if (group == NULL)
564 exit(1);
565 subgroup = config_find_group(group, "test");
566 ok(90, subgroup != NULL);
567 ok_string(91, "test", config_group_type(subgroup));
568 ok(92, config_param_boolean(subgroup, "value", &b_value));
569 ok(93, b_value);
570 subgroup = config_next_group(subgroup);
571 ok(94, subgroup != NULL);
572 ok_string(95, "test", config_group_type(subgroup));
573 ok(96, config_group_tag(subgroup) == NULL);
574 ok(97, config_param_boolean(subgroup, "value", &b_value));
575 subgroup = config_next_group(subgroup);
576 ok(98, subgroup != NULL);
577 ok(99, config_param_signed_number(subgroup, "value", &l_value));
578 ok_int(100, 2, l_value);
579 subgroup = config_next_group(subgroup);
580 ok(101, subgroup != NULL);
581 ok(102, config_param_signed_number(subgroup, "value", &l_value));
582 ok_int(103, 3, l_value);
583 subgroup = config_find_group(subgroup, "test");
584 ok(104, subgroup != NULL);
585 ok(105, config_param_signed_number(subgroup, "value", &l_value));
586 ok_int(106, 2, l_value);
587 subgroup = config_next_group(subgroup);
588 ok(107, subgroup != NULL);
589 ok_string(108, "test", config_group_type(subgroup));
590 ok_string(109, "final", config_group_tag(subgroup));
591 ok(110, config_param_signed_number(subgroup, "value", &l_value));
592 ok_int(111, 4, l_value);
593 subgroup = config_next_group(subgroup);
594 ok(112, subgroup == NULL);
595 subgroup = config_find_group(group, "nest");
596 ok(113, subgroup != NULL);
597 ok_string(114, "nest", config_group_type(subgroup));
598 ok_string(115, "1", config_group_tag(subgroup));
599 ok(116, config_param_signed_number(subgroup, "param", &l_value));
600 ok_int(117, 10, l_value);
601 subgroup = config_next_group(subgroup);
602 ok(118, subgroup != NULL);
603 ok_string(119, "2", config_group_tag(subgroup));
604 ok(120, config_param_signed_number(subgroup, "param", &l_value));
605 ok_int(121, 10, l_value);
606 subgroup = config_next_group(subgroup);
607 ok(122, subgroup != NULL);
608 ok_string(123, "3", config_group_tag(subgroup));
609 ok(124, config_param_signed_number(subgroup, "param", &l_value));
610 ok_int(125, 10, l_value);
611 subgroup = config_next_group(subgroup);
612 ok(126, subgroup != NULL);
613 ok_string(127, "4", config_group_tag(subgroup));
614 ok(128, config_param_signed_number(subgroup, "param", &l_value));
615 ok_int(129, 10, l_value);
616 subgroup = config_next_group(subgroup);
617 ok(130, subgroup == NULL);
618 subgroup = config_find_group(group, "nonexistent");
619 ok(131, subgroup == NULL);
620 subgroup = config_find_group(group, "nest");
621 ok(132, subgroup != NULL);
622 subgroup = config_find_group(subgroup, "params");
623 ok(133, subgroup != NULL);
624 ok_string(134, "params", config_group_type(subgroup));
625 ok_string(135, "first", config_group_tag(subgroup));
626 ok(136, config_param_signed_number(subgroup, "first", &l_value));
627 ok_int(137, 1, l_value);
628 ok(138, !config_param_signed_number(subgroup, "second", &l_value));
629 subgroup = config_next_group(subgroup);
630 ok(139, subgroup != NULL);
631 ok_string(140, "second", config_group_tag(subgroup));
632 ok(141, config_param_signed_number(subgroup, "first", &l_value));
633 ok_int(142, 1, l_value);
634 ok(143, config_param_signed_number(subgroup, "second", &l_value));
635 ok_int(144, 2, l_value);
636 subgroup = config_next_group(subgroup);
637 ok(145, subgroup != NULL);
638 ok_string(146, "third", config_group_tag(subgroup));
639 ok(147, config_param_signed_number(subgroup, "first", &l_value));
640 ok_int(148, 1, l_value);
641 ok(149, config_param_signed_number(subgroup, "second", &l_value));
642 ok_int(150, 2, l_value);
643 ok(151, config_param_signed_number(subgroup, "third", &l_value));
644 ok_int(152, 3, l_value);
645 vector = config_params(subgroup);
646 ok(153, vector != NULL);
647 ok_int(154, 3, vector->count);
648 skip(155, "test to be removed when using the new C TAP Harness syntax");
649 ok_string(156, "third", vector->strings[0]);
650 ok_string(157, "second", vector->strings[1]);
651 ok_string(158, "first", vector->strings[2]);
652 vector_free(vector);
653 config_free(group);
654
655 /* Includes. */
656 group = config_parse_file("config/include");
657 ok(159, group != NULL);
658 if (group == NULL)
659 exit(1);
660 subgroup = config_find_group(group, "group");
661 ok(160, subgroup != NULL);
662 ok(161, config_param_string(subgroup, "foo", &s_value));
663 ok_string(162, "baz", s_value);
664 ok(163, config_param_string(subgroup, "bar", &s_value));
665 ok_string(164, "baz", s_value);
666 ok(165, !config_param_signed_number(subgroup, "value", &l_value));
667 subgroup = config_next_group(subgroup);
668 ok(166, subgroup != NULL);
669 subgroup = config_next_group(subgroup);
670 ok(167, subgroup != NULL);
671 ok_string(168, "test", config_group_tag(subgroup));
672 ok(169, config_param_string(subgroup, "foo", &s_value));
673 ok_string(170, "baz", s_value);
674 ok(171, config_param_signed_number(subgroup, "value", &l_value));
675 ok_int(172, 10, l_value);
676 config_free(group);
677
678 /* Real numbers. */
679 group = config_parse_file("config/reals");
680 ok(173, group != NULL);
681 ok(174, config_param_real(group, "real1", &d_value));
682 ok_double(175, 0.1, d_value);
683 ok(176, config_param_real(group, "real2", &d_value));
684 ok_double(177, -123.45e10, d_value);
685 ok(178, config_param_real(group, "real3", &d_value));
686 ok_double(179, 4.0e-3, d_value);
687 ok(180, config_param_real(group, "real4", &d_value));
688 ok_double(181, 1, d_value);
689 config_free(group);
690
691 /* Errors. */
692 group = parse_error_config("config/null");
693 ok(182, group == NULL);
694 ok_string(183, "config/null: invalid NUL character found in file\n",
695 errors);
696 n = test_errors(184);
697 n = test_warnings(n);
698 n = test_warnings_bool(n);
699 n = test_warnings_int(n);
700 n = test_warnings_uint(n);
701 n = test_warnings_real(n);
702 n = test_warnings_string(n);
703 test_warnings_list(n);
704
705 return 0;
706 }
707