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