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

source code of gtk/subprojects/glib/glib/tests/option-context.c