run-helpers.c 11 KB

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