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