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 #include <math.h>
30 
31 
32 static GOptionEntry main_entries[] = {
33   { "main-switch", 0, 0,
34     G_OPTION_ARG_NONE, NULL,
35     "A switch that is in the main group", NULL },
36   G_OPTION_ENTRY_NULL
37 };
38 
39 static GOptionEntry group_entries[] = {
40   { "test-switch", 0, 0,
41     G_OPTION_ARG_NONE, NULL,
42     "A switch that is in the test group", NULL },
43   G_OPTION_ENTRY_NULL
44 };
45 
46 static GOptionContext *
make_options(int test_number)47 make_options (int test_number)
48 {
49   GOptionContext *options;
50   GOptionGroup   *group = NULL;
51   gboolean have_main_entries = (0 != (test_number & 1));
52   gboolean have_test_entries = (0 != (test_number & 2));
53 
54   options = g_option_context_new (NULL);
55 
56   if (have_main_entries)
57     g_option_context_add_main_entries (options, main_entries, NULL);
58   if (have_test_entries)
59     {
60       group = g_option_group_new ("test", "Test Options",
61                                   "Show all test options",
62                                   NULL, NULL);
63       g_option_context_add_group (options, group);
64       g_option_group_add_entries (group, group_entries);
65     }
66 
67   return options;
68 }
69 
70 static void
print_help(GOptionContext * options,gchar ** argv)71 print_help (GOptionContext *options, gchar **argv)
72 {
73   gint    argc = 3;
74   GError *error = NULL;
75 
76   g_option_context_parse (options, &argc, &argv, &error);
77   g_option_context_free (options);
78   exit(0);
79 }
80 
81 static void
test_group_captions_help(gconstpointer test_number)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
test_group_captions_help_all(gconstpointer test_number)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
test_group_captions_help_test(gconstpointer test_number)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
test_group_captions(void)112 test_group_captions (void)
113 {
114   const gchar *test_name_base[] = { "help", "help-all", "help-test" };
115   gchar *test_name;
116   guint i;
117   gsize j;
118 
119   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=504142");
120 
121   for (i = 0; i < 4; ++i)
122     {
123       gboolean have_main_entries = (0 != (i & 1));
124       gboolean have_test_entries = (0 != (i & 2));
125 
126       for (j = 0; j < G_N_ELEMENTS (test_name_base); ++j)
127         {
128           GTestSubprocessFlags trap_flags = 0;
129           gboolean expect_main_description = FALSE;
130           gboolean expect_main_switch      = FALSE;
131           gboolean expect_test_description = FALSE;
132           gboolean expect_test_switch      = FALSE;
133           gboolean expect_test_group       = FALSE;
134 
135           if (g_test_verbose ())
136             trap_flags |= G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR;
137 
138           test_name = g_strdup_printf ("/option/group/captions/subprocess/%s-%u",
139                                        test_name_base[j], i);
140           g_test_trap_subprocess (test_name, 0, trap_flags);
141           g_free (test_name);
142           g_test_trap_assert_passed ();
143           g_test_trap_assert_stderr ("");
144 
145           switch (j)
146             {
147             case 0:
148               g_assert_cmpstr ("help", ==, test_name_base[j]);
149               expect_main_switch = have_main_entries;
150               expect_test_group  = have_test_entries;
151               break;
152 
153             case 1:
154               g_assert_cmpstr ("help-all", ==, test_name_base[j]);
155               expect_main_switch = have_main_entries;
156               expect_test_switch = have_test_entries;
157               expect_test_group  = have_test_entries;
158               break;
159 
160             case 2:
161               g_assert_cmpstr ("help-test", ==, test_name_base[j]);
162               expect_test_switch = have_test_entries;
163               break;
164 
165             default:
166               g_assert_not_reached ();
167               break;
168             }
169 
170           expect_main_description |= expect_main_switch;
171           expect_test_description |= expect_test_switch;
172 
173           if (expect_main_description)
174             g_test_trap_assert_stdout           ("*Application Options*");
175           else
176             g_test_trap_assert_stdout_unmatched ("*Application Options*");
177           if (expect_main_switch)
178             g_test_trap_assert_stdout           ("*--main-switch*");
179           else
180             g_test_trap_assert_stdout_unmatched ("*--main-switch*");
181 
182           if (expect_test_description)
183             g_test_trap_assert_stdout           ("*Test Options*");
184           else
185             g_test_trap_assert_stdout_unmatched ("*Test Options*");
186           if (expect_test_switch)
187             g_test_trap_assert_stdout           ("*--test-switch*");
188           else
189             g_test_trap_assert_stdout_unmatched ("*--test-switch*");
190 
191           if (expect_test_group)
192             g_test_trap_assert_stdout           ("*--help-test*");
193           else
194             g_test_trap_assert_stdout_unmatched ("*--help-test*");
195         }
196     }
197 }
198 
199 int error_test1_int;
200 char *error_test2_string;
201 gboolean error_test3_boolean;
202 
203 int arg_test1_int;
204 gchar *arg_test2_string;
205 gchar *arg_test3_filename;
206 gdouble arg_test4_double;
207 gdouble arg_test5_double;
208 gint64 arg_test6_int64;
209 gint64 arg_test6_int64_2;
210 
211 gchar *callback_test1_string;
212 int callback_test2_int;
213 
214 gchar *callback_test_optional_string;
215 gboolean callback_test_optional_boolean;
216 
217 gchar **array_test1_array;
218 
219 gboolean ignore_test1_boolean;
220 gboolean ignore_test2_boolean;
221 gchar *ignore_test3_string;
222 
223 static gchar **
split_string(const char * str,int * argc)224 split_string (const char *str, int *argc)
225 {
226   gchar **argv;
227   int len;
228 
229   argv = g_strsplit (str, " ", 0);
230 
231   for (len = 0; argv[len] != NULL; len++);
232 
233   if (argc)
234     *argc = len;
235 
236   return argv;
237 }
238 
239 static gchar *
join_stringv(int argc,char ** argv)240 join_stringv (int argc, char **argv)
241 {
242   int i;
243   GString *str;
244 
245   str = g_string_new (NULL);
246 
247   for (i = 0; i < argc; i++)
248     {
249       g_string_append (str, argv[i]);
250 
251       if (i < argc - 1)
252 	g_string_append_c (str, ' ');
253     }
254 
255   return g_string_free (str, FALSE);
256 }
257 
258 /* Performs a shallow copy */
259 static char **
copy_stringv(char ** argv,int argc)260 copy_stringv (char **argv, int argc)
261 {
262   return g_memdup2 (argv, sizeof (char *) * (argc + 1));
263 }
264 
265 static void
check_identical_stringv(gchar ** before,gchar ** after)266 check_identical_stringv (gchar **before, gchar **after)
267 {
268   guint i;
269 
270   /* Not only is it the same string... */
271   for (i = 0; before[i] != NULL; i++)
272     g_assert_cmpstr (before[i], ==, after[i]);
273 
274   /* ... it is actually the same pointer */
275   for (i = 0; before[i] != NULL; i++)
276     g_assert (before[i] == after[i]);
277 
278   g_assert (after[i] == NULL);
279 }
280 
281 
282 static gboolean
error_test1_pre_parse(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)283 error_test1_pre_parse (GOptionContext *context,
284 		       GOptionGroup   *group,
285 		       gpointer	       data,
286 		       GError        **error)
287 {
288   g_assert (error_test1_int == 0x12345678);
289 
290   return TRUE;
291 }
292 
293 static gboolean
error_test1_post_parse(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)294 error_test1_post_parse (GOptionContext *context,
295 			GOptionGroup   *group,
296 			gpointer	  data,
297 			GError        **error)
298 {
299   g_assert (error_test1_int == 20);
300 
301   /* Set an error in the post hook */
302   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
303 
304   return FALSE;
305 }
306 
307 static void
error_test1(void)308 error_test1 (void)
309 {
310   GOptionContext *context;
311   gboolean retval;
312   GError *error = NULL;
313   gchar **argv;
314   gchar **argv_copy;
315   int argc;
316   GOptionGroup *main_group;
317   GOptionEntry entries [] =
318     { { "test", 0, 0, G_OPTION_ARG_INT, &error_test1_int, NULL, NULL },
319       G_OPTION_ENTRY_NULL };
320 
321   error_test1_int = 0x12345678;
322 
323   context = g_option_context_new (NULL);
324   g_option_context_add_main_entries (context, entries, NULL);
325 
326   /* Set pre and post parse hooks */
327   main_group = g_option_context_get_main_group (context);
328   g_option_group_set_parse_hooks (main_group,
329 				  error_test1_pre_parse, error_test1_post_parse);
330 
331   /* Now try parsing */
332   argv = split_string ("program --test 20", &argc);
333   argv_copy = copy_stringv (argv, argc);
334 
335   retval = g_option_context_parse (context, &argc, &argv, &error);
336   g_assert (retval == FALSE);
337   g_assert (error != NULL);
338   /* An error occurred, so argv has not been changed */
339   check_identical_stringv (argv_copy, argv);
340   g_clear_error (&error);
341 
342   /* On failure, values should be reset */
343   g_assert (error_test1_int == 0x12345678);
344 
345   g_strfreev (argv_copy);
346   g_free (argv);
347   g_option_context_free (context);
348 }
349 
350 static gboolean
error_test2_pre_parse(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)351 error_test2_pre_parse (GOptionContext *context,
352 		       GOptionGroup   *group,
353 		       gpointer	  data,
354 		       GError        **error)
355 {
356   g_assert (strcmp (error_test2_string, "foo") == 0);
357 
358   return TRUE;
359 }
360 
361 static gboolean
error_test2_post_parse(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)362 error_test2_post_parse (GOptionContext *context,
363 			GOptionGroup   *group,
364 			gpointer	  data,
365 			GError        **error)
366 {
367   g_assert (strcmp (error_test2_string, "bar") == 0);
368 
369   /* Set an error in the post hook */
370   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
371 
372   return FALSE;
373 }
374 
375 static void
error_test2(void)376 error_test2 (void)
377 {
378   GOptionContext *context;
379   gboolean retval;
380   GError *error = NULL;
381   gchar **argv;
382   gchar **argv_copy;
383   int argc;
384   GOptionGroup *main_group;
385   GOptionEntry entries [] =
386     { { "test", 0, 0, G_OPTION_ARG_STRING, &error_test2_string, NULL, NULL },
387       G_OPTION_ENTRY_NULL };
388 
389   error_test2_string = "foo";
390 
391   context = g_option_context_new (NULL);
392   g_option_context_add_main_entries (context, entries, NULL);
393 
394   /* Set pre and post parse hooks */
395   main_group = g_option_context_get_main_group (context);
396   g_option_group_set_parse_hooks (main_group,
397 				  error_test2_pre_parse, error_test2_post_parse);
398 
399   /* Now try parsing */
400   argv = split_string ("program --test bar", &argc);
401   argv_copy = copy_stringv (argv, argc);
402   retval = g_option_context_parse (context, &argc, &argv, &error);
403 
404   g_assert (retval == FALSE);
405   g_assert (error != NULL);
406   check_identical_stringv (argv_copy, argv);
407   g_clear_error (&error);
408 
409   g_assert (strcmp (error_test2_string, "foo") == 0);
410 
411   g_strfreev (argv_copy);
412   g_free (argv);
413   g_option_context_free (context);
414 }
415 
416 static gboolean
error_test3_pre_parse(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)417 error_test3_pre_parse (GOptionContext *context,
418 		       GOptionGroup   *group,
419 		       gpointer	  data,
420 		       GError        **error)
421 {
422   g_assert (!error_test3_boolean);
423 
424   return TRUE;
425 }
426 
427 static gboolean
error_test3_post_parse(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)428 error_test3_post_parse (GOptionContext *context,
429 			GOptionGroup   *group,
430 			gpointer	  data,
431 			GError        **error)
432 {
433   g_assert (error_test3_boolean);
434 
435   /* Set an error in the post hook */
436   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
437 
438   return FALSE;
439 }
440 
441 static void
error_test3(void)442 error_test3 (void)
443 {
444   GOptionContext *context;
445   gboolean retval;
446   GError *error = NULL;
447   gchar **argv;
448   gchar **argv_copy;
449   int argc;
450   GOptionGroup *main_group;
451   GOptionEntry entries [] =
452     { { "test", 0, 0, G_OPTION_ARG_NONE, &error_test3_boolean, NULL, NULL },
453       G_OPTION_ENTRY_NULL };
454 
455   error_test3_boolean = FALSE;
456 
457   context = g_option_context_new (NULL);
458   g_option_context_add_main_entries (context, entries, NULL);
459 
460   /* Set pre and post parse hooks */
461   main_group = g_option_context_get_main_group (context);
462   g_option_group_set_parse_hooks (main_group,
463 				  error_test3_pre_parse, error_test3_post_parse);
464 
465   /* Now try parsing */
466   argv = split_string ("program --test", &argc);
467   argv_copy = copy_stringv (argv, argc);
468   retval = g_option_context_parse (context, &argc, &argv, &error);
469 
470   g_assert (retval == FALSE);
471   g_assert (error != NULL);
472   check_identical_stringv (argv_copy, argv);
473   g_clear_error (&error);
474 
475   g_assert (!error_test3_boolean);
476 
477   g_strfreev (argv_copy);
478   g_free (argv);
479   g_option_context_free (context);
480 }
481 
482 static void
arg_test1(void)483 arg_test1 (void)
484 {
485   GOptionContext *context;
486   gboolean retval;
487   GError *error = NULL;
488   gchar **argv;
489   gchar **argv_copy;
490   int argc;
491   GOptionEntry entries [] =
492     { { "test", 0, 0, G_OPTION_ARG_INT, &arg_test1_int, NULL, NULL },
493       G_OPTION_ENTRY_NULL };
494 
495   context = g_option_context_new (NULL);
496   g_option_context_add_main_entries (context, entries, NULL);
497 
498   /* Now try parsing */
499   argv = split_string ("program --test 20 --test 30", &argc);
500   argv_copy = copy_stringv (argv, argc);
501 
502   retval = g_option_context_parse (context, &argc, &argv, &error);
503   g_assert_no_error (error);
504   g_assert (retval);
505 
506   /* Last arg specified is the one that should be stored */
507   g_assert (arg_test1_int == 30);
508 
509   /* We free all of the strings in a copy of argv, because now argv is a
510    * subset - some have been removed in-place
511    */
512   g_strfreev (argv_copy);
513   g_free (argv);
514   g_option_context_free (context);
515 }
516 
517 static void
arg_test2(void)518 arg_test2 (void)
519 {
520   GOptionContext *context;
521   gboolean retval;
522   GError *error = NULL;
523   gchar **argv;
524   gchar **argv_copy;
525   int argc;
526   GOptionEntry entries [] =
527     { { "test", 0, 0, G_OPTION_ARG_STRING, &arg_test2_string, NULL, NULL },
528       G_OPTION_ENTRY_NULL };
529 
530   context = g_option_context_new (NULL);
531   g_option_context_add_main_entries (context, entries, NULL);
532 
533   /* Now try parsing */
534   argv = split_string ("program --test foo --test bar", &argc);
535   argv_copy = copy_stringv (argv, argc);
536 
537   retval = g_option_context_parse (context, &argc, &argv, &error);
538   g_assert_no_error (error);
539   g_assert (retval);
540 
541   /* Last arg specified is the one that should be stored */
542   g_assert (strcmp (arg_test2_string, "bar") == 0);
543 
544   g_free (arg_test2_string);
545 
546   g_strfreev (argv_copy);
547   g_free (argv);
548   g_option_context_free (context);
549 }
550 
551 static void
arg_test3(void)552 arg_test3 (void)
553 {
554   GOptionContext *context;
555   gboolean retval;
556   GError *error = NULL;
557   gchar **argv;
558   gchar **argv_copy;
559   int argc;
560   GOptionEntry entries [] =
561     { { "test", 0, 0, G_OPTION_ARG_FILENAME, &arg_test3_filename, NULL, NULL },
562       G_OPTION_ENTRY_NULL };
563 
564   context = g_option_context_new (NULL);
565   g_option_context_add_main_entries (context, entries, NULL);
566 
567   /* Now try parsing */
568   argv = split_string ("program --test foo.txt", &argc);
569   argv_copy = copy_stringv (argv, argc);
570 
571   retval = g_option_context_parse (context, &argc, &argv, &error);
572   g_assert_no_error (error);
573   g_assert (retval);
574 
575   /* Last arg specified is the one that should be stored */
576   g_assert (strcmp (arg_test3_filename, "foo.txt") == 0);
577 
578   g_free (arg_test3_filename);
579 
580   g_strfreev (argv_copy);
581   g_free (argv);
582   g_option_context_free (context);
583 }
584 
585 static void
arg_test4(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       G_OPTION_ENTRY_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
arg_test5(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.UTF-8";
628   GOptionEntry entries [] =
629     { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test5_double, NULL, NULL },
630       G_OPTION_ENTRY_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
arg_test6(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       G_OPTION_ENTRY_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
callback_parse1(const gchar * option_name,const gchar * value,gpointer data,GError ** error)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
callback_test1(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       G_OPTION_ENTRY_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
callback_parse2(const gchar * option_name,const gchar * value,gpointer data,GError ** error)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
callback_test2(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       G_OPTION_ENTRY_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
callback_parse_optional(const gchar * option_name,const gchar * value,gpointer data,GError ** error)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
callback_test_optional_1(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       G_OPTION_ENTRY_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
callback_test_optional_2(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       G_OPTION_ENTRY_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
callback_test_optional_3(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       G_OPTION_ENTRY_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
callback_test_optional_4(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       G_OPTION_ENTRY_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
callback_test_optional_5(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, NULL },
948       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
949 	callback_parse_optional, NULL, NULL },
950       G_OPTION_ENTRY_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
callback_test_optional_6(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, NULL },
986       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
987 	callback_parse_optional, NULL, NULL },
988       G_OPTION_ENTRY_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
callback_test_optional_7(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, NULL },
1024       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
1025 	callback_parse_optional, NULL, NULL },
1026       G_OPTION_ENTRY_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
callback_test_optional_8(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, NULL },
1062       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
1063 	callback_parse_optional, NULL, NULL },
1064       G_OPTION_ENTRY_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
callback_remaining_test1_callback(const gchar * option_name,const gchar * value,gpointer data,GError ** error)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
callback_remaining_test1(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       G_OPTION_ENTRY_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
callback_error(const gchar * option_name,const gchar * value,gpointer data,GError ** error)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
callback_returns_false(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       G_OPTION_ENTRY_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 an 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 an 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
ignore_test1(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       G_OPTION_ENTRY_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
ignore_test2(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       G_OPTION_ENTRY_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
ignore_test3(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       G_OPTION_ENTRY_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 static void
array_test1(void)1337 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       G_OPTION_ENTRY_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
add_test1(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       G_OPTION_ENTRY_NULL };
1380   GOptionEntry entries2 [] =
1381     { { "test2", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL },
1382       G_OPTION_ENTRY_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
empty_test2(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
empty_test3(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
rest_test1(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       G_OPTION_ENTRY_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
rest_test2(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       G_OPTION_ENTRY_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
rest_test2a(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       G_OPTION_ENTRY_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
rest_test2b(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       G_OPTION_ENTRY_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
rest_test2c(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       G_OPTION_ENTRY_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
rest_test2d(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       G_OPTION_ENTRY_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
rest_test3(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       G_OPTION_ENTRY_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
rest_test4(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       G_OPTION_ENTRY_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
rest_test5(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       G_OPTION_ENTRY_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
unknown_short_test(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 [] = { G_OPTION_ENTRY_NULL };
1777 
1778   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=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
lonely_dash_test(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 ("https://bugzilla.gnome.org/show_bug.cgi?id=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 /* test that three dashes are treated as non-options */
1828 static void
triple_dash_test(void)1829 triple_dash_test (void)
1830 {
1831   GOptionContext *context;
1832   GOptionGroup *group;
1833   gboolean retval;
1834   GError *error = NULL;
1835   gchar **argv;
1836   gchar **argv_copy;
1837   int argc;
1838   gint arg1, arg2;
1839   GOptionEntry entries [] =
1840     { { "foo", 0, 0, G_OPTION_ARG_INT, &arg1, NULL, NULL},
1841       G_OPTION_ENTRY_NULL
1842     };
1843   GOptionEntry group_entries [] =
1844     { { "test", 0, 0, G_OPTION_ARG_INT, &arg2, NULL, NULL},
1845       G_OPTION_ENTRY_NULL
1846     };
1847 
1848   context = g_option_context_new (NULL);
1849   g_option_context_add_main_entries (context, entries, NULL);
1850 
1851   group = g_option_group_new ("group", "Group description", "Group help", NULL, NULL);
1852   g_option_group_add_entries (group, group_entries);
1853 
1854   g_option_context_add_group (context, group);
1855 
1856   /* Now try parsing */
1857   argv = split_string ("program ---test 42", &argc);
1858   argv_copy = copy_stringv (argv, argc);
1859 
1860   retval = g_option_context_parse (context, &argc, &argv, &error);
1861   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION);
1862   g_assert (retval == FALSE);
1863 
1864   g_option_context_free (context);
1865   g_clear_error (&error);
1866   g_strfreev (argv_copy);
1867   g_free (argv);
1868 }
1869 
1870 static void
missing_arg_test(void)1871 missing_arg_test (void)
1872 {
1873   GOptionContext *context;
1874   gboolean retval;
1875   GError *error = NULL;
1876   gchar **argv;
1877   gchar **argv_copy;
1878   int argc;
1879   gchar *arg = NULL;
1880   GOptionEntry entries [] =
1881     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
1882       G_OPTION_ENTRY_NULL };
1883 
1884   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=305576");
1885 
1886   context = g_option_context_new (NULL);
1887   g_option_context_add_main_entries (context, entries, NULL);
1888 
1889   /* Now try parsing */
1890   argv = split_string ("program --test", &argc);
1891   argv_copy = copy_stringv (argv, argc);
1892 
1893   retval = g_option_context_parse (context, &argc, &argv, &error);
1894   g_assert (retval == FALSE);
1895   g_assert (error != NULL);
1896   /* An error occurred, so argv has not been changed */
1897   check_identical_stringv (argv_copy, argv);
1898   g_clear_error (&error);
1899 
1900   g_strfreev (argv_copy);
1901   g_free (argv);
1902 
1903   /* Try parsing again */
1904   argv = split_string ("program -t", &argc);
1905   argv_copy = copy_stringv (argv, argc);
1906 
1907   retval = g_option_context_parse (context, &argc, &argv, &error);
1908   g_assert (retval == FALSE);
1909   g_assert (error != NULL);
1910   /* An error occurred, so argv has not been changed */
1911   check_identical_stringv (argv_copy, argv);
1912   g_clear_error (&error);
1913 
1914   g_strfreev (argv_copy);
1915   g_free (argv);
1916   g_option_context_free (context);
1917 
1918   /* Checking g_option_context_parse_strv on NULL args */
1919   context = g_option_context_new (NULL);
1920   g_assert_true (g_option_context_parse_strv (context, NULL, NULL));
1921   g_option_context_free (context);
1922 }
1923 
1924 static gchar *test_arg;
1925 
cb(const gchar * option_name,const gchar * value,gpointer data,GError ** error)1926 static gboolean cb (const gchar  *option_name,
1927                     const gchar  *value,
1928                     gpointer      data,
1929                     GError      **error)
1930 {
1931   test_arg = g_strdup (value);
1932   return TRUE;
1933 }
1934 
1935 static void
dash_arg_test(void)1936 dash_arg_test (void)
1937 {
1938   GOptionContext *context;
1939   gboolean retval;
1940   GError *error = NULL;
1941   gchar **argv;
1942   gchar **argv_copy;
1943   int argc;
1944   gboolean argb = FALSE;
1945   GOptionEntry entries [] =
1946     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, cb, NULL, NULL },
1947       { "three", '3', 0, G_OPTION_ARG_NONE, &argb, NULL, NULL },
1948       G_OPTION_ENTRY_NULL };
1949 
1950   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=577638");
1951 
1952   context = g_option_context_new (NULL);
1953   g_option_context_add_main_entries (context, entries, NULL);
1954 
1955   /* Now try parsing */
1956   argv = split_string ("program --test=-3", &argc);
1957   argv_copy = copy_stringv (argv, argc);
1958 
1959   test_arg = NULL;
1960   error = NULL;
1961   retval = g_option_context_parse (context, &argc, &argv, &error);
1962   g_assert (retval);
1963   g_assert_no_error (error);
1964   g_assert_cmpstr (test_arg, ==, "-3");
1965 
1966   g_strfreev (argv_copy);
1967   g_free (argv);
1968   g_free (test_arg);
1969   test_arg = NULL;
1970 
1971   /* Try parsing again */
1972   argv = split_string ("program --test -3", &argc);
1973   argv_copy = copy_stringv (argv, argc);
1974 
1975   error = NULL;
1976   retval = g_option_context_parse (context, &argc, &argv, &error);
1977   g_assert_no_error (error);
1978   g_assert (retval);
1979   g_assert_cmpstr (test_arg, ==, NULL);
1980 
1981   g_option_context_free (context);
1982   g_strfreev (argv_copy);
1983   g_free (argv);
1984 }
1985 
1986 static void
test_basic(void)1987 test_basic (void)
1988 {
1989   GOptionContext *context;
1990   gchar *arg = NULL;
1991   GOptionEntry entries [] =
1992     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
1993       G_OPTION_ENTRY_NULL };
1994 
1995   context = g_option_context_new (NULL);
1996   g_option_context_add_main_entries (context, entries, NULL);
1997 
1998   g_assert (g_option_context_get_help_enabled (context));
1999   g_assert (!g_option_context_get_ignore_unknown_options (context));
2000   g_assert_cmpstr (g_option_context_get_summary (context), ==, NULL);
2001   g_assert_cmpstr (g_option_context_get_description (context), ==, NULL);
2002 
2003   g_option_context_set_help_enabled (context, FALSE);
2004   g_option_context_set_ignore_unknown_options (context, TRUE);
2005   g_option_context_set_summary (context, "summary");
2006   g_option_context_set_description(context, "description");
2007 
2008   g_assert (!g_option_context_get_help_enabled (context));
2009   g_assert (g_option_context_get_ignore_unknown_options (context));
2010   g_assert_cmpstr (g_option_context_get_summary (context), ==, "summary");
2011   g_assert_cmpstr (g_option_context_get_description (context), ==, "description");
2012 
2013   g_option_context_free (context);
2014 }
2015 
2016 typedef struct {
2017   gboolean parameter_seen;
2018   gboolean summary_seen;
2019   gboolean description_seen;
2020   gboolean destroyed;
2021 } TranslateData;
2022 
2023 static const gchar *
translate_func(const gchar * str,gpointer data)2024 translate_func (const gchar *str,
2025                 gpointer     data)
2026 {
2027   TranslateData *d = data;
2028 
2029   if (strcmp (str, "parameter") == 0)
2030     d->parameter_seen = TRUE;
2031   else if (strcmp (str, "summary") == 0)
2032     d->summary_seen = TRUE;
2033   else if (strcmp (str, "description") == 0)
2034     d->description_seen = TRUE;
2035 
2036   return str;
2037 }
2038 
2039 static void
destroy_notify(gpointer data)2040 destroy_notify (gpointer data)
2041 {
2042   TranslateData *d = data;
2043 
2044   d->destroyed = TRUE;
2045 }
2046 
2047 static void
test_translate(void)2048 test_translate (void)
2049 {
2050   GOptionContext *context;
2051   gchar *arg = NULL;
2052   GOptionEntry entries [] =
2053     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
2054       G_OPTION_ENTRY_NULL };
2055   TranslateData data = { 0, };
2056   gchar *str;
2057 
2058   context = g_option_context_new ("parameter");
2059   g_option_context_add_main_entries (context, entries, NULL);
2060   g_option_context_set_summary (context, "summary");
2061   g_option_context_set_description (context, "description");
2062 
2063   g_option_context_set_translate_func (context, translate_func, &data, destroy_notify);
2064 
2065   str = g_option_context_get_help (context, FALSE, NULL);
2066   g_free (str);
2067   g_option_context_free (context);
2068 
2069   g_assert (data.parameter_seen);
2070   g_assert (data.summary_seen);
2071   g_assert (data.description_seen);
2072   g_assert (data.destroyed);
2073 }
2074 
2075 static void
test_help(void)2076 test_help (void)
2077 {
2078   GOptionContext *context;
2079   GOptionGroup *group;
2080   gchar *str;
2081   gchar *arg = NULL;
2082   gchar **sarr = NULL;
2083   GOptionEntry entries[] = {
2084     { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Test tests", "Argument to use in test" },
2085     { "test2", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, NULL, "Tests also", NULL },
2086     { "frob", 0, 0, G_OPTION_ARG_NONE, NULL, "Main frob", NULL },
2087     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" },
2088     G_OPTION_ENTRY_NULL
2089   };
2090   GOptionEntry group_entries[] = {
2091     { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Group test", "Group test arg" },
2092     { "frob", 0, G_OPTION_FLAG_NOALIAS, G_OPTION_ARG_NONE, NULL, "Group frob", NULL },
2093     G_OPTION_ENTRY_NULL
2094   };
2095 
2096   context = g_option_context_new ("blabla");
2097   g_option_context_add_main_entries (context, entries, NULL);
2098   g_option_context_set_summary (context, "Summary");
2099   g_option_context_set_description (context, "Description");
2100 
2101   group = g_option_group_new ("group1", "Group1-description", "Group1-help", NULL, NULL);
2102   g_option_group_add_entries (group, group_entries);
2103 
2104   g_option_context_add_group (context, group);
2105 
2106   str = g_option_context_get_help (context, FALSE, NULL);
2107   g_assert (strstr (str, "blabla") != NULL);
2108   g_assert (strstr (str, "Test tests") != NULL);
2109   g_assert (strstr (str, "Argument to use in test") != NULL);
2110   g_assert (strstr (str, "Tests also") == NULL);
2111   g_assert (strstr (str, "REST") != NULL);
2112   g_assert (strstr (str, "Summary") != NULL);
2113   g_assert (strstr (str, "Description") != NULL);
2114   g_assert (strstr (str, "--help") != NULL);
2115   g_assert (strstr (str, "--help-all") != NULL);
2116   g_assert (strstr (str, "--help-group1") != NULL);
2117   g_assert (strstr (str, "Group1-description") != NULL);
2118   g_assert (strstr (str, "Group1-help") != NULL);
2119   g_assert (strstr (str, "Group test arg") != NULL);
2120   g_assert (strstr (str, "Group frob") != NULL);
2121   g_assert (strstr (str, "Main frob") != NULL);
2122   g_assert (strstr (str, "--frob") != NULL);
2123   g_assert (strstr (str, "--group1-test") != NULL);
2124   g_assert (strstr (str, "--group1-frob") == NULL);
2125   g_free (str);
2126 
2127   g_option_context_free (context);
2128 }
2129 
2130 static void
test_help_no_options(void)2131 test_help_no_options (void)
2132 {
2133   GOptionContext *context;
2134   gchar **sarr = NULL;
2135   GOptionEntry entries[] = {
2136     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" },
2137     G_OPTION_ENTRY_NULL
2138   };
2139   gchar *str;
2140 
2141   context = g_option_context_new ("blabla");
2142   g_option_context_add_main_entries (context, entries, NULL);
2143 
2144   str = g_option_context_get_help (context, FALSE, NULL);
2145   g_assert (strstr (str, "blabla") != NULL);
2146   g_assert (strstr (str, "REST") != NULL);
2147   g_assert (strstr (str, "Help Options") != NULL);
2148   g_assert (strstr (str, "Application Options") == NULL);
2149 
2150   g_free (str);
2151   g_option_context_free (context);
2152 }
2153 
2154 static void
test_help_no_help_options(void)2155 test_help_no_help_options (void)
2156 {
2157   GOptionContext *context;
2158   GOptionGroup *group;
2159   gchar *str;
2160   gchar *arg = NULL;
2161   gchar **sarr = NULL;
2162   GOptionEntry entries[] = {
2163     { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Test tests", "Argument to use in test" },
2164     { "test2", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, NULL, "Tests also", NULL },
2165     { "frob", 0, 0, G_OPTION_ARG_NONE, NULL, "Main frob", NULL },
2166     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" },
2167     G_OPTION_ENTRY_NULL
2168   };
2169   GOptionEntry group_entries[] = {
2170     { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Group test", "Group test arg" },
2171     { "frob", 0, G_OPTION_FLAG_NOALIAS, G_OPTION_ARG_NONE, NULL, "Group frob", NULL },
2172     G_OPTION_ENTRY_NULL
2173   };
2174 
2175   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=697652");
2176 
2177   context = g_option_context_new ("blabla");
2178   g_option_context_add_main_entries (context, entries, NULL);
2179   g_option_context_set_summary (context, "Summary");
2180   g_option_context_set_description (context, "Description");
2181   g_option_context_set_help_enabled (context, FALSE);
2182 
2183   group = g_option_group_new ("group1", "Group1-description", "Group1-help", NULL, NULL);
2184   g_option_group_add_entries (group, group_entries);
2185 
2186   g_option_context_add_group (context, group);
2187 
2188   str = g_option_context_get_help (context, FALSE, NULL);
2189   g_assert (strstr (str, "blabla") != NULL);
2190   g_assert (strstr (str, "Test tests") != NULL);
2191   g_assert (strstr (str, "Argument to use in test") != NULL);
2192   g_assert (strstr (str, "Tests also") == NULL);
2193   g_assert (strstr (str, "REST") != NULL);
2194   g_assert (strstr (str, "Summary") != NULL);
2195   g_assert (strstr (str, "Description") != NULL);
2196   g_assert (strstr (str, "Help Options") == NULL);
2197   g_assert (strstr (str, "--help") == NULL);
2198   g_assert (strstr (str, "--help-all") == NULL);
2199   g_assert (strstr (str, "--help-group1") == NULL);
2200   g_assert (strstr (str, "Group1-description") != NULL);
2201   g_assert (strstr (str, "Group1-help") == NULL);
2202   g_assert (strstr (str, "Group test arg") != NULL);
2203   g_assert (strstr (str, "Group frob") != NULL);
2204   g_assert (strstr (str, "Main frob") != NULL);
2205   g_assert (strstr (str, "--frob") != NULL);
2206   g_assert (strstr (str, "--group1-test") != NULL);
2207   g_assert (strstr (str, "--group1-frob") == NULL);
2208   g_free (str);
2209 
2210   g_option_context_free (context);
2211 }
2212 
2213 static void
set_bool(gpointer data)2214 set_bool (gpointer data)
2215 {
2216   gboolean *b = data;
2217 
2218   *b = TRUE;
2219 }
2220 
2221 static void
test_main_group(void)2222 test_main_group (void)
2223 {
2224   GOptionContext *context;
2225   GOptionGroup *group;
2226   gboolean b = FALSE;
2227 
2228   context = g_option_context_new (NULL);
2229   g_assert (g_option_context_get_main_group (context) == NULL);
2230   group = g_option_group_new ("name", "description", "hlep", &b, set_bool);
2231   g_option_context_add_group (context, group);
2232   group = g_option_group_new ("name2", "description", "hlep", NULL, NULL);
2233   g_option_context_add_group (context, group);
2234   g_assert (g_option_context_get_main_group (context) == NULL);
2235   group = g_option_group_new ("name", "description", "hlep", NULL, NULL);
2236   g_option_context_set_main_group (context, group);
2237   g_assert (g_option_context_get_main_group (context) == group);
2238 
2239   g_option_context_free (context);
2240 
2241   g_assert (b);
2242 }
2243 
2244 static gboolean error_func_called = FALSE;
2245 
2246 static void
error_func(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)2247 error_func (GOptionContext  *context,
2248             GOptionGroup    *group,
2249             gpointer         data,
2250             GError         **error)
2251 {
2252   g_assert_cmpint (GPOINTER_TO_INT(data), ==, 1234);
2253   error_func_called = TRUE;
2254 }
2255 
2256 static void
test_error_hook(void)2257 test_error_hook (void)
2258 {
2259   GOptionContext *context;
2260   gchar *arg = NULL;
2261   GOptionEntry entries [] =
2262     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
2263       G_OPTION_ENTRY_NULL };
2264   GOptionGroup *group;
2265   gchar **argv;
2266   gchar **argv_copy;
2267   gint argc;
2268   gboolean retval;
2269   GError *error = NULL;
2270 
2271   context = g_option_context_new (NULL);
2272   group = g_option_group_new ("name", "description", "hlep", GINT_TO_POINTER(1234), NULL);
2273   g_option_group_add_entries (group, entries);
2274   g_option_context_set_main_group (context, group);
2275   g_option_group_set_error_hook (g_option_context_get_main_group (context),
2276                                  error_func);
2277 
2278   argv = split_string ("program --test", &argc);
2279   argv_copy = copy_stringv (argv, argc);
2280 
2281   retval = g_option_context_parse (context, &argc, &argv, &error);
2282   g_assert (retval == FALSE);
2283   g_assert (error != NULL);
2284   /* An error occurred, so argv has not been changed */
2285   check_identical_stringv (argv_copy, argv);
2286   g_clear_error (&error);
2287 
2288   g_assert (error_func_called);
2289 
2290   g_strfreev (argv_copy);
2291   g_free (argv);
2292   g_option_context_free (context);
2293 }
2294 
2295 static void
test_group_parse(void)2296 test_group_parse (void)
2297 {
2298   GOptionContext *context;
2299   GOptionGroup *group;
2300   gchar *arg1 = NULL;
2301   gchar *arg2 = NULL;
2302   gchar *arg3 = NULL;
2303   gchar *arg4 = NULL;
2304   gchar *arg5 = NULL;
2305   GOptionEntry entries[] = {
2306     { "test", 't', 0, G_OPTION_ARG_STRING, &arg1, NULL, NULL },
2307     { "faz", 'f', 0, G_OPTION_ARG_STRING, &arg2, NULL, NULL },
2308     G_OPTION_ENTRY_NULL
2309   };
2310   GOptionEntry group_entries[] = {
2311     { "test", 0, 0, G_OPTION_ARG_STRING, &arg3, NULL, NULL },
2312     { "frob", 'f', 0, G_OPTION_ARG_STRING, &arg4, NULL, NULL },
2313     { "faz", 'z', 0, G_OPTION_ARG_STRING, &arg5, NULL, NULL },
2314     G_OPTION_ENTRY_NULL
2315   };
2316   gchar **argv, **orig_argv;
2317   gint argc;
2318   GError *error = NULL;
2319   gboolean retval;
2320 
2321   context = g_option_context_new (NULL);
2322   g_option_context_add_main_entries (context, entries, NULL);
2323   group = g_option_group_new ("group", "A group", "help for group", NULL, NULL);
2324   g_option_group_add_entries (group, group_entries);
2325   g_option_context_add_group (context, group);
2326 
2327   argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc);
2328   orig_argv = g_memdup2 (argv, (argc + 1) * sizeof (char *));
2329 
2330   retval = g_option_context_parse (context, &argc, &argv, &error);
2331 
2332   g_assert_no_error (error);
2333   g_assert (retval);
2334   g_assert_cmpstr (arg1, ==, "arg1");
2335   g_assert_cmpstr (arg2, ==, "arg2");
2336   g_assert_cmpstr (arg3, ==, "arg3");
2337   g_assert_cmpstr (arg4, ==, "arg4");
2338   g_assert_cmpstr (arg5, ==, "arg5");
2339 
2340   g_free (arg1);
2341   g_free (arg2);
2342   g_free (arg3);
2343   g_free (arg4);
2344   g_free (arg5);
2345 
2346   g_free (argv);
2347   g_strfreev (orig_argv);
2348   g_option_context_free (context);
2349 }
2350 
2351 static gint
option_context_parse_command_line(GOptionContext * context,const gchar * command_line)2352 option_context_parse_command_line (GOptionContext *context,
2353                                    const gchar    *command_line)
2354 {
2355   gchar **argv;
2356   guint argv_len, argv_new_len;
2357   gboolean success;
2358 
2359   argv = split_string (command_line, NULL);
2360   argv_len = g_strv_length (argv);
2361 
2362   success = g_option_context_parse_strv (context, &argv, NULL);
2363   argv_new_len = g_strv_length (argv);
2364 
2365   g_strfreev (argv);
2366   return success ? (gint) (argv_len - argv_new_len) : -1;
2367 }
2368 
2369 static void
test_strict_posix(void)2370 test_strict_posix (void)
2371 {
2372   GOptionContext *context;
2373   gboolean foo;
2374   gboolean bar;
2375   GOptionEntry entries[] = {
2376     { "foo", 'f', 0, G_OPTION_ARG_NONE, &foo, NULL, NULL },
2377     { "bar", 'b', 0, G_OPTION_ARG_NONE, &bar, NULL, NULL },
2378     G_OPTION_ENTRY_NULL
2379   };
2380   gint n_parsed;
2381 
2382   context = g_option_context_new (NULL);
2383   g_option_context_add_main_entries (context, entries, NULL);
2384 
2385   foo = bar = FALSE;
2386   g_option_context_set_strict_posix (context, FALSE);
2387   n_parsed = option_context_parse_command_line (context, "program --foo command --bar");
2388   g_assert_cmpint (n_parsed, ==, 2);
2389   g_assert (foo == TRUE);
2390   g_assert (bar == TRUE);
2391 
2392   foo = bar = FALSE;
2393   g_option_context_set_strict_posix (context, TRUE);
2394   n_parsed = option_context_parse_command_line (context, "program --foo command --bar");
2395   g_assert_cmpint (n_parsed, ==, 1);
2396   g_assert (foo == TRUE);
2397   g_assert (bar == FALSE);
2398 
2399   foo = bar = FALSE;
2400   g_option_context_set_strict_posix (context, TRUE);
2401   n_parsed = option_context_parse_command_line (context, "program --foo --bar command");
2402   g_assert_cmpint (n_parsed, ==, 2);
2403   g_assert (foo == TRUE);
2404   g_assert (bar == TRUE);
2405 
2406   foo = bar = FALSE;
2407   g_option_context_set_strict_posix (context, TRUE);
2408   n_parsed = option_context_parse_command_line (context, "program command --foo --bar");
2409   g_assert_cmpint (n_parsed, ==, 0);
2410   g_assert (foo == FALSE);
2411   g_assert (bar == FALSE);
2412 
2413   g_option_context_free (context);
2414 }
2415 
2416 static void
flag_reverse_string(void)2417 flag_reverse_string (void)
2418 {
2419   GOptionContext *context;
2420   gchar *arg = NULL;
2421   GOptionEntry entries [] =
2422     { { "test", 't', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_STRING, &arg, NULL, NULL },
2423       G_OPTION_ENTRY_NULL };
2424   gchar **argv;
2425   gint argc;
2426   gboolean retval;
2427   GError *error = NULL;
2428 
2429   if (!g_test_undefined ())
2430     return;
2431 
2432   context = g_option_context_new (NULL);
2433 
2434   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
2435                          "*ignoring reverse flag*");
2436   g_option_context_add_main_entries (context, entries, NULL);
2437   g_test_assert_expected_messages ();
2438 
2439   argv = split_string ("program --test bla", &argc);
2440 
2441   retval = g_option_context_parse_strv (context, &argv, &error);
2442   g_assert (retval == TRUE);
2443   g_assert_no_error (error);
2444   g_strfreev (argv);
2445   g_option_context_free (context);
2446   g_free (arg);
2447 }
2448 
2449 static void
flag_optional_int(void)2450 flag_optional_int (void)
2451 {
2452   GOptionContext *context;
2453   gint arg = 0;
2454   GOptionEntry entries [] =
2455     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &arg, NULL, NULL },
2456       G_OPTION_ENTRY_NULL };
2457   gchar **argv;
2458   gint argc;
2459   gboolean retval;
2460   GError *error = NULL;
2461 
2462   if (!g_test_undefined ())
2463     return;
2464 
2465   context = g_option_context_new (NULL);
2466 
2467   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
2468                          "*ignoring no-arg, optional-arg or filename flags*");
2469   g_option_context_add_main_entries (context, entries, NULL);
2470   g_test_assert_expected_messages ();
2471 
2472   argv = split_string ("program --test 5", &argc);
2473 
2474   retval = g_option_context_parse_strv (context, &argv, &error);
2475   g_assert (retval == TRUE);
2476   g_assert_no_error (error);
2477   g_strfreev (argv);
2478   g_option_context_free (context);
2479 }
2480 
2481 static void
short_remaining(void)2482 short_remaining (void)
2483 {
2484   gboolean ignore = FALSE;
2485   gboolean remaining = FALSE;
2486   gint number = 0;
2487   gchar* text = NULL;
2488   gchar** files = NULL;
2489   GError* error = NULL;
2490   GOptionEntry entries[] =
2491   {
2492     { "ignore", 'i', 0, G_OPTION_ARG_NONE, &ignore, NULL, NULL },
2493     { "remaining", 'r', 0, G_OPTION_ARG_NONE, &remaining, NULL, NULL },
2494     { "number", 'n', 0, G_OPTION_ARG_INT, &number, NULL, NULL },
2495     { "text", 't', 0, G_OPTION_ARG_STRING, &text, NULL, NULL },
2496     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files, NULL, NULL },
2497     G_OPTION_ENTRY_NULL
2498   };
2499   GOptionContext* context;
2500   gchar **argv, **argv_copy;
2501   gint argc;
2502 
2503   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=729563");
2504 
2505   argv = split_string ("program -ri -n 4 -t hello file1 file2", &argc);
2506   argv_copy = copy_stringv (argv, argc);
2507 
2508   context = g_option_context_new (NULL);
2509 
2510   g_option_context_add_main_entries (context, entries, NULL);
2511   g_option_context_set_ignore_unknown_options (context, TRUE);
2512 
2513   g_option_context_parse (context, &argc, &argv, &error);
2514   g_assert_no_error (error);
2515 
2516   g_assert (ignore);
2517   g_assert (remaining);
2518   g_assert_cmpint (number, ==, 4);
2519   g_assert_cmpstr (text, ==, "hello");
2520   g_assert_cmpstr (files[0], ==, "file1");
2521   g_assert_cmpstr (files[1], ==, "file2");
2522   g_assert (files[2] == NULL);
2523 
2524   g_free (text);
2525   g_strfreev (files);
2526   g_strfreev (argv_copy);
2527   g_free (argv);
2528   g_option_context_free (context);
2529 }
2530 
2531 static void
double_free(void)2532 double_free (void)
2533 {
2534   gchar* text = NULL;
2535   GOptionEntry entries[] =
2536   {
2537     { "known", 0, 0, G_OPTION_ARG_STRING, &text, NULL, NULL },
2538     G_OPTION_ENTRY_NULL
2539   };
2540   GOptionContext* context;
2541   gchar **argv;
2542   gint argc;
2543   GError *error = NULL;
2544 
2545   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=646926");
2546 
2547   argv = split_string ("program --known=foo --known=bar --unknown=baz", &argc);
2548 
2549   context = g_option_context_new (NULL);
2550 
2551   g_option_context_add_main_entries (context, entries, NULL);
2552   g_option_context_set_ignore_unknown_options (context, FALSE);
2553   g_option_context_parse (context, &argc, &argv, &error);
2554 
2555   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION);
2556   g_assert_null (text);
2557 
2558   g_option_context_free (context);
2559   g_clear_error (&error);
2560   g_strfreev (argv);
2561 
2562 }
2563 
2564 static void
double_zero(void)2565 double_zero (void)
2566 {
2567   GOptionContext *context;
2568   gboolean retval;
2569   GError *error = NULL;
2570   gchar **argv_copy;
2571   gchar **argv;
2572   int argc;
2573   double test_val = NAN;
2574   GOptionEntry entries [] =
2575     { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &test_val, NULL, NULL },
2576       G_OPTION_ENTRY_NULL };
2577 
2578   context = g_option_context_new (NULL);
2579   g_option_context_add_main_entries (context, entries, NULL);
2580 
2581   /* Now try parsing */
2582   argv = split_string ("program --test 0", &argc);
2583   argv_copy = copy_stringv (argv, argc);
2584 
2585   retval = g_option_context_parse (context, &argc, &argv, &error);
2586   g_assert_no_error (error);
2587   g_assert (retval);
2588 
2589   /* Last arg specified is the one that should be stored */
2590   g_assert (test_val == 0);
2591 
2592   g_strfreev (argv_copy);
2593   g_free (argv);
2594   g_option_context_free (context);
2595 }
2596 
2597 int
main(int argc,char * argv[])2598 main (int   argc,
2599       char *argv[])
2600 {
2601   int i;
2602   gchar *test_name;
2603 
2604   g_setenv ("LC_ALL", "C", TRUE);
2605   g_test_init (&argc, &argv, NULL);
2606 
2607   g_test_add_func ("/option/help/options", test_help);
2608   g_test_add_func ("/option/help/no-options", test_help_no_options);
2609   g_test_add_func ("/option/help/no-help-options", test_help_no_help_options);
2610 
2611   g_test_add_func ("/option/basic", test_basic);
2612   g_test_add_func ("/option/translate", test_translate);
2613 
2614   g_test_add_func ("/option/group/captions", test_group_captions);
2615   for (i = 0; i < 4; i++)
2616     {
2617       test_name = g_strdup_printf ("/option/group/captions/subprocess/help-%d", i);
2618       g_test_add_data_func (test_name, GINT_TO_POINTER (i),
2619                             test_group_captions_help);
2620       g_free (test_name);
2621       test_name = g_strdup_printf ("/option/group/captions/subprocess/help-all-%d", i);
2622       g_test_add_data_func (test_name, GINT_TO_POINTER (i),
2623                             test_group_captions_help_all);
2624       g_free (test_name);
2625       test_name = g_strdup_printf ("/option/group/captions/subprocess/help-test-%d", i);
2626       g_test_add_data_func (test_name, GINT_TO_POINTER (i),
2627                             test_group_captions_help_test);
2628 
2629       g_free (test_name);
2630     }
2631 
2632   g_test_add_func ("/option/group/main", test_main_group);
2633   g_test_add_func ("/option/group/error-hook", test_error_hook);
2634   g_test_add_func ("/option/group/parse", test_group_parse);
2635   g_test_add_func ("/option/strict-posix", test_strict_posix);
2636 
2637   /* Test that restoration on failure works */
2638   g_test_add_func ("/option/restoration/int", error_test1);
2639   g_test_add_func ("/option/restoration/string", error_test2);
2640   g_test_add_func ("/option/restoration/boolean", error_test3);
2641 
2642   /* Test that special argument parsing works */
2643   g_test_add_func ("/option/arg/repetition/int", arg_test1);
2644   g_test_add_func ("/option/arg/repetition/string", arg_test2);
2645   g_test_add_func ("/option/arg/repetition/filename", arg_test3);
2646   g_test_add_func ("/option/arg/repetition/double", arg_test4);
2647   g_test_add_func ("/option/arg/repetition/locale", arg_test5);
2648   g_test_add_func ("/option/arg/repetition/int64", arg_test6);
2649 
2650   /* Test string arrays */
2651   g_test_add_func ("/option/arg/array/string", array_test1);
2652 
2653   /* Test callback args */
2654   g_test_add_func ("/option/arg/callback/string", callback_test1);
2655   g_test_add_func ("/option/arg/callback/count", callback_test2);
2656 
2657   /* Test optional arg flag for callback */
2658   g_test_add_func ("/option/arg/callback/optional1", callback_test_optional_1);
2659   g_test_add_func ("/option/arg/callback/optional2", callback_test_optional_2);
2660   g_test_add_func ("/option/arg/callback/optional3", callback_test_optional_3);
2661   g_test_add_func ("/option/arg/callback/optional4", callback_test_optional_4);
2662   g_test_add_func ("/option/arg/callback/optional5", callback_test_optional_5);
2663   g_test_add_func ("/option/arg/callback/optional6", callback_test_optional_6);
2664   g_test_add_func ("/option/arg/callback/optional7", callback_test_optional_7);
2665   g_test_add_func ("/option/arg/callback/optional8", callback_test_optional_8);
2666 
2667   /* Test callback with G_OPTION_REMAINING */
2668   g_test_add_func ("/option/arg/remaining/callback", callback_remaining_test1);
2669 
2670   /* Test callbacks which return FALSE */
2671   g_test_add_func ("/option/arg/remaining/callback-false", callback_returns_false);
2672 
2673   /* Test ignoring options */
2674   g_test_add_func ("/option/arg/ignore/long", ignore_test1);
2675   g_test_add_func ("/option/arg/ignore/short", ignore_test2);
2676   g_test_add_func ("/option/arg/ignore/arg", ignore_test3);
2677   g_test_add_func ("/option/context/add", add_test1);
2678 
2679   /* Test parsing empty args */
2680   /* Note there used to be an empty1 here, but it effectively moved
2681    * to option-argv0.c.
2682    */
2683   g_test_add_func ("/option/context/empty2", empty_test2);
2684   g_test_add_func ("/option/context/empty3", empty_test3);
2685 
2686   /* Test handling of rest args */
2687   g_test_add_func ("/option/arg/rest/non-option", rest_test1);
2688   g_test_add_func ("/option/arg/rest/separator1", rest_test2);
2689   g_test_add_func ("/option/arg/rest/separator2", rest_test2a);
2690   g_test_add_func ("/option/arg/rest/separator3", rest_test2b);
2691   g_test_add_func ("/option/arg/rest/separator4", rest_test2c);
2692   g_test_add_func ("/option/arg/rest/separator5", rest_test2d);
2693   g_test_add_func ("/option/arg/remaining/non-option", rest_test3);
2694   g_test_add_func ("/option/arg/remaining/separator", rest_test4);
2695   g_test_add_func ("/option/arg/remaining/array", rest_test5);
2696 
2697   /* Test some invalid flag combinations */
2698   g_test_add_func ("/option/arg/reverse-string", flag_reverse_string);
2699   g_test_add_func ("/option/arg/optional-int", flag_optional_int);
2700 
2701   /* regression tests for individual bugs */
2702   g_test_add_func ("/option/bug/unknown-short", unknown_short_test);
2703   g_test_add_func ("/option/bug/lonely-dash", lonely_dash_test);
2704   g_test_add_func ("/option/bug/triple-dash", triple_dash_test);
2705   g_test_add_func ("/option/bug/missing-arg", missing_arg_test);
2706   g_test_add_func ("/option/bug/dash-arg", dash_arg_test);
2707   g_test_add_func ("/option/bug/short-remaining", short_remaining);
2708   g_test_add_func ("/option/bug/double-free", double_free);
2709   g_test_add_func ("/option/bug/double-zero", double_zero);
2710 
2711   return g_test_run();
2712 }
2713