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