Add a note about casting the results of g_new() and g_new0().
[platform/upstream/glib.git] / tests / keyfile-test.c
1 #include <glib.h>
2 #include <locale.h>
3 #include <string.h>
4 #include <stdlib.h>
5
6 static GKeyFile *
7 load_data (const gchar   *data, 
8            GKeyFileFlags  flags)
9 {
10   GKeyFile *keyfile;
11   GError *error = NULL;
12
13   keyfile = g_key_file_new ();
14   g_key_file_load_from_data (keyfile, data, -1, flags, &error);
15   if (error)
16     {
17       g_print ("Could not load data: %s\n", error->message);
18       exit (1);
19     }
20   
21   return keyfile;
22 }
23
24 static void
25 check_error (GError **error,
26              GQuark   domain,
27              gint     code)
28 {
29   if (*error == NULL)
30     {
31       g_print ("Missing an error\n");
32       exit (1);
33     }
34   
35   if ((*error)->domain != domain)
36     {
37       g_print ("Wrong error domain: got %s, expected %s\n",
38                g_quark_to_string ((*error)->domain),
39                g_quark_to_string (domain));
40       exit (1);
41     }
42   
43   if ((*error)->code != code)
44     {
45       g_print ("Wrong error code: got %d, expected %d\n",
46                (*error)->code, code);
47       exit (1);
48     }
49
50   g_error_free (*error);
51   *error = NULL;
52 }
53
54 static void 
55 check_no_error (GError **error)
56 {
57   if (*error != NULL)
58     {
59       g_print ("Unexpected error: (%s, %d) %s\n",
60                g_quark_to_string ((*error)->domain),
61                (*error)->code, (*error)->message);
62       exit (1);
63     }
64 }
65
66 static void
67 check_string_value (GKeyFile    *keyfile,
68                     const gchar *group,
69                     const gchar *key,
70                     const gchar *expected) 
71 {
72   GError *error = NULL;
73   gchar *value;
74
75   value = g_key_file_get_string (keyfile, group, key, &error);
76   check_no_error (&error);
77   g_assert (value != NULL);
78
79   if (strcmp (value, expected) != 0)
80     {
81       g_print ("Group %s key %s: "
82                "expected string value '%s', actual value '%s'\n",
83                group, key, expected, value);      
84       exit (1);
85     }
86
87   g_free (value);
88 }
89
90 static void
91 check_locale_string_value (GKeyFile    *keyfile,
92                            const gchar *group,
93                            const gchar *key,
94                            const gchar *locale,
95                            const gchar *expected) 
96 {
97   GError *error = NULL;
98   gchar *value;
99
100   value = g_key_file_get_locale_string (keyfile, group, key, locale, &error);
101   check_no_error (&error);
102   g_assert (value != NULL);
103
104   if (strcmp (value, expected) != 0)
105     {
106       g_print ("Group %s key %s locale %s: "
107                "expected string value '%s', actual value '%s'\n",
108                group, key, locale, expected, value);      
109       exit (1);
110     }
111
112   g_free (value);
113 }
114
115 static void
116 check_string_list_value (GKeyFile    *keyfile,
117                          const gchar *group,
118                          const gchar *key,
119                          ...)
120 {
121   gint i;
122   gchar *v, **value;
123   va_list args;
124   gsize len;
125   GError *error = NULL;
126
127   value = g_key_file_get_string_list (keyfile, group, key, &len, &error);
128   check_no_error (&error);
129   g_assert (value != NULL);
130   
131   va_start (args, key);
132   i = 0;
133   v = va_arg (args, gchar*);
134   while (v)
135     {
136       if (value[i] == NULL)
137         {
138           g_print ("Group %s key %s: list too short (%d)\n", 
139                    group, key, i);      
140           exit (1);
141         }
142       if (strcmp (v, value[i]) != 0)
143         {
144           g_print ("Group %s key %s: mismatch at %d, expected %s, got %s\n", 
145                    group, key, i, v, value[i]);      
146           exit (1);
147         }
148
149       i++;
150       v = va_arg (args, gchar*);
151     }
152
153   va_end (args);
154   
155   g_strfreev (value);
156 }
157
158 static void
159 check_integer_list_value (GKeyFile    *keyfile,
160                           const gchar *group,
161                           const gchar *key,
162                           ...)
163 {
164   gint i;
165   gint v, *value;
166   va_list args;
167   gsize len;
168   GError *error = NULL;
169
170   value = g_key_file_get_integer_list (keyfile, group, key, &len, &error);
171   check_no_error (&error);
172   g_assert (value != NULL);
173   
174   va_start (args, key);
175   i = 0;
176   v = va_arg (args, gint);
177   while (v != -100)
178     {
179       if (i == len)
180         {
181           g_print ("Group %s key %s: list too short (%d)\n", 
182                    group, key, i);      
183           exit (1);
184         }
185       if (value[i] != v)
186         {
187           g_print ("Group %s key %s: mismatch at %d, expected %d, got %d\n", 
188                    group, key, i, v, value[i]);      
189           exit (1);
190         }
191
192       i++;
193       v = va_arg (args, gint);
194     }
195
196   va_end (args);
197   
198   g_free (value);
199 }
200
201 static void
202 check_boolean_list_value (GKeyFile    *keyfile,
203                           const gchar *group,
204                           const gchar *key,
205                           ...)
206 {
207   gint i;
208   gboolean v, *value;
209   va_list args;
210   gsize len;
211   GError *error = NULL;
212
213   value = g_key_file_get_boolean_list (keyfile, group, key, &len, &error);
214   check_no_error (&error);
215   g_assert (value != NULL);
216   
217   va_start (args, key);
218   i = 0;
219   v = va_arg (args, gboolean);
220   while (v != -100)
221     {
222       if (i == len)
223         {
224           g_print ("Group %s key %s: list too short (%d)\n", 
225                    group, key, i);      
226           exit (1);
227         }
228       if (value[i] != v)
229         {
230           g_print ("Group %s key %s: mismatch at %d, expected %d, got %d\n", 
231                    group, key, i, v, value[i]);      
232           exit (1);
233         }
234
235       i++;
236       v = va_arg (args, gboolean);
237     }
238
239   va_end (args);
240   
241   g_free (value);
242 }
243
244 static void
245 check_boolean_value (GKeyFile    *keyfile,
246                      const gchar *group,
247                      const gchar *key,
248                      gboolean     expected) 
249 {
250   GError *error = NULL;
251   gboolean value;
252
253   value = g_key_file_get_boolean (keyfile, group, key, &error);
254   check_no_error (&error);
255
256   if (value != expected)
257     {
258       g_print ("Group %s key %s: "
259                "expected boolean value '%s', actual value '%s'\n",
260                group, key, 
261                expected ? "true" : "false", 
262                value ? "true" : "false");      
263       exit (1);
264     }
265 }
266
267 static void
268 check_integer_value (GKeyFile    *keyfile,
269                      const gchar *group,
270                      const gchar *key,
271                      gint         expected) 
272 {
273   GError *error = NULL;
274   gint value;
275
276   value = g_key_file_get_integer (keyfile, group, key, &error);
277   check_no_error (&error);
278
279   if (value != expected)
280     {
281       g_print ("Group %s key %s: "
282                "expected integer value %d, actual value %d\n",
283                group, key, expected, value);      
284       exit (1);
285     }
286 }
287
288 static void
289 check_name (const gchar *what,
290             const gchar *value,
291             const gchar *expected,
292             gint         position)
293 {
294   if (!value || strcmp (expected, value) != 0)
295     {
296       g_print ("Wrong %s returned: got '%s' at %d, expected '%s'\n",
297                what, value, position, expected);
298       exit (1);
299     }
300 }
301
302 static void
303 check_length (const gchar *what,
304               gint         n_items,
305               gint         length,
306               gint         expected)
307 {
308   if (n_items != length || length != expected)
309     {
310       g_print ("Wrong number of %s returned: got %d items, length %d, expected %d\n",
311                what, n_items, length, expected);
312       exit (1);
313     }
314 }
315
316
317 /* check that both \n and \r\n are accepted as line ends,
318  * and that stray \r are passed through
319  */
320 static void
321 test_line_ends (void)
322 {
323   GKeyFile *keyfile;
324
325   const gchar *data = 
326     "[group1]\n"
327     "key1=value1\n"
328     "key2=value2\r\n"
329     "[group2]\r\n"
330     "key3=value3\r\r\n"
331     "key4=value4\n";
332
333   keyfile = load_data (data, 0);
334
335   check_string_value (keyfile, "group1", "key1", "value1");
336   check_string_value (keyfile, "group1", "key2", "value2");
337   check_string_value (keyfile, "group2", "key3", "value3\r");
338   check_string_value (keyfile, "group2", "key4", "value4");
339
340   g_key_file_free (keyfile);
341 }
342
343 /* check handling of whitespace 
344  */
345 static void
346 test_whitespace (void)
347 {
348   GKeyFile *keyfile;
349
350   const gchar *data = 
351     "[group1]\n"
352     "key1 = value1\n"
353     "key2\t=\tvalue2\n"
354     " [ group2 ] \n"
355     "key3  =  value3  \n"
356     "key4  =  value \t4\n"
357     "  key5  =  value5\n";
358   
359   keyfile = load_data (data, 0);
360
361   check_string_value (keyfile, "group1", "key1", "value1");
362   check_string_value (keyfile, "group1", "key2", "value2");
363   check_string_value (keyfile, " group2 ", "key3", "value3  ");
364   check_string_value (keyfile, " group2 ", "key4", "value \t4");
365   check_string_value (keyfile, " group2 ", "key5", "value5");
366
367   g_key_file_free (keyfile);
368 }
369
370 /* check handling of comments
371  */
372 static void
373 test_comments (void)
374 {
375   GKeyFile *keyfile;
376   gchar **names;
377   gsize len;
378   GError *error = NULL;
379   gchar *comment;
380
381   const gchar *data = 
382     "# top comment\n"
383     "# top comment, continued\n"
384     "[group1]\n"
385     "key1 = value1\n"
386     "# key comment\n"
387     "# key comment, continued\n"
388     "key2 = value2\n"
389     "# line end check\r\n"
390     "key3 = value3\n"
391     "key4 = value4\n"
392     "# group comment\n"
393     "# group comment, continued\n"
394     "[group2]\n";
395
396   const gchar *top_comment= " top comment\n top comment, continued\n";
397   const gchar *group_comment= " group comment\n group comment, continued\n";
398   const gchar *key_comment= " key comment\n key comment, continued\n";
399   
400   keyfile = load_data (data, 0);
401
402   check_string_value (keyfile, "group1", "key1", "value1");
403   check_string_value (keyfile, "group1", "key2", "value2");
404   check_string_value (keyfile, "group1", "key3", "value3");
405   check_string_value (keyfile, "group1", "key4", "value4");
406
407   names = g_key_file_get_keys (keyfile, "group1", &len, &error);
408   check_no_error (&error);
409
410   check_length ("keys", g_strv_length (names), len, 4);
411   check_name ("key", names[0], "key1", 0);
412   check_name ("key", names[1], "key2", 1);
413   check_name ("key", names[2], "key3", 2);
414   check_name ("key", names[3], "key4", 3);
415
416   g_strfreev (names);
417
418   g_key_file_free (keyfile);
419
420   keyfile = load_data (data, G_KEY_FILE_KEEP_COMMENTS);
421
422   names = g_key_file_get_keys (keyfile, "group1", &len, &error);
423   check_no_error (&error);
424
425   check_length ("keys", g_strv_length (names), len, 4);
426   check_name ("key", names[0], "key1", 0);
427   check_name ("key", names[1], "key2", 1);
428   check_name ("key", names[2], "key3", 2);
429   check_name ("key", names[3], "key4", 3);
430
431   g_strfreev (names);
432
433   comment = g_key_file_get_comment (keyfile, NULL, NULL, &error);
434   check_no_error (&error);
435   check_name ("top comment", comment, top_comment, 0);
436   g_free (comment);
437
438   comment = g_key_file_get_comment (keyfile, "group1", "key2", &error);
439   check_no_error (&error);
440   check_name ("key comment", comment, key_comment, 0);
441   g_free (comment);
442
443   comment = g_key_file_get_comment (keyfile, "group2", NULL, &error);
444   check_no_error (&error);
445   check_name ("group comment", comment, group_comment, 0);
446   g_free (comment);
447
448   g_key_file_free (keyfile);
449 }
450
451
452 /* check key and group listing */
453 static void
454 test_listing (void)
455 {
456   GKeyFile *keyfile;
457   gchar **names;
458   gsize len;
459   gchar *start;
460   GError *error = NULL;
461
462   const gchar *data = 
463     "[group1]\n"
464     "key1=value1\n"
465     "key2=value2\n"
466     "[group2]\n"
467     "key3=value3\n"
468     "key4=value4\n";
469   
470   keyfile = load_data (data, 0);
471
472   names = g_key_file_get_groups (keyfile, &len);
473   if (names == NULL)
474     {
475       g_print ("Error listing groups\n");
476       exit (1);
477     }
478
479   check_length ("groups", g_strv_length (names), len, 2);
480   check_name ("group name", names[0], "group1", 0);
481   check_name ("group name", names[1], "group2", 1);
482   
483   g_strfreev (names);
484   
485   names = g_key_file_get_keys (keyfile, "group1", &len, &error);
486   check_no_error (&error);
487
488   check_length ("keys", g_strv_length (names), len, 2);
489   check_name ("key", names[0], "key1", 0);
490   check_name ("key", names[1], "key2", 1);
491
492   g_strfreev (names);
493
494   names = g_key_file_get_keys (keyfile, "no-such-group", &len, &error);
495   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
496
497   g_strfreev (names);
498
499   if (!g_key_file_has_group (keyfile, "group1") ||
500       !g_key_file_has_group (keyfile, "group2") ||
501       g_key_file_has_group (keyfile, "group10") ||
502       g_key_file_has_group (keyfile, "group2 "))      
503     {
504       g_print ("Group finding trouble\n");
505       exit (1);      
506     }
507
508   start = g_key_file_get_start_group (keyfile);
509   if (!start || strcmp (start, "group1") != 0)
510     {
511       g_print ("Start group finding trouble\n");
512       exit (1);
513     }
514   g_free (start);
515
516   if (!g_key_file_has_key (keyfile, "group1", "key1", &error) ||
517       !g_key_file_has_key (keyfile, "group2", "key3", &error) ||
518       g_key_file_has_key (keyfile, "group2", "no-such-key", &error))
519     {
520       g_print ("Key finding trouble\n");
521       exit (1);      
522     }
523   check_no_error (&error);
524   
525   g_key_file_has_key (keyfile, "no-such-group", "key", &error);
526   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
527
528   g_key_file_free (keyfile);
529 }
530
531 /* check parsing of string values */
532 static void
533 test_string (void)
534 {
535   GKeyFile *keyfile;
536   GError *error = NULL;
537   gchar *value;
538
539   const gchar *data = 
540     "[valid]\n"
541     "key1=\\s\\n\\t\\r\\\\\n"
542     "key2=\"quoted\"\n"
543     "key3='quoted'\n"
544     "key4=\xe2\x89\xa0\xe2\x89\xa0\n"
545     "[invalid]\n"
546     "key1=\\a\\b\\0800xff\n"
547     "key2=blabla\\\n";
548   
549   keyfile = load_data (data, 0);
550
551   check_string_value (keyfile, "valid", "key1", " \n\t\r\\");
552   check_string_value (keyfile, "valid", "key2", "\"quoted\"");
553   check_string_value (keyfile, "valid", "key3", "'quoted'");  
554   check_string_value (keyfile, "valid", "key4", "\xe2\x89\xa0\xe2\x89\xa0");  
555   
556   value = g_key_file_get_string (keyfile, "invalid", "key1", &error);
557   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
558   g_free (value);
559
560   value = g_key_file_get_string (keyfile, "invalid", "key2", &error);
561   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
562   g_free (value);
563   
564   g_key_file_free (keyfile);
565 }
566
567 /* check parsing of boolean values */
568 static void
569 test_boolean (void)
570 {
571   GKeyFile *keyfile;
572   GError *error = NULL;
573
574   const gchar *data = 
575     "[valid]\n"
576     "key1=true\n"
577     "key2=false\n"
578     "key3=1\n"
579     "key4=0\n"
580     "[invalid]\n"
581     "key1=t\n"
582     "key2=f\n"
583     "key3=yes\n"
584     "key4=no\n";
585   
586   keyfile = load_data (data, 0);
587
588   check_boolean_value (keyfile, "valid", "key1", TRUE);
589   check_boolean_value (keyfile, "valid", "key2", FALSE);
590   check_boolean_value (keyfile, "valid", "key3", TRUE);
591   check_boolean_value (keyfile, "valid", "key4", FALSE);
592
593   g_key_file_get_boolean (keyfile, "invalid", "key1", &error);
594   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
595
596   g_key_file_get_boolean (keyfile, "invalid", "key2", &error);
597   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
598
599   g_key_file_get_boolean (keyfile, "invalid", "key3", &error);
600   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
601
602   g_key_file_get_boolean (keyfile, "invalid", "key4", &error);
603   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
604
605   g_key_file_free (keyfile);
606 }
607
608 /* check parsing of integer values */
609 static void
610 test_integer (void)
611 {
612   GKeyFile *keyfile;
613   GError *error = NULL;
614
615   const gchar *data = 
616     "[valid]\n"
617     "key1=0\n"
618     "key2=1\n"
619     "key3=-1\n"
620     "key4=2324431\n"
621     "key5=-2324431\n"
622     "key6=000111\n"
623     "[invalid]\n"
624     "key1=0xffff\n"
625     "key2=0.5\n"
626     "key3=1e37\n"
627     "key4=ten\n";
628   
629   keyfile = load_data (data, 0);
630
631   check_integer_value (keyfile, "valid", "key1", 0);
632   check_integer_value (keyfile, "valid", "key2", 1);
633   check_integer_value (keyfile, "valid", "key3", -1);
634   check_integer_value (keyfile, "valid", "key4", 2324431);
635   check_integer_value (keyfile, "valid", "key5", -2324431);
636   check_integer_value (keyfile, "valid", "key6", 111);
637
638   g_key_file_get_integer (keyfile, "invalid", "key1", &error);
639   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
640
641   g_key_file_get_integer (keyfile, "invalid", "key2", &error);
642   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
643
644   g_key_file_get_integer (keyfile, "invalid", "key3", &error);
645   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
646
647   g_key_file_get_integer (keyfile, "invalid", "key4", &error);
648   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
649
650   g_key_file_free (keyfile);
651 }
652
653 /* check handling of translated strings */
654 static void
655 test_locale_string (void)
656 {
657   GKeyFile *keyfile;
658   GError *error = NULL;
659   gchar *value;
660
661   const gchar *data = 
662     "[valid]\n"
663     "key1=v1\n"
664     "key1[de]=v1-de\n"
665     "key1[de_DE]=v1-de_DE\n"
666     "key1[de_DE.UTF8]=v1-de_DE.UTF8\n"
667     "key1[fr]=v1-fr\n"
668     "key1[en] =v1-en\n"
669     "[invalid]\n"
670     "key1[de=v1\n"
671     "key1[fr]]=v2\n"
672     "key1 [en]=v3\n";  
673   
674   keyfile = load_data (data, G_KEY_FILE_KEEP_TRANSLATIONS);
675
676   check_locale_string_value (keyfile, "valid", "key1", "it", "v1");
677   check_locale_string_value (keyfile, "valid", "key1", "de", "v1-de");
678   check_locale_string_value (keyfile, "valid", "key1", "de_DE", "v1-de_DE");
679   check_locale_string_value (keyfile, "valid", "key1", "de_DE.UTF8", "v1-de_DE.UTF8");
680   check_locale_string_value (keyfile, "valid", "key1", "fr", "v1-fr");
681   check_locale_string_value (keyfile, "valid", "key1", "fr_FR", "v1-fr");
682   check_locale_string_value (keyfile, "valid", "key1", "en", "v1-en");
683   
684   value = g_key_file_get_locale_string (keyfile, "invalid", "key1", "de", &error);
685   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
686   g_free (value);
687
688   value = g_key_file_get_locale_string (keyfile, "invalid", "key1", "fr", &error);
689   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
690   g_free (value);
691
692   value = g_key_file_get_locale_string (keyfile, "invalid", "key1", "en", &error);
693   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
694   g_free (value);
695   
696   g_key_file_free (keyfile);
697
698   /* now test that translations are thrown away */
699
700   g_setenv ("LANGUAGE", "de", TRUE);
701   setlocale (LC_ALL, "");
702
703   keyfile = load_data (data, 0);
704
705   check_locale_string_value (keyfile, "valid", "key1", "it", "v1");
706   check_locale_string_value (keyfile, "valid", "key1", "de", "v1-de");
707   check_locale_string_value (keyfile, "valid", "key1", "de_DE", "v1-de");
708   check_locale_string_value (keyfile, "valid", "key1", "de_DE.UTF8", "v1-de");
709   check_locale_string_value (keyfile, "valid", "key1", "fr", "v1");
710   check_locale_string_value (keyfile, "valid", "key1", "fr_FR", "v1");
711   check_locale_string_value (keyfile, "valid", "key1", "en", "v1");
712
713   g_key_file_free (keyfile);  
714 }
715
716 static void
717 test_lists (void)
718 {
719   GKeyFile *keyfile;
720
721   const gchar *data = 
722     "[valid]\n"
723     "key1=v1;v2\n"
724     "key2=v1;v2;\n"
725     "key3=v1,v2\n"
726     "key4=v1\\;v2\n"
727     "key5=true;false\n"
728     "key6=1;0;-1\n"
729     "key7= 1 ; 0 ; -1 \n"
730     "key8=v1\\,v2\n";
731   
732   keyfile = load_data (data, 0);
733
734   check_string_list_value (keyfile, "valid", "key1", "v1", "v2", NULL);
735   check_string_list_value (keyfile, "valid", "key2", "v1", "v2", NULL);
736   check_string_list_value (keyfile, "valid", "key3", "v1,v2", NULL);
737   check_string_list_value (keyfile, "valid", "key4", "v1;v2", NULL);
738   check_boolean_list_value (keyfile, "valid", "key5", TRUE, FALSE, -100);
739   check_integer_list_value (keyfile, "valid", "key6", 1, 0, -1, -100);
740   /* maybe these should be valid */
741   /* check_integer_list_value (keyfile, "valid", "key7", 1, 0, -1, -100);*/
742   /* check_string_list_value (keyfile, "valid", "key8", "v1\\,v2", NULL);*/
743
744   g_key_file_free (keyfile);  
745
746   /* Now check an alternate separator */
747
748   keyfile = load_data (data, 0);
749   g_key_file_set_list_separator (keyfile, ',');
750
751   check_string_list_value (keyfile, "valid", "key1", "v1;v2", NULL);
752   check_string_list_value (keyfile, "valid", "key2", "v1;v2;", NULL);
753   check_string_list_value (keyfile, "valid", "key3", "v1", "v2", NULL);
754
755   g_key_file_free (keyfile);  
756 }
757
758 /* http://bugzilla.gnome.org/show_bug.cgi?id=165887 */
759 static void 
760 test_group_remove (void)
761 {
762   GKeyFile *keyfile;
763   gchar **names;
764   gsize len;
765   GError *error = NULL;
766
767   const gchar *data = 
768     "[group1]\n"
769     "[group2]\n"
770     "key1=bla\n"
771     "key2=bla\n"
772     "[group3]\n"
773     "key1=bla\n"
774     "key2=bla\n";
775   
776   keyfile = load_data (data, 0);
777   
778   names = g_key_file_get_groups (keyfile, &len);
779   if (names == NULL)
780     {
781       g_print ("Error listing groups\n");
782       exit (1);
783     }
784
785   check_length ("groups", g_strv_length (names), len, 3);
786   check_name ("group name", names[0], "group1", 0);
787   check_name ("group name", names[1], "group2", 1);
788   check_name ("group name", names[2], "group3", 2);
789
790   g_key_file_remove_group (keyfile, "group1", &error);
791   check_no_error (&error);
792   
793   g_strfreev (names);
794
795   names = g_key_file_get_groups (keyfile, &len);
796   if (names == NULL)
797     {
798       g_print ("Error listing groups\n");
799       exit (1);
800     }
801
802   check_length ("groups", g_strv_length (names), len, 2);
803   check_name ("group name", names[0], "group2", 0);
804   check_name ("group name", names[1], "group3", 1);
805
806   g_key_file_remove_group (keyfile, "group2", &error);
807   check_no_error (&error);
808   
809   g_strfreev (names);
810
811   names = g_key_file_get_groups (keyfile, &len);
812   if (names == NULL)
813     {
814       g_print ("Error listing groups\n");
815       exit (1);
816     }
817
818   check_length ("groups", g_strv_length (names), len, 1);
819   check_name ("group name", names[0], "group3", 0);
820
821   g_key_file_remove_group (keyfile, "no such group", &error);
822   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
823
824   g_strfreev (names);
825
826   g_key_file_free (keyfile);
827 }
828
829 /* http://bugzilla.gnome.org/show_bug.cgi?id=165980 */
830 static void 
831 test_key_remove (void)
832 {
833   GKeyFile *keyfile;
834   gchar *value;
835   GError *error = NULL;
836
837   const gchar *data = 
838     "[group1]\n"
839     "key1=bla\n"
840     "key2=bla\n";
841   
842   keyfile = load_data (data, 0);
843   
844   check_string_value (keyfile, "group1", "key1", "bla");
845
846   g_key_file_remove_key (keyfile, "group1", "key1", &error);
847   check_no_error (&error);
848
849   value = g_key_file_get_string (keyfile, "group1", "key1", &error);
850   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
851   g_free (value);
852   
853   g_key_file_remove_key (keyfile, "group1", "key1", &error);
854   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
855
856   g_key_file_remove_key (keyfile, "no such group", "key1", &error);
857   check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
858
859   g_key_file_free (keyfile);
860 }
861
862
863 /* http://bugzilla.gnome.org/show_bug.cgi?id=316309 */
864 static void
865 test_groups (void)
866 {
867   GKeyFile *keyfile;
868
869   const gchar *data = 
870     "[1]\n"
871     "key1=123\n"
872     "[2]\n"
873     "key2=123\n";
874   
875   keyfile = load_data (data, 0);
876
877   check_string_value (keyfile, "1", "key1", "123");
878   check_string_value (keyfile, "2", "key2", "123");
879
880   g_key_file_free (keyfile);  
881 }
882
883
884 int
885 main (int argc, char *argv[])
886 {
887   test_line_ends ();
888   test_whitespace ();
889   test_comments ();
890   test_listing ();
891   test_string ();
892   test_boolean ();
893   test_integer ();
894   test_locale_string ();
895   test_lists ();
896   test_group_remove ();
897   test_key_remove ();
898   test_groups ();
899   
900   return 0;
901 }