@@ -29,6 +29,9 @@ concept HasPrintTestParam = requires(TestType value) {
2929 { T::PrintTestParam (value) } -> std::same_as<std::string>;
3030};
3131
32+ template <typename TestTasksList, typename RunTestCase>
33+ void RunTestCasesWithTag (const TestTasksList &test_tasks_list, std::string_view task_tag, RunTestCase run_test_case);
34+
3235template <typename InType, typename OutType, typename TestType = void >
3336// / @brief Base class for running functional tests on parallel tasks.
3437// / @tparam InType Type of input data.
@@ -56,6 +59,16 @@ class BaseRunFuncTests : public ::testing::TestWithParam<FuncTestParam<InType, O
5659 // / @return Initialized input data.
5760 virtual InType GetTestInputData () = 0;
5861
62+ virtual void RunTestCase (const FuncTestParam<InType, OutType, TestType> &test_param) {
63+ ExecuteTest (test_param);
64+ }
65+
66+ template <typename TestTasksList>
67+ void RunTestCasesWithTag (const TestTasksList &test_tasks_list, std::string_view task_tag) {
68+ ppc::util::RunTestCasesWithTag (test_tasks_list, task_tag,
69+ [this ](const auto &test_param) { RunTestCase (test_param); });
70+ }
71+
5972 void ExecuteTest (FuncTestParam<InType, OutType, TestType> test_param) {
6073 const std::string &test_name = std::get<static_cast <std::size_t >(GTestParamIndex::kNameTest )>(test_param);
6174
@@ -120,6 +133,43 @@ class BaseRunFuncTests : public ::testing::TestWithParam<FuncTestParam<InType, O
120133 ppc::task::TaskPtr<InType, OutType> task_;
121134};
122135
136+ namespace detail {
137+
138+ [[nodiscard]] inline std::string MakeFuncTestTaskTagPattern (std::string_view task_tag) {
139+ std::string tag_pattern{task_tag};
140+ if (!tag_pattern.starts_with (' _' )) {
141+ tag_pattern.insert (0 , 1 , ' _' );
142+ }
143+ if (!tag_pattern.ends_with (' _' )) {
144+ tag_pattern.push_back (' _' );
145+ }
146+ return tag_pattern;
147+ }
148+
149+ } // namespace detail
150+
151+ template <typename TestTasksList, typename RunTestCase>
152+ void RunTestCasesWithTag (const TestTasksList &test_tasks_list, std::string_view task_tag, RunTestCase run_test_case) {
153+ if (task_tag.empty ()) {
154+ ADD_FAILURE () << " Functional test task tag must not be empty" ;
155+ return ;
156+ }
157+
158+ const std::string task_tag_pattern = detail::MakeFuncTestTaskTagPattern (task_tag);
159+ bool has_matching_task = false ;
160+ std::apply ([&](const auto &...test_params ) {
161+ auto run_if_tagged = [&](const auto &test_param) {
162+ const std::string &test_name = std::get<static_cast <std::size_t >(GTestParamIndex::kNameTest )>(test_param);
163+ if (test_name.contains (task_tag_pattern)) {
164+ has_matching_task = true ;
165+ std::invoke (run_test_case, test_param);
166+ }
167+ };
168+ (run_if_tagged (test_params), ...);
169+ }, test_tasks_list);
170+ EXPECT_TRUE (has_matching_task) << " No functional test cases matched tag: " << std::string (task_tag);
171+ }
172+
123173template <typename Tuple, std::size_t ... Is>
124174auto ExpandToValuesImpl (const Tuple &t, std::index_sequence<Is...> /* unused*/ ) {
125175 return ::testing::Values (std::get<Is>(t)...);
0 commit comments