PageRenderTime 27ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/test/ceph_argparse.cc

https://github.com/liewegas/ceph
C++ | 478 lines | 413 code | 28 blank | 37 comment | 90 complexity | 63a780dd75a232c8c75717ccef9159f2 MD5 | raw file
  1. // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
  2. // vim: ts=8 sw=2 smarttab
  3. /*
  4. * Ceph - scalable distributed file system
  5. *
  6. * Copyright (C) 2011 New Dream Network
  7. *
  8. * This is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License version 2.1, as published by the Free Software
  11. * Foundation. See file COPYING.
  12. *
  13. */
  14. #include "common/ceph_argparse.h"
  15. #include "gtest/gtest.h"
  16. #include <vector>
  17. /* Holds a std::vector with C-strings.
  18. * Will free() them properly in the destructor.
  19. *
  20. * Note: the ceph_argparse functions modify the vector, removing elements as
  21. * they find them. So we keep a parallel vector, orig, to make sure that we
  22. * never forget to delete a string.
  23. */
  24. class VectorContainer
  25. {
  26. public:
  27. explicit VectorContainer(const char** arr_) {
  28. for (const char **a = arr_; *a; ++a) {
  29. const char *str = (const char*)strdup(*a);
  30. arr.push_back(str);
  31. orig.push_back(str);
  32. }
  33. }
  34. ~VectorContainer() {
  35. for (std::vector<const char*>::iterator i = orig.begin();
  36. i != orig.end(); ++i)
  37. {
  38. free((void*)*i);
  39. }
  40. }
  41. void refresh() {
  42. arr.assign(orig.begin(), orig.end());
  43. }
  44. std::vector < const char* > arr;
  45. private:
  46. std::vector < const char* > orig;
  47. };
  48. TEST(CephArgParse, SimpleArgParse) {
  49. const char *BAR5[] = { "./myprog", "--bar", "5", NULL };
  50. const char *FOO[] = { "./myprog", "--foo", "--baz", NULL };
  51. const char *NONE[] = { "./myprog", NULL };
  52. bool found_foo = false;
  53. std::string found_bar;
  54. VectorContainer bar5(BAR5);
  55. for (std::vector<const char*>::iterator i = bar5.arr.begin();
  56. i != bar5.arr.end(); )
  57. {
  58. if (ceph_argparse_flag(bar5.arr, i, "--foo", (char*)NULL)) {
  59. found_foo = true;
  60. }
  61. else if (ceph_argparse_witharg(bar5.arr, i, &found_bar, "--bar", (char*)NULL)) {
  62. }
  63. else
  64. ++i;
  65. }
  66. ASSERT_EQ(found_foo, false);
  67. ASSERT_EQ(found_bar, "5");
  68. found_foo = false;
  69. found_bar = "";
  70. bool baz_found = false;
  71. std::string found_baz = "";
  72. VectorContainer foo(FOO);
  73. ostringstream err;
  74. for (std::vector<const char*>::iterator i = foo.arr.begin();
  75. i != foo.arr.end(); )
  76. {
  77. if (ceph_argparse_flag(foo.arr, i, "--foo", (char*)NULL)) {
  78. found_foo = true;
  79. }
  80. else if (ceph_argparse_witharg(foo.arr, i, &found_bar, "--bar", (char*)NULL)) {
  81. }
  82. else if (ceph_argparse_witharg(foo.arr, i, &found_baz, err, "--baz", (char*)NULL)) {
  83. ASSERT_NE(string(""), err.str());
  84. baz_found = true;
  85. }
  86. else
  87. ++i;
  88. }
  89. ASSERT_EQ(found_foo, true);
  90. ASSERT_EQ(found_bar, "");
  91. ASSERT_EQ(baz_found, true);
  92. ASSERT_EQ(found_baz, "");
  93. found_foo = false;
  94. found_bar = "";
  95. VectorContainer none(NONE);
  96. for (std::vector<const char*>::iterator i = none.arr.begin();
  97. i != none.arr.end(); )
  98. {
  99. if (ceph_argparse_flag(none.arr, i, "--foo", (char*)NULL)) {
  100. found_foo = true;
  101. }
  102. else if (ceph_argparse_witharg(none.arr, i, &found_bar, "--bar", (char*)NULL)) {
  103. }
  104. else
  105. ++i;
  106. }
  107. ASSERT_EQ(found_foo, false);
  108. ASSERT_EQ(found_bar, "");
  109. }
  110. TEST(CephArgParse, DoubleDash) {
  111. const char *ARGS[] = { "./myprog", "--foo", "5", "--", "--bar", "6", NULL };
  112. int foo = -1, bar = -1;
  113. VectorContainer args(ARGS);
  114. for (std::vector<const char*>::iterator i = args.arr.begin();
  115. i != args.arr.end(); )
  116. {
  117. std::string myarg;
  118. if (ceph_argparse_double_dash(args.arr, i)) {
  119. break;
  120. }
  121. else if (ceph_argparse_witharg(args.arr, i, &myarg, "--foo", (char*)NULL)) {
  122. foo = atoi(myarg.c_str());
  123. }
  124. else if (ceph_argparse_witharg(args.arr, i, &myarg, "--bar", (char*)NULL)) {
  125. bar = atoi(myarg.c_str());
  126. }
  127. else
  128. ++i;
  129. }
  130. ASSERT_EQ(foo, 5);
  131. ASSERT_EQ(bar, -1);
  132. }
  133. TEST(CephArgParse, WithDashesAndUnderscores) {
  134. const char *BAZSTUFF1[] = { "./myprog", "--goo", "--baz-stuff", "50", "--end", NULL };
  135. const char *BAZSTUFF2[] = { "./myprog", "--goo2", "--baz_stuff", "50", NULL };
  136. const char *BAZSTUFF3[] = { "./myprog", "--goo2", "--baz-stuff=50", "50", NULL };
  137. const char *BAZSTUFF4[] = { "./myprog", "--goo2", "--baz_stuff=50", "50", NULL };
  138. const char *NONE1[] = { "./myprog", NULL };
  139. const char *NONE2[] = { "./myprog", "--goo2", "--baz_stuff2", "50", NULL };
  140. const char *NONE3[] = { "./myprog", "--goo2", "__baz_stuff", "50", NULL };
  141. // as flag
  142. std::string found_baz;
  143. VectorContainer bazstuff1(BAZSTUFF1);
  144. for (std::vector<const char*>::iterator i = bazstuff1.arr.begin();
  145. i != bazstuff1.arr.end(); )
  146. {
  147. if (ceph_argparse_flag(bazstuff1.arr, i, "--baz-stuff", (char*)NULL)) {
  148. found_baz = "true";
  149. }
  150. else
  151. ++i;
  152. }
  153. ASSERT_EQ(found_baz, "true");
  154. // as flag
  155. found_baz = "";
  156. VectorContainer bazstuff2(BAZSTUFF2);
  157. for (std::vector<const char*>::iterator i = bazstuff2.arr.begin();
  158. i != bazstuff2.arr.end(); )
  159. {
  160. if (ceph_argparse_flag(bazstuff2.arr, i, "--baz-stuff", (char*)NULL)) {
  161. found_baz = "true";
  162. }
  163. else
  164. ++i;
  165. }
  166. ASSERT_EQ(found_baz, "true");
  167. // with argument
  168. found_baz = "";
  169. bazstuff1.refresh();
  170. for (std::vector<const char*>::iterator i = bazstuff1.arr.begin();
  171. i != bazstuff1.arr.end(); )
  172. {
  173. if (ceph_argparse_witharg(bazstuff1.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
  174. }
  175. else
  176. ++i;
  177. }
  178. ASSERT_EQ(found_baz, "50");
  179. // with argument
  180. found_baz = "";
  181. bazstuff2.refresh();
  182. for (std::vector<const char*>::iterator i = bazstuff2.arr.begin();
  183. i != bazstuff2.arr.end(); )
  184. {
  185. if (ceph_argparse_witharg(bazstuff2.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
  186. }
  187. else
  188. ++i;
  189. }
  190. ASSERT_EQ(found_baz, "50");
  191. // with argument
  192. found_baz = "";
  193. VectorContainer bazstuff3(BAZSTUFF3);
  194. for (std::vector<const char*>::iterator i = bazstuff3.arr.begin();
  195. i != bazstuff3.arr.end(); )
  196. {
  197. if (ceph_argparse_witharg(bazstuff3.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
  198. }
  199. else
  200. ++i;
  201. }
  202. ASSERT_EQ(found_baz, "50");
  203. // with argument
  204. found_baz = "";
  205. VectorContainer bazstuff4(BAZSTUFF4);
  206. for (std::vector<const char*>::iterator i = bazstuff4.arr.begin();
  207. i != bazstuff4.arr.end(); )
  208. {
  209. if (ceph_argparse_witharg(bazstuff4.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
  210. }
  211. else
  212. ++i;
  213. }
  214. ASSERT_EQ(found_baz, "50");
  215. // not found
  216. found_baz = "";
  217. VectorContainer none1(NONE1);
  218. for (std::vector<const char*>::iterator i = none1.arr.begin();
  219. i != none1.arr.end(); )
  220. {
  221. if (ceph_argparse_flag(none1.arr, i, "--baz-stuff", (char*)NULL)) {
  222. found_baz = "true";
  223. }
  224. else if (ceph_argparse_witharg(none1.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
  225. }
  226. else
  227. ++i;
  228. }
  229. ASSERT_EQ(found_baz, "");
  230. // not found
  231. found_baz = "";
  232. VectorContainer none2(NONE2);
  233. for (std::vector<const char*>::iterator i = none2.arr.begin();
  234. i != none2.arr.end(); )
  235. {
  236. if (ceph_argparse_flag(none2.arr, i, "--baz-stuff", (char*)NULL)) {
  237. found_baz = "true";
  238. }
  239. else if (ceph_argparse_witharg(none2.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
  240. }
  241. else
  242. ++i;
  243. }
  244. ASSERT_EQ(found_baz, "");
  245. // not found
  246. found_baz = "";
  247. VectorContainer none3(NONE3);
  248. for (std::vector<const char*>::iterator i = none3.arr.begin();
  249. i != none3.arr.end(); )
  250. {
  251. if (ceph_argparse_flag(none3.arr, i, "--baz-stuff", (char*)NULL)) {
  252. found_baz = "true";
  253. }
  254. else if (ceph_argparse_witharg(none3.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
  255. }
  256. else
  257. ++i;
  258. }
  259. ASSERT_EQ(found_baz, "");
  260. }
  261. TEST(CephArgParse, WithFloat) {
  262. const char *BAZSTUFF1[] = { "./myprog", "--foo", "50.5", "--bar", "52", NULL };
  263. VectorContainer bazstuff1(BAZSTUFF1);
  264. ostringstream err;
  265. float foo;
  266. int bar = -1;
  267. for (std::vector<const char*>::iterator i = bazstuff1.arr.begin();
  268. i != bazstuff1.arr.end(); )
  269. {
  270. if (ceph_argparse_double_dash(bazstuff1.arr, i)) {
  271. break;
  272. } else if (ceph_argparse_witharg(bazstuff1.arr, i, &foo, err, "--foo", (char*)NULL)) {
  273. ASSERT_EQ(string(""), err.str());
  274. } else if (ceph_argparse_witharg(bazstuff1.arr, i, &bar, err, "--bar", (char*)NULL)) {
  275. ASSERT_EQ(string(""), err.str());
  276. }
  277. else {
  278. ++i;
  279. }
  280. }
  281. ASSERT_EQ(foo, 50.5);
  282. ASSERT_EQ(bar, 52);
  283. }
  284. TEST(CephArgParse, WithInt) {
  285. const char *BAZSTUFF1[] = { "./myprog", "--foo", "50", "--bar", "52", NULL };
  286. const char *BAZSTUFF2[] = { "./myprog", "--foo", "--bar", "52", NULL };
  287. const char *BAZSTUFF3[] = { "./myprog", "--foo", "40", "--", "--bar", "42", NULL };
  288. // normal test
  289. VectorContainer bazstuff1(BAZSTUFF1);
  290. ostringstream err;
  291. int foo = -1, bar = -1;
  292. for (std::vector<const char*>::iterator i = bazstuff1.arr.begin();
  293. i != bazstuff1.arr.end(); )
  294. {
  295. if (ceph_argparse_double_dash(bazstuff1.arr, i)) {
  296. break;
  297. } else if (ceph_argparse_witharg(bazstuff1.arr, i, &foo, err, "--foo", (char*)NULL)) {
  298. ASSERT_EQ(string(""), err.str());
  299. } else if (ceph_argparse_witharg(bazstuff1.arr, i, &bar, err, "--bar", (char*)NULL)) {
  300. ASSERT_EQ(string(""), err.str());
  301. }
  302. else {
  303. ++i;
  304. }
  305. }
  306. ASSERT_EQ(foo, 50);
  307. ASSERT_EQ(bar, 52);
  308. // parse error test
  309. VectorContainer bazstuff2(BAZSTUFF2);
  310. ostringstream err2;
  311. for (std::vector<const char*>::iterator i = bazstuff2.arr.begin();
  312. i != bazstuff2.arr.end(); )
  313. {
  314. if (ceph_argparse_double_dash(bazstuff2.arr, i)) {
  315. break;
  316. } else if (ceph_argparse_witharg(bazstuff2.arr, i, &foo, err2, "--foo", (char*)NULL)) {
  317. ASSERT_NE(string(""), err2.str());
  318. }
  319. else {
  320. ++i;
  321. }
  322. }
  323. // double dash test
  324. VectorContainer bazstuff3(BAZSTUFF3);
  325. foo = -1, bar = -1;
  326. for (std::vector<const char*>::iterator i = bazstuff3.arr.begin();
  327. i != bazstuff3.arr.end(); )
  328. {
  329. if (ceph_argparse_double_dash(bazstuff3.arr, i)) {
  330. break;
  331. } else if (ceph_argparse_witharg(bazstuff3.arr, i, &foo, err, "--foo", (char*)NULL)) {
  332. ASSERT_EQ(string(""), err.str());
  333. } else if (ceph_argparse_witharg(bazstuff3.arr, i, &bar, err, "--bar", (char*)NULL)) {
  334. ASSERT_EQ(string(""), err.str());
  335. }
  336. else {
  337. ++i;
  338. }
  339. }
  340. ASSERT_EQ(foo, 40);
  341. ASSERT_EQ(bar, -1);
  342. }
  343. TEST(CephArgParse, env_to_vec) {
  344. {
  345. std::vector<const char*> args;
  346. unsetenv("CEPH_ARGS");
  347. unsetenv("WHATEVER");
  348. env_to_vec(args);
  349. EXPECT_EQ(0u, args.size());
  350. env_to_vec(args, "WHATEVER");
  351. EXPECT_EQ(0u, args.size());
  352. args.push_back("a");
  353. setenv("CEPH_ARGS", "b c", 0);
  354. env_to_vec(args);
  355. EXPECT_EQ(3u, args.size());
  356. EXPECT_EQ(string("b"), args[1]);
  357. EXPECT_EQ(string("c"), args[2]);
  358. setenv("WHATEVER", "d e", 0);
  359. env_to_vec(args, "WHATEVER");
  360. EXPECT_EQ(5u, args.size());
  361. EXPECT_EQ(string("d"), args[3]);
  362. EXPECT_EQ(string("e"), args[4]);
  363. }
  364. {
  365. std::vector<const char*> args;
  366. unsetenv("CEPH_ARGS");
  367. args.push_back("a");
  368. args.push_back("--");
  369. args.push_back("c");
  370. setenv("CEPH_ARGS", "b -- d", 0);
  371. env_to_vec(args);
  372. EXPECT_EQ(5u, args.size());
  373. EXPECT_EQ(string("a"), args[0]);
  374. EXPECT_EQ(string("b"), args[1]);
  375. EXPECT_EQ(string("--"), args[2]);
  376. EXPECT_EQ(string("c"), args[3]);
  377. EXPECT_EQ(string("d"), args[4]);
  378. }
  379. {
  380. std::vector<const char*> args;
  381. unsetenv("CEPH_ARGS");
  382. args.push_back("a");
  383. args.push_back("--");
  384. setenv("CEPH_ARGS", "b -- c", 0);
  385. env_to_vec(args);
  386. EXPECT_EQ(4u, args.size());
  387. EXPECT_EQ(string("a"), args[0]);
  388. EXPECT_EQ(string("b"), args[1]);
  389. EXPECT_EQ(string("--"), args[2]);
  390. EXPECT_EQ(string("c"), args[3]);
  391. }
  392. {
  393. std::vector<const char*> args;
  394. unsetenv("CEPH_ARGS");
  395. args.push_back("--");
  396. args.push_back("c");
  397. setenv("CEPH_ARGS", "b -- d", 0);
  398. env_to_vec(args);
  399. EXPECT_EQ(4u, args.size());
  400. EXPECT_EQ(string("b"), args[0]);
  401. EXPECT_EQ(string("--"), args[1]);
  402. EXPECT_EQ(string("c"), args[2]);
  403. EXPECT_EQ(string("d"), args[3]);
  404. }
  405. {
  406. std::vector<const char*> args;
  407. unsetenv("CEPH_ARGS");
  408. args.push_back("b");
  409. setenv("CEPH_ARGS", "c -- d", 0);
  410. env_to_vec(args);
  411. EXPECT_EQ(4u, args.size());
  412. EXPECT_EQ(string("b"), args[0]);
  413. EXPECT_EQ(string("c"), args[1]);
  414. EXPECT_EQ(string("--"), args[2]);
  415. EXPECT_EQ(string("d"), args[3]);
  416. }
  417. {
  418. std::vector<const char*> args;
  419. unsetenv("CEPH_ARGS");
  420. args.push_back("a");
  421. args.push_back("--");
  422. args.push_back("c");
  423. setenv("CEPH_ARGS", "-- d", 0);
  424. env_to_vec(args);
  425. EXPECT_EQ(4u, args.size());
  426. EXPECT_EQ(string("a"), args[0]);
  427. EXPECT_EQ(string("--"), args[1]);
  428. EXPECT_EQ(string("c"), args[2]);
  429. EXPECT_EQ(string("d"), args[3]);
  430. }
  431. {
  432. std::vector<const char*> args;
  433. unsetenv("CEPH_ARGS");
  434. args.push_back("a");
  435. args.push_back("--");
  436. args.push_back("c");
  437. setenv("CEPH_ARGS", "d", 0);
  438. env_to_vec(args);
  439. EXPECT_EQ(4u, args.size());
  440. EXPECT_EQ(string("a"), args[0]);
  441. EXPECT_EQ(string("d"), args[1]);
  442. EXPECT_EQ(string("--"), args[2]);
  443. EXPECT_EQ(string("c"), args[3]);
  444. }
  445. }
  446. /*
  447. * Local Variables:
  448. * compile-command: "cd .. ; make unittest_ceph_argparse && ./unittest_ceph_argparse"
  449. * End:
  450. */