indentation
[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_NO
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,
79                const char *section, const char *option, 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 DEBUG
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, "new-value");
188       GNUNET_free (key);
189     }
190     break;
191   }
192   case REMOVE_SECTION:
193     break;
194   case REMOVE_ENTRY:
195     break;
196   default:
197     break;
198   }
199
200   return diffsCB.cfgDiffs;
201 }
202
203 /**
204  * Checking configuration diffs
205  */
206 static int
207 checkDiffs (struct GNUNET_CONFIGURATION_Handle *cfgDefault, int option)
208 {
209   struct GNUNET_CONFIGURATION_Handle *cfg;
210   struct GNUNET_CONFIGURATION_Handle *cfgDiffs;
211   struct DiffsCBData cbData;
212   int ret;
213   char *diffsFileName;
214
215   initDiffsCBData (&cbData);
216
217   cfg = GNUNET_CONFIGURATION_create ();
218   /* load defaults */
219   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (cfg, NULL));
220
221   /* Modify configuration and save it */
222   cfgDiffs = editConfiguration (cfg, option);
223   diffsFileName = GNUNET_DISK_mktemp ("gnunet-test-configurations-diffs.conf");
224   if (diffsFileName == NULL)
225   {
226     GNUNET_break (0);
227     GNUNET_CONFIGURATION_destroy (cfg);
228     GNUNET_CONFIGURATION_destroy (cfgDiffs);
229     return 1;
230   }
231   GNUNET_CONFIGURATION_write_diffs (cfgDefault, cfg, diffsFileName);
232   GNUNET_CONFIGURATION_destroy (cfg);
233
234   /* Compare the dumped configuration with modifications done */
235   cfg = GNUNET_CONFIGURATION_create ();
236   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, diffsFileName));
237   remove (diffsFileName);
238   cbData.callBackOption = COMPARE;
239   cbData.cfgDiffs = cfgDiffs;
240   GNUNET_CONFIGURATION_iterate (cfg, diffsCallBack, &cbData);
241   if (1 == (ret = cbData.status))
242   {
243     fprintf (stderr,
244              "Incorrect Configuration Diffs: Diffs may contain data not actually edited\n");
245     goto housekeeping;
246   }
247   cbData.cfgDiffs = cfg;
248   GNUNET_CONFIGURATION_iterate (cfgDiffs, diffsCallBack, &cbData);
249   if ((ret = cbData.status) == 1)
250     fprintf (stderr,
251              "Incorrect Configuration Diffs: Data may be missing in diffs\n");
252
253 housekeeping:
254 #if DEBUG
255   cbData.section = NULL;
256   cbData.callBackOption = PRINT;
257   printf ("\nExpected Diffs:\n");
258   GNUNET_CONFIGURATION_iterate (cfgDiffs, diffsCallBack, &cbData);
259   cbData.section = NULL;
260   printf ("\nActual Diffs:\n");
261   GNUNET_CONFIGURATION_iterate (cfg, diffsCallBack, &cbData);
262 #endif
263   GNUNET_CONFIGURATION_destroy (cfg);
264   GNUNET_CONFIGURATION_destroy (cfgDiffs);
265   GNUNET_free (diffsFileName);
266   return ret;
267 }
268
269
270 static int
271 testConfig ()
272 {
273   char *c;
274   unsigned long long l;
275
276   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "test", "b", &c))
277     return 1;
278   if (0 != strcmp ("b", c))
279   {
280     fprintf (stderr, "Got `%s'\n", c);
281     GNUNET_free (c);
282     return 2;
283   }
284   GNUNET_free (c);
285   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
286                                                           "test", "five", &l))
287   {
288     GNUNET_break (0);
289     return 3;
290   }
291   if (5 != l)
292   {
293     GNUNET_break (0);
294     return 4;
295   }
296   GNUNET_CONFIGURATION_set_value_string (cfg, "more", "c", "YES");
297   if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno (cfg, "more", "c"))
298   {
299     GNUNET_break (0);
300     return 5;
301   }
302   GNUNET_CONFIGURATION_set_value_number (cfg, "NUMBERS", "TEN", 10);
303   if (GNUNET_OK !=
304       GNUNET_CONFIGURATION_get_value_string (cfg, "NUMBERS", "TEN", &c))
305   {
306     GNUNET_break (0);
307     return 6;
308   }
309   if (0 != strcmp (c, "10"))
310   {
311     GNUNET_free (c);
312     GNUNET_break (0);
313     return 7;
314   }
315   GNUNET_free (c);
316
317   if (GNUNET_OK !=
318       GNUNET_CONFIGURATION_get_value_filename (cfg, "last", "test", &c))
319   {
320     GNUNET_break (0);
321     return 8;
322   }
323 #ifndef MINGW
324   if (0 != strcmp (c, "/hello/world"))
325 #else
326 #define HI "\\hello\\world"
327   if (strstr (c, HI) != c + strlen (c) - strlen (HI))
328 #endif
329   {
330     GNUNET_break (0);
331     GNUNET_free (c);
332     return 9;
333   }
334   GNUNET_free (c);
335
336   return 0;
337 }
338
339 static const char *want[] = {
340   "/Hello",
341   "/File Name",
342   "/World",
343   NULL,
344   NULL,
345 };
346
347 static int
348 check (void *data, const char *fn)
349 {
350   int *idx = data;
351
352   if (0 == strcmp (want[*idx], fn))
353   {
354     (*idx)++;
355     return GNUNET_OK;
356   }
357   GNUNET_break (0);
358   return GNUNET_SYSERR;
359 }
360
361 static int
362 testConfigFilenames ()
363 {
364   int idx;
365
366   idx = 0;
367   if (3 != GNUNET_CONFIGURATION_iterate_value_filenames (cfg,
368                                                          "FILENAMES",
369                                                          "test", &check, &idx))
370   {
371     GNUNET_break (0);
372     return 8;
373   }
374   if (idx != 3)
375     return 16;
376   if (GNUNET_OK !=
377       GNUNET_CONFIGURATION_remove_value_filename (cfg,
378                                                   "FILENAMES",
379                                                   "test", "/File Name"))
380   {
381     GNUNET_break (0);
382     return 24;
383   }
384
385   if (GNUNET_NO !=
386       GNUNET_CONFIGURATION_remove_value_filename (cfg,
387                                                   "FILENAMES",
388                                                   "test", "/File Name"))
389   {
390     GNUNET_break (0);
391     return 32;
392   }
393   if (GNUNET_NO !=
394       GNUNET_CONFIGURATION_remove_value_filename (cfg,
395                                                   "FILENAMES", "test", "Stuff"))
396   {
397     GNUNET_break (0);
398     return 40;
399   }
400
401   if (GNUNET_NO !=
402       GNUNET_CONFIGURATION_append_value_filename (cfg,
403                                                   "FILENAMES",
404                                                   "test", "/Hello"))
405   {
406     GNUNET_break (0);
407     return 48;
408   }
409   if (GNUNET_NO !=
410       GNUNET_CONFIGURATION_append_value_filename (cfg,
411                                                   "FILENAMES",
412                                                   "test", "/World"))
413   {
414     GNUNET_break (0);
415     return 56;
416   }
417
418   if (GNUNET_YES !=
419       GNUNET_CONFIGURATION_append_value_filename (cfg,
420                                                   "FILENAMES",
421                                                   "test", "/File 1"))
422   {
423     GNUNET_break (0);
424     return 64;
425   }
426
427   if (GNUNET_YES !=
428       GNUNET_CONFIGURATION_append_value_filename (cfg,
429                                                   "FILENAMES",
430                                                   "test", "/File 2"))
431   {
432     GNUNET_break (0);
433     return 72;
434   }
435
436   idx = 0;
437   want[1] = "/World";
438   want[2] = "/File 1";
439   want[3] = "/File 2";
440   if (4 != GNUNET_CONFIGURATION_iterate_value_filenames (cfg,
441                                                          "FILENAMES",
442                                                          "test", &check, &idx))
443   {
444     GNUNET_break (0);
445     return 80;
446   }
447   if (idx != 4)
448   {
449     GNUNET_break (0);
450     return 88;
451   }
452   return 0;
453 }
454
455
456 int
457 main (int argc, char *argv[])
458 {
459   int failureCount = 0;
460   char *c;
461
462   GNUNET_log_setup ("test_configuration", "WARNING", NULL);
463   cfg = GNUNET_CONFIGURATION_create ();
464   GNUNET_assert (cfg != NULL);
465   if (GNUNET_OK !=
466       GNUNET_CONFIGURATION_parse (cfg, "test_configuration_data.conf"))
467   {
468     fprintf (stderr, "Failed to parse configuration file\n");
469     GNUNET_CONFIGURATION_destroy (cfg);
470     return 1;
471   }
472   failureCount += testConfig ();
473   if (failureCount > 0)
474     goto error;
475
476   failureCount = testConfigFilenames ();
477   if (failureCount > 0)
478     goto error;
479
480   if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, "/tmp/gnunet-test.conf"))
481   {
482     fprintf (stderr, "Failed to write configuration file\n");
483     GNUNET_CONFIGURATION_destroy (cfg);
484     return 1;
485   }
486   GNUNET_CONFIGURATION_destroy (cfg);
487   GNUNET_assert (0 == UNLINK ("/tmp/gnunet-test.conf"));
488
489   cfg = GNUNET_CONFIGURATION_create ();
490   if (GNUNET_OK !=
491       GNUNET_CONFIGURATION_load (cfg, "test_configuration_data.conf"))
492   {
493     GNUNET_break (0);
494     GNUNET_CONFIGURATION_destroy (cfg);
495     return 1;
496   }
497   if (GNUNET_OK !=
498       GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING", "WEAKRANDOM", &c))
499   {
500     GNUNET_break (0);
501     GNUNET_CONFIGURATION_destroy (cfg);
502     return 1;
503   }
504   if (0 != strcmp (c, "YES"))
505   {
506     GNUNET_break (0);
507     GNUNET_free (c);
508     GNUNET_CONFIGURATION_destroy (cfg);
509     return 1;
510   }
511
512   GNUNET_free (c);
513   GNUNET_CONFIGURATION_destroy (cfg);
514
515   /* Testing configuration diffs */
516   cfgDefault = GNUNET_CONFIGURATION_create ();
517   if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfgDefault, NULL))
518   {
519     GNUNET_break (0);
520     GNUNET_CONFIGURATION_destroy (cfgDefault);
521     return 1;
522   }
523
524   /* Nothing changed in the new configuration */
525   failureCount += checkDiffs (cfgDefault, EDIT_NOTHING);
526
527   /* Modify all entries of the last section */
528   failureCount += checkDiffs (cfgDefault, EDIT_SECTION);
529
530   /* Add a new section */
531   failureCount += checkDiffs (cfgDefault, ADD_NEW_SECTION);
532
533   /* Add a new entry to the last section */
534   failureCount += checkDiffs (cfgDefault, ADD_NEW_ENTRY);
535
536   /* Modify all entries in the configuration */
537   failureCount += checkDiffs (cfgDefault, EDIT_ALL);
538
539   GNUNET_CONFIGURATION_destroy (cfgDefault);
540
541 error:
542   if (failureCount != 0)
543   {
544     fprintf (stderr, "Test failed: %u\n", failureCount);
545     return 1;
546   }
547   return 0;
548 }