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