Skip to content

Commit 640986f

Browse files
committed
enabled examples-tables-undefined and global-hooks compatibility test
1 parent 028dcc5 commit 640986f

21 files changed

+426
-108
lines changed

compatibility/compatibility.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ namespace compatibility
7878
jsonIter = json.erase(jsonIter);
7979
else if (key == "start")
8080
jsonIter = json.erase(jsonIter);
81+
else if (key == "snippets")
82+
jsonIter = json.erase(jsonIter);
8183
else if (value.is_object())
8284
{
8385
SanitizeExpectedJson(value);
@@ -133,6 +135,8 @@ namespace compatibility
133135
jsonIter = json.erase(jsonIter);
134136
else if (key == "line")
135137
jsonIter = json.erase(jsonIter);
138+
else if (key == "snippets")
139+
jsonIter = json.erase(jsonIter);
136140
else if (value.is_object())
137141
{
138142
SanitizeActualJson(value);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include "cucumber_cpp/CucumberCpp.hpp"
2+
#include "gtest/gtest.h"
3+
#include <cstdint>
4+
#include <gmock/gmock.h>
5+
6+
GIVEN(R"(there are {int} cucumbers)", (std::int32_t initialCount))
7+
{
8+
context.Insert(initialCount);
9+
}
10+
11+
WHEN(R"(I eat {int} cucumbers)", (std::int32_t eatCount))
12+
{
13+
context.Get<std::int32_t>() -= eatCount;
14+
}
15+
16+
THEN(R"(I should have {int} cucumbers)", (std::int32_t expectedCount))
17+
{
18+
ASSERT_THAT(context.Get<std::int32_t>(), testing::Eq(expectedCount));
19+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include "cucumber_cpp/CucumberCpp.hpp"
2+
#include <gmock/gmock.h>
3+
4+
HOOK_BEFORE_ALL()
5+
{
6+
// no-op
7+
}
8+
9+
HOOK_BEFORE_ALL()
10+
{
11+
// no-op
12+
}
13+
14+
WHEN(R"(a step passes)")
15+
{
16+
// no-op
17+
}
18+
19+
WHEN(R"(a step fails)")
20+
{
21+
ASSERT_THAT(true, false);
22+
}
23+
24+
HOOK_AFTER_ALL()
25+
{
26+
// no-op
27+
}
28+
29+
HOOK_AFTER_ALL()
30+
{
31+
// no-op
32+
}

cucumber_cpp/example/hooks/Hooks.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,14 @@ HOOK_BEFORE_ALL()
1212
context.Emplace<NordicBleFixture>();
1313
}
1414

15-
HOOK_BEFORE_SCENARIO("@dingus")
15+
HOOK_BEFORE_ALL(.name = "Initialize something") // does NOT have a .tagExpression
16+
{}
17+
18+
HOOK_BEFORE_SCENARIO(.name = "explicit name only")
19+
{
20+
}
21+
22+
HOOK_BEFORE_SCENARIO("@dingus", "name", 10)
1623
{
1724
}
1825

cucumber_cpp/library/HookRegistry.cpp

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11

22
#include "cucumber_cpp/library/HookRegistry.hpp"
3+
#include "cucumber/gherkin/id_generator.hpp"
4+
#include "cucumber/messages/hook_type.hpp"
5+
#include "cucumber/messages/location.hpp"
36
#include "cucumber/messages/pickle_tag.hpp"
7+
#include "cucumber/messages/source_reference.hpp"
48
#include "cucumber/messages/tag.hpp"
59
#include "cucumber_cpp/library/Context.hpp"
10+
#include "cucumber_cpp/library/support/SupportCodeLibrary.hpp"
11+
#include "cucumber_cpp/library/tag_expression/Parser.hpp"
612
#include <algorithm>
713
#include <cstddef>
14+
#include <map>
15+
#include <optional>
816
#include <ranges>
917
#include <source_location>
1018
#include <span>
1119
#include <string>
1220
#include <string_view>
21+
#include <utility>
1322
#include <vector>
1423

1524
namespace cucumber_cpp::library
@@ -39,16 +48,51 @@ namespace cucumber_cpp::library
3948
return keyValue.second.tagExpression->Evaluate(tags);
4049
};
4150
}
51+
52+
std::map<HookType, cucumber::messages::hook_type> HookTypeMap{
53+
{ HookType::beforeAll, cucumber::messages::hook_type::BEFORE_TEST_RUN },
54+
{ HookType::afterAll, cucumber::messages::hook_type::AFTER_TEST_RUN },
55+
// { HookType::beforeFeature, cucumber::messages::hook_type::BEFORE_TEST_CASE },
56+
// { HookType::afterFeature, cucumber::messages::hook_type::AFTER_TEST_CASE },
57+
{ HookType::before, cucumber::messages::hook_type::BEFORE_TEST_CASE },
58+
{ HookType::after, cucumber::messages::hook_type::AFTER_TEST_CASE },
59+
{ HookType::beforeStep, cucumber::messages::hook_type::BEFORE_TEST_STEP },
60+
{ HookType::afterStep, cucumber::messages::hook_type::AFTER_TEST_STEP },
61+
};
4262
}
4363

