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.

154 lines
4.2 KiB

2 years ago
  1. #ifndef CLIPP_TESTING_H_
  2. #define CLIPP_TESTING_H_
  3. //don't include anything else before the test subject
  4. #include "../include/clipp.h"
  5. #include <initializer_list>
  6. #include <algorithm>
  7. #include <stdexcept>
  8. #include <string>
  9. #include <vector>
  10. #include <iostream>
  11. #include <functional>
  12. #include <type_traits>
  13. #include <limits>
  14. /*************************************************************************//**
  15. *
  16. * @brief stores the location of a test definition
  17. *
  18. *****************************************************************************/
  19. struct test_location
  20. {
  21. test_location(std::string file_, int line_):
  22. file{std::move(file_)}, line{line_}
  23. {}
  24. std::string file;
  25. int line;
  26. };
  27. /*************************************************************************//**
  28. *
  29. * @brief returns wrapped/nested variants of the input command line interface
  30. *
  31. *****************************************************************************/
  32. template<class CLI>
  33. std::vector<CLI>
  34. wrapped_variants(const CLI& cli)
  35. {
  36. using namespace clipp;
  37. return {
  38. /* 1*/ cli
  39. ,
  40. /* 2*/ group{cli}
  41. ,
  42. /* 3*/ group{group{cli}}
  43. ,
  44. /* 4*/ group{option("?a?"), cli}
  45. ,
  46. /* 5*/ group{cli, option("?a?")}
  47. ,
  48. /* 6*/ group{option("?b?"), cli, option("?a?")}
  49. ,
  50. /* 7*/ group{group{option("?a?")}, cli}
  51. ,
  52. /* 8*/ group{cli, group{option("?a?")}}
  53. ,
  54. /* 9*/ group{option("?a?"), group{cli}}
  55. ,
  56. /*10*/ group{group{cli}, option("?a?")}
  57. ,
  58. /*11*/ group{option("?b?"), group{cli}, option("?a?")}
  59. };
  60. }
  61. /*************************************************************************//**
  62. *
  63. * @brief runs CLI validity tests based on differently wrapped variants of
  64. * the original input CLI
  65. *
  66. *****************************************************************************/
  67. template<class CLI>
  68. void run_wrapped_variants(
  69. const test_location& info,
  70. const std::initializer_list<const char*>& args,
  71. const CLI& cli,
  72. std::function<void()> initialize,
  73. std::function<bool()> valid)
  74. {
  75. using std::cout;
  76. using std::to_string;
  77. int variant = 0;
  78. for(const auto& wrappedCli : wrapped_variants(cli)) {
  79. ++variant;
  80. initialize();
  81. parse(args, wrappedCli);
  82. // cout << "==============================================\n"
  83. // << " in file " << info.file << " in line " << info.line
  84. // << " with variant " << variant << '\n'
  85. // << "==============================================\n";
  86. // clipp::debug::print(cout, wrappedCli);
  87. // cout << "args = { ";
  88. // for(const auto& a : args) cout << '"' << a << "\" ";
  89. // cout << "}\n";
  90. // auto res = clipp::parse(args, wrappedCli);
  91. // cout << "----------------------------------------------\n";
  92. // clipp::debug::print(cout, res);
  93. if(!valid()) {
  94. throw std::runtime_error{"failed test " + info.file +
  95. " in line " + to_string(info.line) +
  96. " with variant " + to_string(variant) };
  97. }
  98. }
  99. }
  100. /*************************************************************************//**
  101. *
  102. * @brief runs CLI validity test
  103. *
  104. *****************************************************************************/
  105. template<class CLI>
  106. void run_test(
  107. const test_location& info,
  108. const std::initializer_list<const char*>& args,
  109. const CLI& cli,
  110. std::function<bool()> valid)
  111. {
  112. using std::cout;
  113. using std::to_string;
  114. parse(args, cli);
  115. // cout << "==============================================\n"
  116. // << " in file " << info.file << " in line " << info.line << '\n'
  117. // << "==============================================\n";
  118. // clipp::debug::print(cout, cli);
  119. // cout << "args = { ";
  120. // for(const auto& a : args) cout << '"' << a << "\" ";
  121. // cout << "}\n";
  122. // auto res = clipp::parse(args, cli);
  123. // cout << "----------------------------------------------\n";
  124. // clipp::debug::print(cout, res);
  125. if(!valid()) {
  126. throw std::runtime_error{"failed test " + info.file +
  127. " in line " + to_string(info.line) };
  128. }
  129. }
  130. #endif