run-helpers.c 10 KB

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