4464
HookBase::HookBase(Context& context)
4565
: context{ context }
4666
{}
4767

48-
HookRegistry::HookRegistry()
68+
HookRegistry::Definition::Definition(std::string id, HookType type, std::string_view expression, HookFactory factory, std::source_location sourceLocation)
69+
: type{ type }
70+
, tagExpression{ tag_expression::Parse(expression) }
71+
, factory{ factory }
72+
, hook{
73+
.id = id,
74+
.source_reference = cucumber::messages::source_reference{
75+
.uri = sourceLocation.file_name(),
76+
.location = cucumber::messages::location{
77+
.line = sourceLocation.line(),
78+
},
79+
},
80+
.tag_expression = !expression.empty() ? std::make_optional(std::string{ expression }) : std::nullopt,
81+
.type = HookTypeMap.contains(type) ? std::make_optional(HookTypeMap.at(type)) : std::nullopt,
82+
}
83+
{}
84+
85+
HookRegistry::HookRegistry(cucumber::gherkin::id_generator_ptr idGenerator)
86+
: idGenerator{ std::move(idGenerator) }
4987
{
50-
for (const auto& matcher : HookRegistration::Instance().GetEntries())
51-
Register(matcher.type, matcher.expression, matcher.factory, matcher.sourceLocation);
88+
}
89+
90+
void HookRegistry::LoadHooks()
91+
{
92+
93+
for (const auto& matcher : support::DefinitionRegistration::Instance().GetHooks())
94+
// for (const auto& matcher : HookRegistration::Instance().GetEntries())
95+
Register(matcher.id, matcher.type, matcher.expression, matcher.factory, matcher.sourceLocation);
5296
}
5397

5498
std::vector<std::string> HookRegistry::FindIds(HookType hookType, std::span<const cucumber::messages::pickle_tag> tags) const
@@ -83,9 +127,8 @@ namespace cucumber_cpp::library
83127
return registry.at(id);
84128
}
85129

86-
void HookRegistry::Register(HookType type, std::string_view expression, HookFactory factory, std::source_location sourceLocation)
130+
void HookRegistry::Register(std::string id, HookType type, std::string_view expression, HookFactory factory, std::source_location sourceLocation)
87131
{
88-
auto id = std::to_string(nextId++);
89132
registry.emplace(id, Definition{ id, type, expression, factory, sourceLocation });
90133
}
91134

cucumber_cpp/library/HookRegistry.hpp

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#ifndef CUCUMBER_CPP_HOOKREGISTRY_HPP
22
#define CUCUMBER_CPP_HOOKREGISTRY_HPP
33

