[kdbus] Add SipHash algorithm
[platform/upstream/glib.git] / glib / tests / option-context.c
1 /* Unit tests for GOptionContext
2  * Copyright (C) 2007 Openismus GmbH
3  * Authors: Mathias Hasselmann
4  *
5  * This work is provided "as is"; redistribution and modification
6  * in whole or in part, in any medium, physical or electronic is
7  * permitted without restriction.
8  *
9  * This work is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * In no event shall the authors or contributors be liable for any
14  * direct, indirect, incidental, special, exemplary, or consequential
15  * damages (including, but not limited to, procurement of substitute
16  * goods or services; loss of use, data, or profits; or business
17  * interruption) however caused and on any theory of liability, whether
18  * in contract, strict liability, or tort (including negligence or
19  * otherwise) arising in any way out of the use of this software, even
20  * if advised of the possibility of such damage.
21  */
22
23 #include <glib.h>
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <locale.h>
29
30 static GOptionEntry main_entries[] = {
31   { "main-switch", 0, 0,
32     G_OPTION_ARG_NONE, NULL,
33     "A switch that is in the main group", NULL },
34   { NULL }
35 };
36
37 static GOptionEntry group_entries[] = {
38   { "test-switch", 0, 0,
39     G_OPTION_ARG_NONE, NULL,
40     "A switch that is in the test group", NULL },
41   { NULL }
42 };
43
44 static GOptionContext *
45 make_options (int test_number)
46 {
47   GOptionContext *options;
48   GOptionGroup   *group = NULL;
49   gboolean have_main_entries = (0 != (test_number & 1));
50   gboolean have_test_entries = (0 != (test_number & 2));
51
52   options = g_option_context_new (NULL);
53
54   if (have_main_entries)
55     g_option_context_add_main_entries (options, main_entries, NULL);
56   if (have_test_entries)
57     {
58       group = g_option_group_new ("test", "Test Options",
59                                   "Show all test options",
60                                   NULL, NULL);
61       g_option_context_add_group (options, group);
62       g_option_group_add_entries (group, group_entries);
63     }
64
65   return options;
66 }
67
68 static void
69 print_help (GOptionContext *options, gchar **argv)
70 {
71   gint    argc = 3;
72   GError *error = NULL;
73
74   g_setenv ("LANG", "C", TRUE);
75
76   g_option_context_parse (options, &argc, &argv, &error);
77   g_option_context_free (options);
78   exit(0);
79 }
80
81 static void
82 test_group_captions_help (gconstpointer test_number)
83 {
84   GOptionContext *options;
85   gchar *argv[] = { __FILE__, "--help", NULL };
86
87   options = make_options (GPOINTER_TO_INT (test_number));
88   print_help (options, argv);
89 }
90
91 static void
92 test_group_captions_help_all (gconstpointer test_number)
93 {
94   GOptionContext *options;
95   gchar *argv[] = { __FILE__, "--help-all", NULL };
96
97   options = make_options (GPOINTER_TO_INT (test_number));
98   print_help (options, argv);
99 }
100
101 static void
102 test_group_captions_help_test (gconstpointer test_number)
103 {
104   GOptionContext *options;
105   gchar *argv[] = { __FILE__, "--help-test", NULL };
106
107   options = make_options (GPOINTER_TO_INT (test_number));
108   print_help (options, argv);
109 }
110
111 static void
112 test_group_captions (void)
113 {
114   const gchar *test_name_base[] = { "help", "help-all", "help-test" };
115   gchar *test_name;
116   gint i, j;
117
118   g_test_bug ("504142");
119
120   for (i = 0; i < 4; ++i)
121     {
122       gboolean have_main_entries = (0 != (i & 1));
123       gboolean have_test_entries = (0 != (i & 2));
124
125       for (j = 0; j < G_N_ELEMENTS (test_name_base); ++j)
126         {
127           GTestSubprocessFlags trap_flags = 0;
128           gboolean expect_main_description = FALSE;
129           gboolean expect_main_switch      = FALSE;
130           gboolean expect_test_description = FALSE;
131           gboolean expect_test_switch      = FALSE;
132           gboolean expect_test_group       = FALSE;
133
134           if (g_test_verbose ())
135             trap_flags |= G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR;
136
137           test_name = g_strdup_printf ("/option/group/captions/subprocess/%s-%d",
138                                        test_name_base[j], i);
139           g_test_trap_subprocess (test_name, 0, trap_flags);
140           g_free (test_name);
141           g_test_trap_assert_passed ();
142           g_test_trap_assert_stderr ("");
143
144           switch (j)
145             {
146             case 0:
147               g_assert_cmpstr ("help", ==, test_name_base[j]);
148               expect_main_switch = have_main_entries;
149               expect_test_group  = have_test_entries;
150               break;
151
152             case 1:
153               g_assert_cmpstr ("help-all", ==, test_name_base[j]);
154               expect_main_switch = have_main_entries;
155               expect_test_switch = have_test_entries;
156               expect_test_group  = have_test_entries;
157               break;
158
159             case 2:
160               g_assert_cmpstr ("help-test", ==, test_name_base[j]);
161               expect_test_switch = have_test_entries;
162               break;
163
164             default:
165               g_assert_not_reached ();
166               break;
167             }
168
169           expect_main_description |= expect_main_switch;
170           expect_test_description |= expect_test_switch;
171
172           if (expect_main_description)
173             g_test_trap_assert_stdout           ("*Application Options*");
174           else
175             g_test_trap_assert_stdout_unmatched ("*Application Options*");
176           if (expect_main_switch)
177             g_test_trap_assert_stdout           ("*--main-switch*");
178           else
179             g_test_trap_assert_stdout_unmatched ("*--main-switch*");
180
181           if (expect_test_description)
182             g_test_trap_assert_stdout           ("*Test Options*");
183           else
184             g_test_trap_assert_stdout_unmatched ("*Test Options*");
185           if (expect_test_switch)
186             g_test_trap_assert_stdout           ("*--test-switch*");
187           else
188             g_test_trap_assert_stdout_unmatched ("*--test-switch*");
189
190           if (expect_test_group)
191             g_test_trap_assert_stdout           ("*--help-test*");
192           else
193             g_test_trap_assert_stdout_unmatched ("*--help-test*");
194         }
195     }
196 }
197
198 int error_test1_int;
199 char *error_test2_string;
200 gboolean error_test3_boolean;
201
202 int arg_test1_int;
203 gchar *arg_test2_string;
204 gchar *arg_test3_filename;
205 gdouble arg_test4_double;
206 gdouble arg_test5_double;
207 gint64 arg_test6_int64;
208 gint64 arg_test6_int64_2;
209
210 gchar *callback_test1_string;
211 int callback_test2_int;
212
213 gchar *callback_test_optional_string;
214 gboolean callback_test_optional_boolean;
215
216 gchar **array_test1_array;
217
218 gboolean ignore_test1_boolean;
219 gboolean ignore_test2_boolean;
220 gchar *ignore_test3_string;
221
222 static gchar **
223 split_string (const char *str, int *argc)
224 {
225   gchar **argv;
226   int len;
227   
228   argv = g_strsplit (str, " ", 0);
229
230   for (len = 0; argv[len] != NULL; len++);
231
232   if (argc)
233     *argc = len;
234     
235   return argv;
236 }
237
238 static gchar *
239 join_stringv (int argc, char **argv)
240 {
241   int i;
242   GString *str;
243
244   str = g_string_new (NULL);
245
246   for (i = 0; i < argc; i++)
247     {
248       g_string_append (str, argv[i]);
249
250       if (i < argc - 1)
251         g_string_append_c (str, ' ');
252     }
253
254   return g_string_free (str, FALSE);
255 }
256
257 /* Performs a shallow copy */
258 static char **
259 copy_stringv (char **argv, int argc)
260 {
261   return g_memdup (argv, sizeof (char *) * (argc + 1));
262 }
263
264 static void
265 check_identical_stringv (gchar **before, gchar **after)
266 {
267   guint i;
268
269   /* Not only is it the same string... */
270   for (i = 0; before[i] != NULL; i++)
271     g_assert_cmpstr (before[i], ==, after[i]);
272
273   /* ... it is actually the same pointer */
274   for (i = 0; before[i] != NULL; i++)
275     g_assert (before[i] == after[i]);
276
277   g_assert (after[i] == NULL);
278 }
279
280
281 static gboolean
282 error_test1_pre_parse (GOptionContext *context,
283                        GOptionGroup   *group,
284                        gpointer        data,
285                        GError        **error)
286 {
287   g_assert (error_test1_int == 0x12345678);
288
289   return TRUE;
290 }
291
292 static gboolean
293 error_test1_post_parse (GOptionContext *context,
294                         GOptionGroup   *group,
295                         gpointer          data,
296                         GError        **error)
297 {
298   g_assert (error_test1_int == 20);
299
300   /* Set an error in the post hook */
301   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
302
303   return FALSE;
304 }
305
306 static void
307 error_test1 (void)
308 {
309   GOptionContext *context;
310   gboolean retval;
311   GError *error = NULL;
312   gchar **argv;
313   gchar **argv_copy;
314   int argc;
315   GOptionGroup *main_group;
316   GOptionEntry entries [] =
317     { { "test", 0, 0, G_OPTION_ARG_INT, &error_test1_int, NULL, NULL },
318       { NULL } };
319   
320   error_test1_int = 0x12345678;
321
322   context = g_option_context_new (NULL);
323   g_option_context_add_main_entries (context, entries, NULL);
324
325   /* Set pre and post parse hooks */
326   main_group = g_option_context_get_main_group (context);
327   g_option_group_set_parse_hooks (main_group,
328                                   error_test1_pre_parse, error_test1_post_parse);
329   
330   /* Now try parsing */
331   argv = split_string ("program --test 20", &argc);
332   argv_copy = copy_stringv (argv, argc);
333
334   retval = g_option_context_parse (context, &argc, &argv, &error);
335   g_assert (retval == FALSE);
336   g_assert (error != NULL);
337   /* An error occurred, so argv has not been changed */
338   check_identical_stringv (argv_copy, argv);
339   g_clear_error (&error);
340
341   /* On failure, values should be reset */
342   g_assert (error_test1_int == 0x12345678);
343
344   g_strfreev (argv_copy);
345   g_free (argv);
346   g_option_context_free (context);
347 }
348
349 static gboolean
350 error_test2_pre_parse (GOptionContext *context,
351                        GOptionGroup   *group,
352                        gpointer   data,
353                        GError        **error)
354 {
355   g_assert (strcmp (error_test2_string, "foo") == 0);
356
357   return TRUE;
358 }
359
360 static gboolean
361 error_test2_post_parse (GOptionContext *context,
362                         GOptionGroup   *group,
363                         gpointer          data,
364                         GError        **error)
365 {
366   g_assert (strcmp (error_test2_string, "bar") == 0);
367
368   /* Set an error in the post hook */
369   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
370
371   return FALSE;
372 }
373
374 static void
375 error_test2 (void)
376 {
377   GOptionContext *context;
378   gboolean retval;
379   GError *error = NULL;
380   gchar **argv;
381   gchar **argv_copy;
382   int argc;
383   GOptionGroup *main_group;
384   GOptionEntry entries [] =
385     { { "test", 0, 0, G_OPTION_ARG_STRING, &error_test2_string, NULL, NULL },
386       { NULL } };
387
388   error_test2_string = "foo";
389
390   context = g_option_context_new (NULL);
391   g_option_context_add_main_entries (context, entries, NULL);
392
393   /* Set pre and post parse hooks */
394   main_group = g_option_context_get_main_group (context);
395   g_option_group_set_parse_hooks (main_group,
396                                   error_test2_pre_parse, error_test2_post_parse);
397   
398   /* Now try parsing */
399   argv = split_string ("program --test bar", &argc);
400   argv_copy = copy_stringv (argv, argc);
401   retval = g_option_context_parse (context, &argc, &argv, &error);
402
403   g_assert (retval == FALSE);
404   g_assert (error != NULL);
405   check_identical_stringv (argv_copy, argv);
406   g_clear_error (&error);
407
408   g_assert (strcmp (error_test2_string, "foo") == 0);
409
410   g_strfreev (argv_copy);
411   g_free (argv);
412   g_option_context_free (context);
413 }
414
415 static gboolean
416 error_test3_pre_parse (GOptionContext *context,
417                        GOptionGroup   *group,
418                        gpointer   data,
419                        GError        **error)
420 {
421   g_assert (!error_test3_boolean);
422
423   return TRUE;
424 }
425
426 static gboolean
427 error_test3_post_parse (GOptionContext *context,
428                         GOptionGroup   *group,
429                         gpointer          data,
430                         GError        **error)
431 {
432   g_assert (error_test3_boolean);
433
434   /* Set an error in the post hook */
435   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
436
437   return FALSE;
438 }
439
440 static void
441 error_test3 (void)
442 {
443   GOptionContext *context;
444   gboolean retval;
445   GError *error = NULL;
446   gchar **argv;
447   gchar **argv_copy;
448   int argc;
449   GOptionGroup *main_group;
450   GOptionEntry entries [] =
451     { { "test", 0, 0, G_OPTION_ARG_NONE, &error_test3_boolean, NULL, NULL },
452       { NULL } };
453
454   error_test3_boolean = FALSE;
455
456   context = g_option_context_new (NULL);
457   g_option_context_add_main_entries (context, entries, NULL);
458
459   /* Set pre and post parse hooks */
460   main_group = g_option_context_get_main_group (context);
461   g_option_group_set_parse_hooks (main_group,
462                                   error_test3_pre_parse, error_test3_post_parse);
463   
464   /* Now try parsing */
465   argv = split_string ("program --test", &argc);
466   argv_copy = copy_stringv (argv, argc);
467   retval = g_option_context_parse (context, &argc, &argv, &error);
468
469   g_assert (retval == FALSE);
470   g_assert (error != NULL);
471   check_identical_stringv (argv_copy, argv);
472   g_clear_error (&error);
473
474   g_assert (!error_test3_boolean);
475
476   g_strfreev (argv_copy);
477   g_free (argv);
478   g_option_context_free (context);
479 }
480
481 static void
482 arg_test1 (void)
483 {
484   GOptionContext *context;
485   gboolean retval;
486   GError *error = NULL;
487   gchar **argv;
488   gchar **argv_copy;
489   int argc;
490   GOptionEntry entries [] =
491     { { "test", 0, 0, G_OPTION_ARG_INT, &arg_test1_int, NULL, NULL },
492       { NULL } };
493
494   context = g_option_context_new (NULL);
495   g_option_context_add_main_entries (context, entries, NULL);
496
497   /* Now try parsing */
498   argv = split_string ("program --test 20 --test 30", &argc);
499   argv_copy = copy_stringv (argv, argc);
500
501   retval = g_option_context_parse (context, &argc, &argv, &error);
502   g_assert_no_error (error);
503   g_assert (retval);
504
505   /* Last arg specified is the one that should be stored */
506   g_assert (arg_test1_int == 30);
507
508   /* We free all of the strings in a copy of argv, because now argv is a
509    * subset - some have been removed in-place
510    */
511   g_strfreev (argv_copy);
512   g_free (argv);
513   g_option_context_free (context);
514 }
515
516 static void
517 arg_test2 (void)
518 {
519   GOptionContext *context;
520   gboolean retval;
521   GError *error = NULL;
522   gchar **argv;
523   gchar **argv_copy;
524   int argc;
525   GOptionEntry entries [] =
526     { { "test", 0, 0, G_OPTION_ARG_STRING, &arg_test2_string, NULL, NULL },
527       { NULL } };
528   
529   context = g_option_context_new (NULL);
530   g_option_context_add_main_entries (context, entries, NULL);
531
532   /* Now try parsing */
533   argv = split_string ("program --test foo --test bar", &argc);
534   argv_copy = copy_stringv (argv, argc);
535
536   retval = g_option_context_parse (context, &argc, &argv, &error);
537   g_assert_no_error (error);
538   g_assert (retval);
539
540   /* Last arg specified is the one that should be stored */
541   g_assert (strcmp (arg_test2_string, "bar") == 0);
542
543   g_free (arg_test2_string);
544
545   g_strfreev (argv_copy);
546   g_free (argv);
547   g_option_context_free (context);
548 }
549
550 static void
551 arg_test3 (void)
552 {
553   GOptionContext *context;
554   gboolean retval;
555   GError *error = NULL;
556   gchar **argv;
557   gchar **argv_copy;
558   int argc;
559   GOptionEntry entries [] =
560     { { "test", 0, 0, G_OPTION_ARG_FILENAME, &arg_test3_filename, NULL, NULL },
561       { NULL } };
562   
563   context = g_option_context_new (NULL);
564   g_option_context_add_main_entries (context, entries, NULL);
565
566   /* Now try parsing */
567   argv = split_string ("program --test foo.txt", &argc);
568   argv_copy = copy_stringv (argv, argc);
569
570   retval = g_option_context_parse (context, &argc, &argv, &error);
571   g_assert_no_error (error);
572   g_assert (retval);
573
574   /* Last arg specified is the one that should be stored */
575   g_assert (strcmp (arg_test3_filename, "foo.txt") == 0);
576
577   g_free (arg_test3_filename);
578
579   g_strfreev (argv_copy);
580   g_free (argv);
581   g_option_context_free (context);
582 }
583
584
585 static void
586 arg_test4 (void)
587 {
588   GOptionContext *context;
589   gboolean retval;
590   GError *error = NULL;
591   gchar **argv_copy;
592   gchar **argv;
593   int argc;
594   GOptionEntry entries [] =
595     { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test4_double, NULL, NULL },
596       { NULL } };
597
598   context = g_option_context_new (NULL);
599   g_option_context_add_main_entries (context, entries, NULL);
600
601   /* Now try parsing */
602   argv = split_string ("program --test 20.0 --test 30.03", &argc);
603   argv_copy = copy_stringv (argv, argc);
604
605   retval = g_option_context_parse (context, &argc, &argv, &error);
606   g_assert_no_error (error);
607   g_assert (retval);
608
609   /* Last arg specified is the one that should be stored */
610   g_assert (arg_test4_double == 30.03);
611
612   g_strfreev (argv_copy);
613   g_free (argv);
614   g_option_context_free (context);
615 }
616
617 static void
618 arg_test5 (void)
619 {
620   GOptionContext *context;
621   gboolean retval;
622   GError *error = NULL;
623   gchar **argv;
624   gchar **argv_copy;
625   int argc;
626   char *old_locale, *current_locale;
627   const char *locale = "de_DE";
628   GOptionEntry entries [] =
629     { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test5_double, NULL, NULL },
630       { NULL } };
631
632   context = g_option_context_new (NULL);
633   g_option_context_add_main_entries (context, entries, NULL);
634
635   /* Now try parsing */
636   argv = split_string ("program --test 20,0 --test 30,03", &argc);
637   argv_copy = copy_stringv (argv, argc);
638
639   /* set it to some locale that uses commas instead of decimal points */
640   
641   old_locale = g_strdup (setlocale (LC_NUMERIC, locale));
642   current_locale = setlocale (LC_NUMERIC, NULL);
643   if (strcmp (current_locale, locale) != 0)
644     {
645       fprintf (stderr, "Cannot set locale to %s, skipping\n", locale);
646       goto cleanup; 
647     }
648
649   retval = g_option_context_parse (context, &argc, &argv, &error);
650   g_assert_no_error (error);
651   g_assert (retval);
652
653   /* Last arg specified is the one that should be stored */
654   g_assert (arg_test5_double == 30.03);
655
656  cleanup:
657   setlocale (LC_NUMERIC, old_locale);
658   g_free (old_locale);
659
660   g_strfreev (argv_copy);
661   g_free (argv);
662   g_option_context_free (context);
663 }
664
665 static void
666 arg_test6 (void)
667 {
668   GOptionContext *context;
669   gboolean retval;
670   GError *error = NULL;
671   gchar **argv;
672   gchar **argv_copy;
673   int argc;
674   GOptionEntry entries [] =
675     { { "test", 0, 0, G_OPTION_ARG_INT64, &arg_test6_int64, NULL, NULL },
676       { "test2", 0, 0, G_OPTION_ARG_INT64, &arg_test6_int64_2, NULL, NULL },
677       { NULL } };
678
679   context = g_option_context_new (NULL);
680   g_option_context_add_main_entries (context, entries, NULL);
681
682   /* Now try parsing */
683   argv = split_string ("program --test 4294967297 --test 4294967296 --test2 0xfffffffff", &argc);
684   argv_copy = copy_stringv (argv, argc);
685
686   retval = g_option_context_parse (context, &argc, &argv, &error);
687   g_assert_no_error (error);
688   g_assert (retval);
689
690   /* Last arg specified is the one that should be stored */
691   g_assert (arg_test6_int64 == G_GINT64_CONSTANT(4294967296));
692   g_assert (arg_test6_int64_2 == G_GINT64_CONSTANT(0xfffffffff));
693
694   g_strfreev (argv_copy);
695   g_free (argv);
696   g_option_context_free (context);
697 }
698
699 static gboolean
700 callback_parse1 (const gchar *option_name, const gchar *value,
701                  gpointer data, GError **error)
702 {
703         callback_test1_string = g_strdup (value);
704         return TRUE;
705 }
706
707 static void
708 callback_test1 (void)
709 {
710   GOptionContext *context;
711   gboolean retval;
712   GError *error = NULL;
713   gchar **argv;
714   gchar **argv_copy;
715   int argc;
716   GOptionEntry entries [] =
717     { { "test", 0, 0, G_OPTION_ARG_CALLBACK, callback_parse1, NULL, NULL },
718       { NULL } };
719   
720   context = g_option_context_new (NULL);
721   g_option_context_add_main_entries (context, entries, NULL);
722
723   /* Now try parsing */
724   argv = split_string ("program --test foo.txt", &argc);
725   argv_copy = copy_stringv (argv, argc);
726
727   retval = g_option_context_parse (context, &argc, &argv, &error);
728   g_assert_no_error (error);
729   g_assert (retval);
730
731   g_assert (strcmp (callback_test1_string, "foo.txt") == 0);
732
733   g_free (callback_test1_string);
734
735   g_strfreev (argv_copy);
736   g_free (argv);
737   g_option_context_free (context);
738 }
739
740 static gboolean
741 callback_parse2 (const gchar *option_name, const gchar *value,
742                  gpointer data, GError **error)
743 {
744         callback_test2_int++;
745         return TRUE;
746 }
747
748 static void
749 callback_test2 (void)
750 {
751   GOptionContext *context;
752   gboolean retval;
753   GError *error = NULL;
754   gchar **argv;
755   gchar **argv_copy;
756   int argc;
757   GOptionEntry entries [] =
758     { { "test", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_parse2, NULL, NULL },
759       { NULL } };
760   
761   context = g_option_context_new (NULL);
762   g_option_context_add_main_entries (context, entries, NULL);
763
764   /* Now try parsing */
765   argv = split_string ("program --test --test", &argc);
766   argv_copy = copy_stringv (argv, argc);
767
768   retval = g_option_context_parse (context, &argc, &argv, &error);
769   g_assert_no_error (error);
770   g_assert (retval);
771
772   g_assert (callback_test2_int == 2);
773
774   g_strfreev (argv_copy);
775   g_free (argv);
776   g_option_context_free (context);
777 }
778
779 static gboolean
780 callback_parse_optional (const gchar *option_name, const gchar *value,
781                  gpointer data, GError **error)
782 {
783         callback_test_optional_boolean = TRUE;
784         if (value)
785                 callback_test_optional_string = g_strdup (value);
786         else
787                 callback_test_optional_string = NULL;
788         return TRUE;
789 }
790
791 static void
792 callback_test_optional_1 (void)
793 {
794   GOptionContext *context;
795   gboolean retval;
796   GError *error = NULL;
797   gchar **argv;
798   gchar **argv_copy;
799   int argc;
800   GOptionEntry entries [] =
801     { { "test", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
802         callback_parse_optional, NULL, NULL },
803       { NULL } };
804   
805   context = g_option_context_new (NULL);
806   g_option_context_add_main_entries (context, entries, NULL);
807
808   /* Now try parsing */
809   argv = split_string ("program --test foo.txt", &argc);
810   argv_copy = copy_stringv (argv, argc);
811
812   retval = g_option_context_parse (context, &argc, &argv, &error);
813   g_assert_no_error (error);
814   g_assert (retval);
815
816   g_assert (strcmp (callback_test_optional_string, "foo.txt") == 0);
817   
818   g_assert (callback_test_optional_boolean);
819
820   g_free (callback_test_optional_string);
821
822   g_strfreev (argv_copy);
823   g_free (argv);
824   g_option_context_free (context);
825 }
826
827 static void
828 callback_test_optional_2 (void)
829 {
830   GOptionContext *context;
831   gboolean retval;
832   GError *error = NULL;
833   gchar **argv;
834   gchar **argv_copy;
835   int argc;
836   GOptionEntry entries [] =
837     { { "test", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
838         callback_parse_optional, NULL, NULL },
839       { NULL } };
840   
841   context = g_option_context_new (NULL);
842   g_option_context_add_main_entries (context, entries, NULL);
843
844   /* Now try parsing */
845   argv = split_string ("program --test", &argc);
846   argv_copy = copy_stringv (argv, argc);
847
848   retval = g_option_context_parse (context, &argc, &argv, &error);
849   g_assert_no_error (error);
850   g_assert (retval);
851
852   g_assert (callback_test_optional_string == NULL);
853   
854   g_assert (callback_test_optional_boolean);
855
856   g_free (callback_test_optional_string);
857
858   g_strfreev (argv_copy);
859   g_free (argv);
860   g_option_context_free (context);
861 }
862
863 static void
864 callback_test_optional_3 (void)
865 {
866   GOptionContext *context;
867   gboolean retval;
868   GError *error = NULL;
869   gchar **argv_copy;
870   gchar **argv;
871   int argc;
872   GOptionEntry entries [] =
873     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
874         callback_parse_optional, NULL, NULL },
875       { NULL } };
876   
877   context = g_option_context_new (NULL);
878   g_option_context_add_main_entries (context, entries, NULL);
879
880   /* Now try parsing */
881   argv = split_string ("program -t foo.txt", &argc);
882   argv_copy = copy_stringv (argv, argc);
883
884   retval = g_option_context_parse (context, &argc, &argv, &error);
885   g_assert_no_error (error);
886   g_assert (retval);
887
888   g_assert (strcmp (callback_test_optional_string, "foo.txt") == 0);
889   
890   g_assert (callback_test_optional_boolean);
891
892   g_free (callback_test_optional_string);
893
894   g_strfreev (argv_copy);
895   g_free (argv);
896   g_option_context_free (context);
897 }
898
899
900 static void
901 callback_test_optional_4 (void)
902 {
903   GOptionContext *context;
904   gboolean retval;
905   GError *error = NULL;
906   gchar **argv;
907   gchar **argv_copy;
908   int argc;
909   GOptionEntry entries [] =
910     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
911         callback_parse_optional, NULL, NULL },
912       { NULL } };
913   
914   context = g_option_context_new (NULL);
915   g_option_context_add_main_entries (context, entries, NULL);
916
917   /* Now try parsing */
918   argv = split_string ("program -t", &argc);
919   argv_copy = copy_stringv (argv, argc);
920
921   retval = g_option_context_parse (context, &argc, &argv, &error);
922   g_assert_no_error (error);
923   g_assert (retval);
924
925   g_assert (callback_test_optional_string == NULL);
926   
927   g_assert (callback_test_optional_boolean);
928
929   g_free (callback_test_optional_string);
930
931   g_strfreev (argv_copy);
932   g_free (argv);
933   g_option_context_free (context);
934 }
935
936 static void
937 callback_test_optional_5 (void)
938 {
939   GOptionContext *context;
940   gboolean dummy;
941   gboolean retval;
942   GError *error = NULL;
943   gchar **argv;
944   gchar **argv_copy;
945   int argc;
946   GOptionEntry entries [] =
947     { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
948       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
949         callback_parse_optional, NULL, NULL },
950       { NULL } };
951   
952   context = g_option_context_new (NULL);
953   g_option_context_add_main_entries (context, entries, NULL);
954
955   /* Now try parsing */
956   argv = split_string ("program --test --dummy", &argc);
957   argv_copy = copy_stringv (argv, argc);
958
959   retval = g_option_context_parse (context, &argc, &argv, &error);
960   g_assert_no_error (error);
961   g_assert (retval);
962
963   g_assert (callback_test_optional_string == NULL);
964   
965   g_assert (callback_test_optional_boolean);
966
967   g_free (callback_test_optional_string);
968
969   g_strfreev (argv_copy);
970   g_free (argv);
971   g_option_context_free (context);
972 }
973
974 static void
975 callback_test_optional_6 (void)
976 {
977   GOptionContext *context;
978   gboolean dummy;
979   gboolean retval;
980   GError *error = NULL;
981   gchar **argv;
982   gchar **argv_copy;
983   int argc;
984   GOptionEntry entries [] =
985     { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
986       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
987         callback_parse_optional, NULL, NULL },
988       { NULL } };
989   
990   context = g_option_context_new (NULL);
991   g_option_context_add_main_entries (context, entries, NULL);
992
993   /* Now try parsing */
994   argv = split_string ("program -t -d", &argc);
995   argv_copy = copy_stringv (argv, argc);
996
997   retval = g_option_context_parse (context, &argc, &argv, &error);
998   g_assert_no_error (error);
999   g_assert (retval);
1000
1001   g_assert (callback_test_optional_string == NULL);
1002   
1003   g_assert (callback_test_optional_boolean);
1004
1005   g_free (callback_test_optional_string);
1006
1007   g_strfreev (argv_copy);
1008   g_free (argv);
1009   g_option_context_free (context);
1010 }
1011
1012 static void
1013 callback_test_optional_7 (void)
1014 {
1015   GOptionContext *context;
1016   gboolean dummy;
1017   gboolean retval;
1018   GError *error = NULL;
1019   gchar **argv;
1020   gchar **argv_copy;
1021   int argc;
1022   GOptionEntry entries [] =
1023     { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
1024       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
1025         callback_parse_optional, NULL, NULL },
1026       { NULL } };
1027   
1028   context = g_option_context_new (NULL);
1029   g_option_context_add_main_entries (context, entries, NULL);
1030
1031   /* Now try parsing */
1032   argv = split_string ("program -td", &argc);
1033   argv_copy = copy_stringv (argv, argc);
1034
1035   retval = g_option_context_parse (context, &argc, &argv, &error);
1036   g_assert_no_error (error);
1037   g_assert (retval);
1038
1039   g_assert (callback_test_optional_string == NULL);
1040   
1041   g_assert (callback_test_optional_boolean);
1042
1043   g_free (callback_test_optional_string);
1044
1045   g_strfreev (argv_copy);
1046   g_free (argv);
1047   g_option_context_free (context);
1048 }
1049
1050 static void
1051 callback_test_optional_8 (void)
1052 {
1053   GOptionContext *context;
1054   gboolean dummy;
1055   gboolean retval;
1056   GError *error = NULL;
1057   gchar **argv;
1058   gchar **argv_copy;
1059   int argc;
1060   GOptionEntry entries [] =
1061     { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
1062       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
1063         callback_parse_optional, NULL, NULL },
1064       { NULL } };
1065   
1066   context = g_option_context_new (NULL);
1067   g_option_context_add_main_entries (context, entries, NULL);
1068
1069   /* Now try parsing */
1070   argv = split_string ("program -dt foo.txt", &argc);
1071   argv_copy = copy_stringv (argv, argc);
1072
1073   retval = g_option_context_parse (context, &argc, &argv, &error);
1074   g_assert_no_error (error);
1075   g_assert (retval);
1076
1077   g_assert (callback_test_optional_string);
1078   
1079   g_assert (callback_test_optional_boolean);
1080
1081   g_free (callback_test_optional_string);
1082
1083   g_strfreev (argv_copy);
1084   g_free (argv);
1085   g_option_context_free (context);
1086 }
1087
1088 static GPtrArray *callback_remaining_args;
1089 static gboolean
1090 callback_remaining_test1_callback (const gchar *option_name, const gchar *value,
1091                          gpointer data, GError **error)
1092 {
1093         g_ptr_array_add (callback_remaining_args, g_strdup (value));
1094         return TRUE;
1095 }
1096
1097 static void
1098 callback_remaining_test1 (void)
1099 {
1100   GOptionContext *context;
1101   gboolean retval;
1102   GError *error = NULL;
1103   gchar **argv;
1104   gchar **argv_copy;
1105   int argc;
1106   GOptionEntry entries [] =
1107     { { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_CALLBACK, callback_remaining_test1_callback, NULL, NULL },
1108       { NULL } };
1109   
1110   callback_remaining_args = g_ptr_array_new ();
1111   context = g_option_context_new (NULL);
1112   g_option_context_add_main_entries (context, entries, NULL);
1113
1114   /* Now try parsing */
1115   argv = split_string ("program foo.txt blah.txt", &argc);
1116   argv_copy = copy_stringv (argv, argc);
1117
1118   retval = g_option_context_parse (context, &argc, &argv, &error);
1119   g_assert_no_error (error);
1120   g_assert (retval);
1121
1122   g_assert (callback_remaining_args->len == 2);
1123   g_assert (strcmp (callback_remaining_args->pdata[0], "foo.txt") == 0);
1124   g_assert (strcmp (callback_remaining_args->pdata[1], "blah.txt") == 0);
1125
1126   g_ptr_array_foreach (callback_remaining_args, (GFunc) g_free, NULL);
1127   g_ptr_array_free (callback_remaining_args, TRUE);
1128
1129   g_strfreev (argv_copy);
1130   g_free (argv);
1131   g_option_context_free (context);
1132 }
1133
1134 static gboolean
1135 callback_error (const gchar *option_name, const gchar *value,
1136                 gpointer data, GError **error)
1137 {
1138   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "42");
1139   return FALSE;
1140 }
1141
1142 static void
1143 callback_returns_false (void)
1144 {
1145   GOptionContext *context;
1146   gboolean retval;
1147   GError *error = NULL;
1148   gchar **argv;
1149   gchar **argv_copy;
1150   int argc;
1151   GOptionEntry entries [] =
1152     { { "error", 0, 0, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
1153       { "error-no-arg", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
1154       { "error-optional-arg", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
1155       { NULL } };
1156
1157   context = g_option_context_new (NULL);
1158   g_option_context_add_main_entries (context, entries, NULL);
1159
1160   /* Now try parsing */
1161   argv = split_string ("program --error value", &argc);
1162   argv_copy = copy_stringv (argv, argc);
1163
1164   retval = g_option_context_parse (context, &argc, &argv, &error);
1165   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
1166   g_assert (retval == FALSE);
1167   check_identical_stringv (argv_copy, argv);
1168
1169   g_option_context_free (context);
1170   g_clear_error (&error);
1171   g_strfreev (argv_copy);
1172   g_free (argv);
1173
1174   /* And again, this time with a no-arg variant */
1175   context = g_option_context_new (NULL);
1176   g_option_context_add_main_entries (context, entries, NULL);
1177
1178   argv = split_string ("program --error-no-arg", &argc);
1179   argv_copy = copy_stringv (argv, argc);
1180
1181   retval = g_option_context_parse (context, &argc, &argv, &error);
1182   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
1183   g_assert (retval == FALSE);
1184   check_identical_stringv (argv_copy, argv);
1185
1186   g_option_context_free (context);
1187   g_clear_error (&error);
1188   g_strfreev (argv_copy);
1189   g_free (argv);
1190
1191   /* And again, this time with a optional arg variant, with argument */
1192   context = g_option_context_new (NULL);
1193   g_option_context_add_main_entries (context, entries, NULL);
1194
1195   argv = split_string ("program --error-optional-arg value", &argc);
1196   argv_copy = copy_stringv (argv, argc);
1197
1198   retval = g_option_context_parse (context, &argc, &argv, &error);
1199   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
1200   g_assert (retval == FALSE);
1201   check_identical_stringv (argv_copy, argv);
1202
1203   g_option_context_free (context);
1204   g_clear_error (&error);
1205   g_strfreev (argv_copy);
1206   g_free (argv);
1207
1208   /* And again, this time with a optional arg variant, without argument */
1209   context = g_option_context_new (NULL);
1210   g_option_context_add_main_entries (context, entries, NULL);
1211
1212   argv = split_string ("program --error-optional-arg", &argc);
1213   argv_copy = copy_stringv (argv, argc);
1214
1215   retval = g_option_context_parse (context, &argc, &argv, &error);
1216   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
1217   g_assert (retval == FALSE);
1218   check_identical_stringv (argv_copy, argv);
1219
1220   g_option_context_free (context);
1221   g_clear_error (&error);
1222   g_strfreev (argv_copy);
1223   g_free (argv);
1224 }
1225
1226
1227 static void
1228 ignore_test1 (void)
1229 {
1230   GOptionContext *context;
1231   gboolean retval;
1232   GError *error = NULL;
1233   gchar **argv, **argv_copy;
1234   int argc;
1235   gchar *arg;
1236   GOptionEntry entries [] =
1237     { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1238       { NULL } };
1239
1240   context = g_option_context_new (NULL);
1241   g_option_context_set_ignore_unknown_options (context, TRUE);
1242   g_option_context_add_main_entries (context, entries, NULL);
1243
1244   /* Now try parsing */
1245   argv = split_string ("program --test --hello", &argc);
1246   argv_copy = copy_stringv (argv, argc);
1247   
1248   retval = g_option_context_parse (context, &argc, &argv, &error);
1249   g_assert_no_error (error);
1250   g_assert (retval);
1251
1252   /* Check array */
1253   arg = join_stringv (argc, argv);
1254   g_assert (strcmp (arg, "program --hello") == 0);
1255
1256   g_free (arg);
1257   g_strfreev (argv_copy);
1258   g_free (argv);
1259   g_option_context_free (context);
1260 }
1261
1262 static void
1263 ignore_test2 (void)
1264 {
1265   GOptionContext *context;
1266   gboolean retval;
1267   GError *error = NULL;
1268   gchar **argv;
1269   gchar **argv_copy;
1270   int argc;
1271   gchar *arg;
1272   GOptionEntry entries [] =
1273     { { "test", 't', 0, G_OPTION_ARG_NONE, &ignore_test2_boolean, NULL, NULL },
1274       { NULL } };
1275
1276   context = g_option_context_new (NULL);
1277   g_option_context_set_ignore_unknown_options (context, TRUE);
1278   g_option_context_add_main_entries (context, entries, NULL);
1279
1280   /* Now try parsing */
1281   argv = split_string ("program -test", &argc);
1282   argv_copy = copy_stringv (argv, argc);
1283
1284   retval = g_option_context_parse (context, &argc, &argv, &error);
1285   g_assert_no_error (error);
1286   g_assert (retval);
1287
1288   /* Check array */
1289   arg = join_stringv (argc, argv);
1290   g_assert (strcmp (arg, "program -es") == 0);
1291
1292   g_free (arg);
1293   g_strfreev (argv_copy);
1294   g_free (argv);
1295   g_option_context_free (context);
1296 }
1297
1298 static void
1299 ignore_test3 (void)
1300 {
1301   GOptionContext *context;
1302   gboolean retval;
1303   GError *error = NULL;
1304   gchar **argv, **argv_copy;
1305   int argc;
1306   gchar *arg;
1307   GOptionEntry entries [] =
1308     { { "test", 0, 0, G_OPTION_ARG_STRING, &ignore_test3_string, NULL, NULL },
1309       { NULL } };
1310
1311   context = g_option_context_new (NULL);
1312   g_option_context_set_ignore_unknown_options (context, TRUE);
1313   g_option_context_add_main_entries (context, entries, NULL);
1314
1315   /* Now try parsing */
1316   argv = split_string ("program --test foo --hello", &argc);
1317   argv_copy = copy_stringv (argv, argc);
1318   
1319   retval = g_option_context_parse (context, &argc, &argv, &error);
1320   g_assert_no_error (error);
1321   g_assert (retval);
1322
1323   /* Check array */
1324   arg = join_stringv (argc, argv);
1325   g_assert (strcmp (arg, "program --hello") == 0);
1326
1327   g_assert (strcmp (ignore_test3_string, "foo") == 0);
1328   g_free (ignore_test3_string);
1329
1330   g_free (arg);
1331   g_strfreev (argv_copy);
1332   g_free (argv);
1333   g_option_context_free (context);
1334 }
1335
1336 void
1337 static array_test1 (void)
1338 {
1339   GOptionContext *context;
1340   gboolean retval;
1341   GError *error = NULL;
1342   gchar **argv;
1343   gchar **argv_copy;
1344   int argc;
1345   GOptionEntry entries [] =
1346     { { "test", 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
1347       { NULL } };
1348         
1349   context = g_option_context_new (NULL);
1350   g_option_context_add_main_entries (context, entries, NULL);
1351
1352   /* Now try parsing */
1353   argv = split_string ("program --test foo --test bar", &argc);
1354   argv_copy = copy_stringv (argv, argc);
1355
1356   retval = g_option_context_parse (context, &argc, &argv, &error);
1357   g_assert_no_error (error);
1358   g_assert (retval);
1359
1360   /* Check array */
1361   g_assert (strcmp (array_test1_array[0], "foo") == 0);
1362   g_assert (strcmp (array_test1_array[1], "bar") == 0);
1363   g_assert (array_test1_array[2] == NULL);
1364
1365   g_strfreev (array_test1_array);
1366   
1367   g_strfreev (argv_copy);
1368   g_free (argv);
1369   g_option_context_free (context);
1370 }
1371
1372 static void
1373 add_test1 (void)
1374 {
1375   GOptionContext *context;
1376
1377   GOptionEntry entries1 [] =
1378     { { "test1", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL },
1379       { NULL } };
1380   GOptionEntry entries2 [] =
1381     { { "test2", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL },
1382       { NULL } };
1383
1384   context = g_option_context_new (NULL);
1385   g_option_context_add_main_entries (context, entries1, NULL);
1386   g_option_context_add_main_entries (context, entries2, NULL);
1387
1388   g_option_context_free (context);
1389 }
1390
1391 static void
1392 empty_test2 (void)
1393 {
1394   GOptionContext *context;
1395
1396   context = g_option_context_new (NULL);
1397   g_option_context_parse (context, NULL, NULL, NULL);
1398   
1399   g_option_context_free (context);
1400 }
1401
1402 static void
1403 empty_test3 (void)
1404 {
1405   GOptionContext *context;
1406   gint argc;
1407   gchar **argv;
1408
1409   argc = 0;
1410   argv = NULL;
1411
1412   context = g_option_context_new (NULL);
1413   g_option_context_parse (context, &argc, &argv, NULL);
1414   
1415   g_option_context_free (context);
1416 }
1417
1418 /* check that non-option arguments are left in argv by default */
1419 static void
1420 rest_test1 (void)
1421 {
1422   GOptionContext *context;
1423   gboolean retval;
1424   GError *error = NULL;
1425   gchar **argv;
1426   gchar **argv_copy;
1427   int argc;
1428   GOptionEntry entries [] = { 
1429       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1430       { NULL } 
1431   };
1432         
1433   context = g_option_context_new (NULL);
1434   g_option_context_add_main_entries (context, entries, NULL);
1435
1436   /* Now try parsing */
1437   argv = split_string ("program foo --test bar", &argc);
1438   argv_copy = copy_stringv (argv, argc);
1439
1440   retval = g_option_context_parse (context, &argc, &argv, &error);
1441   g_assert_no_error (error);
1442   g_assert (retval);
1443
1444   /* Check array */
1445   g_assert (ignore_test1_boolean);
1446   g_assert (strcmp (argv[0], "program") == 0);
1447   g_assert (strcmp (argv[1], "foo") == 0);
1448   g_assert (strcmp (argv[2], "bar") == 0);
1449   g_assert (argv[3] == NULL);
1450
1451   g_strfreev (argv_copy);
1452   g_free (argv);
1453   g_option_context_free (context);
1454 }
1455
1456 /* check that -- works */
1457 static void
1458 rest_test2 (void)
1459 {
1460   GOptionContext *context;
1461   gboolean retval;
1462   GError *error = NULL;
1463   gchar **argv;
1464   gchar **argv_copy;
1465   int argc;
1466   GOptionEntry entries [] = { 
1467       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1468       { NULL } 
1469   };
1470         
1471   context = g_option_context_new (NULL);
1472   g_option_context_add_main_entries (context, entries, NULL);
1473
1474   /* Now try parsing */
1475   argv = split_string ("program foo --test -- -bar", &argc);
1476   argv_copy = copy_stringv (argv, argc);
1477
1478   retval = g_option_context_parse (context, &argc, &argv, &error);
1479   g_assert_no_error (error);
1480   g_assert (retval);
1481
1482   /* Check array */
1483   g_assert (ignore_test1_boolean);
1484   g_assert (strcmp (argv[0], "program") == 0);
1485   g_assert (strcmp (argv[1], "foo") == 0);
1486   g_assert (strcmp (argv[2], "--") == 0);
1487   g_assert (strcmp (argv[3], "-bar") == 0);
1488   g_assert (argv[4] == NULL);
1489
1490   g_strfreev (argv_copy);
1491   g_free (argv);
1492   g_option_context_free (context);
1493 }
1494
1495 /* check that -- stripping works */
1496 static void
1497 rest_test2a (void)
1498 {
1499   GOptionContext *context;
1500   gboolean retval;
1501   GError *error = NULL;
1502   gchar **argv;
1503   gchar **argv_copy;
1504   int argc;
1505   GOptionEntry entries [] = { 
1506       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1507       { NULL } 
1508   };
1509         
1510   context = g_option_context_new (NULL);
1511   g_option_context_add_main_entries (context, entries, NULL);
1512
1513   /* Now try parsing */
1514   argv = split_string ("program foo --test -- bar", &argc);
1515   argv_copy = copy_stringv (argv, argc);
1516
1517   retval = g_option_context_parse (context, &argc, &argv, &error);
1518   g_assert_no_error (error);
1519   g_assert (retval);
1520
1521   /* Check array */
1522   g_assert (ignore_test1_boolean);
1523   g_assert (strcmp (argv[0], "program") == 0);
1524   g_assert (strcmp (argv[1], "foo") == 0);
1525   g_assert (strcmp (argv[2], "bar") == 0);
1526   g_assert (argv[3] == NULL);
1527
1528   g_strfreev (argv_copy);
1529   g_free (argv);
1530   g_option_context_free (context);
1531 }
1532
1533 static void
1534 rest_test2b (void)
1535 {
1536   GOptionContext *context;
1537   gboolean retval;
1538   GError *error = NULL;
1539   gchar **argv;
1540   gchar **argv_copy;
1541   int argc;
1542   GOptionEntry entries [] = { 
1543       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1544       { NULL } 
1545   };
1546         
1547   context = g_option_context_new (NULL);
1548   g_option_context_set_ignore_unknown_options (context, TRUE);
1549   g_option_context_add_main_entries (context, entries, NULL);
1550
1551   /* Now try parsing */
1552   argv = split_string ("program foo --test -bar --", &argc);
1553   argv_copy = copy_stringv (argv, argc);
1554
1555   retval = g_option_context_parse (context, &argc, &argv, &error);
1556   g_assert_no_error (error);
1557   g_assert (retval);
1558
1559   /* Check array */
1560   g_assert (ignore_test1_boolean);
1561   g_assert (strcmp (argv[0], "program") == 0);
1562   g_assert (strcmp (argv[1], "foo") == 0);
1563   g_assert (strcmp (argv[2], "-bar") == 0);
1564   g_assert (argv[3] == NULL);
1565
1566   g_strfreev (argv_copy);
1567   g_free (argv);
1568   g_option_context_free (context);
1569 }
1570
1571 static void
1572 rest_test2c (void)
1573 {
1574   GOptionContext *context;
1575   gboolean retval;
1576   GError *error = NULL;
1577   gchar **argv;
1578   gchar **argv_copy;
1579   int argc;
1580   GOptionEntry entries [] = { 
1581       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1582       { NULL } 
1583   };
1584         
1585   context = g_option_context_new (NULL);
1586   g_option_context_add_main_entries (context, entries, NULL);
1587
1588   /* Now try parsing */
1589   argv = split_string ("program --test foo -- bar", &argc);
1590   argv_copy = copy_stringv (argv, argc);
1591
1592   retval = g_option_context_parse (context, &argc, &argv, &error);
1593   g_assert_no_error (error);
1594   g_assert (retval);
1595
1596   /* Check array */
1597   g_assert (ignore_test1_boolean);
1598   g_assert (strcmp (argv[0], "program") == 0);
1599   g_assert (strcmp (argv[1], "foo") == 0);
1600   g_assert (strcmp (argv[2], "bar") == 0);
1601   g_assert (argv[3] == NULL);
1602
1603   g_strfreev (argv_copy);
1604   g_free (argv);
1605   g_option_context_free (context);
1606 }
1607
1608 static void
1609 rest_test2d (void)
1610 {
1611   GOptionContext *context;
1612   gboolean retval;
1613   GError *error = NULL;
1614   gchar **argv;
1615   gchar **argv_copy;
1616   int argc;
1617   GOptionEntry entries [] = { 
1618       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1619       { NULL } 
1620   };
1621         
1622   context = g_option_context_new (NULL);
1623   g_option_context_add_main_entries (context, entries, NULL);
1624
1625   /* Now try parsing */
1626   argv = split_string ("program --test -- -bar", &argc);
1627   argv_copy = copy_stringv (argv, argc);
1628
1629   retval = g_option_context_parse (context, &argc, &argv, &error);
1630   g_assert_no_error (error);
1631   g_assert (retval);
1632
1633   /* Check array */
1634   g_assert (ignore_test1_boolean);
1635   g_assert (strcmp (argv[0], "program") == 0);
1636   g_assert (strcmp (argv[1], "--") == 0);
1637   g_assert (strcmp (argv[2], "-bar") == 0);
1638   g_assert (argv[3] == NULL);
1639
1640   g_strfreev (argv_copy);
1641   g_free (argv);
1642   g_option_context_free (context);
1643 }
1644
1645
1646 /* check that G_OPTION_REMAINING collects non-option arguments */
1647 static void
1648 rest_test3 (void)
1649 {
1650   GOptionContext *context;
1651   gboolean retval;
1652   GError *error = NULL;
1653   gchar **argv;
1654   gchar **argv_copy;
1655   int argc;
1656   GOptionEntry entries [] = { 
1657       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1658       { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
1659       { NULL } 
1660   };
1661         
1662   context = g_option_context_new (NULL);
1663   g_option_context_add_main_entries (context, entries, NULL);
1664
1665   /* Now try parsing */
1666   argv = split_string ("program foo --test bar", &argc);
1667   argv_copy = copy_stringv (argv, argc);
1668
1669   retval = g_option_context_parse (context, &argc, &argv, &error);
1670   g_assert_no_error (error);
1671   g_assert (retval);
1672
1673   /* Check array */
1674   g_assert (ignore_test1_boolean);
1675   g_assert (strcmp (array_test1_array[0], "foo") == 0);
1676   g_assert (strcmp (array_test1_array[1], "bar") == 0);
1677   g_assert (array_test1_array[2] == NULL);
1678
1679   g_strfreev (array_test1_array);
1680
1681   g_strfreev (argv_copy);
1682   g_free (argv);
1683   g_option_context_free (context);
1684 }
1685
1686
1687 /* check that G_OPTION_REMAINING and -- work together */
1688 static void
1689 rest_test4 (void)
1690 {
1691   GOptionContext *context;
1692   gboolean retval;
1693   GError *error = NULL;
1694   gchar **argv;
1695   gchar **argv_copy;
1696   int argc;
1697   GOptionEntry entries [] = { 
1698       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1699       { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
1700       { NULL } 
1701   };
1702         
1703   context = g_option_context_new (NULL);
1704   g_option_context_add_main_entries (context, entries, NULL);
1705
1706   /* Now try parsing */
1707   argv = split_string ("program foo --test -- -bar", &argc);
1708   argv_copy = copy_stringv (argv, argc);
1709
1710   retval = g_option_context_parse (context, &argc, &argv, &error);
1711   g_assert_no_error (error);
1712   g_assert (retval);
1713
1714   /* Check array */
1715   g_assert (ignore_test1_boolean);
1716   g_assert (strcmp (array_test1_array[0], "foo") == 0);
1717   g_assert (strcmp (array_test1_array[1], "-bar") == 0);
1718   g_assert (array_test1_array[2] == NULL);
1719
1720   g_strfreev (array_test1_array);
1721
1722   g_strfreev (argv_copy);
1723   g_free (argv);
1724   g_option_context_free (context);
1725 }
1726
1727 /* test that G_OPTION_REMAINING works with G_OPTION_ARG_FILENAME_ARRAY */
1728 static void
1729 rest_test5 (void)
1730 {
1731   GOptionContext *context;
1732   gboolean retval;
1733   GError *error = NULL;
1734   gchar **argv;
1735   gchar **argv_copy;
1736   int argc;
1737   GOptionEntry entries [] = { 
1738       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1739       { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &array_test1_array, NULL, NULL },
1740       { NULL } 
1741   };
1742         
1743   context = g_option_context_new (NULL);
1744   g_option_context_add_main_entries (context, entries, NULL);
1745
1746   /* Now try parsing */
1747   argv = split_string ("program foo --test bar", &argc);
1748   argv_copy = copy_stringv (argv, argc);
1749
1750   retval = g_option_context_parse (context, &argc, &argv, &error);
1751   g_assert_no_error (error);
1752   g_assert (retval);
1753
1754   /* Check array */
1755   g_assert (ignore_test1_boolean);
1756   g_assert (strcmp (array_test1_array[0], "foo") == 0);
1757   g_assert (strcmp (array_test1_array[1], "bar") == 0);
1758   g_assert (array_test1_array[2] == NULL);
1759
1760   g_strfreev (array_test1_array);
1761
1762   g_strfreev (argv_copy);
1763   g_free (argv);
1764   g_option_context_free (context);
1765 }
1766
1767 static void
1768 unknown_short_test (void)
1769 {
1770   GOptionContext *context;
1771   gboolean retval;
1772   GError *error = NULL;
1773   gchar **argv;
1774   gchar **argv_copy;
1775   int argc;
1776   GOptionEntry entries [] = { { NULL } };
1777
1778   g_test_bug ("166609");
1779
1780   context = g_option_context_new (NULL);
1781   g_option_context_add_main_entries (context, entries, NULL);
1782
1783   /* Now try parsing */
1784   argv = split_string ("program -0", &argc);
1785   argv_copy = copy_stringv (argv, argc);
1786
1787   retval = g_option_context_parse (context, &argc, &argv, &error);
1788   g_assert (!retval);
1789   g_assert (error != NULL);
1790   g_clear_error (&error);
1791
1792   g_strfreev (argv_copy);
1793   g_free (argv);
1794   g_option_context_free (context);
1795 }
1796
1797 /* test that lone dashes are treated as non-options */
1798 static void
1799 lonely_dash_test (void)
1800 {
1801   GOptionContext *context;
1802   gboolean retval;
1803   GError *error = NULL;
1804   gchar **argv;
1805   gchar **argv_copy;
1806   int argc;
1807
1808   g_test_bug ("168008");
1809
1810   context = g_option_context_new (NULL);
1811
1812   /* Now try parsing */
1813   argv = split_string ("program -", &argc);
1814   argv_copy = copy_stringv (argv, argc);
1815
1816   retval = g_option_context_parse (context, &argc, &argv, &error);
1817   g_assert_no_error (error);
1818   g_assert (retval);
1819
1820   g_assert (argv[1] && strcmp (argv[1], "-") == 0);
1821
1822   g_strfreev (argv_copy);
1823   g_free (argv);
1824   g_option_context_free (context);
1825 }
1826
1827 static void
1828 missing_arg_test (void)
1829 {
1830   GOptionContext *context;
1831   gboolean retval;
1832   GError *error = NULL;
1833   gchar **argv;
1834   gchar **argv_copy;
1835   int argc;
1836   gchar *arg = NULL;
1837   GOptionEntry entries [] =
1838     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
1839       { NULL } };
1840
1841   g_test_bug ("305576");
1842
1843   context = g_option_context_new (NULL);
1844   g_option_context_add_main_entries (context, entries, NULL);
1845
1846   /* Now try parsing */
1847   argv = split_string ("program --test", &argc);
1848   argv_copy = copy_stringv (argv, argc);
1849
1850   retval = g_option_context_parse (context, &argc, &argv, &error);
1851   g_assert (retval == FALSE);
1852   g_assert (error != NULL);
1853   /* An error occurred, so argv has not been changed */
1854   check_identical_stringv (argv_copy, argv);
1855   g_clear_error (&error);
1856
1857   g_strfreev (argv_copy);
1858   g_free (argv);
1859
1860   /* Try parsing again */
1861   argv = split_string ("program -t", &argc);
1862   argv_copy = copy_stringv (argv, argc);
1863
1864   retval = g_option_context_parse (context, &argc, &argv, &error);
1865   g_assert (retval == FALSE);
1866   g_assert (error != NULL);
1867   /* An error occurred, so argv has not been changed */
1868   check_identical_stringv (argv_copy, argv);
1869   g_clear_error (&error);
1870
1871   g_strfreev (argv_copy);
1872   g_free (argv);
1873   g_option_context_free (context);
1874 }
1875
1876 static gchar *test_arg;
1877
1878 static gboolean cb (const gchar  *option_name,
1879                     const gchar  *value,
1880                     gpointer      data,
1881                     GError      **error)
1882 {
1883   test_arg = g_strdup (value);
1884   return TRUE;
1885 }
1886
1887 static void
1888 dash_arg_test (void)
1889 {
1890   GOptionContext *context;
1891   gboolean retval;
1892   GError *error = NULL;
1893   gchar **argv;
1894   gchar **argv_copy;
1895   int argc;
1896   gboolean argb = FALSE;
1897   GOptionEntry entries [] =
1898     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, cb, NULL, NULL },
1899       { "three", '3', 0, G_OPTION_ARG_NONE, &argb, NULL, NULL },
1900       { NULL } };
1901
1902   g_test_bug ("577638");
1903
1904   context = g_option_context_new (NULL);
1905   g_option_context_add_main_entries (context, entries, NULL);
1906
1907   /* Now try parsing */
1908   argv = split_string ("program --test=-3", &argc);
1909   argv_copy = copy_stringv (argv, argc);
1910
1911   test_arg = NULL;
1912   error = NULL;
1913   retval = g_option_context_parse (context, &argc, &argv, &error);
1914   g_assert (retval);
1915   g_assert_no_error (error);
1916   g_assert_cmpstr (test_arg, ==, "-3");
1917
1918   g_strfreev (argv_copy);
1919   g_free (argv);
1920   g_free (test_arg);
1921   test_arg = NULL;
1922
1923   /* Try parsing again */
1924   argv = split_string ("program --test -3", &argc);
1925   argv_copy = copy_stringv (argv, argc);
1926
1927   error = NULL;
1928   retval = g_option_context_parse (context, &argc, &argv, &error);
1929   g_assert_no_error (error);
1930   g_assert (retval);
1931   g_assert_cmpstr (test_arg, ==, NULL);
1932
1933   g_option_context_free (context);
1934   g_strfreev (argv_copy);
1935   g_free (argv);
1936 }
1937
1938 static void
1939 test_basic (void)
1940 {
1941   GOptionContext *context;
1942   gchar *arg = NULL;
1943   GOptionEntry entries [] =
1944     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
1945       { NULL } };
1946
1947   context = g_option_context_new (NULL);
1948   g_option_context_add_main_entries (context, entries, NULL);
1949
1950   g_assert (g_option_context_get_help_enabled (context));
1951   g_assert (!g_option_context_get_ignore_unknown_options (context));
1952   g_assert_cmpstr (g_option_context_get_summary (context), ==, NULL);
1953   g_assert_cmpstr (g_option_context_get_description (context), ==, NULL);
1954
1955   g_option_context_set_help_enabled (context, FALSE);
1956   g_option_context_set_ignore_unknown_options (context, TRUE);
1957   g_option_context_set_summary (context, "summary");
1958   g_option_context_set_description(context, "description");
1959
1960   g_assert (!g_option_context_get_help_enabled (context));
1961   g_assert (g_option_context_get_ignore_unknown_options (context));
1962   g_assert_cmpstr (g_option_context_get_summary (context), ==, "summary");
1963   g_assert_cmpstr (g_option_context_get_description (context), ==, "description");
1964
1965   g_option_context_free (context);
1966 }
1967
1968 typedef struct {
1969   gboolean parameter_seen;
1970   gboolean summary_seen;
1971   gboolean description_seen;
1972   gboolean destroyed;
1973 } TranslateData;
1974
1975 static const gchar *
1976 translate_func (const gchar *str,
1977                 gpointer     data)
1978 {
1979   TranslateData *d = data;
1980
1981   if (strcmp (str, "parameter") == 0)
1982     d->parameter_seen = TRUE;
1983   else if (strcmp (str, "summary") == 0)
1984     d->summary_seen = TRUE;
1985   else if (strcmp (str, "description") == 0)
1986     d->description_seen = TRUE;
1987   
1988   return str;
1989 }
1990
1991 static void
1992 destroy_notify (gpointer data)
1993 {
1994   TranslateData *d = data;
1995
1996   d->destroyed = TRUE;
1997 }
1998
1999 static void
2000 test_translate (void)
2001 {
2002   GOptionContext *context;
2003   gchar *arg = NULL;
2004   GOptionEntry entries [] =
2005     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
2006       { NULL } };
2007   TranslateData data = { 0, };
2008   gchar *str;
2009
2010   context = g_option_context_new ("parameter");
2011   g_option_context_add_main_entries (context, entries, NULL);
2012   g_option_context_set_summary (context, "summary");
2013   g_option_context_set_description (context, "description");
2014
2015   g_option_context_set_translate_func (context, translate_func, &data, destroy_notify);
2016   
2017   str = g_option_context_get_help (context, FALSE, NULL);
2018   g_free (str);
2019   g_option_context_free (context);
2020
2021   g_assert (data.parameter_seen);
2022   g_assert (data.summary_seen);
2023   g_assert (data.description_seen);
2024   g_assert (data.destroyed);
2025 }
2026
2027 static void
2028 test_help (void)
2029 {
2030   GOptionContext *context;
2031   GOptionGroup *group;
2032   gchar *str;
2033   gchar *arg = NULL;
2034   gchar **sarr = NULL;
2035   GOptionEntry entries[] = {
2036     { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Test tests", "Argument to use in test" },
2037     { "test2", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, NULL, "Tests also", NULL },
2038     { "frob", 0, 0, G_OPTION_ARG_NONE, NULL, "Main frob", NULL },
2039     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" },
2040     { NULL }
2041   };
2042   GOptionEntry group_entries[] = {
2043     { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Group test", "Group test arg" },
2044     { "frob", 0, G_OPTION_FLAG_NOALIAS, G_OPTION_ARG_NONE, NULL, "Group frob", NULL },
2045     { NULL }
2046   };
2047
2048   context = g_option_context_new ("blabla");
2049   g_option_context_add_main_entries (context, entries, NULL);
2050   g_option_context_set_summary (context, "Summary");
2051   g_option_context_set_description (context, "Description");
2052
2053   group = g_option_group_new ("group1", "Group1-description", "Group1-help", NULL, NULL);
2054   g_option_group_add_entries (group, group_entries);
2055
2056   g_option_context_add_group (context, group);
2057
2058   str = g_option_context_get_help (context, FALSE, NULL);
2059   g_assert (strstr (str, "blabla") != NULL);
2060   g_assert (strstr (str, "Test tests") != NULL);
2061   g_assert (strstr (str, "Argument to use in test") != NULL);
2062   g_assert (strstr (str, "Tests also") == NULL);
2063   g_assert (strstr (str, "REST") != NULL);
2064   g_assert (strstr (str, "Summary") != NULL);
2065   g_assert (strstr (str, "Description") != NULL);
2066   g_assert (strstr (str, "--help") != NULL);
2067   g_assert (strstr (str, "--help-all") != NULL);
2068   g_assert (strstr (str, "--help-group1") != NULL);
2069   g_assert (strstr (str, "Group1-description") != NULL);
2070   g_assert (strstr (str, "Group1-help") != NULL);
2071   g_assert (strstr (str, "Group test arg") != NULL);
2072   g_assert (strstr (str, "Group frob") != NULL);
2073   g_assert (strstr (str, "Main frob") != NULL);
2074   g_assert (strstr (str, "--frob") != NULL);
2075   g_assert (strstr (str, "--group1-test") != NULL);
2076   g_assert (strstr (str, "--group1-frob") == NULL);
2077   g_free (str);
2078
2079   g_option_context_free (context);
2080 }
2081
2082 static void
2083 test_help_no_options (void)
2084 {
2085   GOptionContext *context;
2086   gchar **sarr = NULL;
2087   GOptionEntry entries[] = {
2088     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" },
2089     { NULL }
2090   };
2091   gchar *str;
2092
2093   context = g_option_context_new ("blabla");
2094   g_option_context_add_main_entries (context, entries, NULL);
2095
2096   str = g_option_context_get_help (context, FALSE, NULL);
2097   g_assert (strstr (str, "blabla") != NULL);
2098   g_assert (strstr (str, "REST") != NULL);
2099   g_assert (strstr (str, "Help Options") != NULL);
2100   g_assert (strstr (str, "Application Options") == NULL);
2101
2102   g_free (str);
2103   g_option_context_free (context);
2104 }
2105
2106 static void
2107 test_help_no_help_options (void)
2108 {
2109   GOptionContext *context;
2110   GOptionGroup *group;
2111   gchar *str;
2112   gchar *arg = NULL;
2113   gchar **sarr = NULL;
2114   GOptionEntry entries[] = {
2115     { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Test tests", "Argument to use in test" },
2116     { "test2", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, NULL, "Tests also", NULL },
2117     { "frob", 0, 0, G_OPTION_ARG_NONE, NULL, "Main frob", NULL },
2118     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" },
2119     { NULL }
2120   };
2121   GOptionEntry group_entries[] = {
2122     { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Group test", "Group test arg" },
2123     { "frob", 0, G_OPTION_FLAG_NOALIAS, G_OPTION_ARG_NONE, NULL, "Group frob", NULL },
2124     { NULL }
2125   };
2126
2127   g_test_bug ("697652");
2128
2129   context = g_option_context_new ("blabla");
2130   g_option_context_add_main_entries (context, entries, NULL);
2131   g_option_context_set_summary (context, "Summary");
2132   g_option_context_set_description (context, "Description");
2133   g_option_context_set_help_enabled (context, FALSE);
2134
2135   group = g_option_group_new ("group1", "Group1-description", "Group1-help", NULL, NULL);
2136   g_option_group_add_entries (group, group_entries);
2137
2138   g_option_context_add_group (context, group);
2139
2140   str = g_option_context_get_help (context, FALSE, NULL);
2141   g_assert (strstr (str, "blabla") != NULL);
2142   g_assert (strstr (str, "Test tests") != NULL);
2143   g_assert (strstr (str, "Argument to use in test") != NULL);
2144   g_assert (strstr (str, "Tests also") == NULL);
2145   g_assert (strstr (str, "REST") != NULL);
2146   g_assert (strstr (str, "Summary") != NULL);
2147   g_assert (strstr (str, "Description") != NULL);
2148   g_assert (strstr (str, "Help Options") == NULL);
2149   g_assert (strstr (str, "--help") == NULL);
2150   g_assert (strstr (str, "--help-all") == NULL);
2151   g_assert (strstr (str, "--help-group1") == NULL);
2152   g_assert (strstr (str, "Group1-description") != NULL);
2153   g_assert (strstr (str, "Group1-help") == NULL);
2154   g_assert (strstr (str, "Group test arg") != NULL);
2155   g_assert (strstr (str, "Group frob") != NULL);
2156   g_assert (strstr (str, "Main frob") != NULL);
2157   g_assert (strstr (str, "--frob") != NULL);
2158   g_assert (strstr (str, "--group1-test") != NULL);
2159   g_assert (strstr (str, "--group1-frob") == NULL);
2160   g_free (str);
2161
2162   g_option_context_free (context);
2163 }
2164
2165 static void
2166 set_bool (gpointer data)
2167 {
2168   gboolean *b = data;
2169
2170   *b = TRUE;
2171 }
2172
2173 static void
2174 test_main_group (void)
2175 {
2176   GOptionContext *context;
2177   GOptionGroup *group;
2178   gboolean b = FALSE;
2179
2180   context = g_option_context_new (NULL);
2181   g_assert (g_option_context_get_main_group (context) == NULL);
2182   group = g_option_group_new ("name", "description", "hlep", &b, set_bool);
2183   g_option_context_add_group (context, group);
2184   group = g_option_group_new ("name2", "description", "hlep", NULL, NULL);
2185   g_option_context_add_group (context, group);
2186   g_assert (g_option_context_get_main_group (context) == NULL);
2187   group = g_option_group_new ("name", "description", "hlep", NULL, NULL);
2188   g_option_context_set_main_group (context, group);
2189   g_assert (g_option_context_get_main_group (context) == group);
2190
2191   g_option_context_free (context);
2192
2193   g_assert (b);
2194 }
2195
2196 static gboolean error_func_called = FALSE;
2197
2198 static void
2199 error_func (GOptionContext  *context,
2200             GOptionGroup    *group,
2201             gpointer         data,
2202             GError         **error)
2203 {
2204   g_assert_cmpint (GPOINTER_TO_INT(data), ==, 1234);
2205   error_func_called = TRUE;
2206 }
2207
2208 static void
2209 test_error_hook (void)
2210 {
2211   GOptionContext *context;
2212   gchar *arg = NULL;
2213   GOptionEntry entries [] =
2214     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
2215       { NULL } };
2216   GOptionGroup *group;
2217   gchar **argv;
2218   gchar **argv_copy;
2219   gint argc;
2220   gboolean retval;
2221   GError *error = NULL;
2222
2223   context = g_option_context_new (NULL);
2224   group = g_option_group_new ("name", "description", "hlep", GINT_TO_POINTER(1234), NULL);
2225   g_option_group_add_entries (group, entries);
2226   g_option_context_set_main_group (context, group);
2227   g_option_group_set_error_hook (g_option_context_get_main_group (context),
2228                                  error_func);
2229
2230   argv = split_string ("program --test", &argc);
2231   argv_copy = copy_stringv (argv, argc);
2232
2233   retval = g_option_context_parse (context, &argc, &argv, &error);
2234   g_assert (retval == FALSE);
2235   g_assert (error != NULL);
2236   /* An error occurred, so argv has not been changed */
2237   check_identical_stringv (argv_copy, argv);
2238   g_clear_error (&error);
2239
2240   g_assert (error_func_called);
2241
2242   g_strfreev (argv_copy);
2243   g_free (argv);
2244   g_option_context_free (context);
2245 }
2246
2247 static void
2248 test_group_parse (void)
2249 {
2250   GOptionContext *context;
2251   GOptionGroup *group;
2252   gchar *arg1 = NULL;
2253   gchar *arg2 = NULL;
2254   gchar *arg3 = NULL;
2255   gchar *arg4 = NULL;
2256   gchar *arg5 = NULL;
2257   GOptionEntry entries[] = {
2258     { "test", 't', 0, G_OPTION_ARG_STRING, &arg1, NULL, NULL },
2259     { "faz", 'f', 0, G_OPTION_ARG_STRING, &arg2, NULL, NULL },
2260     { NULL }
2261   };
2262   GOptionEntry group_entries[] = {
2263     { "test", 0, 0, G_OPTION_ARG_STRING, &arg3, NULL, NULL },
2264     { "frob", 'f', 0, G_OPTION_ARG_STRING, &arg4, NULL, NULL },
2265     { "faz", 'z', 0, G_OPTION_ARG_STRING, &arg5, NULL, NULL },
2266     { NULL }
2267   };
2268   gchar **argv, **orig_argv;
2269   gint argc;
2270   GError *error = NULL;
2271   gboolean retval;
2272
2273   context = g_option_context_new (NULL);
2274   g_option_context_add_main_entries (context, entries, NULL);
2275   group = g_option_group_new ("group", "A group", "help for group", NULL, NULL);
2276   g_option_group_add_entries (group, group_entries);
2277   g_option_context_add_group (context, group);
2278
2279   argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc);
2280   orig_argv = g_memdup (argv, (argc + 1) * sizeof (char *));
2281
2282   retval = g_option_context_parse (context, &argc, &argv, &error);
2283
2284   g_assert_no_error (error);
2285   g_assert (retval);
2286   g_assert_cmpstr (arg1, ==, "arg1");
2287   g_assert_cmpstr (arg2, ==, "arg2");
2288   g_assert_cmpstr (arg3, ==, "arg3");
2289   g_assert_cmpstr (arg4, ==, "arg4");
2290   g_assert_cmpstr (arg5, ==, "arg5");
2291
2292   g_free (arg1);
2293   g_free (arg2);
2294   g_free (arg3);
2295   g_free (arg4);
2296   g_free (arg5);
2297
2298   g_free (argv);
2299   g_strfreev (orig_argv);
2300   g_option_context_free (context);
2301 }
2302
2303 static gint
2304 option_context_parse_command_line (GOptionContext *context,
2305                                    const gchar    *command_line)
2306 {
2307   gchar **argv;
2308   guint argv_len, argv_new_len;
2309   gboolean success;
2310
2311   argv = split_string (command_line, NULL);
2312   argv_len = g_strv_length (argv);
2313
2314   success = g_option_context_parse_strv (context, &argv, NULL);
2315   argv_new_len = g_strv_length (argv);
2316
2317   g_strfreev (argv);
2318   return success ? argv_len - argv_new_len : -1;
2319 }
2320
2321 static void
2322 test_strict_posix (void)
2323 {
2324   GOptionContext *context;
2325   gboolean foo;
2326   gboolean bar;
2327   GOptionEntry entries[] = {
2328     { "foo", 'f', 0, G_OPTION_ARG_NONE, &foo, NULL, NULL },
2329     { "bar", 'b', 0, G_OPTION_ARG_NONE, &bar, NULL, NULL },
2330     { NULL }
2331   };
2332   gint n_parsed;
2333
2334   context = g_option_context_new (NULL);
2335   g_option_context_add_main_entries (context, entries, NULL);
2336
2337   foo = bar = FALSE;
2338   g_option_context_set_strict_posix (context, FALSE);
2339   n_parsed = option_context_parse_command_line (context, "program --foo command --bar");
2340   g_assert_cmpint (n_parsed, ==, 2);
2341   g_assert (foo == TRUE);
2342   g_assert (bar == TRUE);
2343
2344   foo = bar = FALSE;
2345   g_option_context_set_strict_posix (context, TRUE);
2346   n_parsed = option_context_parse_command_line (context, "program --foo command --bar");
2347   g_assert_cmpint (n_parsed, ==, 1);
2348   g_assert (foo == TRUE);
2349   g_assert (bar == FALSE);
2350
2351   foo = bar = FALSE;
2352   g_option_context_set_strict_posix (context, TRUE);
2353   n_parsed = option_context_parse_command_line (context, "program --foo --bar command");
2354   g_assert_cmpint (n_parsed, ==, 2);
2355   g_assert (foo == TRUE);
2356   g_assert (bar == TRUE);
2357
2358   foo = bar = FALSE;
2359   g_option_context_set_strict_posix (context, TRUE);
2360   n_parsed = option_context_parse_command_line (context, "program command --foo --bar");
2361   g_assert_cmpint (n_parsed, ==, 0);
2362   g_assert (foo == FALSE);
2363   g_assert (bar == FALSE);
2364
2365   g_option_context_free (context);
2366 }
2367
2368 static void
2369 flag_reverse_string (void)
2370 {
2371   GOptionContext *context;
2372   gchar *arg = NULL;
2373   GOptionEntry entries [] =
2374     { { "test", 't', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_STRING, &arg, NULL, NULL },
2375       { NULL } };
2376   gchar **argv;
2377   gint argc;
2378   gboolean retval;
2379   GError *error = NULL;
2380
2381   if (!g_test_undefined ())
2382     return;
2383
2384   context = g_option_context_new (NULL);
2385
2386   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
2387                          "*ignoring reverse flag*");
2388   g_option_context_add_main_entries (context, entries, NULL);
2389   g_test_assert_expected_messages ();
2390
2391   argv = split_string ("program --test bla", &argc);
2392
2393   retval = g_option_context_parse_strv (context, &argv, &error);
2394   g_assert (retval == TRUE);
2395   g_assert_no_error (error);
2396   g_strfreev (argv);
2397   g_option_context_free (context);
2398   g_free (arg);
2399 }
2400
2401 static void
2402 flag_optional_int (void)
2403 {
2404   GOptionContext *context;
2405   gint arg = 0;
2406   GOptionEntry entries [] =
2407     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &arg, NULL, NULL },
2408       { NULL } };
2409   gchar **argv;
2410   gint argc;
2411   gboolean retval;
2412   GError *error = NULL;
2413
2414   if (!g_test_undefined ())
2415     return;
2416
2417   context = g_option_context_new (NULL);
2418
2419   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
2420                          "*ignoring no-arg, optional-arg or filename flags*");
2421   g_option_context_add_main_entries (context, entries, NULL);
2422   g_test_assert_expected_messages ();
2423
2424   argv = split_string ("program --test 5", &argc);
2425
2426   retval = g_option_context_parse_strv (context, &argv, &error);
2427   g_assert (retval == TRUE);
2428   g_assert_no_error (error);
2429   g_strfreev (argv);
2430   g_option_context_free (context);
2431 }
2432
2433 static void
2434 short_remaining (void)
2435 {
2436   gboolean ignore = FALSE;
2437   gboolean remaining = FALSE;
2438   gint number = 0;
2439   gchar* text = NULL;
2440   gchar** files = NULL;
2441   GError* error = NULL;
2442   GOptionEntry entries[] =
2443   {
2444     { "ignore", 'i', 0, G_OPTION_ARG_NONE, &ignore, NULL, NULL },
2445     { "remaining", 'r', 0, G_OPTION_ARG_NONE, &remaining, NULL, NULL },
2446     { "number", 'n', 0, G_OPTION_ARG_INT, &number, NULL, NULL },
2447     { "text", 't', 0, G_OPTION_ARG_STRING, &text, NULL, NULL },
2448     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files, NULL, NULL },
2449     { NULL }
2450   };
2451   GOptionContext* context;
2452   gchar **argv, **argv_copy;
2453   gint argc;
2454
2455   g_test_bug ("729563");
2456
2457   argv = split_string ("program -ri -n 4 -t hello file1 file2", &argc);
2458   argv_copy = copy_stringv (argv, argc);
2459
2460   context = g_option_context_new (NULL);
2461
2462   g_option_context_add_main_entries (context, entries, NULL);
2463   g_option_context_set_ignore_unknown_options (context, TRUE);
2464
2465   g_option_context_parse (context, &argc, &argv, &error);
2466   g_assert_no_error (error);
2467
2468   g_assert (ignore);
2469   g_assert (remaining);
2470   g_assert_cmpint (number, ==, 4);
2471   g_assert_cmpstr (text, ==, "hello");
2472   g_assert_cmpstr (files[0], ==, "file1"); 
2473   g_assert_cmpstr (files[1], ==, "file2"); 
2474   g_assert (files[2] == NULL); 
2475
2476   g_free (text);
2477   g_strfreev (files);
2478   g_strfreev (argv_copy);
2479   g_free (argv);
2480   g_option_context_free (context);
2481 }
2482
2483 int
2484 main (int   argc,
2485       char *argv[])
2486 {
2487   int i;
2488   gchar *test_name;
2489
2490   g_test_init (&argc, &argv, NULL);
2491
2492   g_test_bug_base ("http://bugzilla.gnome.org/");
2493
2494   g_test_add_func ("/option/help/options", test_help);
2495   g_test_add_func ("/option/help/no-options", test_help_no_options);
2496   g_test_add_func ("/option/help/no-help-options", test_help_no_help_options);
2497
2498   g_test_add_func ("/option/basic", test_basic);
2499   g_test_add_func ("/option/translate", test_translate);
2500
2501   g_test_add_func ("/option/group/captions", test_group_captions);
2502   for (i = 0; i < 4; i++)
2503     {
2504       test_name = g_strdup_printf ("/option/group/captions/subprocess/help-%d", i);
2505       g_test_add_data_func (test_name, GINT_TO_POINTER (i),
2506                             test_group_captions_help);
2507       g_free (test_name);
2508       test_name = g_strdup_printf ("/option/group/captions/subprocess/help-all-%d", i);
2509       g_test_add_data_func (test_name, GINT_TO_POINTER (i),
2510                             test_group_captions_help_all);
2511       g_free (test_name);
2512       test_name = g_strdup_printf ("/option/group/captions/subprocess/help-test-%d", i);
2513       g_test_add_data_func (test_name, GINT_TO_POINTER (i),
2514                             test_group_captions_help_test);
2515                             
2516       g_free (test_name);
2517     }
2518
2519   g_test_add_func ("/option/group/main", test_main_group);
2520   g_test_add_func ("/option/group/error-hook", test_error_hook);
2521   g_test_add_func ("/option/group/parse", test_group_parse);
2522   g_test_add_func ("/option/strict-posix", test_strict_posix);
2523
2524   /* Test that restoration on failure works */
2525   g_test_add_func ("/option/restoration/int", error_test1);
2526   g_test_add_func ("/option/restoration/string", error_test2);
2527   g_test_add_func ("/option/restoration/boolean", error_test3);
2528
2529   /* Test that special argument parsing works */
2530   g_test_add_func ("/option/arg/repetition/int", arg_test1);
2531   g_test_add_func ("/option/arg/repetition/string", arg_test2);
2532   g_test_add_func ("/option/arg/repetition/filename", arg_test3);
2533   g_test_add_func ("/option/arg/repetition/double", arg_test4);
2534   g_test_add_func ("/option/arg/repetition/locale", arg_test5);
2535   g_test_add_func ("/option/arg/repetition/int64", arg_test6);
2536
2537   /* Test string arrays */
2538   g_test_add_func ("/option/arg/array/string", array_test1);
2539
2540   /* Test callback args */
2541   g_test_add_func ("/option/arg/callback/string", callback_test1);
2542   g_test_add_func ("/option/arg/callback/count", callback_test2);
2543
2544   /* Test optional arg flag for callback */
2545   g_test_add_func ("/option/arg/callback/optional1", callback_test_optional_1);
2546   g_test_add_func ("/option/arg/callback/optional2", callback_test_optional_2);
2547   g_test_add_func ("/option/arg/callback/optional3", callback_test_optional_3);
2548   g_test_add_func ("/option/arg/callback/optional4", callback_test_optional_4);
2549   g_test_add_func ("/option/arg/callback/optional5", callback_test_optional_5);
2550   g_test_add_func ("/option/arg/callback/optional6", callback_test_optional_6);
2551   g_test_add_func ("/option/arg/callback/optional7", callback_test_optional_7);
2552   g_test_add_func ("/option/arg/callback/optional8", callback_test_optional_8);
2553
2554   /* Test callback with G_OPTION_REMAINING */
2555   g_test_add_func ("/option/arg/remaining/callback", callback_remaining_test1);
2556
2557   /* Test callbacks which return FALSE */
2558   g_test_add_func ("/option/arg/remaining/callback-false", callback_returns_false);
2559
2560   /* Test ignoring options */
2561   g_test_add_func ("/option/arg/ignore/long", ignore_test1);
2562   g_test_add_func ("/option/arg/ignore/short", ignore_test2);
2563   g_test_add_func ("/option/arg/ignore/arg", ignore_test3);
2564   g_test_add_func ("/option/context/add", add_test1);
2565
2566   /* Test parsing empty args */
2567   /* Note there used to be an empty1 here, but it effectively moved
2568    * to option-argv0.c.
2569    */
2570   g_test_add_func ("/option/context/empty2", empty_test2);
2571   g_test_add_func ("/option/context/empty3", empty_test3);
2572
2573   /* Test handling of rest args */
2574   g_test_add_func ("/option/arg/rest/non-option", rest_test1);
2575   g_test_add_func ("/option/arg/rest/separator1", rest_test2);
2576   g_test_add_func ("/option/arg/rest/separator2", rest_test2a);
2577   g_test_add_func ("/option/arg/rest/separator3", rest_test2b);
2578   g_test_add_func ("/option/arg/rest/separator4", rest_test2c);
2579   g_test_add_func ("/option/arg/rest/separator5", rest_test2d);
2580   g_test_add_func ("/option/arg/remaining/non-option", rest_test3);
2581   g_test_add_func ("/option/arg/remaining/separator", rest_test4);
2582   g_test_add_func ("/option/arg/remaining/array", rest_test5);
2583
2584   /* Test some invalid flag combinations */
2585   g_test_add_func ("/option/arg/reverse-string", flag_reverse_string);
2586   g_test_add_func ("/option/arg/optional-int", flag_optional_int);
2587
2588   /* regression tests for individual bugs */
2589   g_test_add_func ("/option/bug/unknown-short", unknown_short_test);
2590   g_test_add_func ("/option/bug/lonely-dash", lonely_dash_test);
2591   g_test_add_func ("/option/bug/missing-arg", missing_arg_test);
2592   g_test_add_func ("/option/bug/dash-arg", dash_arg_test);
2593   g_test_add_func ("/option/bug/short-remaining", short_remaining); 
2594
2595   return g_test_run();
2596 }