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