4+
#include "cucumber/gherkin/id_generator.hpp"
45
#include "cucumber/messages/hook.hpp"
6+
#include "cucumber/messages/hook_type.hpp"
57
#include "cucumber/messages/location.hpp"
68
#include "cucumber/messages/pickle_tag.hpp"
79
#include "cucumber/messages/source_reference.hpp"
@@ -14,6 +16,8 @@
1416
#include <cstdint>
1517
#include <map>
1618
#include <memory>
19+
#include <optional>
20+
#include <ranges>
1721
#include <source_location>
1822
#include <span>
1923
#include <string>
@@ -76,46 +80,63 @@ namespace cucumber_cpp::library
7680
{
7781
struct Definition
7882
{
79-
Definition(std::string id, HookType type, std::string_view expression, HookFactory factory, std::source_location sourceLocation)
80-
: type{ type }
81-
, tagExpression{ tag_expression::Parse(expression) }
82-
, factory{ factory }
83-
, hook{
84-
.id = id,
85-
.source_reference = cucumber::messages::source_reference{
86-
.uri = sourceLocation.file_name(),
87-
.location = cucumber::messages::location{
88-
.line = sourceLocation.line(),
89-
},
90-
},
91-
.tag_expression = std::string{ expression },
92-
}
93-
{}
83+
Definition(std::string id, HookType type, std::string_view expression, HookFactory factory, std::source_location sourceLocation);
9484

9585
HookType type;
9686
std::unique_ptr<tag_expression::Expression> tagExpression;
9787
HookFactory factory;
9888
cucumber::messages::hook hook;
9989
};
10090

101-
explicit HookRegistry();
91+
explicit HookRegistry(cucumber::gherkin::id_generator_ptr idGenerator);
92+
93+
void LoadHooks();
10294

10395
std::vector<std::string> FindIds(HookType hookType, std::span<const cucumber::messages::pickle_tag> tags = {}) const;
10496
std::vector<std::string> FindIds(HookType hookType, std::span<const cucumber::messages::tag> tags) const;
10597

98+
std::vector<cucumber::messages::hook> HooksByType(HookType hookType) const
99+
{
100+
auto filtered = registry |
101+
std::views::values |
102+
std::views::filter([hookType](const Definition& definition)
103+
{
104+
return definition.type == hookType;
105+
}) |
106+
std::views::transform([](const Definition& definition)
107+
{
108+
return definition.hook;
109+
});
110+
111+
return { filtered.begin(), filtered.end() };
112+
}
113+
106114
[[nodiscard]] std::size_t Size() const;
107115
[[nodiscard]] std::size_t Size(HookType hookType) const;
108116

109117
HookFactory GetFactoryById(std::string id) const;
110118
const Definition& GetDefinitionById(std::string id) const;
111119

112120
private:
113-
void Register(HookType type, std::string_view expression, HookFactory factory, std::source_location sourceLocation);
121+
void Register(std::string id, HookType type, std::string_view expression, HookFactory factory, std::source_location sourceLocation);
114122

115-
std::uint32_t nextId{ 1 };
123+
cucumber::gherkin::id_generator_ptr idGenerator;
116124
std::map<std::string, Definition> registry;
117125
};
118126

127+
struct GlobalHook
128+
{
129+
std::string_view name{ "anonymous" };
130+
std::int32_t order{ 0 };
131+
};
132+
133+
struct Hook
134+
{
135+
std::string_view tagExpression{ "" };
136+
std::string_view name{ "anonymous" };
137+
std::int32_t order{ 0 };
138+
};
139+
119140
struct HookRegistration
120141
{
121142
private:
@@ -141,10 +162,15 @@ namespace cucumber_cpp::library
141162
std::string_view expression;
142163
HookFactory factory;
143164
std::source_location sourceLocation;
165+
std::string id{ "unassigned" };
144166
};
145167

146168
template<class T>
147169
static std::size_t Register(std::string_view tagExpression, HookType hookType, std::source_location sourceLocation = std::source_location::current());
170+
template<class T>
171+
static std::size_t Register(Hook hook, HookType hookType, std::source_location sourceLocation = std::source_location::current());
172+
template<class T>
173+
static std::size_t Register(GlobalHook hook, HookType hookType, std::source_location sourceLocation = std::source_location::current());
148174

149175
std::span<Entry> GetEntries();
150176
[[nodiscard]] std::span<const Entry> GetEntries() const;
@@ -163,6 +189,20 @@ namespace cucumber_cpp::library
163189
Instance().registry.emplace_back(hookType, tagExpression, HookBodyFactory<T>, sourceLocation);
164190
return Instance().registry.size();
165191
}
192+
193+
template<class T>
194+
std::size_t HookRegistration::Register(Hook hook, HookType hookType, std::source_location sourceLocation)
195+
{
196+
Instance().registry.emplace_back(hookType, hook.tagExpression, HookBodyFactory<T>, sourceLocation);
197+
return Instance().registry.size();
198+
}
199+
200+
template<class T>
201+
std::size_t HookRegistration::Register(GlobalHook hook, HookType hookType, std::source_location sourceLocation)
202+
{
203+
Instance().registry.emplace_back(hookType, "", HookBodyFactory<T>, sourceLocation);
204+
return Instance().registry.size();
205+
}
166206
}
167207

