xref: /aosp_15_r20/external/libconfig/tests/tests.c (revision 2e9d491483b805f09ea864149eadd5680efcc72a)
1 /* ----------------------------------------------------------------------------
2    libconfig - A library for processing structured configuration files
3    Copyright (C) 2005-2018  Mark A Lindner
4 
5    This file is part of libconfig.
6 
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public License
9    as published by the Free Software Foundation; either version 2.1 of
10    the License, or (at your option) any later version.
11 
12    This library is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16 
17    You should have received a copy of the GNU Library General Public
18    License along with this library; if not, see
19    <http://www.gnu.org/licenses/>.
20    ----------------------------------------------------------------------------
21 */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/stat.h>
26 
27 #ifdef _MSC_VER
28 #define snprintf _snprintf
29 #endif
30 
31 #include <libconfig.h>
32 #include <tinytest.h>
33 
34 /* ------------------------------------------------------------------------- */
35 
parse_and_compare(const char * input_file,const char * output_file)36 static void parse_and_compare(const char *input_file, const char *output_file)
37 {
38   config_t cfg;
39   int ok;
40 
41   config_init(&cfg);
42   config_set_include_dir(&cfg, "./testdata");
43 
44   ok = config_read_file(&cfg, input_file);
45   if(!ok)
46   {
47     printf("error: %s:%d\n", config_error_text(&cfg),
48            config_error_line(&cfg));
49   }
50   TT_ASSERT_TRUE(ok);
51 
52   remove("temp.cfg");
53   TT_ASSERT_TRUE(config_write_file(&cfg, "temp.cfg"));
54 
55   TT_ASSERT_TXTFILE_EQ("temp.cfg", output_file);
56   remove("temp.cfg");
57 
58   config_destroy(&cfg);
59 }
60 
61 /* ------------------------------------------------------------------------- */
62 
parse_file_and_compare_error(const char * input_file,const char * parse_error)63 static void parse_file_and_compare_error(const char *input_file,
64                                          const char *parse_error)
65 {
66   config_t cfg;
67   char actual_error[128];
68   char expected_error[128];
69 
70   config_init(&cfg);
71   TT_ASSERT_FALSE(config_read_file(&cfg, input_file));
72 
73   snprintf(expected_error, sizeof(expected_error), "%s:%s",
74            input_file, parse_error);
75 
76   snprintf(actual_error, sizeof(actual_error), "%s:%d %s\n",
77            config_error_file(&cfg), config_error_line(&cfg),
78            config_error_text(&cfg));
79 
80   config_destroy(&cfg);
81 
82   TT_ASSERT_STR_EQ(actual_error, expected_error);
83 }
84 
85 /* ------------------------------------------------------------------------- */
86 
parse_string_and_compare_error(const char * input_text,const char * parse_error)87 static void parse_string_and_compare_error(const char *input_text,
88                                            const char *parse_error)
89 {
90   config_t cfg;
91   char actual_error[128];
92   char expected_error[128];
93 
94   config_init(&cfg);
95   TT_ASSERT_FALSE(config_read_string(&cfg, input_text));
96 
97   snprintf(expected_error, sizeof(expected_error), "(null):%s", parse_error);
98 
99   snprintf(actual_error, sizeof(actual_error), "%s:%d %s\n",
100            config_error_file(&cfg), config_error_line(&cfg),
101            config_error_text(&cfg));
102 
103   config_destroy(&cfg);
104 
105   TT_ASSERT_STR_EQ(actual_error, expected_error);
106 }
107 
108 /* ------------------------------------------------------------------------- */
109 
read_file_to_string(const char * file)110 static const char *read_file_to_string(const char *file)
111 {
112   struct stat stbuf;
113   FILE *fp;
114   int size;
115   char *buf;
116   size_t r;
117 
118   TT_ASSERT_INT_EQ(0, stat(file, &stbuf));
119 
120   size = stbuf.st_size;
121   buf = (char *)malloc(size + 1);
122   TT_ASSERT_PTR_NOTNULL(buf);
123 
124   fp = fopen(file, "rt");
125   TT_ASSERT_PTR_NOTNULL(fp);
126 
127   r = fread(buf, 1, size, fp);
128   fclose(fp);
129 
130   TT_ASSERT_INT_EQ(size, r);
131 
132   *(buf + size) = 0;
133   return(buf);
134 }
135 
136 /* ------------------------------------------------------------------------- */
137 
TT_TEST(ParsingAndFormatting)138 TT_TEST(ParsingAndFormatting)
139 {
140   int i;
141 
142   for(i = 0;; ++i)
143   {
144     char input_file[128], output_file[128];
145     sprintf(input_file, "testdata/input_%d.cfg", i);
146     sprintf(output_file, "testdata/output_%d.cfg", i);
147     printf("parsing %s\n", input_file);
148 
149     if(!tt_file_exists(input_file) || !tt_file_exists(output_file))
150       break;
151 
152     parse_and_compare(input_file, output_file);
153   }
154 }
155 
156 /* ------------------------------------------------------------------------- */
157 
TT_TEST(ParseInvalidFiles)158 TT_TEST(ParseInvalidFiles)
159 {
160   int i;
161 
162   for(i = 0;; ++i)
163   {
164     char input_file[128], error_file[128];
165     char error_text[128];
166     FILE *fp;
167 
168     sprintf(input_file, "testdata/bad_input_%d.cfg", i);
169     sprintf(error_file, "testdata/parse_error_%d.txt", i);
170 
171     if(!tt_file_exists(input_file) || !tt_file_exists(error_file))
172       break;
173 
174     fp = fopen(error_file, "rt");
175     TT_ASSERT_PTR_NOTNULL(fp);
176     TT_ASSERT_PTR_NOTNULL(fgets(error_text, sizeof(error_text), fp));
177     fclose(fp);
178 
179     parse_file_and_compare_error(input_file, error_text);
180   }
181 }
182 
183 /* ------------------------------------------------------------------------- */
184 
TT_TEST(ParseInvalidStrings)185 TT_TEST(ParseInvalidStrings)
186 {
187   int i;
188 
189   for(i = 0;; ++i)
190   {
191     char input_file[128], error_file[128];
192     const char *input_text;
193     char error_text[128];
194     FILE *fp;
195 
196     sprintf(input_file, "testdata/bad_input_%d.cfg", i);
197     sprintf(error_file, "testdata/parse_error_%d.txt", i);
198 
199     if(!tt_file_exists(input_file) || !tt_file_exists(error_file))
200       break;
201 
202     input_text = read_file_to_string(input_file);
203 
204     fp = fopen(error_file, "rt");
205     TT_ASSERT_PTR_NOTNULL(fp);
206     TT_ASSERT_PTR_NOTNULL(fgets(error_text, sizeof(error_text), fp));
207     fclose(fp);
208 
209     parse_string_and_compare_error(input_text, error_text);
210 
211     free((void *)input_text);
212   }
213 }
214 
215 /* ------------------------------------------------------------------------- */
216 
TT_TEST(BigInt1)217 TT_TEST(BigInt1)
218 {
219   char *buf;
220   config_t cfg;
221   int rc;
222   int ival;
223   long long llval;
224 
225   buf = "someint=5;";
226 
227   config_init(&cfg);
228   rc = config_read_string(&cfg, buf);
229   TT_ASSERT_TRUE(rc);
230 
231   rc = config_lookup_int(&cfg, "someint", &ival);
232   TT_ASSERT_TRUE(rc);
233   TT_ASSERT_INT_EQ(ival, 5);
234 
235   rc = config_lookup_int64(&cfg, "someint", &llval);
236   TT_ASSERT_TRUE(rc);
237   TT_ASSERT_INT_EQ(llval, 5);
238 
239   config_destroy(&cfg);
240 }
241 
242 /* ------------------------------------------------------------------------- */
243 
TT_TEST(BigInt2)244 TT_TEST(BigInt2)
245 {
246   char *buf;
247   config_t cfg;
248   int rc;
249   int ival = 123;
250   long long llval;
251 
252   buf = "someint=8589934592;"; /* 2^33 */
253 
254   config_init(&cfg);
255   rc = config_read_string(&cfg, buf);
256   TT_ASSERT_TRUE(rc);
257 
258   /* Should fail because value was parsed as an int64. */
259   rc = config_lookup_int(&cfg, "someint", &ival);
260   TT_ASSERT_FALSE(rc);
261   TT_ASSERT_INT_EQ(ival, 123);
262 
263   rc = config_lookup_int64(&cfg, "someint", &llval);
264   TT_ASSERT_TRUE(rc);
265   TT_ASSERT_INT64_EQ(llval, 8589934592LL);
266 
267   config_destroy(&cfg);
268 }
269 
270 /* ------------------------------------------------------------------------- */
271 
TT_TEST(BigInt3)272 TT_TEST(BigInt3)
273 {
274   char *buf;
275   config_t cfg;
276   int rc;
277   int ival = 123;
278   long long llval;
279 
280   buf = "someint=-8589934592;"; /* -2^33 */
281 
282   config_init(&cfg);
283   rc = config_read_string(&cfg, buf);
284   TT_ASSERT_TRUE(rc);
285 
286   /* Should fail because value was parsed as an int64. */
287   rc = config_lookup_int(&cfg, "someint", &ival);
288   TT_ASSERT_FALSE(rc);
289   TT_ASSERT_INT_EQ(ival, 123);
290 
291   rc = config_lookup_int64(&cfg, "someint", &llval);
292   TT_ASSERT_TRUE(rc);
293   TT_ASSERT_INT64_EQ(llval, -8589934592LL);
294 
295   config_destroy(&cfg);
296 }
297 
298 /* ------------------------------------------------------------------------- */
299 
TT_TEST(BigInt4)300 TT_TEST(BigInt4)
301 {
302   char *buf;
303   config_t cfg;
304   int rc;
305   int ival = 123;
306   long long llval;
307 
308   buf = "someint=2147483647;";  /* 2^31-1 */
309 
310   config_init(&cfg);
311   rc = config_read_string(&cfg, buf);
312   TT_ASSERT_TRUE(rc);
313 
314   rc = config_lookup_int(&cfg, "someint", &ival);
315   TT_ASSERT_TRUE(rc);
316   TT_ASSERT_INT_EQ(ival, 2147483647);
317 
318   rc = config_lookup_int64(&cfg, "someint", &llval);
319   TT_ASSERT_TRUE(rc);
320   TT_ASSERT_INT64_EQ(llval, 2147483647LL);
321 
322   config_destroy(&cfg);
323 }
324 
325 /* ------------------------------------------------------------------------- */
326 
TT_TEST(BigInt5)327 TT_TEST(BigInt5)
328 {
329   char *buf;
330   config_t cfg;
331   int rc;
332   int ival = 123;
333   long long llval;
334 
335   buf = "someint=2147483648;"; /* 2^31 */
336 
337   config_init(&cfg);
338   rc = config_read_string(&cfg, buf);
339   TT_ASSERT_TRUE(rc);
340 
341   /* Should fail because value was parsed as an int64. */
342   rc = config_lookup_int(&cfg, "someint", &ival);
343   TT_ASSERT_FALSE(rc);
344   TT_ASSERT_INT_EQ(ival, 123);
345 
346   rc = config_lookup_int64(&cfg, "someint", &llval);
347   TT_ASSERT_TRUE(rc);
348   TT_ASSERT_INT64_EQ(llval, 2147483648LL);
349 
350   config_destroy(&cfg);
351 }
352 
353 /* ------------------------------------------------------------------------- */
354 
TT_TEST(BigInt6)355 TT_TEST(BigInt6)
356 {
357   char *buf;
358   config_t cfg;
359   int rc;
360   int ival;
361   long long llval;
362 
363   buf = "someint=-2147483648;"; /* -2^31 */
364 
365   config_init(&cfg);
366   rc = config_read_string(&cfg, buf);
367   TT_ASSERT_TRUE(rc);
368 
369   rc = config_lookup_int(&cfg, "someint", &ival);
370   TT_ASSERT_TRUE(rc);
371   TT_ASSERT_INT_EQ(ival, -2147483648LL);
372 
373   rc = config_lookup_int64(&cfg, "someint", &llval);
374   TT_ASSERT_TRUE(rc);
375   TT_ASSERT_INT64_EQ(llval, -2147483648LL);
376 
377   config_destroy(&cfg);
378 }
379 
380 /* ------------------------------------------------------------------------- */
381 
TT_TEST(BigInt7)382 TT_TEST(BigInt7)
383 {
384   char *buf;
385   config_t cfg;
386   int rc;
387   int ival = 123;
388   long long llval;
389 
390   buf = "someint=-2147483649;"; /* -2^31-1 */
391 
392   config_init(&cfg);
393   rc = config_read_string(&cfg, buf);
394   TT_ASSERT_TRUE(rc);
395 
396   /* Should fail because value was parsed as an int64. */
397   rc = config_lookup_int(&cfg, "someint", &ival);
398   TT_ASSERT_FALSE(rc);
399   TT_ASSERT_INT_EQ(ival, 123);
400 
401   rc = config_lookup_int64(&cfg, "someint", &llval);
402   TT_ASSERT_TRUE(rc);
403   TT_ASSERT_INT64_EQ(llval, -2147483649LL);
404 
405   config_destroy(&cfg);
406 }
407 
408 /* ------------------------------------------------------------------------- */
409 
TT_TEST(RemoveSetting)410 TT_TEST(RemoveSetting)
411 {
412   char *buf;
413   config_t cfg;
414   int rc;
415   config_setting_t* rootSetting;
416 
417   buf = "a:{b:3;c:4;}";
418 
419   config_init(&cfg);
420   rc = config_read_string(&cfg, buf);
421   TT_ASSERT_TRUE(rc);
422 
423   rootSetting = config_root_setting(&cfg);
424   rc = config_setting_remove(rootSetting, "a.c");
425   TT_ASSERT_TRUE(rc);
426 
427   /* a and a.b are found */
428   rootSetting = config_lookup(&cfg, "a");
429   TT_EXPECT_PTR_NOTNULL(rootSetting);
430   rootSetting = config_lookup(&cfg, "a.b");
431   TT_EXPECT_PTR_NOTNULL(rootSetting);
432   rootSetting = config_lookup(&cfg, "a.c");
433   TT_EXPECT_PTR_NULL(rootSetting);
434 
435   config_destroy(&cfg);
436 }
437 
438 /* ------------------------------------------------------------------------- */
439 
TT_TEST(EscapedStrings)440 TT_TEST(EscapedStrings)
441 {
442   config_t cfg;
443   int ok;
444   const char *str;
445 
446   config_init(&cfg);
447   config_set_include_dir(&cfg, "./testdata");
448 
449   ok = config_read_file(&cfg, "testdata/strings.cfg");
450   if(!ok)
451   {
452     printf("error: %s:%d\n", config_error_text(&cfg),
453            config_error_line(&cfg));
454   }
455   TT_ASSERT_TRUE(ok);
456 
457   ok = config_lookup_string(&cfg, "escape_seqs.str", &str);
458   TT_ASSERT_TRUE(ok);
459   TT_ASSERT_STR_EQ("abc", str);
460 
461   ok = config_lookup_string(&cfg, "escape_seqs.newline", &str);
462   TT_ASSERT_TRUE(ok);
463   TT_ASSERT_STR_EQ("abc\ndef\n", str);
464 
465   ok = config_lookup_string(&cfg, "escape_seqs.cr", &str);
466   TT_ASSERT_TRUE(ok);
467   TT_ASSERT_STR_EQ("abc\rdef\r", str);
468 
469   ok = config_lookup_string(&cfg, "escape_seqs.tab", &str);
470   TT_ASSERT_TRUE(ok);
471   TT_ASSERT_STR_EQ("abc\tdef\t", str);
472 
473   ok = config_lookup_string(&cfg, "escape_seqs.feed", &str);
474   TT_ASSERT_TRUE(ok);
475   TT_ASSERT_STR_EQ("abc\fdef\f", str);
476 
477   ok = config_lookup_string(&cfg, "escape_seqs.backslash", &str);
478   TT_ASSERT_TRUE(ok);
479   TT_ASSERT_STR_EQ("abc\\def\\", str);
480 
481   ok = config_lookup_string(&cfg, "escape_seqs.dquote", &str);
482   TT_ASSERT_TRUE(ok);
483   TT_ASSERT_STR_EQ("abc\"def\"", str);
484 
485   config_destroy(&cfg);
486 }
487 
488 /* ------------------------------------------------------------------------- */
489 
TT_TEST(OverrideSetting)490 TT_TEST(OverrideSetting)
491 {
492   config_t cfg;
493   int ok;
494   int ival;
495   const char *str;
496 
497   config_init(&cfg);
498   config_set_options(&cfg, CONFIG_OPTION_ALLOW_OVERRIDES);
499   config_set_include_dir(&cfg, "./testdata");
500 
501   ok = config_read_file(&cfg, "testdata/override_setting.cfg");
502   if(!ok)
503   {
504     printf("error: %s:%d\n", config_error_text(&cfg),
505            config_error_line(&cfg));
506   }
507   TT_ASSERT_TRUE(ok);
508 
509   ok = config_lookup_string(&cfg, "group.message", &str);
510   TT_ASSERT_TRUE(ok);
511   TT_ASSERT_STR_EQ("overridden", str);
512 
513   ok = config_lookup_string(&cfg, "group.inner.name", &str);
514   TT_ASSERT_TRUE(ok);
515   TT_ASSERT_STR_EQ("overridden", str);
516 
517   ok = config_lookup_string(&cfg, "group.inner.other", &str);
518   TT_ASSERT_TRUE(ok);
519   TT_ASSERT_STR_EQ("other", str);
520 
521   ok = config_lookup_string(&cfg, "group.inner.none", &str);
522   TT_ASSERT_FALSE(ok);
523 
524   ok = config_lookup_string(&cfg, "group.inner.other", &str);
525   TT_ASSERT_TRUE(ok);
526   TT_ASSERT_STR_EQ("other", str);
527 
528   ok = config_lookup_string(&cfg, "string", &str);
529   TT_ASSERT_TRUE(ok);
530   TT_ASSERT_STR_EQ("overridden", str);
531 
532   ok = config_lookup_int(&cfg, "int", &ival);
533   TT_ASSERT_TRUE(ok);
534   TT_ASSERT_INT_EQ(ival, 2);
535 
536   ok = config_lookup_int(&cfg, "group.array.[0]", &ival);
537   TT_ASSERT_TRUE(ok);
538   TT_ASSERT_INT_EQ(ival, 3);
539 
540   ok = config_lookup_int(&cfg, "group.array.[1]", &ival);
541   TT_ASSERT_FALSE(ok);
542 
543   config_destroy(&cfg);
544 }
545 
546 /* ------------------------------------------------------------------------- */
547 
main(int argc,char ** argv)548 int main(int argc, char **argv)
549 {
550   int failures;
551 
552   TT_SUITE_START(LibConfigTests);
553   TT_SUITE_TEST(LibConfigTests, ParsingAndFormatting);
554   TT_SUITE_TEST(LibConfigTests, ParseInvalidFiles);
555   TT_SUITE_TEST(LibConfigTests, ParseInvalidStrings);
556   TT_SUITE_TEST(LibConfigTests, BigInt1);
557   TT_SUITE_TEST(LibConfigTests, BigInt2);
558   TT_SUITE_TEST(LibConfigTests, BigInt3);
559   TT_SUITE_TEST(LibConfigTests, BigInt4);
560   TT_SUITE_TEST(LibConfigTests, BigInt5);
561   TT_SUITE_TEST(LibConfigTests, BigInt6);
562   TT_SUITE_TEST(LibConfigTests, BigInt7);
563   TT_SUITE_TEST(LibConfigTests, RemoveSetting);
564   TT_SUITE_TEST(LibConfigTests, EscapedStrings);
565   TT_SUITE_TEST(LibConfigTests, OverrideSetting);
566   TT_SUITE_RUN(LibConfigTests);
567   failures = TT_SUITE_NUM_FAILURES(LibConfigTests);
568   TT_SUITE_END(LibConfigTests);
569 
570   if (failures)
571     return EXIT_FAILURE;
572 
573   return EXIT_SUCCESS;
574 }
575