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