168208
#endif

cucumber_cpp/library/Hooks.hpp

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,47 +6,49 @@
66

77
#include "cucumber_cpp/library/BodyMacro.hpp"
88
#include "cucumber_cpp/library/HookRegistry.hpp"
9+
#include "cucumber_cpp/library/support/SupportCodeLibrary.hpp"
910

10-
#define HOOK_(matcher, type) BODY(matcher, type, (), cucumber_cpp::library::HookRegistration::Register, cucumber_cpp::library::HookBase)
11+
// #define HOOK_(matcher, type) BODY(matcher, type, (), cucumber_cpp::library::HookRegistration::Register, cucumber_cpp::library::HookBase)
12+
#define HOOK_(matcher, type) BODY(matcher, type, (), cucumber_cpp::library::support::DefinitionRegistration::Register, cucumber_cpp::library::HookBase)
1113

12-
#define HOOK_BEFORE_ALL() \
13-
HOOK_( \
14-
"", \
14+
#define HOOK_BEFORE_ALL(...) \
15+
HOOK_( \
16+
(cucumber_cpp::library::GlobalHook{ __VA_ARGS__ }), \
1517
cucumber_cpp::library::HookType::beforeAll)
1618

17-
#define HOOK_AFTER_ALL() \
18-
HOOK_( \
19-
"", \
19+
#define HOOK_AFTER_ALL(...) \
20+
HOOK_( \
21+
(cucumber_cpp::library::GlobalHook{ __VA_ARGS__ }), \
2022
cucumber_cpp::library::HookType::afterAll)
2123

22-
#define HOOK_BEFORE_FEATURE(...) \
23-
HOOK_( \
24-
BODY_MATCHER(__VA_ARGS__ __VA_OPT__(, ) ""), \
24+
#define HOOK_BEFORE_FEATURE(...) \
25+
HOOK_( \
26+
(cucumber_cpp::library::Hook{ __VA_ARGS__ }), \
2527
cucumber_cpp::library::HookType::beforeFeature)
2628

27-
#define HOOK_AFTER_FEATURE(...) \
28-
HOOK_( \
29-
BODY_MATCHER(__VA_ARGS__ __VA_OPT__(, ) ""), \
29+
#define HOOK_AFTER_FEATURE(...) \
30+
HOOK_( \
31+
(cucumber_cpp::library::Hook{ __VA_ARGS__ }), \
3032
cucumber_cpp::library::HookType::afterFeature)
3133

32-
#define HOOK_BEFORE_SCENARIO(...) \
33-
HOOK_( \
34-
BODY_MATCHER(__VA_ARGS__ __VA_OPT__(, ) ""), \
34+
#define HOOK_BEFORE_SCENARIO(...) \
35+
HOOK_( \
36+
(cucumber_cpp::library::Hook{ __VA_ARGS__ }), \
3537
cucumber_cpp::library::HookType::before)
3638

37-
#define HOOK_AFTER_SCENARIO(...) \
38-
HOOK_( \
39-
BODY_MATCHER(__VA_ARGS__ __VA_OPT__(, ) ""), \
39+
#define HOOK_AFTER_SCENARIO(...) \
40+
HOOK_( \
41+
(cucumber_cpp::library::Hook{ __VA_ARGS__ }), \
4042
cucumber_cpp::library::HookType::after)
4143

42-
#define HOOK_BEFORE_STEP(...) \
43-
HOOK_( \
44-
BODY_MATCHER(__VA_ARGS__ __VA_OPT__(, ) ""), \
44+
#define HOOK_BEFORE_STEP(...) \
45+
HOOK_( \
46+
(cucumber_cpp::library::Hook{ __VA_ARGS__ }), \
4547
cucumber_cpp::library::HookType::beforeStep)
4648

47-
#define HOOK_AFTER_STEP(...) \
48-
HOOK_( \
49-
BODY_MATCHER(__VA_ARGS__ __VA_OPT__(, ) ""), \
49+
#define HOOK_AFTER_STEP(...) \
50+
HOOK_( \
51+
(cucumber_cpp::library::Hook{ __VA_ARGS__ }), \
5052
cucumber_cpp::library::HookType::afterStep)
5153

5254
#endif

0 commit comments

Comments
 (0)