opt: minor API tweaks.
[ccan] / ccan / opt / test / run-helpers.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 "utils.h"
8
9 /* We don't actually want it to exit... */
10 static jmp_buf exited;
11 #define exit(status) longjmp(exited, (status) + 1)
12
13 #define printf saved_printf
14 static int saved_printf(const char *fmt, ...);
15
16 #include <ccan/opt/helpers.c>
17 #include <ccan/opt/opt.c>
18 #include <ccan/opt/usage.c>
19
20 static void reset_options(void)
21 {
22         free(opt_table);
23         opt_table = NULL;
24         opt_count = opt_num_short = opt_num_short_arg = opt_num_long = 0;
25 }
26
27 static char *output = NULL;
28
29 static int saved_printf(const char *fmt, ...)
30 {
31         va_list ap;
32         char *p;
33         int ret;
34
35         va_start(ap, fmt);
36         ret = vasprintf(&p, fmt, ap);
37         va_end(ap);
38
39         if (output) {
40                 output = realloc(output, strlen(output) + strlen(p) + 1);
41                 strcat(output, p);
42                 free(p);
43         } else
44                 output = p;
45
46         return ret;
47 }       
48
49 /* Test helpers. */
50 int main(int argc, char *argv[])
51 {
52         plan_tests(96);
53
54         /* opt_set_bool */
55         {
56                 bool arg = false;
57                 reset_options();
58                 opt_register_noarg("-a", opt_set_bool, &arg, "");
59                 ok1(parse_args(&argc, &argv, "-a", NULL));
60                 ok1(arg);
61                 opt_register_arg("-b", opt_set_bool_arg, NULL, &arg, "");
62                 ok1(parse_args(&argc, &argv, "-b", "no", NULL));
63                 ok1(!arg);
64                 ok1(parse_args(&argc, &argv, "-b", "yes", NULL));
65                 ok1(arg);
66                 ok1(parse_args(&argc, &argv, "-b", "false", NULL));
67                 ok1(!arg);
68                 ok1(parse_args(&argc, &argv, "-b", "true", NULL));
69                 ok1(arg);
70                 ok1(!parse_args(&argc, &argv, "-b", "unknown", NULL));
71                 ok1(arg);
72                 ok1(strstr(err_output, ": -b: Invalid argument 'unknown'"));
73         }
74         /* opt_set_invbool */
75         {
76                 bool arg = true;
77                 reset_options();
78                 opt_register_noarg("-a", opt_set_invbool, &arg, "");
79                 ok1(parse_args(&argc, &argv, "-a", NULL));
80                 ok1(!arg);
81                 opt_register_arg("-b", opt_set_invbool_arg, NULL,
82                                  &arg, "");
83                 ok1(parse_args(&argc, &argv, "-b", "no", NULL));
84                 ok1(arg);
85                 ok1(parse_args(&argc, &argv, "-b", "yes", NULL));
86                 ok1(!arg);
87                 ok1(parse_args(&argc, &argv, "-b", "false", NULL));
88                 ok1(arg);
89                 ok1(parse_args(&argc, &argv, "-b", "true", NULL));
90                 ok1(!arg);
91                 ok1(!parse_args(&argc, &argv, "-b", "unknown", NULL));
92                 ok1(!arg);
93                 ok1(strstr(err_output, ": -b: Invalid argument 'unknown'"));
94         }
95         /* opt_set_charp */
96         {
97                 char *arg = (char *)"wrong";
98                 reset_options();
99                 opt_register_arg("-a", opt_set_charp, NULL, &arg, "All");
100                 ok1(parse_args(&argc, &argv, "-a", "string", NULL));
101                 ok1(strcmp(arg, "string") == 0);
102         }
103         /* opt_set_intval */
104         {
105                 int arg = 1000;
106                 reset_options();
107                 opt_register_arg("-a", opt_set_intval, NULL, &arg, "All");
108                 ok1(parse_args(&argc, &argv, "-a", "9999", NULL));
109                 ok1(arg == 9999);
110                 ok1(parse_args(&argc, &argv, "-a", "-9999", NULL));
111                 ok1(arg == -9999);
112                 ok1(parse_args(&argc, &argv, "-a", "0", NULL));
113                 ok1(arg == 0);
114                 ok1(!parse_args(&argc, &argv, "-a", "100crap", NULL));
115                 if (sizeof(int) == 4)
116                         ok1(!parse_args(&argc, &argv, "-a", "4294967296", NULL));
117                 else
118                         fail("Handle other int sizes");
119         }
120         /* opt_set_uintval */
121         {
122                 unsigned int arg = 1000;
123                 reset_options();
124                 opt_register_arg("-a", opt_set_uintval, NULL, &arg, "All");
125                 ok1(parse_args(&argc, &argv, "-a", "9999", NULL));
126                 ok1(arg == 9999);
127                 ok1(!parse_args(&argc, &argv, "-a", "-9999", NULL));
128                 ok1(parse_args(&argc, &argv, "-a", "0", NULL));
129                 ok1(arg == 0);
130                 ok1(!parse_args(&argc, &argv, "-a", "100crap", NULL));
131                 ok1(!parse_args(&argc, &argv, "-a", "4294967296", NULL));
132                 if (ULONG_MAX == UINT_MAX) {
133                         pass("Can't test overflow");
134                         pass("Can't test error message");
135                 } else {
136                         char buf[30];
137                         sprintf(buf, "%lu", ULONG_MAX);
138                         ok1(!parse_args(&argc, &argv, "-a", buf, NULL));
139                         ok1(strstr(err_output, ": -a: value '")
140                             && strstr(err_output, buf)
141                             && strstr(err_output, "' does not fit into an integer"));
142                 }
143         }
144         /* opt_set_longval */
145         {
146                 long int arg = 1000;
147                 reset_options();
148                 opt_register_arg("-a", opt_set_longval, NULL, &arg, "All");
149                 ok1(parse_args(&argc, &argv, "-a", "9999", NULL));
150                 ok1(arg == 9999);
151                 ok1(parse_args(&argc, &argv, "-a", "-9999", NULL));
152                 ok1(arg == -9999);
153                 ok1(parse_args(&argc, &argv, "-a", "0", NULL));
154                 ok1(arg == 0);
155                 ok1(!parse_args(&argc, &argv, "-a", "100crap", NULL));
156                 if (sizeof(long) == 4)
157                         ok1(!parse_args(&argc, &argv, "-a", "4294967296", NULL));
158                 else if (sizeof(long)== 8)
159                         ok1(!parse_args(&argc, &argv, "-a", "18446744073709551616", NULL));
160                 else
161                         fail("FIXME: Handle other long sizes");
162         }
163         /* opt_set_ulongval */
164         {
165                 unsigned long int arg = 1000;
166                 reset_options();
167                 opt_register_arg("-a", opt_set_ulongval, NULL, &arg, "All");
168                 ok1(parse_args(&argc, &argv, "-a", "9999", NULL));
169                 ok1(arg == 9999);
170                 ok1(!parse_args(&argc, &argv, "-a", "-9999", NULL));
171                 ok1(parse_args(&argc, &argv, "-a", "0", NULL));
172                 ok1(arg == 0);
173                 ok1(!parse_args(&argc, &argv, "-a", "100crap", NULL));
174                 if (sizeof(long) == 4)
175                         ok1(!parse_args(&argc, &argv, "-a", "4294967296", NULL));
176                 else if (sizeof(long)== 8)
177                         ok1(!parse_args(&argc, &argv, "-a", "18446744073709551616", NULL));
178                 else
179                         fail("FIXME: Handle other long sizes");
180         }
181         /* opt_inc_intval */
182         {
183                 int arg = 1000;
184                 reset_options();
185                 opt_register_noarg("-a", opt_inc_intval, &arg, "");
186                 ok1(parse_args(&argc, &argv, "-a", NULL));
187                 ok1(arg == 1001);
188                 ok1(parse_args(&argc, &argv, "-a", "-a", NULL));
189                 ok1(arg == 1003);
190                 ok1(parse_args(&argc, &argv, "-aa", NULL));
191                 ok1(arg == 1005);
192         }
193
194         /* opt_show_version_and_exit. */
195         {
196                 int exitval;
197                 reset_options();
198                 opt_register_noarg("-a",
199                                    opt_version_and_exit, "1.2.3", "");
200                 exitval = setjmp(exited);
201                 if (exitval == 0) {
202                         parse_args(&argc, &argv, "-a", NULL);
203                         fail("opt_show_version_and_exit returned?");
204                 } else {
205                         ok1(exitval - 1 == 0);
206                 }
207                 ok1(strcmp(output, "1.2.3\n") == 0);
208                 free(output);
209                 output = NULL;
210         }
211
212         /* opt_usage_and_exit. */
213         {
214                 int exitval;
215                 reset_options();
216                 opt_register_noarg("-a",
217                                    opt_usage_and_exit, "[args]", "");
218                 exitval = setjmp(exited);
219                 if (exitval == 0) {
220                         parse_args(&argc, &argv, "-a", NULL);
221                         fail("opt_usage_and_exit returned?");
222                 } else {
223                         ok1(exitval - 1 == 0);
224                 }
225                 ok1(strstr(output, "[args]"));
226                 ok1(strstr(output, argv[0]));
227                 ok1(strstr(output, "[-a]"));
228                 free(output);
229                 output = NULL;
230         }
231
232         /* opt_show_bool */
233         {
234                 bool b;
235                 char buf[OPT_SHOW_LEN+2] = { 0 };
236                 buf[OPT_SHOW_LEN] = '!';
237
238                 b = true;
239                 opt_show_bool(buf, &b);
240                 ok1(strcmp(buf, "true") == 0);
241                 ok1(buf[OPT_SHOW_LEN] == '!');
242
243                 b = false;
244                 opt_show_bool(buf, &b);
245                 ok1(strcmp(buf, "false") == 0);
246                 ok1(buf[OPT_SHOW_LEN] == '!');
247         }
248
249         /* opt_show_invbool */
250         {
251                 bool b;
252                 char buf[OPT_SHOW_LEN+2] = { 0 };
253                 buf[OPT_SHOW_LEN] = '!';
254
255                 b = true;
256                 opt_show_invbool(buf, &b);
257                 ok1(strcmp(buf, "false") == 0);
258                 ok1(buf[OPT_SHOW_LEN] == '!');
259
260                 b = false;
261                 opt_show_invbool(buf, &b);
262                 ok1(strcmp(buf, "true") == 0);
263                 ok1(buf[OPT_SHOW_LEN] == '!');
264         }
265
266         /* opt_show_charp */
267         {
268                 char str[OPT_SHOW_LEN*2], *p;
269                 char buf[OPT_SHOW_LEN+2] = { 0 };
270                 buf[OPT_SHOW_LEN] = '!';
271
272                 /* Short test. */
273                 p = str;
274                 strcpy(p, "short");
275                 opt_show_charp(buf, &p);
276                 ok1(strcmp(buf, "\"short\"") == 0);
277                 ok1(buf[OPT_SHOW_LEN] == '!');
278
279                 /* Truncate test. */
280                 memset(p, 'x', OPT_SHOW_LEN*2);
281                 p[OPT_SHOW_LEN*2-1] = '\0';
282                 opt_show_charp(buf, &p);
283                 ok1(buf[0] == '"');
284                 ok1(buf[OPT_SHOW_LEN-1] == '"');
285                 ok1(buf[OPT_SHOW_LEN] == '!');
286                 ok1(strspn(buf+1, "x") == OPT_SHOW_LEN-2);
287         }
288
289         /* opt_show_intval */
290         {
291                 int i;
292                 char buf[OPT_SHOW_LEN+2] = { 0 };
293                 buf[OPT_SHOW_LEN] = '!';
294
295                 i = -77;
296                 opt_show_intval(buf, &i);
297                 ok1(strcmp(buf, "-77") == 0);
298                 ok1(buf[OPT_SHOW_LEN] == '!');
299
300                 i = 77;
301                 opt_show_intval(buf, &i);
302                 ok1(strcmp(buf, "77") == 0);
303                 ok1(buf[OPT_SHOW_LEN] == '!');
304         }
305
306         /* opt_show_uintval */
307         {
308                 unsigned int ui;
309                 char buf[OPT_SHOW_LEN+2] = { 0 };
310                 buf[OPT_SHOW_LEN] = '!';
311
312                 ui = 4294967295U;
313                 opt_show_uintval(buf, &ui);
314                 ok1(strcmp(buf, "4294967295") == 0);
315                 ok1(buf[OPT_SHOW_LEN] == '!');
316         }
317
318         /* opt_show_longval */
319         {
320                 long l;
321                 char buf[OPT_SHOW_LEN+2] = { 0 };
322                 buf[OPT_SHOW_LEN] = '!';
323
324                 l = 1234567890L;
325                 opt_show_longval(buf, &l);
326                 ok1(strcmp(buf, "1234567890") == 0);
327                 ok1(buf[OPT_SHOW_LEN] == '!');
328         }
329
330         /* opt_show_ulongval */
331         {
332                 unsigned long ul;
333                 char buf[OPT_SHOW_LEN+2] = { 0 };
334                 buf[OPT_SHOW_LEN] = '!';
335
336                 ul = 4294967295UL;
337                 opt_show_ulongval(buf, &ul);
338                 ok1(strcmp(buf, "4294967295") == 0);
339                 ok1(buf[OPT_SHOW_LEN] == '!');
340         }
341
342         return exit_status();
343 }