action_test.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. //
  2. // action_test.cpp
  3. // program_args-test
  4. //
  5. // Created by Sam Jaffe on 2/13/22.
  6. //
  7. #include "program_args/arguments.h"
  8. #include "xcode_gtest_helper.h"
  9. using testing::NotNull;
  10. namespace program {
  11. struct ArgumentTestHelper {
  12. template <typename Impl> static int main(Impl const & args) {
  13. return args.invoke();
  14. }
  15. };
  16. }
  17. template <typename T, size_t N> static T parse(char const * const (&argv)[N]) {
  18. return T(N, argv);
  19. }
  20. program::detail::Any g_action;
  21. template <typename Args, typename Action>
  22. int typed_main(Args const &, Action const & action) {
  23. g_action = program::detail::Any(&action);
  24. return 0;
  25. }
  26. struct Checkout : program::Arguments<Checkout> {
  27. using Arguments::Arguments;
  28. std::string commitish = argument(0, "commit-ish");
  29. };
  30. struct Commit : program::Arguments<Commit> {
  31. using Arguments::Arguments;
  32. std::string message = option("message", 'm');
  33. };
  34. class Push : public program::Arguments<Push> {
  35. public:
  36. using Arguments::Arguments;
  37. std::string remote = argument(0, "repository") = PROGRAM_DEFER(_remote());
  38. private:
  39. std::string _remote() const;
  40. };
  41. struct Bad1 : program::Arguments<Bad1> {
  42. using Arguments::Arguments;
  43. Commit commit = action("commit");
  44. std::string arg0 = argument(0, "arg0");
  45. };
  46. struct Bad2 : program::Arguments<Bad2> {
  47. using Arguments::Arguments;
  48. std::string arg0 = argument(0, "arg0");
  49. Commit commit = action("commit");
  50. };
  51. struct Git : program::Arguments<Git> {
  52. using Arguments::Arguments;
  53. std::string pwd = option('C');
  54. bool verbose = flag("verbose", 'v');
  55. Commit commit = action("commit");
  56. Checkout checkout = action("checkout");
  57. Push push = action("push");
  58. };
  59. PROGRAM_ARGS_INVOKE(Git, commit, checkout, push)
  60. std::string Push::_remote() const {
  61. if (Git const * git = Arguments::parent<Git>()) { return git->pwd; }
  62. return "";
  63. }
  64. TEST(ActionTest, CannotMixActionAndArgument) {
  65. EXPECT_THROW(Bad1(), program::ArgumentMixingError);
  66. EXPECT_THROW(Bad2(), program::ArgumentMixingError);
  67. }
  68. TEST(ActionTest, CanRunWithMultipleActions) { EXPECT_NO_THROW(Git()); }
  69. TEST(ActionTest, ActionIsRouted) {
  70. Git git = parse<Git>({"", "-v", "commit", "-m", "this is a message"});
  71. EXPECT_THAT(git.commit.message, "this is a message");
  72. }
  73. TEST(ActionTest, CanDiveIntoTypedMain) {
  74. Git git = parse<Git>({"", "-v", "commit", "-m", "this is a message"});
  75. program::ArgumentTestHelper::main(git);
  76. EXPECT_THAT(g_action.get<Commit>(), NotNull());
  77. }
  78. TEST(ActionTest, CanFetchParentInfo) {
  79. Git git = parse<Git>({"", "-C", "./submodules/X", "push"});
  80. EXPECT_THAT(git.push.remote, "./submodules/X");
  81. }