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