fix
[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   if (GNUNET_OK !=
341       GNUNET_CONFIGURATION_get_value_size (cfg, "last", "size", &l))
342   {
343     GNUNET_break (0);
344     return 10;
345   }
346   if (l != 512 * 1024)
347   {
348     GNUNET_break (0);
349     return 11;
350   }
351   return 0;
352 }
353
354 static const char *want[] = {
355   "/Hello",
356   "/File Name",
357   "/World",
358   NULL,
359   NULL,
360 };
361
362 static int
363 check (void *data, const char *fn)
364 {
365   int *idx = data;
366
367   if (0 == strcmp (want[*idx], fn))
368     {
369       (*idx)++;
370       return GNUNET_OK;
371     }
372   GNUNET_break (0);
373   return GNUNET_SYSERR;
374 }
375
376 static int
377 testConfigFilenames ()
378 {
379   int idx;
380
381   idx = 0;
382   if (3 !=
383       GNUNET_CONFIGURATION_iterate_value_filenames (cfg, "FILENAMES", "test",
384                                                     &check, &idx))
385     {
386       GNUNET_break (0);
387       return 8;
388     }
389   if (idx != 3)
390     return 16;
391   if (GNUNET_OK !=
392       GNUNET_CONFIGURATION_remove_value_filename (cfg, "FILENAMES", "test",
393                                                   "/File Name"))
394     {
395       GNUNET_break (0);
396       return 24;
397     }
398
399   if (GNUNET_NO !=
400       GNUNET_CONFIGURATION_remove_value_filename (cfg, "FILENAMES", "test",
401                                                   "/File Name"))
402     {
403       GNUNET_break (0);
404       return 32;
405     }
406   if (GNUNET_NO !=
407       GNUNET_CONFIGURATION_remove_value_filename (cfg, "FILENAMES", "test",
408                                                   "Stuff"))
409     {
410       GNUNET_break (0);
411       return 40;
412     }
413
414   if (GNUNET_NO !=
415       GNUNET_CONFIGURATION_append_value_filename (cfg, "FILENAMES", "test",
416                                                   "/Hello"))
417     {
418       GNUNET_break (0);
419       return 48;
420     }
421   if (GNUNET_NO !=
422       GNUNET_CONFIGURATION_append_value_filename (cfg, "FILENAMES", "test",
423                                                   "/World"))
424     {
425       GNUNET_break (0);
426       return 56;
427     }
428
429   if (GNUNET_YES !=
430       GNUNET_CONFIGURATION_append_value_filename (cfg, "FILENAMES", "test",
431                                                   "/File 1"))
432     {
433       GNUNET_break (0);
434       return 64;
435     }
436
437   if (GNUNET_YES !=
438       GNUNET_CONFIGURATION_append_value_filename (cfg, "FILENAMES", "test",
439                                                   "/File 2"))
440     {
441       GNUNET_break (0);
442       return 72;
443     }
444
445   idx = 0;
446   want[1] = "/World";
447   want[2] = "/File 1";
448   want[3] = "/File 2";
449   if (4 !=
450       GNUNET_CONFIGURATION_iterate_value_filenames (cfg, "FILENAMES", "test",
451                                                     &check, &idx))
452     {
453       GNUNET_break (0);
454       return 80;
455     }
456   if (idx != 4)
457     {
458       GNUNET_break (0);
459       return 88;
460     }
461   return 0;
462 }
463
464
465 int
466 main (int argc, char *argv[])
467 {
468   int failureCount = 0;
469   char *c;
470
471   GNUNET_log_setup ("test_configuration", "WARNING", NULL);
472   cfg = GNUNET_CONFIGURATION_create ();
473   GNUNET_assert (cfg != NULL);
474   if (GNUNET_OK !=
475       GNUNET_CONFIGURATION_parse (cfg, "test_configuration_data.conf"))
476     {
477       fprintf (stderr, "Failed to parse configuration file\n");
478       GNUNET_CONFIGURATION_destroy (cfg);
479       return 1;
480     }
481   failureCount += testConfig ();
482   if (failureCount > 0)
483     goto error;
484
485   failureCount = testConfigFilenames ();
486   if (failureCount > 0)
487     goto error;
488
489   if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, "/tmp/gnunet-test.conf"))
490     {
491       fprintf (stderr, "Failed to write configuration file\n");
492       GNUNET_CONFIGURATION_destroy (cfg);
493       return 1;
494     }
495   GNUNET_CONFIGURATION_destroy (cfg);
496   GNUNET_assert (0 == UNLINK ("/tmp/gnunet-test.conf"));
497
498   cfg = GNUNET_CONFIGURATION_create ();
499   if (GNUNET_OK !=
500       GNUNET_CONFIGURATION_load (cfg, "test_configuration_data.conf"))
501     {
502       GNUNET_break (0);
503       GNUNET_CONFIGURATION_destroy (cfg);
504       return 1;
505     }
506   if (GNUNET_OK !=
507       GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING", "WEAKRANDOM",
508                                              &c))
509     {
510       GNUNET_break (0);
511       GNUNET_CONFIGURATION_destroy (cfg);
512       return 1;
513     }
514   if (0 != strcmp (c, "YES"))
515     {
516       GNUNET_break (0);
517       GNUNET_free (c);
518       GNUNET_CONFIGURATION_destroy (cfg);
519       return 1;
520     }
521
522   GNUNET_free (c);
523   GNUNET_CONFIGURATION_destroy (cfg);
524
525   /* Testing configuration diffs */
526   cfgDefault = GNUNET_CONFIGURATION_create ();
527   if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfgDefault, NULL))
528     {
529       GNUNET_break (0);
530       GNUNET_CONFIGURATION_destroy (cfgDefault);
531       return 1;
532     }
533
534   /* Nothing changed in the new configuration */
535   failureCount += checkDiffs (cfgDefault, EDIT_NOTHING);
536
537   /* Modify all entries of the last section */
538   failureCount += checkDiffs (cfgDefault, EDIT_SECTION);
539
540   /* Add a new section */
541   failureCount += checkDiffs (cfgDefault, ADD_NEW_SECTION);
542
543   /* Add a new entry to the last section */
544   failureCount += checkDiffs (cfgDefault, ADD_NEW_ENTRY);
545
546   /* Modify all entries in the configuration */
547   failureCount += checkDiffs (cfgDefault, EDIT_ALL);
548
549   GNUNET_CONFIGURATION_destroy (cfgDefault);
550
551 error:
552   if (failureCount != 0)
553     {
554       fprintf (stderr, "Test failed: %u\n", failureCount);
555       return 1;
556     }
557   return 0;
558 }