5b839d9faf92bc6678b4b310505ed1c09e65b57a
[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 void
31 group_captions (void)
32 {
33   gchar *help_variants[] = { "--help", "--help-all", "--help-test" };
34
35   GOptionEntry main_entries[] = {
36     { "main-switch", 0, 0,
37       G_OPTION_ARG_NONE, NULL,
38       "A switch that is in the main group", NULL },
39     { NULL }
40   };
41
42   GOptionEntry group_entries[] = {
43     { "test-switch", 0, 0,
44       G_OPTION_ARG_NONE, NULL,
45       "A switch that is in the test group", NULL },
46     { NULL }
47   };
48
49   gint i, j;
50
51   g_test_bug ("504142");
52
53   for (i = 0; i < 4; ++i)
54     {
55       gboolean have_main_entries = (0 != (i & 1));
56       gboolean have_test_entries = (0 != (i & 2));
57
58       GOptionContext *options;
59       GOptionGroup   *group = NULL;
60
61       options = g_option_context_new (NULL);
62
63       if (have_main_entries)
64         g_option_context_add_main_entries (options, main_entries, NULL);
65       if (have_test_entries)
66         {
67           group = g_option_group_new ("test", "Test Options",
68                                       "Show all test options",
69                                       NULL, NULL);
70           g_option_context_add_group (options, group);
71           g_option_group_add_entries (group, group_entries);
72         }
73
74       for (j = 0; j < G_N_ELEMENTS (help_variants); ++j)
75         {
76           GTestTrapFlags trap_flags = 0;
77           gchar *args[3];
78
79           args[0] = __FILE__;
80           args[1] = help_variants[j];
81           args[2] = NULL;
82
83           if (!g_test_verbose ())
84             trap_flags |= G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR;
85
86           g_test_message ("test setup: args='%s', main-entries=%d, test-entries=%d",
87                           args[1], have_main_entries, have_test_entries);
88
89           if (g_test_trap_fork (0, trap_flags))
90             {
91               gchar **argv = args;
92               gint    argc = 2;
93               GError *error = NULL;
94
95               g_setenv ("LANG", "C", TRUE);
96
97               g_option_context_parse (options, &argc, &argv, &error);
98               g_option_context_free (options);
99               exit(0);
100             }
101           else
102             {
103               gboolean expect_main_description = FALSE;
104               gboolean expect_main_switch      = FALSE;
105
106               gboolean expect_test_description = FALSE;
107               gboolean expect_test_switch      = FALSE;
108               gboolean expect_test_group       = FALSE;
109
110               g_test_trap_assert_passed ();
111               g_test_trap_assert_stderr ("");
112
113               switch (j)
114                 {
115                   case 0:
116                     g_assert_cmpstr ("--help", ==, args[1]);
117                     expect_main_switch = have_main_entries;
118                     expect_test_group  = have_test_entries;
119                     break;
120
121                   case 1:
122                     g_assert_cmpstr ("--help-all", ==, args[1]);
123                     expect_main_switch = have_main_entries;
124                     expect_test_switch = have_test_entries;
125                     expect_test_group  = have_test_entries;
126                     break;
127
128                   case 2:
129                     g_assert_cmpstr ("--help-test", ==, args[1]);
130                     expect_test_switch = have_test_entries;
131                     break;
132
133                   default:
134                     g_assert_not_reached ();
135                     break;
136                 }
137
138               expect_main_description |= expect_main_switch;
139               expect_test_description |= expect_test_switch;
140
141               if (expect_main_description)
142                 g_test_trap_assert_stdout           ("*Application Options*");
143               else
144                 g_test_trap_assert_stdout_unmatched ("*Application Options*");
145               if (expect_main_switch)
146                 g_test_trap_assert_stdout           ("*--main-switch*");
147               else
148                 g_test_trap_assert_stdout_unmatched ("*--main-switch*");
149
150               if (expect_test_description)
151                 g_test_trap_assert_stdout           ("*Test Options*");
152               else
153                 g_test_trap_assert_stdout_unmatched ("*Test Options*");
154               if (expect_test_switch)
155                 g_test_trap_assert_stdout           ("*--test-switch*");
156               else
157                 g_test_trap_assert_stdout_unmatched ("*--test-switch*");
158
159               if (expect_test_group)
160                 g_test_trap_assert_stdout           ("*--help-test*");
161               else
162                 g_test_trap_assert_stdout_unmatched ("*--help-test*");
163             }
164         }
165
166       g_option_context_free (options);
167     }
168 }
169
170 int error_test1_int;
171 char *error_test2_string;
172 gboolean error_test3_boolean;
173
174 int arg_test1_int;
175 gchar *arg_test2_string;
176 gchar *arg_test3_filename;
177 gdouble arg_test4_double;
178 gdouble arg_test5_double;
179 gint64 arg_test6_int64;
180 gint64 arg_test6_int64_2;
181
182 gchar *callback_test1_string;
183 int callback_test2_int;
184
185 gchar *callback_test_optional_string;
186 gboolean callback_test_optional_boolean;
187
188 gchar **array_test1_array;
189
190 gboolean ignore_test1_boolean;
191 gboolean ignore_test2_boolean;
192 gchar *ignore_test3_string;
193
194 static gchar **
195 split_string (const char *str, int *argc)
196 {
197   gchar **argv;
198   int len;
199   
200   argv = g_strsplit (str, " ", 0);
201
202   for (len = 0; argv[len] != NULL; len++);
203
204   if (argc)
205     *argc = len;
206     
207   return argv;
208 }
209
210 static gchar *
211 join_stringv (int argc, char **argv)
212 {
213   int i;
214   GString *str;
215
216   str = g_string_new (NULL);
217
218   for (i = 0; i < argc; i++)
219     {
220       g_string_append (str, argv[i]);
221
222       if (i < argc - 1)
223         g_string_append_c (str, ' ');
224     }
225
226   return g_string_free (str, FALSE);
227 }
228
229 /* Performs a shallow copy */
230 static char **
231 copy_stringv (char **argv, int argc)
232 {
233   return g_memdup (argv, sizeof (char *) * (argc + 1));
234 }
235
236 static void
237 check_identical_stringv (gchar **before, gchar **after)
238 {
239   guint i;
240
241   /* Not only is it the same string... */
242   for (i = 0; before[i] != NULL; i++)
243     g_assert_cmpstr (before[i], ==, after[i]);
244
245   /* ... it is actually the same pointer */
246   for (i = 0; before[i] != NULL; i++)
247     g_assert (before[i] == after[i]);
248
249   g_assert (after[i] == NULL);
250 }
251
252
253 static gboolean
254 error_test1_pre_parse (GOptionContext *context,
255                        GOptionGroup   *group,
256                        gpointer        data,
257                        GError        **error)
258 {
259   g_assert (error_test1_int == 0x12345678);
260
261   return TRUE;
262 }
263
264 static gboolean
265 error_test1_post_parse (GOptionContext *context,
266                         GOptionGroup   *group,
267                         gpointer          data,
268                         GError        **error)
269 {
270   g_assert (error_test1_int == 20);
271
272   /* Set an error in the post hook */
273   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
274
275   return FALSE;
276 }
277
278 static void
279 error_test1 (void)
280 {
281   GOptionContext *context;
282   gboolean retval;
283   GError *error = NULL;
284   gchar **argv;
285   gchar **argv_copy;
286   int argc;
287   GOptionGroup *main_group;
288   GOptionEntry entries [] =
289     { { "test", 0, 0, G_OPTION_ARG_INT, &error_test1_int, NULL, NULL },
290       { NULL } };
291   
292   error_test1_int = 0x12345678;
293
294   context = g_option_context_new (NULL);
295   g_option_context_add_main_entries (context, entries, NULL);
296
297   /* Set pre and post parse hooks */
298   main_group = g_option_context_get_main_group (context);
299   g_option_group_set_parse_hooks (main_group,
300                                   error_test1_pre_parse, error_test1_post_parse);
301   
302   /* Now try parsing */
303   argv = split_string ("program --test 20", &argc);
304   argv_copy = copy_stringv (argv, argc);
305
306   retval = g_option_context_parse (context, &argc, &argv, &error);
307   g_assert (retval == FALSE);
308   g_assert (error != NULL);
309   /* An error occurred, so argv has not been changed */
310   check_identical_stringv (argv_copy, argv);
311   g_clear_error (&error);
312
313   /* On failure, values should be reset */
314   g_assert (error_test1_int == 0x12345678);
315
316   g_strfreev (argv_copy);
317   g_free (argv);
318   g_option_context_free (context);
319 }
320
321 static gboolean
322 error_test2_pre_parse (GOptionContext *context,
323                        GOptionGroup   *group,
324                        gpointer   data,
325                        GError        **error)
326 {
327   g_assert (strcmp (error_test2_string, "foo") == 0);
328
329   return TRUE;
330 }
331
332 static gboolean
333 error_test2_post_parse (GOptionContext *context,
334                         GOptionGroup   *group,
335                         gpointer          data,
336                         GError        **error)
337 {
338   g_assert (strcmp (error_test2_string, "bar") == 0);
339
340   /* Set an error in the post hook */
341   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
342
343   return FALSE;
344 }
345
346 static void
347 error_test2 (void)
348 {
349   GOptionContext *context;
350   gboolean retval;
351   GError *error = NULL;
352   gchar **argv;
353   gchar **argv_copy;
354   int argc;
355   GOptionGroup *main_group;
356   GOptionEntry entries [] =
357     { { "test", 0, 0, G_OPTION_ARG_STRING, &error_test2_string, NULL, NULL },
358       { NULL } };
359
360   error_test2_string = "foo";
361
362   context = g_option_context_new (NULL);
363   g_option_context_add_main_entries (context, entries, NULL);
364
365   /* Set pre and post parse hooks */
366   main_group = g_option_context_get_main_group (context);
367   g_option_group_set_parse_hooks (main_group,
368                                   error_test2_pre_parse, error_test2_post_parse);
369   
370   /* Now try parsing */
371   argv = split_string ("program --test bar", &argc);
372   argv_copy = copy_stringv (argv, argc);
373   retval = g_option_context_parse (context, &argc, &argv, &error);
374
375   g_assert (retval == FALSE);
376   g_assert (error != NULL);
377   check_identical_stringv (argv_copy, argv);
378   g_clear_error (&error);
379
380   g_assert (strcmp (error_test2_string, "foo") == 0);
381
382   g_strfreev (argv_copy);
383   g_free (argv);
384   g_option_context_free (context);
385 }
386
387 static gboolean
388 error_test3_pre_parse (GOptionContext *context,
389                        GOptionGroup   *group,
390                        gpointer   data,
391                        GError        **error)
392 {
393   g_assert (!error_test3_boolean);
394
395   return TRUE;
396 }
397
398 static gboolean
399 error_test3_post_parse (GOptionContext *context,
400                         GOptionGroup   *group,
401                         gpointer          data,
402                         GError        **error)
403 {
404   g_assert (error_test3_boolean);
405
406   /* Set an error in the post hook */
407   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
408
409   return FALSE;
410 }
411
412 static void
413 error_test3 (void)
414 {
415   GOptionContext *context;
416   gboolean retval;
417   GError *error = NULL;
418   gchar **argv;
419   gchar **argv_copy;
420   int argc;
421   GOptionGroup *main_group;
422   GOptionEntry entries [] =
423     { { "test", 0, 0, G_OPTION_ARG_NONE, &error_test3_boolean, NULL, NULL },
424       { NULL } };
425
426   error_test3_boolean = FALSE;
427
428   context = g_option_context_new (NULL);
429   g_option_context_add_main_entries (context, entries, NULL);
430
431   /* Set pre and post parse hooks */
432   main_group = g_option_context_get_main_group (context);
433   g_option_group_set_parse_hooks (main_group,
434                                   error_test3_pre_parse, error_test3_post_parse);
435   
436   /* Now try parsing */
437   argv = split_string ("program --test", &argc);
438   argv_copy = copy_stringv (argv, argc);
439   retval = g_option_context_parse (context, &argc, &argv, &error);
440
441   g_assert (retval == FALSE);
442   g_assert (error != NULL);
443   check_identical_stringv (argv_copy, argv);
444   g_clear_error (&error);
445
446   g_assert (!error_test3_boolean);
447
448   g_strfreev (argv_copy);
449   g_free (argv);
450   g_option_context_free (context);
451 }
452
453 static void
454 arg_test1 (void)
455 {
456   GOptionContext *context;
457   gboolean retval;
458   GError *error = NULL;
459   gchar **argv;
460   gchar **argv_copy;
461   int argc;
462   GOptionEntry entries [] =
463     { { "test", 0, 0, G_OPTION_ARG_INT, &arg_test1_int, NULL, NULL },
464       { NULL } };
465
466   context = g_option_context_new (NULL);
467   g_option_context_add_main_entries (context, entries, NULL);
468
469   /* Now try parsing */
470   argv = split_string ("program --test 20 --test 30", &argc);
471   argv_copy = copy_stringv (argv, argc);
472
473   retval = g_option_context_parse (context, &argc, &argv, &error);
474   g_assert_no_error (error);
475   g_assert (retval);
476
477   /* Last arg specified is the one that should be stored */
478   g_assert (arg_test1_int == 30);
479
480   /* We free all of the strings in a copy of argv, because now argv is a
481    * subset - some have been removed in-place
482    */
483   g_strfreev (argv_copy);
484   g_free (argv);
485   g_option_context_free (context);
486 }
487
488 static void
489 arg_test2 (void)
490 {
491   GOptionContext *context;
492   gboolean retval;
493   GError *error = NULL;
494   gchar **argv;
495   gchar **argv_copy;
496   int argc;
497   GOptionEntry entries [] =
498     { { "test", 0, 0, G_OPTION_ARG_STRING, &arg_test2_string, NULL, NULL },
499       { NULL } };
500   
501   context = g_option_context_new (NULL);
502   g_option_context_add_main_entries (context, entries, NULL);
503
504   /* Now try parsing */
505   argv = split_string ("program --test foo --test bar", &argc);
506   argv_copy = copy_stringv (argv, argc);
507
508   retval = g_option_context_parse (context, &argc, &argv, &error);
509   g_assert_no_error (error);
510   g_assert (retval);
511
512   /* Last arg specified is the one that should be stored */
513   g_assert (strcmp (arg_test2_string, "bar") == 0);
514
515   g_free (arg_test2_string);
516
517   g_strfreev (argv_copy);
518   g_free (argv);
519   g_option_context_free (context);
520 }
521
522 static void
523 arg_test3 (void)
524 {
525   GOptionContext *context;
526   gboolean retval;
527   GError *error = NULL;
528   gchar **argv;
529   gchar **argv_copy;
530   int argc;
531   GOptionEntry entries [] =
532     { { "test", 0, 0, G_OPTION_ARG_FILENAME, &arg_test3_filename, NULL, NULL },
533       { NULL } };
534   
535   context = g_option_context_new (NULL);
536   g_option_context_add_main_entries (context, entries, NULL);
537
538   /* Now try parsing */
539   argv = split_string ("program --test foo.txt", &argc);
540   argv_copy = copy_stringv (argv, argc);
541
542   retval = g_option_context_parse (context, &argc, &argv, &error);
543   g_assert_no_error (error);
544   g_assert (retval);
545
546   /* Last arg specified is the one that should be stored */
547   g_assert (strcmp (arg_test3_filename, "foo.txt") == 0);
548
549   g_free (arg_test3_filename);
550
551   g_strfreev (argv_copy);
552   g_free (argv);
553   g_option_context_free (context);
554 }
555
556
557 static void
558 arg_test4 (void)
559 {
560   GOptionContext *context;
561   gboolean retval;
562   GError *error = NULL;
563   gchar **argv_copy;
564   gchar **argv;
565   int argc;
566   GOptionEntry entries [] =
567     { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test4_double, NULL, NULL },
568       { NULL } };
569
570   context = g_option_context_new (NULL);
571   g_option_context_add_main_entries (context, entries, NULL);
572
573   /* Now try parsing */
574   argv = split_string ("program --test 20.0 --test 30.03", &argc);
575   argv_copy = copy_stringv (argv, argc);
576
577   retval = g_option_context_parse (context, &argc, &argv, &error);
578   g_assert_no_error (error);
579   g_assert (retval);
580
581   /* Last arg specified is the one that should be stored */
582   g_assert (arg_test4_double == 30.03);
583
584   g_strfreev (argv_copy);
585   g_free (argv);
586   g_option_context_free (context);
587 }
588
589 static void
590 arg_test5 (void)
591 {
592   GOptionContext *context;
593   gboolean retval;
594   GError *error = NULL;
595   gchar **argv;
596   gchar **argv_copy;
597   int argc;
598   char *old_locale, *current_locale;
599   const char *locale = "de_DE";
600   GOptionEntry entries [] =
601     { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test5_double, NULL, NULL },
602       { NULL } };
603
604   context = g_option_context_new (NULL);
605   g_option_context_add_main_entries (context, entries, NULL);
606
607   /* Now try parsing */
608   argv = split_string ("program --test 20,0 --test 30,03", &argc);
609   argv_copy = copy_stringv (argv, argc);
610
611   /* set it to some locale that uses commas instead of decimal points */
612   
613   old_locale = g_strdup (setlocale (LC_NUMERIC, locale));
614   current_locale = setlocale (LC_NUMERIC, NULL);
615   if (strcmp (current_locale, locale) != 0)
616     {
617       fprintf (stderr, "Cannot set locale to %s, skipping\n", locale);
618       goto cleanup; 
619     }
620
621   retval = g_option_context_parse (context, &argc, &argv, &error);
622   g_assert_no_error (error);
623   g_assert (retval);
624
625   /* Last arg specified is the one that should be stored */
626   g_assert (arg_test5_double == 30.03);
627
628  cleanup:
629   setlocale (LC_NUMERIC, old_locale);
630   g_free (old_locale);
631
632   g_strfreev (argv_copy);
633   g_free (argv);
634   g_option_context_free (context);
635 }
636
637 static void
638 arg_test6 (void)
639 {
640   GOptionContext *context;
641   gboolean retval;
642   GError *error = NULL;
643   gchar **argv;
644   gchar **argv_copy;
645   int argc;
646   GOptionEntry entries [] =
647     { { "test", 0, 0, G_OPTION_ARG_INT64, &arg_test6_int64, NULL, NULL },
648       { "test2", 0, 0, G_OPTION_ARG_INT64, &arg_test6_int64_2, NULL, NULL },
649       { NULL } };
650
651   context = g_option_context_new (NULL);
652   g_option_context_add_main_entries (context, entries, NULL);
653
654   /* Now try parsing */
655   argv = split_string ("program --test 4294967297 --test 4294967296 --test2 0xfffffffff", &argc);
656   argv_copy = copy_stringv (argv, argc);
657
658   retval = g_option_context_parse (context, &argc, &argv, &error);
659   g_assert_no_error (error);
660   g_assert (retval);
661
662   /* Last arg specified is the one that should be stored */
663   g_assert (arg_test6_int64 == G_GINT64_CONSTANT(4294967296));
664   g_assert (arg_test6_int64_2 == G_GINT64_CONSTANT(0xfffffffff));
665
666   g_strfreev (argv_copy);
667   g_free (argv);
668   g_option_context_free (context);
669 }
670
671 static gboolean
672 callback_parse1 (const gchar *option_name, const gchar *value,
673                  gpointer data, GError **error)
674 {
675         callback_test1_string = g_strdup (value);
676         return TRUE;
677 }
678
679 static void
680 callback_test1 (void)
681 {
682   GOptionContext *context;
683   gboolean retval;
684   GError *error = NULL;
685   gchar **argv;
686   gchar **argv_copy;
687   int argc;
688   GOptionEntry entries [] =
689     { { "test", 0, 0, G_OPTION_ARG_CALLBACK, callback_parse1, NULL, NULL },
690       { NULL } };
691   
692   context = g_option_context_new (NULL);
693   g_option_context_add_main_entries (context, entries, NULL);
694
695   /* Now try parsing */
696   argv = split_string ("program --test foo.txt", &argc);
697   argv_copy = copy_stringv (argv, argc);
698
699   retval = g_option_context_parse (context, &argc, &argv, &error);
700   g_assert_no_error (error);
701   g_assert (retval);
702
703   g_assert (strcmp (callback_test1_string, "foo.txt") == 0);
704
705   g_free (callback_test1_string);
706
707   g_strfreev (argv_copy);
708   g_free (argv);
709   g_option_context_free (context);
710 }
711
712 static gboolean
713 callback_parse2 (const gchar *option_name, const gchar *value,
714                  gpointer data, GError **error)
715 {
716         callback_test2_int++;
717         return TRUE;
718 }
719
720 static void
721 callback_test2 (void)
722 {
723   GOptionContext *context;
724   gboolean retval;
725   GError *error = NULL;
726   gchar **argv;
727   gchar **argv_copy;
728   int argc;
729   GOptionEntry entries [] =
730     { { "test", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_parse2, NULL, NULL },
731       { NULL } };
732   
733   context = g_option_context_new (NULL);
734   g_option_context_add_main_entries (context, entries, NULL);
735
736   /* Now try parsing */
737   argv = split_string ("program --test --test", &argc);
738   argv_copy = copy_stringv (argv, argc);
739
740   retval = g_option_context_parse (context, &argc, &argv, &error);
741   g_assert_no_error (error);
742   g_assert (retval);
743
744   g_assert (callback_test2_int == 2);
745
746   g_strfreev (argv_copy);
747   g_free (argv);
748   g_option_context_free (context);
749 }
750
751 static gboolean
752 callback_parse_optional (const gchar *option_name, const gchar *value,
753                  gpointer data, GError **error)
754 {
755         callback_test_optional_boolean = TRUE;
756         if (value)
757                 callback_test_optional_string = g_strdup (value);
758         else
759                 callback_test_optional_string = NULL;
760         return TRUE;
761 }
762
763 static void
764 callback_test_optional_1 (void)
765 {
766   GOptionContext *context;
767   gboolean retval;
768   GError *error = NULL;
769   gchar **argv;
770   gchar **argv_copy;
771   int argc;
772   GOptionEntry entries [] =
773     { { "test", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
774         callback_parse_optional, NULL, NULL },
775       { NULL } };
776   
777   context = g_option_context_new (NULL);
778   g_option_context_add_main_entries (context, entries, NULL);
779
780   /* Now try parsing */
781   argv = split_string ("program --test foo.txt", &argc);
782   argv_copy = copy_stringv (argv, argc);
783
784   retval = g_option_context_parse (context, &argc, &argv, &error);
785   g_assert_no_error (error);
786   g_assert (retval);
787
788   g_assert (strcmp (callback_test_optional_string, "foo.txt") == 0);
789   
790   g_assert (callback_test_optional_boolean);
791
792   g_free (callback_test_optional_string);
793
794   g_strfreev (argv_copy);
795   g_free (argv);
796   g_option_context_free (context);
797 }
798
799 static void
800 callback_test_optional_2 (void)
801 {
802   GOptionContext *context;
803   gboolean retval;
804   GError *error = NULL;
805   gchar **argv;
806   gchar **argv_copy;
807   int argc;
808   GOptionEntry entries [] =
809     { { "test", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
810         callback_parse_optional, NULL, NULL },
811       { NULL } };
812   
813   context = g_option_context_new (NULL);
814   g_option_context_add_main_entries (context, entries, NULL);
815
816   /* Now try parsing */
817   argv = split_string ("program --test", &argc);
818   argv_copy = copy_stringv (argv, argc);
819
820   retval = g_option_context_parse (context, &argc, &argv, &error);
821   g_assert_no_error (error);
822   g_assert (retval);
823
824   g_assert (callback_test_optional_string == NULL);
825   
826   g_assert (callback_test_optional_boolean);
827
828   g_free (callback_test_optional_string);
829
830   g_strfreev (argv_copy);
831   g_free (argv);
832   g_option_context_free (context);
833 }
834
835 static void
836 callback_test_optional_3 (void)
837 {
838   GOptionContext *context;
839   gboolean retval;
840   GError *error = NULL;
841   gchar **argv_copy;
842   gchar **argv;
843   int argc;
844   GOptionEntry entries [] =
845     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
846         callback_parse_optional, NULL, NULL },
847       { NULL } };
848   
849   context = g_option_context_new (NULL);
850   g_option_context_add_main_entries (context, entries, NULL);
851
852   /* Now try parsing */
853   argv = split_string ("program -t foo.txt", &argc);
854   argv_copy = copy_stringv (argv, argc);
855
856   retval = g_option_context_parse (context, &argc, &argv, &error);
857   g_assert_no_error (error);
858   g_assert (retval);
859
860   g_assert (strcmp (callback_test_optional_string, "foo.txt") == 0);
861   
862   g_assert (callback_test_optional_boolean);
863
864   g_free (callback_test_optional_string);
865
866   g_strfreev (argv_copy);
867   g_free (argv);
868   g_option_context_free (context);
869 }
870
871
872 static void
873 callback_test_optional_4 (void)
874 {
875   GOptionContext *context;
876   gboolean retval;
877   GError *error = NULL;
878   gchar **argv;
879   gchar **argv_copy;
880   int argc;
881   GOptionEntry entries [] =
882     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
883         callback_parse_optional, NULL, NULL },
884       { NULL } };
885   
886   context = g_option_context_new (NULL);
887   g_option_context_add_main_entries (context, entries, NULL);
888
889   /* Now try parsing */
890   argv = split_string ("program -t", &argc);
891   argv_copy = copy_stringv (argv, argc);
892
893   retval = g_option_context_parse (context, &argc, &argv, &error);
894   g_assert_no_error (error);
895   g_assert (retval);
896
897   g_assert (callback_test_optional_string == NULL);
898   
899   g_assert (callback_test_optional_boolean);
900
901   g_free (callback_test_optional_string);
902
903   g_strfreev (argv_copy);
904   g_free (argv);
905   g_option_context_free (context);
906 }
907
908 static void
909 callback_test_optional_5 (void)
910 {
911   GOptionContext *context;
912   gboolean dummy;
913   gboolean retval;
914   GError *error = NULL;
915   gchar **argv;
916   gchar **argv_copy;
917   int argc;
918   GOptionEntry entries [] =
919     { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
920       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
921         callback_parse_optional, NULL, NULL },
922       { NULL } };
923   
924   context = g_option_context_new (NULL);
925   g_option_context_add_main_entries (context, entries, NULL);
926
927   /* Now try parsing */
928   argv = split_string ("program --test --dummy", &argc);
929   argv_copy = copy_stringv (argv, argc);
930
931   retval = g_option_context_parse (context, &argc, &argv, &error);
932   g_assert_no_error (error);
933   g_assert (retval);
934
935   g_assert (callback_test_optional_string == NULL);
936   
937   g_assert (callback_test_optional_boolean);
938
939   g_free (callback_test_optional_string);
940
941   g_strfreev (argv_copy);
942   g_free (argv);
943   g_option_context_free (context);
944 }
945
946 static void
947 callback_test_optional_6 (void)
948 {
949   GOptionContext *context;
950   gboolean dummy;
951   gboolean retval;
952   GError *error = NULL;
953   gchar **argv;
954   gchar **argv_copy;
955   int argc;
956   GOptionEntry entries [] =
957     { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
958       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
959         callback_parse_optional, NULL, NULL },
960       { NULL } };
961   
962   context = g_option_context_new (NULL);
963   g_option_context_add_main_entries (context, entries, NULL);
964
965   /* Now try parsing */
966   argv = split_string ("program -t -d", &argc);
967   argv_copy = copy_stringv (argv, argc);
968
969   retval = g_option_context_parse (context, &argc, &argv, &error);
970   g_assert_no_error (error);
971   g_assert (retval);
972
973   g_assert (callback_test_optional_string == NULL);
974   
975   g_assert (callback_test_optional_boolean);
976
977   g_free (callback_test_optional_string);
978
979   g_strfreev (argv_copy);
980   g_free (argv);
981   g_option_context_free (context);
982 }
983
984 static void
985 callback_test_optional_7 (void)
986 {
987   GOptionContext *context;
988   gboolean dummy;
989   gboolean retval;
990   GError *error = NULL;
991   gchar **argv;
992   gchar **argv_copy;
993   int argc;
994   GOptionEntry entries [] =
995     { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
996       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
997         callback_parse_optional, NULL, NULL },
998       { NULL } };
999   
1000   context = g_option_context_new (NULL);
1001   g_option_context_add_main_entries (context, entries, NULL);
1002
1003   /* Now try parsing */
1004   argv = split_string ("program -td", &argc);
1005   argv_copy = copy_stringv (argv, argc);
1006
1007   retval = g_option_context_parse (context, &argc, &argv, &error);
1008   g_assert_no_error (error);
1009   g_assert (retval);
1010
1011   g_assert (callback_test_optional_string == NULL);
1012   
1013   g_assert (callback_test_optional_boolean);
1014
1015   g_free (callback_test_optional_string);
1016
1017   g_strfreev (argv_copy);
1018   g_free (argv);
1019   g_option_context_free (context);
1020 }
1021
1022 static void
1023 callback_test_optional_8 (void)
1024 {
1025   GOptionContext *context;
1026   gboolean dummy;
1027   gboolean retval;
1028   GError *error = NULL;
1029   gchar **argv;
1030   gchar **argv_copy;
1031   int argc;
1032   GOptionEntry entries [] =
1033     { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
1034       { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 
1035         callback_parse_optional, NULL, NULL },
1036       { NULL } };
1037   
1038   context = g_option_context_new (NULL);
1039   g_option_context_add_main_entries (context, entries, NULL);
1040
1041   /* Now try parsing */
1042   argv = split_string ("program -dt foo.txt", &argc);
1043   argv_copy = copy_stringv (argv, argc);
1044
1045   retval = g_option_context_parse (context, &argc, &argv, &error);
1046   g_assert_no_error (error);
1047   g_assert (retval);
1048
1049   g_assert (callback_test_optional_string);
1050   
1051   g_assert (callback_test_optional_boolean);
1052
1053   g_free (callback_test_optional_string);
1054
1055   g_strfreev (argv_copy);
1056   g_free (argv);
1057   g_option_context_free (context);
1058 }
1059
1060 static GPtrArray *callback_remaining_args;
1061 static gboolean
1062 callback_remaining_test1_callback (const gchar *option_name, const gchar *value,
1063                          gpointer data, GError **error)
1064 {
1065         g_ptr_array_add (callback_remaining_args, g_strdup (value));
1066         return TRUE;
1067 }
1068
1069 static void
1070 callback_remaining_test1 (void)
1071 {
1072   GOptionContext *context;
1073   gboolean retval;
1074   GError *error = NULL;
1075   gchar **argv;
1076   gchar **argv_copy;
1077   int argc;
1078   GOptionEntry entries [] =
1079     { { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_CALLBACK, callback_remaining_test1_callback, NULL, NULL },
1080       { NULL } };
1081   
1082   callback_remaining_args = g_ptr_array_new ();
1083   context = g_option_context_new (NULL);
1084   g_option_context_add_main_entries (context, entries, NULL);
1085
1086   /* Now try parsing */
1087   argv = split_string ("program foo.txt blah.txt", &argc);
1088   argv_copy = copy_stringv (argv, argc);
1089
1090   retval = g_option_context_parse (context, &argc, &argv, &error);
1091   g_assert_no_error (error);
1092   g_assert (retval);
1093
1094   g_assert (callback_remaining_args->len == 2);
1095   g_assert (strcmp (callback_remaining_args->pdata[0], "foo.txt") == 0);
1096   g_assert (strcmp (callback_remaining_args->pdata[1], "blah.txt") == 0);
1097
1098   g_ptr_array_foreach (callback_remaining_args, (GFunc) g_free, NULL);
1099   g_ptr_array_free (callback_remaining_args, TRUE);
1100
1101   g_strfreev (argv_copy);
1102   g_free (argv);
1103   g_option_context_free (context);
1104 }
1105
1106 static gboolean
1107 callback_error (const gchar *option_name, const gchar *value,
1108                 gpointer data, GError **error)
1109 {
1110   g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "42");
1111   return FALSE;
1112 }
1113
1114 static void
1115 callback_returns_false (void)
1116 {
1117   GOptionContext *context;
1118   gboolean retval;
1119   GError *error = NULL;
1120   gchar **argv;
1121   gchar **argv_copy;
1122   int argc;
1123   GOptionEntry entries [] =
1124     { { "error", 0, 0, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
1125       { "error-no-arg", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
1126       { "error-optional-arg", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
1127       { NULL } };
1128
1129   context = g_option_context_new (NULL);
1130   g_option_context_add_main_entries (context, entries, NULL);
1131
1132   /* Now try parsing */
1133   argv = split_string ("program --error value", &argc);
1134   argv_copy = copy_stringv (argv, argc);
1135
1136   retval = g_option_context_parse (context, &argc, &argv, &error);
1137   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
1138   g_assert (retval == FALSE);
1139   check_identical_stringv (argv_copy, argv);
1140
1141   g_option_context_free (context);
1142   g_clear_error (&error);
1143   g_strfreev (argv_copy);
1144   g_free (argv);
1145
1146   /* And again, this time with a no-arg variant */
1147   context = g_option_context_new (NULL);
1148   g_option_context_add_main_entries (context, entries, NULL);
1149
1150   argv = split_string ("program --error-no-arg", &argc);
1151   argv_copy = copy_stringv (argv, argc);
1152
1153   retval = g_option_context_parse (context, &argc, &argv, &error);
1154   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
1155   g_assert (retval == FALSE);
1156   check_identical_stringv (argv_copy, argv);
1157
1158   g_option_context_free (context);
1159   g_clear_error (&error);
1160   g_strfreev (argv_copy);
1161   g_free (argv);
1162
1163   /* And again, this time with a optional arg variant, with argument */
1164   context = g_option_context_new (NULL);
1165   g_option_context_add_main_entries (context, entries, NULL);
1166
1167   argv = split_string ("program --error-optional-arg value", &argc);
1168   argv_copy = copy_stringv (argv, argc);
1169
1170   retval = g_option_context_parse (context, &argc, &argv, &error);
1171   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
1172   g_assert (retval == FALSE);
1173   check_identical_stringv (argv_copy, argv);
1174
1175   g_option_context_free (context);
1176   g_clear_error (&error);
1177   g_strfreev (argv_copy);
1178   g_free (argv);
1179
1180   /* And again, this time with a optional arg variant, without argument */
1181   context = g_option_context_new (NULL);
1182   g_option_context_add_main_entries (context, entries, NULL);
1183
1184   argv = split_string ("program --error-optional-arg", &argc);
1185   argv_copy = copy_stringv (argv, argc);
1186
1187   retval = g_option_context_parse (context, &argc, &argv, &error);
1188   g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
1189   g_assert (retval == FALSE);
1190   check_identical_stringv (argv_copy, argv);
1191
1192   g_option_context_free (context);
1193   g_clear_error (&error);
1194   g_strfreev (argv_copy);
1195   g_free (argv);
1196 }
1197
1198
1199 static void
1200 ignore_test1 (void)
1201 {
1202   GOptionContext *context;
1203   gboolean retval;
1204   GError *error = NULL;
1205   gchar **argv, **argv_copy;
1206   int argc;
1207   gchar *arg;
1208   GOptionEntry entries [] =
1209     { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1210       { NULL } };
1211
1212   context = g_option_context_new (NULL);
1213   g_option_context_set_ignore_unknown_options (context, TRUE);
1214   g_option_context_add_main_entries (context, entries, NULL);
1215
1216   /* Now try parsing */
1217   argv = split_string ("program --test --hello", &argc);
1218   argv_copy = copy_stringv (argv, argc);
1219   
1220   retval = g_option_context_parse (context, &argc, &argv, &error);
1221   g_assert_no_error (error);
1222   g_assert (retval);
1223
1224   /* Check array */
1225   arg = join_stringv (argc, argv);
1226   g_assert (strcmp (arg, "program --hello") == 0);
1227
1228   g_free (arg);
1229   g_strfreev (argv_copy);
1230   g_free (argv);
1231   g_option_context_free (context);
1232 }
1233
1234 static void
1235 ignore_test2 (void)
1236 {
1237   GOptionContext *context;
1238   gboolean retval;
1239   GError *error = NULL;
1240   gchar **argv;
1241   gchar **argv_copy;
1242   int argc;
1243   gchar *arg;
1244   GOptionEntry entries [] =
1245     { { "test", 't', 0, G_OPTION_ARG_NONE, &ignore_test2_boolean, NULL, NULL },
1246       { NULL } };
1247
1248   context = g_option_context_new (NULL);
1249   g_option_context_set_ignore_unknown_options (context, TRUE);
1250   g_option_context_add_main_entries (context, entries, NULL);
1251
1252   /* Now try parsing */
1253   argv = split_string ("program -test", &argc);
1254   argv_copy = copy_stringv (argv, argc);
1255
1256   retval = g_option_context_parse (context, &argc, &argv, &error);
1257   g_assert_no_error (error);
1258   g_assert (retval);
1259
1260   /* Check array */
1261   arg = join_stringv (argc, argv);
1262   g_assert (strcmp (arg, "program -es") == 0);
1263
1264   g_free (arg);
1265   g_strfreev (argv_copy);
1266   g_free (argv);
1267   g_option_context_free (context);
1268 }
1269
1270 static void
1271 ignore_test3 (void)
1272 {
1273   GOptionContext *context;
1274   gboolean retval;
1275   GError *error = NULL;
1276   gchar **argv, **argv_copy;
1277   int argc;
1278   gchar *arg;
1279   GOptionEntry entries [] =
1280     { { "test", 0, 0, G_OPTION_ARG_STRING, &ignore_test3_string, NULL, NULL },
1281       { NULL } };
1282
1283   context = g_option_context_new (NULL);
1284   g_option_context_set_ignore_unknown_options (context, TRUE);
1285   g_option_context_add_main_entries (context, entries, NULL);
1286
1287   /* Now try parsing */
1288   argv = split_string ("program --test foo --hello", &argc);
1289   argv_copy = copy_stringv (argv, argc);
1290   
1291   retval = g_option_context_parse (context, &argc, &argv, &error);
1292   g_assert_no_error (error);
1293   g_assert (retval);
1294
1295   /* Check array */
1296   arg = join_stringv (argc, argv);
1297   g_assert (strcmp (arg, "program --hello") == 0);
1298
1299   g_assert (strcmp (ignore_test3_string, "foo") == 0);
1300   g_free (ignore_test3_string);
1301
1302   g_free (arg);
1303   g_strfreev (argv_copy);
1304   g_free (argv);
1305   g_option_context_free (context);
1306 }
1307
1308 void
1309 static array_test1 (void)
1310 {
1311   GOptionContext *context;
1312   gboolean retval;
1313   GError *error = NULL;
1314   gchar **argv;
1315   gchar **argv_copy;
1316   int argc;
1317   GOptionEntry entries [] =
1318     { { "test", 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
1319       { NULL } };
1320         
1321   context = g_option_context_new (NULL);
1322   g_option_context_add_main_entries (context, entries, NULL);
1323
1324   /* Now try parsing */
1325   argv = split_string ("program --test foo --test bar", &argc);
1326   argv_copy = copy_stringv (argv, argc);
1327
1328   retval = g_option_context_parse (context, &argc, &argv, &error);
1329   g_assert_no_error (error);
1330   g_assert (retval);
1331
1332   /* Check array */
1333   g_assert (strcmp (array_test1_array[0], "foo") == 0);
1334   g_assert (strcmp (array_test1_array[1], "bar") == 0);
1335   g_assert (array_test1_array[2] == NULL);
1336
1337   g_strfreev (array_test1_array);
1338   
1339   g_strfreev (argv_copy);
1340   g_free (argv);
1341   g_option_context_free (context);
1342 }
1343
1344 static void
1345 add_test1 (void)
1346 {
1347   GOptionContext *context;
1348
1349   GOptionEntry entries1 [] =
1350     { { "test1", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL },
1351       { NULL } };
1352   GOptionEntry entries2 [] =
1353     { { "test2", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL },
1354       { NULL } };
1355
1356   context = g_option_context_new (NULL);
1357   g_option_context_add_main_entries (context, entries1, NULL);
1358   g_option_context_add_main_entries (context, entries2, NULL);
1359
1360   g_option_context_free (context);
1361 }
1362
1363 static void
1364 empty_test2 (void)
1365 {
1366   GOptionContext *context;
1367
1368   context = g_option_context_new (NULL);
1369   g_option_context_parse (context, NULL, NULL, NULL);
1370   
1371   g_option_context_free (context);
1372 }
1373
1374 static void
1375 empty_test3 (void)
1376 {
1377   GOptionContext *context;
1378   gint argc;
1379   gchar **argv;
1380
1381   argc = 0;
1382   argv = NULL;
1383
1384   context = g_option_context_new (NULL);
1385   g_option_context_parse (context, &argc, &argv, NULL);
1386   
1387   g_option_context_free (context);
1388 }
1389
1390 /* check that non-option arguments are left in argv by default */
1391 static void
1392 rest_test1 (void)
1393 {
1394   GOptionContext *context;
1395   gboolean retval;
1396   GError *error = NULL;
1397   gchar **argv;
1398   gchar **argv_copy;
1399   int argc;
1400   GOptionEntry entries [] = { 
1401       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1402       { NULL } 
1403   };
1404         
1405   context = g_option_context_new (NULL);
1406   g_option_context_add_main_entries (context, entries, NULL);
1407
1408   /* Now try parsing */
1409   argv = split_string ("program foo --test bar", &argc);
1410   argv_copy = copy_stringv (argv, argc);
1411
1412   retval = g_option_context_parse (context, &argc, &argv, &error);
1413   g_assert_no_error (error);
1414   g_assert (retval);
1415
1416   /* Check array */
1417   g_assert (ignore_test1_boolean);
1418   g_assert (strcmp (argv[0], "program") == 0);
1419   g_assert (strcmp (argv[1], "foo") == 0);
1420   g_assert (strcmp (argv[2], "bar") == 0);
1421   g_assert (argv[3] == NULL);
1422
1423   g_strfreev (argv_copy);
1424   g_free (argv);
1425   g_option_context_free (context);
1426 }
1427
1428 /* check that -- works */
1429 static void
1430 rest_test2 (void)
1431 {
1432   GOptionContext *context;
1433   gboolean retval;
1434   GError *error = NULL;
1435   gchar **argv;
1436   gchar **argv_copy;
1437   int argc;
1438   GOptionEntry entries [] = { 
1439       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1440       { NULL } 
1441   };
1442         
1443   context = g_option_context_new (NULL);
1444   g_option_context_add_main_entries (context, entries, NULL);
1445
1446   /* Now try parsing */
1447   argv = split_string ("program foo --test -- -bar", &argc);
1448   argv_copy = copy_stringv (argv, argc);
1449
1450   retval = g_option_context_parse (context, &argc, &argv, &error);
1451   g_assert_no_error (error);
1452   g_assert (retval);
1453
1454   /* Check array */
1455   g_assert (ignore_test1_boolean);
1456   g_assert (strcmp (argv[0], "program") == 0);
1457   g_assert (strcmp (argv[1], "foo") == 0);
1458   g_assert (strcmp (argv[2], "--") == 0);
1459   g_assert (strcmp (argv[3], "-bar") == 0);
1460   g_assert (argv[4] == NULL);
1461
1462   g_strfreev (argv_copy);
1463   g_free (argv);
1464   g_option_context_free (context);
1465 }
1466
1467 /* check that -- stripping works */
1468 static void
1469 rest_test2a (void)
1470 {
1471   GOptionContext *context;
1472   gboolean retval;
1473   GError *error = NULL;
1474   gchar **argv;
1475   gchar **argv_copy;
1476   int argc;
1477   GOptionEntry entries [] = { 
1478       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1479       { NULL } 
1480   };
1481         
1482   context = g_option_context_new (NULL);
1483   g_option_context_add_main_entries (context, entries, NULL);
1484
1485   /* Now try parsing */
1486   argv = split_string ("program foo --test -- bar", &argc);
1487   argv_copy = copy_stringv (argv, argc);
1488
1489   retval = g_option_context_parse (context, &argc, &argv, &error);
1490   g_assert_no_error (error);
1491   g_assert (retval);
1492
1493   /* Check array */
1494   g_assert (ignore_test1_boolean);
1495   g_assert (strcmp (argv[0], "program") == 0);
1496   g_assert (strcmp (argv[1], "foo") == 0);
1497   g_assert (strcmp (argv[2], "bar") == 0);
1498   g_assert (argv[3] == NULL);
1499
1500   g_strfreev (argv_copy);
1501   g_free (argv);
1502   g_option_context_free (context);
1503 }
1504
1505 static void
1506 rest_test2b (void)
1507 {
1508   GOptionContext *context;
1509   gboolean retval;
1510   GError *error = NULL;
1511   gchar **argv;
1512   gchar **argv_copy;
1513   int argc;
1514   GOptionEntry entries [] = { 
1515       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1516       { NULL } 
1517   };
1518         
1519   context = g_option_context_new (NULL);
1520   g_option_context_set_ignore_unknown_options (context, TRUE);
1521   g_option_context_add_main_entries (context, entries, NULL);
1522
1523   /* Now try parsing */
1524   argv = split_string ("program foo --test -bar --", &argc);
1525   argv_copy = copy_stringv (argv, argc);
1526
1527   retval = g_option_context_parse (context, &argc, &argv, &error);
1528   g_assert_no_error (error);
1529   g_assert (retval);
1530
1531   /* Check array */
1532   g_assert (ignore_test1_boolean);
1533   g_assert (strcmp (argv[0], "program") == 0);
1534   g_assert (strcmp (argv[1], "foo") == 0);
1535   g_assert (strcmp (argv[2], "-bar") == 0);
1536   g_assert (argv[3] == NULL);
1537
1538   g_strfreev (argv_copy);
1539   g_free (argv);
1540   g_option_context_free (context);
1541 }
1542
1543 static void
1544 rest_test2c (void)
1545 {
1546   GOptionContext *context;
1547   gboolean retval;
1548   GError *error = NULL;
1549   gchar **argv;
1550   gchar **argv_copy;
1551   int argc;
1552   GOptionEntry entries [] = { 
1553       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1554       { NULL } 
1555   };
1556         
1557   context = g_option_context_new (NULL);
1558   g_option_context_add_main_entries (context, entries, NULL);
1559
1560   /* Now try parsing */
1561   argv = split_string ("program --test foo -- bar", &argc);
1562   argv_copy = copy_stringv (argv, argc);
1563
1564   retval = g_option_context_parse (context, &argc, &argv, &error);
1565   g_assert_no_error (error);
1566   g_assert (retval);
1567
1568   /* Check array */
1569   g_assert (ignore_test1_boolean);
1570   g_assert (strcmp (argv[0], "program") == 0);
1571   g_assert (strcmp (argv[1], "foo") == 0);
1572   g_assert (strcmp (argv[2], "bar") == 0);
1573   g_assert (argv[3] == NULL);
1574
1575   g_strfreev (argv_copy);
1576   g_free (argv);
1577   g_option_context_free (context);
1578 }
1579
1580 static void
1581 rest_test2d (void)
1582 {
1583   GOptionContext *context;
1584   gboolean retval;
1585   GError *error = NULL;
1586   gchar **argv;
1587   gchar **argv_copy;
1588   int argc;
1589   GOptionEntry entries [] = { 
1590       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1591       { NULL } 
1592   };
1593         
1594   context = g_option_context_new (NULL);
1595   g_option_context_add_main_entries (context, entries, NULL);
1596
1597   /* Now try parsing */
1598   argv = split_string ("program --test -- -bar", &argc);
1599   argv_copy = copy_stringv (argv, argc);
1600
1601   retval = g_option_context_parse (context, &argc, &argv, &error);
1602   g_assert_no_error (error);
1603   g_assert (retval);
1604
1605   /* Check array */
1606   g_assert (ignore_test1_boolean);
1607   g_assert (strcmp (argv[0], "program") == 0);
1608   g_assert (strcmp (argv[1], "--") == 0);
1609   g_assert (strcmp (argv[2], "-bar") == 0);
1610   g_assert (argv[3] == NULL);
1611
1612   g_strfreev (argv_copy);
1613   g_free (argv);
1614   g_option_context_free (context);
1615 }
1616
1617
1618 /* check that G_OPTION_REMAINING collects non-option arguments */
1619 static void
1620 rest_test3 (void)
1621 {
1622   GOptionContext *context;
1623   gboolean retval;
1624   GError *error = NULL;
1625   gchar **argv;
1626   gchar **argv_copy;
1627   int argc;
1628   GOptionEntry entries [] = { 
1629       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1630       { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
1631       { NULL } 
1632   };
1633         
1634   context = g_option_context_new (NULL);
1635   g_option_context_add_main_entries (context, entries, NULL);
1636
1637   /* Now try parsing */
1638   argv = split_string ("program foo --test bar", &argc);
1639   argv_copy = copy_stringv (argv, argc);
1640
1641   retval = g_option_context_parse (context, &argc, &argv, &error);
1642   g_assert_no_error (error);
1643   g_assert (retval);
1644
1645   /* Check array */
1646   g_assert (ignore_test1_boolean);
1647   g_assert (strcmp (array_test1_array[0], "foo") == 0);
1648   g_assert (strcmp (array_test1_array[1], "bar") == 0);
1649   g_assert (array_test1_array[2] == NULL);
1650
1651   g_strfreev (array_test1_array);
1652
1653   g_strfreev (argv_copy);
1654   g_free (argv);
1655   g_option_context_free (context);
1656 }
1657
1658
1659 /* check that G_OPTION_REMAINING and -- work together */
1660 static void
1661 rest_test4 (void)
1662 {
1663   GOptionContext *context;
1664   gboolean retval;
1665   GError *error = NULL;
1666   gchar **argv;
1667   gchar **argv_copy;
1668   int argc;
1669   GOptionEntry entries [] = { 
1670       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1671       { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
1672       { NULL } 
1673   };
1674         
1675   context = g_option_context_new (NULL);
1676   g_option_context_add_main_entries (context, entries, NULL);
1677
1678   /* Now try parsing */
1679   argv = split_string ("program foo --test -- -bar", &argc);
1680   argv_copy = copy_stringv (argv, argc);
1681
1682   retval = g_option_context_parse (context, &argc, &argv, &error);
1683   g_assert_no_error (error);
1684   g_assert (retval);
1685
1686   /* Check array */
1687   g_assert (ignore_test1_boolean);
1688   g_assert (strcmp (array_test1_array[0], "foo") == 0);
1689   g_assert (strcmp (array_test1_array[1], "-bar") == 0);
1690   g_assert (array_test1_array[2] == NULL);
1691
1692   g_strfreev (array_test1_array);
1693
1694   g_strfreev (argv_copy);
1695   g_free (argv);
1696   g_option_context_free (context);
1697 }
1698
1699 /* test that G_OPTION_REMAINING works with G_OPTION_ARG_FILENAME_ARRAY */
1700 static void
1701 rest_test5 (void)
1702 {
1703   GOptionContext *context;
1704   gboolean retval;
1705   GError *error = NULL;
1706   gchar **argv;
1707   gchar **argv_copy;
1708   int argc;
1709   GOptionEntry entries [] = { 
1710       { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
1711       { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &array_test1_array, NULL, NULL },
1712       { NULL } 
1713   };
1714         
1715   context = g_option_context_new (NULL);
1716   g_option_context_add_main_entries (context, entries, NULL);
1717
1718   /* Now try parsing */
1719   argv = split_string ("program foo --test bar", &argc);
1720   argv_copy = copy_stringv (argv, argc);
1721
1722   retval = g_option_context_parse (context, &argc, &argv, &error);
1723   g_assert_no_error (error);
1724   g_assert (retval);
1725
1726   /* Check array */
1727   g_assert (ignore_test1_boolean);
1728   g_assert (strcmp (array_test1_array[0], "foo") == 0);
1729   g_assert (strcmp (array_test1_array[1], "bar") == 0);
1730   g_assert (array_test1_array[2] == NULL);
1731
1732   g_strfreev (array_test1_array);
1733
1734   g_strfreev (argv_copy);
1735   g_free (argv);
1736   g_option_context_free (context);
1737 }
1738
1739 static void
1740 unknown_short_test (void)
1741 {
1742   GOptionContext *context;
1743   gboolean retval;
1744   GError *error = NULL;
1745   gchar **argv;
1746   gchar **argv_copy;
1747   int argc;
1748   GOptionEntry entries [] = { { NULL } };
1749
1750   g_test_bug ("166609");
1751
1752   context = g_option_context_new (NULL);
1753   g_option_context_add_main_entries (context, entries, NULL);
1754
1755   /* Now try parsing */
1756   argv = split_string ("program -0", &argc);
1757   argv_copy = copy_stringv (argv, argc);
1758
1759   retval = g_option_context_parse (context, &argc, &argv, &error);
1760   g_assert (!retval);
1761   g_assert (error != NULL);
1762   g_clear_error (&error);
1763
1764   g_strfreev (argv_copy);
1765   g_free (argv);
1766   g_option_context_free (context);
1767 }
1768
1769 /* test that lone dashes are treated as non-options */
1770 static void
1771 lonely_dash_test (void)
1772 {
1773   GOptionContext *context;
1774   gboolean retval;
1775   GError *error = NULL;
1776   gchar **argv;
1777   gchar **argv_copy;
1778   int argc;
1779
1780   g_test_bug ("168008");
1781
1782   context = g_option_context_new (NULL);
1783
1784   /* Now try parsing */
1785   argv = split_string ("program -", &argc);
1786   argv_copy = copy_stringv (argv, argc);
1787
1788   retval = g_option_context_parse (context, &argc, &argv, &error);
1789   g_assert_no_error (error);
1790   g_assert (retval);
1791
1792   g_assert (argv[1] && strcmp (argv[1], "-") == 0);
1793
1794   g_strfreev (argv_copy);
1795   g_free (argv);
1796   g_option_context_free (context);
1797 }
1798
1799 static void
1800 missing_arg_test (void)
1801 {
1802   GOptionContext *context;
1803   gboolean retval;
1804   GError *error = NULL;
1805   gchar **argv;
1806   gchar **argv_copy;
1807   int argc;
1808   gchar *arg = NULL;
1809   GOptionEntry entries [] =
1810     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
1811       { NULL } };
1812
1813   g_test_bug ("305576");
1814
1815   context = g_option_context_new (NULL);
1816   g_option_context_add_main_entries (context, entries, NULL);
1817
1818   /* Now try parsing */
1819   argv = split_string ("program --test", &argc);
1820   argv_copy = copy_stringv (argv, argc);
1821
1822   retval = g_option_context_parse (context, &argc, &argv, &error);
1823   g_assert (retval == FALSE);
1824   g_assert (error != NULL);
1825   /* An error occurred, so argv has not been changed */
1826   check_identical_stringv (argv_copy, argv);
1827   g_clear_error (&error);
1828
1829   g_strfreev (argv_copy);
1830   g_free (argv);
1831
1832   /* Try parsing again */
1833   argv = split_string ("program -t", &argc);
1834   argv_copy = copy_stringv (argv, argc);
1835
1836   retval = g_option_context_parse (context, &argc, &argv, &error);
1837   g_assert (retval == FALSE);
1838   g_assert (error != NULL);
1839   /* An error occurred, so argv has not been changed */
1840   check_identical_stringv (argv_copy, argv);
1841   g_clear_error (&error);
1842
1843   g_strfreev (argv_copy);
1844   g_free (argv);
1845   g_option_context_free (context);
1846 }
1847
1848 static gchar *test_arg;
1849
1850 static gboolean cb (const gchar  *option_name,
1851                     const gchar  *value,
1852                     gpointer      data,
1853                     GError      **error)
1854 {
1855   test_arg = g_strdup (value);
1856   return TRUE;
1857 }
1858
1859 static void
1860 dash_arg_test (void)
1861 {
1862   GOptionContext *context;
1863   gboolean retval;
1864   GError *error = NULL;
1865   gchar **argv;
1866   gchar **argv_copy;
1867   int argc;
1868   gboolean argb = FALSE;
1869   GOptionEntry entries [] =
1870     { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, cb, NULL, NULL },
1871       { "three", '3', 0, G_OPTION_ARG_NONE, &argb, NULL, NULL },
1872       { NULL } };
1873
1874   g_test_bug ("577638");
1875
1876   context = g_option_context_new (NULL);
1877   g_option_context_add_main_entries (context, entries, NULL);
1878
1879   /* Now try parsing */
1880   argv = split_string ("program --test=-3", &argc);
1881   argv_copy = copy_stringv (argv, argc);
1882
1883   test_arg = NULL;
1884   error = NULL;
1885   retval = g_option_context_parse (context, &argc, &argv, &error);
1886   g_assert (retval);
1887   g_assert_no_error (error);
1888   g_assert_cmpstr (test_arg, ==, "-3");
1889
1890   g_strfreev (argv_copy);
1891   g_free (argv);
1892   g_free (test_arg);
1893   test_arg = NULL;
1894
1895   /* Try parsing again */
1896   argv = split_string ("program --test -3", &argc);
1897   argv_copy = copy_stringv (argv, argc);
1898
1899   error = NULL;
1900   retval = g_option_context_parse (context, &argc, &argv, &error);
1901   g_assert_no_error (error);
1902   g_assert (retval);
1903   g_assert_cmpstr (test_arg, ==, NULL);
1904
1905   g_option_context_free (context);
1906   g_strfreev (argv_copy);
1907   g_free (argv);
1908 }
1909
1910 static void
1911 test_basic (void)
1912 {
1913   GOptionContext *context;
1914   gchar *arg = NULL;
1915   GOptionEntry entries [] =
1916     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
1917       { NULL } };
1918
1919   context = g_option_context_new (NULL);
1920   g_option_context_add_main_entries (context, entries, NULL);
1921
1922   g_assert (g_option_context_get_help_enabled (context));
1923   g_assert (!g_option_context_get_ignore_unknown_options (context));
1924   g_assert_cmpstr (g_option_context_get_summary (context), ==, NULL);
1925   g_assert_cmpstr (g_option_context_get_description (context), ==, NULL);
1926
1927   g_option_context_set_help_enabled (context, FALSE);
1928   g_option_context_set_ignore_unknown_options (context, TRUE);
1929   g_option_context_set_summary (context, "summary");
1930   g_option_context_set_description(context, "description");
1931
1932   g_assert (!g_option_context_get_help_enabled (context));
1933   g_assert (g_option_context_get_ignore_unknown_options (context));
1934   g_assert_cmpstr (g_option_context_get_summary (context), ==, "summary");
1935   g_assert_cmpstr (g_option_context_get_description (context), ==, "description");
1936
1937   g_option_context_free (context);
1938 }
1939
1940 static void
1941 test_main_group (void)
1942 {
1943   GOptionContext *context;
1944   GOptionGroup *group;
1945
1946   context = g_option_context_new (NULL);
1947   g_assert (g_option_context_get_main_group (context) == NULL);
1948   group = g_option_group_new ("name", "description", "hlep", NULL, NULL);
1949   g_option_context_add_group (context, group);
1950   g_assert (g_option_context_get_main_group (context) == NULL);
1951   group = g_option_group_new ("name", "description", "hlep", NULL, NULL);
1952   g_option_context_set_main_group (context, group);
1953   g_assert (g_option_context_get_main_group (context) == group);
1954
1955   g_option_context_free (context);
1956 }
1957
1958 static gboolean error_func_called = FALSE;
1959
1960 static void
1961 error_func (GOptionContext  *context,
1962             GOptionGroup    *group,
1963             gpointer         data,
1964             GError         **error)
1965 {
1966   g_assert_cmpint (GPOINTER_TO_INT(data), ==, 1234);
1967   error_func_called = TRUE;
1968 }
1969
1970 static void
1971 test_error_hook (void)
1972 {
1973   GOptionContext *context;
1974   gchar *arg = NULL;
1975   GOptionEntry entries [] =
1976     { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
1977       { NULL } };
1978   GOptionGroup *group;
1979   gchar **argv;
1980   gchar **argv_copy;
1981   gint argc;
1982   gboolean retval;
1983   GError *error = NULL;
1984
1985   context = g_option_context_new (NULL);
1986   group = g_option_group_new ("name", "description", "hlep", GINT_TO_POINTER(1234), NULL);
1987   g_option_group_add_entries (group, entries);
1988   g_option_context_set_main_group (context, group);
1989   g_option_group_set_error_hook (g_option_context_get_main_group (context),
1990                                  error_func);
1991
1992   argv = split_string ("program --test", &argc);
1993   argv_copy = copy_stringv (argv, argc);
1994
1995   retval = g_option_context_parse (context, &argc, &argv, &error);
1996   g_assert (retval == FALSE);
1997   g_assert (error != NULL);
1998   /* An error occurred, so argv has not been changed */
1999   check_identical_stringv (argv_copy, argv);
2000   g_clear_error (&error);
2001
2002   g_assert (error_func_called);
2003
2004   g_strfreev (argv_copy);
2005   g_free (argv);
2006   g_option_context_free (context);
2007 }
2008
2009 static void
2010 flag_reverse_string (void)
2011 {
2012   if (!g_test_undefined ())
2013     return;
2014
2015   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
2016     {
2017       GOptionContext *context;
2018       gchar *arg = NULL;
2019       GOptionEntry entries [] =
2020         { { "test", 't', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_STRING, &arg, NULL, NULL },
2021           { NULL } };
2022       gchar **argv;
2023       gint argc;
2024       gboolean retval;
2025       GError *error = NULL;
2026
2027       context = g_option_context_new (NULL);
2028       g_option_context_add_main_entries (context, entries, NULL);
2029
2030       argv = split_string ("program --test bla", &argc);
2031
2032       retval = g_option_context_parse (context, &argc, &argv, &error);
2033       g_assert (retval == FALSE);
2034       g_clear_error (&error);
2035       g_strfreev (argv);
2036       g_option_context_free (context);
2037       exit (0);
2038     }
2039   g_test_trap_assert_failed ();
2040   g_test_trap_assert_stderr ("*ignoring reverse flag*");
2041 }
2042
2043 static void
2044 flag_optional_int (void)
2045 {
2046   if (!g_test_undefined ())
2047     return;
2048
2049   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
2050     {
2051       GOptionContext *context;
2052       gint arg = 0;
2053       GOptionEntry entries [] =
2054         { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &arg, NULL, NULL },
2055           { NULL } };
2056       gchar **argv;
2057       gint argc;
2058       gboolean retval;
2059       GError *error = NULL;
2060
2061       context = g_option_context_new (NULL);
2062       g_option_context_add_main_entries (context, entries, NULL);
2063
2064       argv = split_string ("program --test 5", &argc);
2065
2066       retval = g_option_context_parse (context, &argc, &argv, &error);
2067       g_assert (retval == FALSE);
2068       g_clear_error (&error);
2069       g_strfreev (argv);
2070       g_option_context_free (context);
2071       exit (0);
2072     }
2073   g_test_trap_assert_failed ();
2074   g_test_trap_assert_stderr ("*ignoring no-arg, optional-arg or filename flags*");
2075 }
2076 int
2077 main (int   argc,
2078       char *argv[])
2079 {
2080   g_test_init (&argc, &argv, NULL);
2081
2082   g_test_bug_base ("http://bugzilla.gnome.org/");
2083
2084   g_test_add_func ("/option/basic", test_basic);
2085   g_test_add_func ("/option/group/captions", group_captions);
2086   g_test_add_func ("/option/group/main", test_main_group);
2087   g_test_add_func ("/option/group/error-hook", test_error_hook);
2088
2089   /* Test that restoration on failure works */
2090   g_test_add_func ("/option/restoration/int", error_test1);
2091   g_test_add_func ("/option/restoration/string", error_test2);
2092   g_test_add_func ("/option/restoration/boolean", error_test3);
2093
2094   /* Test that special argument parsing works */
2095   g_test_add_func ("/option/arg/repetition/int", arg_test1);
2096   g_test_add_func ("/option/arg/repetition/string", arg_test2);
2097   g_test_add_func ("/option/arg/repetition/filename", arg_test3);
2098   g_test_add_func ("/option/arg/repetition/double", arg_test4);
2099   g_test_add_func ("/option/arg/repetition/locale", arg_test5);
2100   g_test_add_func ("/option/arg/repetition/int64", arg_test6);
2101
2102   /* Test string arrays */
2103   g_test_add_func ("/option/arg/array/string", array_test1);
2104
2105   /* Test callback args */
2106   g_test_add_func ("/option/arg/callback/string", callback_test1);
2107   g_test_add_func ("/option/arg/callback/count", callback_test2);
2108
2109   /* Test optional arg flag for callback */
2110   g_test_add_func ("/option/arg/callback/optional1", callback_test_optional_1);
2111   g_test_add_func ("/option/arg/callback/optional2", callback_test_optional_2);
2112   g_test_add_func ("/option/arg/callback/optional3", callback_test_optional_3);
2113   g_test_add_func ("/option/arg/callback/optional4", callback_test_optional_4);
2114   g_test_add_func ("/option/arg/callback/optional5", callback_test_optional_5);
2115   g_test_add_func ("/option/arg/callback/optional6", callback_test_optional_6);
2116   g_test_add_func ("/option/arg/callback/optional7", callback_test_optional_7);
2117   g_test_add_func ("/option/arg/callback/optional8", callback_test_optional_8);
2118
2119   /* Test callback with G_OPTION_REMAINING */
2120   g_test_add_func ("/option/arg/remaining/callback", callback_remaining_test1);
2121
2122   /* Test callbacks which return FALSE */
2123   g_test_add_func ("/option/arg/remaining/callback-false", callback_returns_false);
2124
2125   /* Test ignoring options */
2126   g_test_add_func ("/option/arg/ignore/long", ignore_test1);
2127   g_test_add_func ("/option/arg/ignore/short", ignore_test2);
2128   g_test_add_func ("/option/arg/ignore/arg", ignore_test3);
2129   g_test_add_func ("/option/context/add", add_test1);
2130
2131   /* Test parsing empty args */
2132   /* Note there used to be an empty1 here, but it effectively moved
2133    * to option-argv0.c.
2134    */
2135   g_test_add_func ("/option/context/empty2", empty_test2);
2136   g_test_add_func ("/option/context/empty3", empty_test3);
2137
2138   /* Test handling of rest args */
2139   g_test_add_func ("/option/arg/rest/non-option", rest_test1);
2140   g_test_add_func ("/option/arg/rest/separator1", rest_test2);
2141   g_test_add_func ("/option/arg/rest/separator2", rest_test2a);
2142   g_test_add_func ("/option/arg/rest/separator3", rest_test2b);
2143   g_test_add_func ("/option/arg/rest/separator4", rest_test2c);
2144   g_test_add_func ("/option/arg/rest/separator5", rest_test2d);
2145   g_test_add_func ("/option/arg/remaining/non-option", rest_test3);
2146   g_test_add_func ("/option/arg/remaining/separator", rest_test4);
2147   g_test_add_func ("/option/arg/remaining/array", rest_test5);
2148
2149   /* Test some invalid flag combinations */
2150   g_test_add_func ("/option/arg/reverse-string", flag_reverse_string);
2151   g_test_add_func ("/option/arg/optional-int", flag_optional_int);
2152
2153   /* regression tests for individual bugs */
2154   g_test_add_func ("/option/bug/unknown-short", unknown_short_test);
2155   g_test_add_func ("/option/bug/lonely-dash", lonely_dash_test);
2156   g_test_add_func ("/option/bug/missing-arg", missing_arg_test);
2157   g_test_add_func ("/option/bug/dash-arg", dash_arg_test);
2158
2159   return g_test_run();
2160 }