style fix
[oweals/gnunet.git] / src / util / test_configuration.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2003, 2004, 2005, 2006, 2007 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @file util/test_configuration.c
22  * @brief Test that the configuration module works.
23  * @author Christian Grothoff
24  */
25
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28
29
30 /* Test Configuration Diffs Options */
31 enum {
32   EDIT_NOTHING,
33   EDIT_SECTION,
34   EDIT_ALL,
35   ADD_NEW_SECTION,
36   ADD_NEW_ENTRY,
37   REMOVE_SECTION,
38   REMOVE_ENTRY,
39   COMPARE,
40   PRINT
41 };
42
43 static struct GNUNET_CONFIGURATION_Handle *cfg;
44 static struct GNUNET_CONFIGURATION_Handle *cfg_default;
45
46 struct DiffsCBData {
47   struct GNUNET_CONFIGURATION_Handle *cfg;
48   struct GNUNET_CONFIGURATION_Handle *cfgDiffs;
49   const char *section;
50   int callBackOption;
51   int status;
52 };
53
54
55 static void
56 initDiffsCBData(struct DiffsCBData *cbData)
57 {
58   cbData->section = NULL;
59   cbData->cfg = NULL;
60   cbData->cfgDiffs = NULL;
61   cbData->callBackOption = -1;
62   cbData->status = 0;
63 }
64
65
66 /**
67  * callback function for modifying
68  * and comparing configuration
69  */
70 static void
71 diffsCallBack(void *cls, const char *section, const char *option,
72               const char *value)
73 {
74   struct DiffsCBData *cbData = cls;
75   int cbOption = cbData->callBackOption;
76
77   switch (cbOption)
78     {
79     case EDIT_SECTION:
80       if (NULL == cbData->section)
81         cbData->section = section;
82       if (strcmp(cbData->section, section) == 0)
83         {
84           GNUNET_CONFIGURATION_set_value_string(cbData->cfg, section, option,
85                                                 "new-value");
86           GNUNET_CONFIGURATION_set_value_string(cbData->cfgDiffs, section, option,
87                                                 "new-value");
88         }
89       break;
90
91     case EDIT_ALL:
92       GNUNET_CONFIGURATION_set_value_string(cbData->cfg, section, option,
93                                             "new-value");
94       GNUNET_CONFIGURATION_set_value_string(cbData->cfgDiffs, section, option,
95                                             "new-value");
96       break;
97
98     case ADD_NEW_ENTRY:
99     {
100       static int hit = 0;
101
102       if (hit == 0)
103         {
104           hit = 1;
105           GNUNET_CONFIGURATION_set_value_string(cbData->cfg, section, "new-key",
106                                                 "new-value");
107           GNUNET_CONFIGURATION_set_value_string(cbData->cfgDiffs, section,
108                                                 "new-key", "new-value");
109         }
110       break;
111     }
112
113     case COMPARE:
114     {
115       int ret;
116       char *diffValue;
117
118       diffValue = NULL;
119       ret =
120         GNUNET_CONFIGURATION_get_value_string(cbData->cfgDiffs, section,
121                                               option, &diffValue);
122       if (NULL != diffValue)
123         {
124           if (ret == GNUNET_SYSERR || strcmp(diffValue, value) != 0)
125             cbData->status = 1;
126         }
127       else
128         cbData->status = 1;
129       GNUNET_free_non_null(diffValue);
130       break;
131     }
132
133 #if 0
134     case PRINT:
135       if (NULL == cbData->section)
136         {
137           cbData->section = section;
138           printf("\nSection: %s\n", section);
139         }
140       else if (strcmp(cbData->section, section) != 0)
141         {
142           cbData->section = section;
143           printf("\nSection: %s\n", section);
144         }
145       printf("%s = %s\n", option, value);
146 #endif
147     default:
148       break;
149     }
150 }
151
152
153 static struct GNUNET_CONFIGURATION_Handle *
154 editConfiguration(struct GNUNET_CONFIGURATION_Handle *cfg, int option)
155 {
156   struct DiffsCBData diffsCB;
157
158   initDiffsCBData(&diffsCB);
159   diffsCB.cfgDiffs = GNUNET_CONFIGURATION_create();
160
161   switch (option)
162     {
163     case EDIT_SECTION:
164     case EDIT_ALL:
165     case ADD_NEW_ENTRY:
166       diffsCB.callBackOption = option;
167       diffsCB.cfg = cfg;
168       GNUNET_CONFIGURATION_iterate(cfg, diffsCallBack, &diffsCB);
169       break;
170
171     case EDIT_NOTHING:
172       /* Do nothing */
173       break;
174
175     case ADD_NEW_SECTION:
176     {
177       int i;
178       char *key;
179
180       for (i = 0; i < 5; i++)
181         {
182           GNUNET_asprintf(&key, "key%d", i);
183           GNUNET_CONFIGURATION_set_value_string(cfg, "new-section", key,
184                                                 "new-value");
185           GNUNET_CONFIGURATION_set_value_string(diffsCB.cfgDiffs, "new-section",
186                                                 key, "new-value");
187           GNUNET_free(key);
188         }
189       break;
190     }
191
192     case REMOVE_SECTION:
193       break;
194
195     case REMOVE_ENTRY:
196       break;
197
198     default:
199       break;
200     }
201
202   return diffsCB.cfgDiffs;
203 }
204
205 /**
206  * Checking configuration diffs
207  */
208 static int
209 checkDiffs(struct GNUNET_CONFIGURATION_Handle *cfg_default, int option)
210 {
211   struct GNUNET_CONFIGURATION_Handle *cfg;
212   struct GNUNET_CONFIGURATION_Handle *cfgDiffs;
213   struct DiffsCBData cbData;
214   int ret;
215   char *diffsFileName;
216
217   initDiffsCBData(&cbData);
218
219   cfg = GNUNET_CONFIGURATION_create();
220   /* load defaults */
221   GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_load(cfg, NULL));
222
223   /* Modify configuration and save it */
224   cfgDiffs = editConfiguration(cfg, option);
225   diffsFileName = GNUNET_DISK_mktemp("gnunet-test-configurations-diffs.conf");
226   if (diffsFileName == NULL)
227     {
228       GNUNET_break(0);
229       GNUNET_CONFIGURATION_destroy(cfg);
230       GNUNET_CONFIGURATION_destroy(cfgDiffs);
231       return 1;
232     }
233   GNUNET_CONFIGURATION_write_diffs(cfg_default, cfg, diffsFileName);
234   GNUNET_CONFIGURATION_destroy(cfg);
235
236   /* Compare the dumped configuration with modifications done */
237   cfg = GNUNET_CONFIGURATION_create();
238   GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_parse(cfg, diffsFileName));
239   if (0 != remove(diffsFileName))
240     GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_WARNING, "remove", diffsFileName);
241   cbData.callBackOption = COMPARE;
242   cbData.cfgDiffs = cfgDiffs;
243   GNUNET_CONFIGURATION_iterate(cfg, diffsCallBack, &cbData);
244   if (1 == (ret = cbData.status))
245     {
246       fprintf(stderr, "%s",
247               "Incorrect Configuration Diffs: Diffs may contain data not actually edited\n");
248       goto housekeeping;
249     }
250   cbData.cfgDiffs = cfg;
251   GNUNET_CONFIGURATION_iterate(cfgDiffs, diffsCallBack, &cbData);
252   if ((ret = cbData.status) == 1)
253     fprintf(stderr, "%s",
254             "Incorrect Configuration Diffs: Data may be missing in diffs\n");
255
256 housekeeping:
257 #if 0
258   cbData.section = NULL;
259   cbData.callBackOption = PRINT;
260   printf("\nExpected Diffs:\n");
261   GNUNET_CONFIGURATION_iterate(cfgDiffs, diffsCallBack, &cbData);
262   cbData.section = NULL;
263   printf("\nActual Diffs:\n");
264   GNUNET_CONFIGURATION_iterate(cfg, diffsCallBack, &cbData);
265 #endif
266   GNUNET_CONFIGURATION_destroy(cfg);
267   GNUNET_CONFIGURATION_destroy(cfgDiffs);
268   GNUNET_free(diffsFileName);
269   return ret;
270 }
271
272
273 static int
274 testConfig()
275 {
276   char *c;
277   unsigned long long l;
278
279   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "test", "b", &c))
280     return 1;
281   if (0 != strcmp("b", c))
282     {
283       fprintf(stderr, "Got `%s'\n", c);
284       GNUNET_free(c);
285       return 2;
286     }
287   GNUNET_free(c);
288   if (GNUNET_OK !=
289       GNUNET_CONFIGURATION_get_value_number(cfg, "test", "five", &l))
290     {
291       GNUNET_break(0);
292       return 3;
293     }
294   if (5 != l)
295     {
296       GNUNET_break(0);
297       return 4;
298     }
299   GNUNET_CONFIGURATION_set_value_string(cfg, "more", "c", "YES");
300   if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno(cfg, "more", "c"))
301     {
302       GNUNET_break(0);
303       return 5;
304     }
305   GNUNET_CONFIGURATION_set_value_number(cfg, "NUMBERS", "TEN", 10);
306   if (GNUNET_OK !=
307       GNUNET_CONFIGURATION_get_value_string(cfg, "NUMBERS", "TEN", &c))
308     {
309       GNUNET_break(0);
310       return 6;
311     }
312   if (0 != strcmp(c, "10"))
313     {
314       GNUNET_free(c);
315       GNUNET_break(0);
316       return 7;
317     }
318   GNUNET_free(c);
319
320   if (GNUNET_OK !=
321       GNUNET_CONFIGURATION_get_value_filename(cfg, "last", "test", &c))
322     {
323       GNUNET_break(0);
324       return 8;
325     }
326
327   if (0 != strcmp(c, "/hello/world"))
328     {
329       GNUNET_break(0);
330       GNUNET_free(c);
331       return 9;
332     }
333   GNUNET_free(c);
334
335   if (GNUNET_OK !=
336       GNUNET_CONFIGURATION_get_value_size(cfg, "last", "size", &l))
337     {
338       GNUNET_break(0);
339       return 10;
340     }
341   if (l != 512 * 1024)
342     {
343       GNUNET_break(0);
344       return 11;
345     }
346   return 0;
347 }
348
349 static const char *want[] = {
350   "/Hello",
351   "/File Name",
352   "/World",
353   NULL,
354   NULL,
355 };
356
357 static int
358 check(void *data, const char *fn)
359 {
360   int *idx = data;
361
362   if (0 == strcmp(want[*idx], fn))
363     {
364       (*idx)++;
365       return GNUNET_OK;
366     }
367   GNUNET_break(0);
368   return GNUNET_SYSERR;
369 }
370
371 static int
372 testConfigFilenames()
373 {
374   int idx;
375
376   idx = 0;
377   if (3 !=
378       GNUNET_CONFIGURATION_iterate_value_filenames(cfg, "FILENAMES", "test",
379                                                    &check, &idx))
380     {
381       GNUNET_break(0);
382       return 8;
383     }
384   if (idx != 3)
385     return 16;
386   if (GNUNET_OK !=
387       GNUNET_CONFIGURATION_remove_value_filename(cfg, "FILENAMES", "test",
388                                                  "/File Name"))
389     {
390       GNUNET_break(0);
391       return 24;
392     }
393
394   if (GNUNET_NO !=
395       GNUNET_CONFIGURATION_remove_value_filename(cfg, "FILENAMES", "test",
396                                                  "/File Name"))
397     {
398       GNUNET_break(0);
399       return 32;
400     }
401   if (GNUNET_NO !=
402       GNUNET_CONFIGURATION_remove_value_filename(cfg, "FILENAMES", "test",
403                                                  "Stuff"))
404     {
405       GNUNET_break(0);
406       return 40;
407     }
408
409   if (GNUNET_NO !=
410       GNUNET_CONFIGURATION_append_value_filename(cfg, "FILENAMES", "test",
411                                                  "/Hello"))
412     {
413       GNUNET_break(0);
414       return 48;
415     }
416   if (GNUNET_NO !=
417       GNUNET_CONFIGURATION_append_value_filename(cfg, "FILENAMES", "test",
418                                                  "/World"))
419     {
420       GNUNET_break(0);
421       return 56;
422     }
423
424   if (GNUNET_YES !=
425       GNUNET_CONFIGURATION_append_value_filename(cfg, "FILENAMES", "test",
426                                                  "/File 1"))
427     {
428       GNUNET_break(0);
429       return 64;
430     }
431
432   if (GNUNET_YES !=
433       GNUNET_CONFIGURATION_append_value_filename(cfg, "FILENAMES", "test",
434                                                  "/File 2"))
435     {
436       GNUNET_break(0);
437       return 72;
438     }
439
440   idx = 0;
441   want[1] = "/World";
442   want[2] = "/File 1";
443   want[3] = "/File 2";
444   if (4 !=
445       GNUNET_CONFIGURATION_iterate_value_filenames(cfg, "FILENAMES", "test",
446                                                    &check, &idx))
447     {
448       GNUNET_break(0);
449       return 80;
450     }
451   if (idx != 4)
452     {
453       GNUNET_break(0);
454       return 88;
455     }
456   return 0;
457 }
458
459
460 int
461 main(int argc, char *argv[])
462 {
463   int failureCount = 0;
464   char *c;
465
466   GNUNET_log_setup("test_configuration", "WARNING", NULL);
467   cfg = GNUNET_CONFIGURATION_create();
468   GNUNET_assert(cfg != NULL);
469   if (GNUNET_OK !=
470       GNUNET_CONFIGURATION_parse(cfg, "test_configuration_data.conf"))
471     {
472       fprintf(stderr, "%s", "Failed to parse configuration file\n");
473       GNUNET_CONFIGURATION_destroy(cfg);
474       return 1;
475     }
476   failureCount += testConfig();
477   if (failureCount > 0)
478     goto error;
479
480   failureCount = testConfigFilenames();
481   if (failureCount > 0)
482     goto error;
483
484   if (GNUNET_OK != GNUNET_CONFIGURATION_write(cfg, "/tmp/gnunet-test.conf"))
485     {
486       fprintf(stderr, "%s", "Failed to write configuration file\n");
487       GNUNET_CONFIGURATION_destroy(cfg);
488       return 1;
489     }
490   GNUNET_CONFIGURATION_destroy(cfg);
491   GNUNET_assert(0 == unlink("/tmp/gnunet-test.conf"));
492
493   cfg = GNUNET_CONFIGURATION_create();
494   if (GNUNET_OK !=
495       GNUNET_CONFIGURATION_load(cfg, "test_configuration_data.conf"))
496     {
497       GNUNET_break(0);
498       GNUNET_CONFIGURATION_destroy(cfg);
499       return 1;
500     }
501   if (GNUNET_OK !=
502       GNUNET_CONFIGURATION_get_value_string(cfg, "TESTING", "WEAKRANDOM", &c))
503     {
504       GNUNET_break(0);
505       GNUNET_CONFIGURATION_destroy(cfg);
506       return 1;
507     }
508   if (0 != strcmp(c, "YES"))
509     {
510       GNUNET_break(0);
511       GNUNET_free(c);
512       GNUNET_CONFIGURATION_destroy(cfg);
513       return 1;
514     }
515
516   GNUNET_free(c);
517   GNUNET_CONFIGURATION_destroy(cfg);
518
519   /* Testing configuration diffs */
520   cfg_default = GNUNET_CONFIGURATION_create();
521   if (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_default, NULL))
522     {
523       GNUNET_break(0);
524       GNUNET_CONFIGURATION_destroy(cfg_default);
525       return 1;
526     }
527
528   /* Nothing changed in the new configuration */
529   failureCount += checkDiffs(cfg_default, EDIT_NOTHING);
530
531   /* Modify all entries of the last section */
532   failureCount += checkDiffs(cfg_default, EDIT_SECTION);
533
534   /* Add a new section */
535   failureCount += checkDiffs(cfg_default, ADD_NEW_SECTION);
536
537   /* Add a new entry to the last section */
538   failureCount += checkDiffs(cfg_default, ADD_NEW_ENTRY);
539
540   /* Modify all entries in the configuration */
541   failureCount += checkDiffs(cfg_default, EDIT_ALL);
542
543   GNUNET_CONFIGURATION_destroy(cfg_default);
544
545 error:
546   if (failureCount != 0)
547     {
548       fprintf(stderr, "Test failed: %u\n", failureCount);
549       return 1;
550     }
551   return 0;
552 }