opt: wean off getopt_long, beef up tests.
[ccan] / ccan / opt / test / run-checkopt.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <ccan/tap/tap.h>
4 #include <setjmp.h>
5 #include <stdlib.h>
6 #include <limits.h>
7 #include <err.h>
8 #include "utils.h"
9
10 /* We don't actually want it to exit... */
11 static jmp_buf exited;
12 #define errx save_and_jump
13
14 static void save_and_jump(int ecode, const char *fmt, ...);
15
16 #include <ccan/opt/helpers.c>
17 #include <ccan/opt/opt.c>
18 #include <ccan/opt/usage.c>
19 #include <ccan/opt/parse.c>
20
21 static char *output = NULL;
22
23 static int saved_vprintf(const char *fmt, va_list ap)
24 {
25         char *p;
26         int ret = vasprintf(&p, fmt, ap);
27
28         if (output) {
29                 output = realloc(output, strlen(output) + strlen(p) + 1);
30                 strcat(output, p);
31                 free(p);
32         } else
33                 output = p;
34         return ret;
35 }
36
37 static void save_and_jump(int ecode, const char *fmt, ...)
38 {
39         va_list ap;
40
41         va_start(ap, fmt);
42         saved_vprintf(fmt, ap);
43         va_end(ap);
44         longjmp(exited, ecode + 1);
45 }
46
47 static void reset(void)
48 {
49         free(output);
50         output = NULL;
51         free(opt_table);
52         opt_table = NULL;
53         opt_count = opt_num_short = opt_num_short_arg = opt_num_long = 0;
54 }
55
56 int main(int argc, char *argv[])
57 {
58         int exitval;
59
60         plan_tests(14);
61
62         exitval = setjmp(exited);
63         if (exitval == 0) {
64                 /* Bad type. */
65                 _opt_register("-a", OPT_SUBTABLE, (void *)opt_version_and_exit,
66                               NULL, NULL, "1.2.3", "");
67                 fail("_opt_register returned?");
68         } else {
69                 ok1(exitval - 1 == 1);
70                 ok1(strstr(output, "Option -a: unknown entry type"));
71         }
72         reset();
73
74         exitval = setjmp(exited);
75         if (exitval == 0) {
76                 /* NULL description. */
77                 opt_register_noarg("-a", test_noarg, "", NULL);
78                 fail("_opt_register returned?");
79         } else {
80                 ok1(exitval - 1 == 1);
81                 ok1(strstr(output, "Option -a: description cannot be NULL"));
82         }
83         reset();
84
85         exitval = setjmp(exited);
86         if (exitval == 0) {
87                 /* Bad option name. */
88                 opt_register_noarg("a", test_noarg, "", "");
89                 fail("_opt_register returned?");
90         } else {
91                 ok1(exitval - 1 == 1);
92                 ok1(strstr(output, "Option a: does not begin with '-'"));
93         }
94
95         reset();
96
97         exitval = setjmp(exited);
98         if (exitval == 0) {
99                 /* Bad option name. */
100                 opt_register_noarg("--", test_noarg, "", "");
101                 fail("_opt_register returned?");
102         } else {
103                 ok1(exitval - 1 == 1);
104                 ok1(strstr(output, "Option --: invalid long option '--'"));
105         }
106
107         reset();
108
109         exitval = setjmp(exited);
110         if (exitval == 0) {
111                 /* Bad option name. */
112                 opt_register_noarg("--a|-aaa", test_noarg, "", "");
113                 fail("_opt_register returned?");
114         } else {
115                 ok1(exitval - 1 == 1);
116                 ok1(strstr(output,
117                            "Option --a|-aaa: invalid short option '-aaa'"));
118         }
119         reset();
120
121         exitval = setjmp(exited);
122         if (exitval == 0) {
123                 /* Documentation for non-optios. */
124                 opt_register_noarg("--a foo", test_noarg, "", "");
125                 fail("_opt_register returned?");
126         } else {
127                 ok1(exitval - 1 == 1);
128                 ok1(strstr(output,
129                            "Option --a foo: does not take arguments 'foo'"));
130         }
131         reset();
132
133         exitval = setjmp(exited);
134         if (exitval == 0) {
135                 /* Documentation for non-optios. */
136                 opt_register_noarg("--a=foo", test_noarg, "", "");
137                 fail("_opt_register returned?");
138         } else {
139                 ok1(exitval - 1 == 1);
140                 ok1(strstr(output,
141                            "Option --a=foo: does not take arguments 'foo'"));
142         }
143         return exit_status();
144 }