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