11
22#include " cucumber_cpp/library/cucumber_expression/Expression.hpp"
33#include " cucumber_cpp/library/cucumber_expression/ParameterRegistry.hpp"
4+ #include " yaml-cpp/node/node.h"
5+ #include " yaml-cpp/node/parse.h"
6+ #include " yaml-cpp/yaml.h"
47#include " gmock/gmock.h"
58#include < any>
69#include < cctype>
710#include < cstdint>
811#include < cstdlib>
12+ #include < filesystem>
913#include < format>
1014#include < functional>
1115#include < gtest/gtest.h>
2024
2125namespace cucumber_cpp ::library::cucumber_expression
2226{
27+ namespace
28+ {
29+ std::vector<std::pair<std::string, YAML::Node>> GetTestData (const std::string& path)
30+ {
31+ std::vector<std::pair<std::string, YAML::Node>> testdata;
32+
33+ for (const auto & file : std::filesystem::directory_iterator (path))
34+ if (file.is_regular_file () && file.path ().extension () == " .yaml" )
35+ testdata.emplace_back (file.path ().string (), YAML::LoadFile (file.path ()));
36+
37+ return testdata;
38+ }
39+
40+ std::string FormatMessage (const YAML::Node& node, const Expression& expression)
41+ {
42+ return std::format (" failed to match {}\n "
43+ " regex {}\n "
44+ " against {}" ,
45+ node[" expression" ].as <std::string>(), expression.Pattern (), node[" text" ].as <std::string>());
46+ }
47+ }
48+
2349 struct TestExpression : testing::Test
2450 {
2551 ParameterRegistry parameterRegistry{};
@@ -31,41 +57,44 @@ namespace cucumber_cpp::library::cucumber_expression
3157 }
3258 };
3359
34- TEST_F (TestExpression, Escape)
35- {
36- auto match = Match (R"( hello \{world?)" , " hello {world?" );
37- EXPECT_THAT (match, testing::IsTrue ());
38- }
39-
40- TEST_F (TestExpression, MatchOptional)
41- {
42- Expression expression{ R"( hello (world))" , parameterRegistry };
43- EXPECT_THAT (expression.Pattern (), testing::StrEq (R"__( ^hello (?:world)?$)__" ));
44- EXPECT_THAT (expression.Match (" hello world" ), testing::IsTrue ());
45- EXPECT_THAT (expression.Match (" hello " ), testing::IsTrue ());
46- }
47-
48- TEST_F (TestExpression, MatchAlternative)
60+ TEST_F (TestExpression, TestFromFiles)
4961 {
50- Expression expression{ R"( hello country/wo\/rld/city)" , parameterRegistry };
51- EXPECT_THAT (expression.Pattern (), testing::StrEq (R"__( ^hello (?:country|wo/rld|city)$)__" ));
52- EXPECT_THAT (expression.Match (" hello country" ), testing::IsTrue ());
53- EXPECT_THAT (expression.Match (" hello wo/rld" ), testing::IsTrue ());
54- EXPECT_THAT (expression.Match (" hello city" ), testing::IsTrue ());
55- }
62+ std::filesystem::path testdataPath = " testdata/cucumber-expression/matching" ;
5663
57- TEST_F (TestExpression, MatchString)
58- {
59- auto match = Match (R"__( hello {string})__" , R"__( hello "beautiful world")__" );
60- EXPECT_THAT (match, testing::IsTrue ());
61- EXPECT_THAT (std::any_cast<std::string>((*match)[0 ]), testing::StrEq (R"__( beautiful world)__" ));
62- }
63-
64- TEST_F (TestExpression, MatchInt)
65- {
66- auto match = Match (R"__( there are {int} cucumbers)__" , R"__( there are 15 cucumbers)__" );
67- EXPECT_THAT (match, testing::IsTrue ());
68- EXPECT_THAT (std::any_cast<std::int64_t >((*match)[0 ]), testing::Eq (15 ));
64+ for (const auto & [file, testdata] : GetTestData (testdataPath))
65+ {
66+ if (testdata[" exception" ])
67+ ASSERT_ANY_THROW (Match (testdata[" expression" ].as <std::string>(), testdata[" text" ].as <std::string>()))
68+ << std::format (" Test failed for file: {}" , file);
69+ else
70+ {
71+ if (testdata[" expected_args" ].IsNull ())
72+ ASSERT_THAT (Match (testdata[" expression" ].as <std::string>(), testdata[" text" ].as <std::string>()), testing::IsFalse ());
73+ else
74+ {
75+ const auto expression = Expression{ testdata[" expression" ].as <std::string>(), parameterRegistry };
76+ const auto matchOpt = expression.Match (testdata[" text" ].as <std::string>());
77+
78+ ASSERT_THAT (matchOpt, testing::IsTrue ()) << FormatMessage (testdata, expression);
79+
80+ const auto match = *matchOpt;
81+ for (std::size_t i = 0 ; i < testdata[" expected_args" ].size (); ++i)
82+ {
83+ if (match[i].type () == typeid (std::string))
84+ ASSERT_THAT (std::any_cast<std::string>(match[i]), testdata[" expected_args" ][i].as <std::string>()) << FormatMessage (testdata, expression);
85+ else if (match[i].type () == typeid (std::int64_t ))
86+ ASSERT_THAT (std::any_cast<std::int64_t >(match[i]), testdata[" expected_args" ][i].as <std::int64_t >()) << FormatMessage (testdata, expression);
87+ else if (match[i].type () == typeid (float ))
88+ ASSERT_THAT (std::any_cast<float >(match[i]), testdata[" expected_args" ][i].as <float >()) << FormatMessage (testdata, expression);
89+ else if (match[i].type () == typeid (double ))
90+ ASSERT_THAT (std::any_cast<double >(match[i]), testdata[" expected_args" ][i].as <double >()) << FormatMessage (testdata, expression);
91+ else
92+ FAIL () << " Unknown type: " << match[i].type ().name () << " for:\n "
93+ << FormatMessage (testdata, expression);
94+ }
95+ }
96+ }
97+ }
6998 }
7099
71100 TEST_F (TestExpression, MatchFloat)
@@ -157,10 +186,4 @@ namespace cucumber_cpp::library::cucumber_expression
157186 Expression expression{ expr, parameterRegistry };
158187 EXPECT_THAT (expr, testing::StrEq (expression.Source ()));
159188 }
160-
161- TEST_F (TestExpression, MultiParamParsing)
162- {
163- auto matchString{ Match (R"__( Step with cucumber expression syntax {float} {string} {int})__" , R"__( Step with cucumber expression syntax 1.1 "string" 10)__" ) };
164- EXPECT_THAT (matchString, testing::IsTrue ());
165- }
166189}
0 commit comments