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