Minor formatting changes.
[gnulib.git] / tests / test-argp.c
1 /* Test suite for argp.
2    Copyright (C) 2006-2007, 2009-2010 Free Software Foundation, Inc.
3    This file is part of the GNUlib Library.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include <config.h>
19
20 #include "argp.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #if HAVE_STRING_H
25 # include <string.h>
26 #endif
27 #if HAVE_STRINGS_H
28 # include <strings.h>
29 #endif
30 #include "progname.h"
31
32 struct test_args
33 {
34   int test;
35   int verbose;
36   char *file;
37   int read;
38   char *hidden;
39   int opt;
40   char *optional;
41   int optional_set;
42   int group_2_1_option;
43   int group_1_1_option;
44 };
45
46 static struct argp_option group1_option[] = {
47   { NULL, 0, NULL, 0, "Option Group 1", 0 },
48   { "verbose", 'v', NULL, 0, "Simple option without arguments", 1 },
49   { "file", 'f', "FILE", 0, "Option with a mandatory argument", 1 },
50   { "input", 0, NULL, OPTION_ALIAS, NULL, 1 },
51   { "read", 'r', NULL, OPTION_ALIAS, NULL, 1 },
52   { "hidden", 'H', "FILE", OPTION_HIDDEN, "Hidden option", 1 },
53   { NULL, 0, NULL, 0, NULL, 0 }
54 };
55
56 static error_t
57 group1_parser (int key, char *arg, struct argp_state *state)
58 {
59   struct test_args *args = state->input;
60
61   switch (key)
62     {
63     case 'v':
64       args->verbose++;
65       break;
66
67     case 'r':
68       args->read = 1;
69       /* fall through */
70     case 'f':
71       args->file = arg;
72       break;
73
74     case 'H':
75       args->hidden = arg;
76       break;
77
78     default:
79       return ARGP_ERR_UNKNOWN;
80     }
81   return 0;
82 }
83
84 struct argp group1_argp = {
85   group1_option,
86   group1_parser
87 };
88
89 struct argp_child group1_child = {
90   &group1_argp,
91   0,
92   "",
93   1
94 };
95 \f
96
97 static struct argp_option group1_1_option[] = {
98   { NULL, 0, NULL, 0, "Option Group 1.1", 0 },
99   { "cantiga", 'C', NULL, 0, "create a cantiga" },
100   { "sonet", 'S', NULL, 0, "create a sonet" },
101   { NULL, 0, NULL, 0, NULL, 0 }
102 };
103
104 static error_t
105 group1_1_parser (int key, char *arg, struct argp_state *state)
106 {
107   struct test_args *args = state->input;
108   switch (key)
109     {
110     case 'C':
111     case 'S':
112       args->group_1_1_option = key;
113       break;
114     default:
115       return ARGP_ERR_UNKNOWN;
116     }
117   return 0;
118 }
119
120 struct argp group1_1_argp = {
121   group1_1_option,
122   group1_1_parser
123 };
124
125 struct argp_child group1_1_child = {
126   &group1_1_argp,
127   0,
128   "",
129   2
130 };
131 \f
132
133 static struct argp_option group2_option[] = {
134   { NULL, 0, NULL, 0, "Option Group 2", 0 },
135   { "option", 'O', NULL, 0, "An option", 1 },
136   { "optional", 'o', "ARG", OPTION_ARG_OPTIONAL,
137     "Option with an optional argument. ARG is one of the following:", 2 },
138   { "one", 0, NULL, OPTION_DOC | OPTION_NO_TRANS, "one unit", 3 },
139   { "two", 0, NULL, OPTION_DOC | OPTION_NO_TRANS, "two units", 3 },
140   { "many", 0, NULL, OPTION_DOC | OPTION_NO_TRANS, "many units", 3 },
141   { NULL, 0, NULL, 0, NULL, 0 }
142 };
143
144 static error_t
145 group2_parser (int key, char *arg, struct argp_state *state)
146 {
147   struct test_args *args = state->input;
148
149   switch (key)
150     {
151     case 'O':
152       args->opt = 1;
153       break;
154
155     case 'o':
156       args->optional_set = 1;
157       args->optional = arg;
158       break;
159
160     default:
161       return ARGP_ERR_UNKNOWN;
162     }
163   return 0;
164 }
165
166 struct argp group2_argp = {
167   group2_option,
168   group2_parser
169 };
170
171 struct argp_child group2_child = {
172   &group2_argp,
173   0,
174   "",
175   2
176 };
177 \f
178
179 static struct argp_option group2_1_option[] = {
180   { NULL, 0, NULL, 0, "Option Group 2.1", 0 },
181   { "poem", 'p', NULL, 0, "create a poem" },
182   { "limerick", 'l', NULL, 0, "create a limerick" },
183   { NULL, 0, NULL, 0, NULL, 0 }
184 };
185
186 static error_t
187 group2_1_parser (int key, char *arg, struct argp_state *state)
188 {
189   struct test_args *args = state->input;
190   switch (key)
191     {
192     case 'p':
193     case 'e':
194       args->group_2_1_option = key;
195       break;
196     default:
197       return ARGP_ERR_UNKNOWN;
198     }
199   return 0;
200 }
201
202 struct argp group2_1_argp = {
203   group2_1_option,
204   group2_1_parser
205 };
206
207 struct argp_child group2_1_child = {
208   &group2_1_argp,
209   0,
210   "",
211   2
212 };
213 \f
214
215 static struct argp_option main_options[] = {
216   { NULL, 0, NULL, 0, "Main options", 0 },
217   { "test", 't', NULL, 0, NULL, 1 },
218   { NULL, 0, NULL, 0, NULL, 0 }
219 };
220
221 static error_t
222 parse_opt (int key, char *arg, struct argp_state *state)
223 {
224   struct test_args *args = state->input;
225   int i;
226
227   switch (key)
228     {
229     case ARGP_KEY_INIT:
230       for (i = 0; state->root_argp->children[i].argp; i++)
231         state->child_inputs[i] = args;
232       break;
233
234     case 't':
235       args->test = 1;
236       break;
237
238     default:
239       return ARGP_ERR_UNKNOWN;
240     }
241   return 0;
242 }
243
244 const char *argp_program_version = "test_argp (" PACKAGE_NAME ") " VERSION;
245 const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
246 static char doc[] = "documentation string";
247
248 struct argp test_argp = {
249   main_options,
250   parse_opt,
251   "ARGS...",
252   doc,
253   NULL,
254   NULL,
255   NULL
256 };
257
258 #define NARGS(a) (sizeof(a) / sizeof((a)[0]) - 1)
259 #define ARGV0 "test-argp"
260 #define init_args(a) memset (&(a), 0, sizeof (a));
261
262 #define INIT_TEST_COMMON(n)     \
263  int argc = NARGS (argv);       \
264  struct test_args test_args;    \
265  init_args (test_args);         \
266  test_number = n;
267
268 #define INIT_TEST1(n, arg1)            \
269  char *argv[] = { ARGV0, arg1, NULL }; \
270  INIT_TEST_COMMON (n)
271
272 #define INIT_TEST2(n, arg1, arg2)            \
273  char *argv[] = { ARGV0, arg1, arg2, NULL }; \
274  INIT_TEST_COMMON (n)
275
276 #define INIT_TEST3(n, arg1, arg2, arg3)            \
277  char *argv[] = { ARGV0, arg1, arg2, arg3, NULL }; \
278  INIT_TEST_COMMON (n)
279
280 int test_number;
281 unsigned failure_count = 0;
282
283 void
284 fail (const char *msg)
285 {
286   fprintf (stderr, "Test %d: %s\n", test_number, msg);
287   failure_count++;
288 }
289
290 void
291 test1 (struct argp *argp)
292 {
293   INIT_TEST1 (1, "--test");
294   if (argp_parse (argp, argc, argv, 0, NULL, &test_args))
295     fail ("argp_parse failed");
296   else if (test_args.test != 1)
297     fail ("option not processed");
298 }
299
300 void
301 test2 (struct argp *argp)
302 {
303   INIT_TEST1 (2, "-t");
304   if (argp_parse (argp, argc, argv, 0, NULL, &test_args))
305     fail ("argp_parse failed");
306   else if (test_args.test != 1)
307     fail ("option not processed");
308 }
309
310 void
311 test_file (struct argp *argp, int argc, char **argv, struct test_args *args)
312 {
313   if (argp_parse (argp, argc, argv, 0, NULL, args))
314     fail ("argp_parse failed");
315   else if (!args->file)
316     fail ("option not processed");
317   else if (strcmp (args->file, "FILE"))
318     fail ("option processed incorrectly");
319 }
320
321 void
322 test3 (struct argp *argp)
323 {
324   INIT_TEST1 (3, "--file=FILE");
325   test_file (argp, argc, argv, &test_args);
326 }
327
328 void
329 test4 (struct argp *argp)
330 {
331   INIT_TEST2 (4, "--file", "FILE");
332   test_file (argp, argc, argv, &test_args);
333 }
334
335 void
336 test5 (struct argp *argp)
337 {
338   INIT_TEST1 (5, "--input=FILE");
339   test_file (argp, argc, argv, &test_args);
340 }
341
342 void
343 test6 (struct argp *argp)
344 {
345   INIT_TEST2 (6, "--input", "FILE");
346   test_file (argp, argc, argv, &test_args);
347 }
348
349 void
350 test_optional (struct argp *argp, int argc, char **argv,
351                struct test_args *args, char *val, char *a)
352 {
353   int index;
354   if (argp_parse (argp, argc, argv, 0, &index, args))
355     fail ("argp_parse failed");
356   else if (!args->optional_set)
357     fail ("option not processed");
358
359   if (!val)
360     {
361       if (args->optional)
362         fail ("option processed incorrectly");
363     }
364   else if (strcmp (args->optional, val))
365     fail ("option processed incorrectly");
366
367   if (a)
368     {
369       if (index == argc)
370         fail ("expected command line argument not found");
371       else if (strcmp (argv[index], a))
372         fail ("expected command line argument does not match");
373     }
374 }
375
376 void
377 test7 (struct argp *argp)
378 {
379   INIT_TEST1 (7, "-oARG");
380   test_optional (argp, argc, argv, &test_args, "ARG", NULL);
381 }
382
383 void
384 test8 (struct argp *argp)
385 {
386   INIT_TEST2 (8, "-o", "ARG");
387   test_optional (argp, argc, argv, &test_args, NULL, "ARG");
388 }
389
390 void
391 test9 (struct argp *argp)
392 {
393   INIT_TEST1 (9, "--optional=ARG");
394   test_optional (argp, argc, argv, &test_args, "ARG", NULL);
395 }
396
397 void
398 test10 (struct argp *argp)
399 {
400   INIT_TEST2 (10, "--optional", "ARG");
401   test_optional (argp, argc, argv, &test_args, NULL, "ARG");
402 }
403
404 void
405 test11 (struct argp *argp)
406 {
407   INIT_TEST1 (11, "--optiona=ARG");
408   test_optional (argp, argc, argv, &test_args, "ARG", NULL);
409 }
410
411 void
412 test12 (struct argp *argp)
413 {
414   INIT_TEST3 (12, "--option", "--optional=OPT", "FILE");
415   test_optional (argp, argc, argv, &test_args, "OPT", "FILE");
416 }
417
418 void
419 test13 (struct argp *argp)
420 {
421   INIT_TEST1 (1, "--cantiga");
422   if (argp_parse (argp, argc, argv, 0, NULL, &test_args))
423     fail ("argp_parse failed");
424   else if (test_args.group_1_1_option != 'C')
425     fail ("option not processed");
426 }
427
428 void
429 test14 (struct argp *argp)
430 {
431   INIT_TEST1 (1, "--limerick");
432   if (argp_parse (argp, argc, argv, 0, NULL, &test_args))
433     fail ("argp_parse failed");
434   else if (test_args.group_2_1_option != 'l')
435     fail ("option not processed");
436 }
437
438 void
439 test15 (struct argp *argp)
440 {
441   INIT_TEST2 (1, "-r", "FILE");
442   test_file (argp, argc, argv, &test_args);
443   if (!test_args.read)
444     fail ("short alias not recognized properly");
445 }
446
447
448 typedef void (*test_fp) (struct argp *argp);
449
450 test_fp test_fun[] = {
451   test1,  test2,  test3,  test4,
452   test5,  test6,  test7,  test8,
453   test9,  test10, test11, test12,
454   test13, test14, test15,
455   NULL
456 };
457
458 int
459 main (int argc, char **argv)
460 {
461   struct argp_child argp_children[3], group1_children[2], group2_children[2];
462   test_fp *fun;
463
464   set_program_name (argv[0]);
465
466   group1_children[0] = group1_1_child;
467   group1_children[1].argp = NULL;
468   group1_argp.children = group1_children;
469
470   group2_children[0] = group2_1_child;
471   group2_children[1].argp = NULL;
472   group2_argp.children = group2_children;
473
474   argp_children[0] = group1_child;
475   argp_children[1] = group2_child;
476   argp_children[2].argp = NULL;
477   test_argp.children = argp_children;
478
479   if (argc > 0)
480     {
481       struct test_args test_args;
482       init_args (test_args);
483       return argp_parse (&test_argp, argc, argv, 0, NULL, &test_args);
484     }
485
486   for (fun = test_fun; *fun; fun++)
487     (*fun) (&test_argp);
488
489   if (failure_count)
490     return 1;
491
492   return 0;
493 }