You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
9.6 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
  1. #ifdef WITH_MODULE
  2. import argparse;
  3. #else
  4. #include <argparse/argparse.hpp>
  5. #endif
  6. #include <doctest.hpp>
  7. #include <cmath>
  8. #include <string>
  9. #include <vector>
  10. using doctest::test_suite;
  11. TEST_CASE("Add subparsers" * test_suite("subparsers")) {
  12. argparse::ArgumentParser program("test");
  13. program.add_argument("--output");
  14. argparse::ArgumentParser command_1("add");
  15. command_1.add_argument("file").nargs(2);
  16. argparse::ArgumentParser command_2("clean");
  17. program.add_subparser(command_1);
  18. program.add_subparser(command_2);
  19. program.parse_args({"test", "--output", "thrust_profile.csv"});
  20. REQUIRE(program.is_subcommand_used("add") == false);
  21. REQUIRE(program.get("--output") == "thrust_profile.csv");
  22. }
  23. TEST_CASE("Parse subparser command" * test_suite("subparsers")) {
  24. argparse::ArgumentParser program("test");
  25. program.add_argument("--output");
  26. argparse::ArgumentParser command_1("add");
  27. command_1.add_argument("file").nargs(2);
  28. argparse::ArgumentParser command_2("clean");
  29. command_2.add_argument("--fullclean")
  30. .default_value(false)
  31. .implicit_value(true);
  32. program.add_subparser(command_1);
  33. program.add_subparser(command_2);
  34. SUBCASE("command 1") {
  35. program.parse_args({"test", "add", "file1.txt", "file2.txt"});
  36. REQUIRE(program.is_subcommand_used("add") == true);
  37. REQUIRE(command_1.is_used("file"));
  38. REQUIRE((command_1.get<std::vector<std::string>>("file") ==
  39. std::vector<std::string>{"file1.txt", "file2.txt"}));
  40. }
  41. SUBCASE("command 2") {
  42. program.parse_args({"test", "clean", "--fullclean"});
  43. REQUIRE(program.is_subcommand_used("clean") == true);
  44. REQUIRE(command_2.get<bool>("--fullclean") == true);
  45. }
  46. }
  47. TEST_CASE("Parse subparser command with optional argument" *
  48. test_suite("subparsers")) {
  49. argparse::ArgumentParser program("test");
  50. program.add_argument("--verbose").flag();
  51. argparse::ArgumentParser command_1("add");
  52. command_1.add_argument("file");
  53. argparse::ArgumentParser command_2("clean");
  54. command_2.add_argument("--fullclean")
  55. .default_value(false)
  56. .implicit_value(true);
  57. program.add_subparser(command_1);
  58. program.add_subparser(command_2);
  59. SUBCASE("Optional argument BEFORE subcommand") {
  60. program.parse_args({"test", "--verbose", "clean", "--fullclean"});
  61. REQUIRE(program.is_subcommand_used("clean") == true);
  62. REQUIRE(program.get<bool>("--verbose") == true);
  63. REQUIRE(command_2.get<bool>("--fullclean") == true);
  64. }
  65. SUBCASE("Optional argument AFTER subcommand") {
  66. REQUIRE_THROWS_WITH_AS(
  67. program.parse_args({"test", "clean", "--fullclean", "--verbose"}),
  68. "Unknown argument: --verbose", std::runtime_error);
  69. }
  70. }
  71. TEST_CASE("Parse subparser command with parent parser" *
  72. test_suite("subparsers")) {
  73. argparse::ArgumentParser program("test");
  74. argparse::ArgumentParser parent("parent");
  75. parent.add_argument("--verbose").flag();
  76. program.add_parents(parent);
  77. argparse::ArgumentParser command_1("add");
  78. command_1.add_argument("file");
  79. argparse::ArgumentParser command_2("clean");
  80. command_2.add_argument("--fullclean")
  81. .default_value(false)
  82. .implicit_value(true);
  83. program.add_subparser(command_1);
  84. program.add_subparser(command_2);
  85. SUBCASE("Optional argument BEFORE subcommand") {
  86. program.parse_args({"test", "--verbose", "clean", "--fullclean"});
  87. REQUIRE(program.is_subcommand_used("clean") == true);
  88. REQUIRE(program.get<bool>("--verbose") == true);
  89. REQUIRE(command_2.get<bool>("--fullclean") == true);
  90. }
  91. SUBCASE("Optional argument AFTER subcommand") {
  92. REQUIRE_THROWS_WITH_AS(
  93. program.parse_args({"test", "clean", "--fullclean", "--verbose"}),
  94. "Unknown argument: --verbose", std::runtime_error);
  95. }
  96. }
  97. TEST_CASE("Parse git commands" * test_suite("subparsers")) {
  98. argparse::ArgumentParser program("git");
  99. argparse::ArgumentParser add_command("add");
  100. add_command.add_argument("files").remaining();
  101. argparse::ArgumentParser commit_command("commit");
  102. commit_command.add_argument("-a").flag();
  103. commit_command.add_argument("-m");
  104. argparse::ArgumentParser catfile_command("cat-file");
  105. catfile_command.add_argument("-t");
  106. catfile_command.add_argument("-p");
  107. argparse::ArgumentParser submodule_command("submodule");
  108. argparse::ArgumentParser submodule_update_command("update");
  109. submodule_update_command.add_argument("--init")
  110. .default_value(false)
  111. .implicit_value(true);
  112. submodule_update_command.add_argument("--recursive")
  113. .default_value(false)
  114. .implicit_value(true);
  115. submodule_command.add_subparser(submodule_update_command);
  116. program.add_subparser(add_command);
  117. program.add_subparser(commit_command);
  118. program.add_subparser(catfile_command);
  119. program.add_subparser(submodule_command);
  120. SUBCASE("git add") {
  121. program.parse_args({"git", "add", "main.cpp", "foo.hpp", "foo.cpp"});
  122. REQUIRE(program.is_subcommand_used("add") == true);
  123. REQUIRE((add_command.get<std::vector<std::string>>("files") ==
  124. std::vector<std::string>{"main.cpp", "foo.hpp", "foo.cpp"}));
  125. }
  126. SUBCASE("git commit") {
  127. program.parse_args({"git", "commit", "-am", "Initial commit"});
  128. REQUIRE(program.is_subcommand_used("commit") == true);
  129. REQUIRE(commit_command.get<bool>("-a") == true);
  130. REQUIRE(commit_command.get<std::string>("-m") ==
  131. std::string{"Initial commit"});
  132. }
  133. SUBCASE("git cat-file -t") {
  134. program.parse_args({"git", "cat-file", "-t", "3739f5"});
  135. REQUIRE(program.is_subcommand_used("cat-file") == true);
  136. REQUIRE(catfile_command.get<std::string>("-t") == std::string{"3739f5"});
  137. }
  138. SUBCASE("git cat-file -p") {
  139. program.parse_args({"git", "cat-file", "-p", "3739f5"});
  140. REQUIRE(program.is_subcommand_used("cat-file") == true);
  141. REQUIRE(catfile_command.get<std::string>("-p") == std::string{"3739f5"});
  142. }
  143. SUBCASE("git submodule update") {
  144. program.parse_args({"git", "submodule", "update"});
  145. REQUIRE(program.is_subcommand_used("submodule") == true);
  146. REQUIRE(submodule_command.is_subcommand_used("update") == true);
  147. }
  148. SUBCASE("git submodule update --init") {
  149. program.parse_args({"git", "submodule", "update", "--init"});
  150. REQUIRE(program.is_subcommand_used("submodule") == true);
  151. REQUIRE(submodule_command.is_subcommand_used("update") == true);
  152. REQUIRE(submodule_update_command.get<bool>("--init") == true);
  153. REQUIRE(submodule_update_command.get<bool>("--recursive") == false);
  154. }
  155. SUBCASE("git submodule update --recursive") {
  156. program.parse_args({"git", "submodule", "update", "--recursive"});
  157. REQUIRE(program.is_subcommand_used("submodule") == true);
  158. REQUIRE(submodule_command.is_subcommand_used("update") == true);
  159. REQUIRE(submodule_update_command.get<bool>("--recursive") == true);
  160. }
  161. SUBCASE("git submodule update --init --recursive") {
  162. program.parse_args({"git", "submodule", "update", "--init", "--recursive"});
  163. REQUIRE(program.is_subcommand_used("submodule") == true);
  164. REQUIRE(submodule_command.is_subcommand_used("update") == true);
  165. REQUIRE(submodule_update_command.get<bool>("--init") == true);
  166. REQUIRE(submodule_update_command.get<bool>("--recursive") == true);
  167. }
  168. }
  169. TEST_CASE("Check is_subcommand_used after parse" * test_suite("subparsers")) {
  170. argparse::ArgumentParser command_1("add");
  171. argparse::ArgumentParser command_2("clean");
  172. command_2.add_argument("--fullclean")
  173. .default_value(false)
  174. .implicit_value(true);
  175. argparse::ArgumentParser program("test");
  176. program.add_subparser(command_1);
  177. program.add_subparser(command_2);
  178. SUBCASE("command 1") {
  179. program.parse_args({"test", "add"});
  180. REQUIRE(program.is_subcommand_used("add") == true);
  181. REQUIRE(program.is_subcommand_used(command_1) == true);
  182. REQUIRE(program.is_subcommand_used("clean") == false);
  183. REQUIRE(program.is_subcommand_used(command_2) == false);
  184. }
  185. SUBCASE("command 2") {
  186. program.parse_args({"test", "clean", "--fullclean"});
  187. REQUIRE(program.is_subcommand_used("add") == false);
  188. REQUIRE(program.is_subcommand_used(command_1) == false);
  189. REQUIRE(program.is_subcommand_used("clean") == true);
  190. REQUIRE(program.is_subcommand_used(command_2) == true);
  191. }
  192. SUBCASE("none") {
  193. program.parse_args({"test"});
  194. REQUIRE(program.is_subcommand_used("add") == false);
  195. REQUIRE(program.is_subcommand_used(command_1) == false);
  196. REQUIRE(program.is_subcommand_used("clean") == false);
  197. REQUIRE(program.is_subcommand_used(command_2) == false);
  198. }
  199. }
  200. static bool contains(const std::string &haystack, const std::string &needle) {
  201. return haystack.find(needle) != std::string::npos;
  202. }
  203. TEST_CASE("Check set_suppress" * test_suite("subparsers")) {
  204. argparse::ArgumentParser command("cmd");
  205. command.add_argument("arg").remaining();
  206. argparse::ArgumentParser program("test");
  207. program.add_subparser(command);
  208. SUBCASE("help message contain info if subcommand not suppressed") {
  209. command.set_suppress(false);
  210. REQUIRE(contains(program.help().str(), "Subcommands") == true);
  211. REQUIRE(contains(program.help().str(), "cmd") == true);
  212. }
  213. SUBCASE("help message does not contain info if subcommand suppressed") {
  214. command.set_suppress(true);
  215. REQUIRE(contains(program.help().str(), "Subcommands") == false);
  216. REQUIRE(contains(program.help().str(), "cmd") == false);
  217. }
  218. SUBCASE("help message contain info if not all subcommands suppressed") {
  219. argparse::ArgumentParser command_2("command_2");
  220. program.add_subparser(command_2);
  221. command.set_suppress(true);
  222. command_2.set_suppress(false);
  223. REQUIRE(contains(program.help().str(), "Subcommands") == true);
  224. REQUIRE(contains(program.help().str(), "cmd") == false);
  225. REQUIRE(contains(program.help().str(), "command_2") == true);
  226. }
  227. }