1616#include " GUnit/GMake.h"
1717#include " GUnit/GMock.h"
1818
19- #if !defined(GUNIT_SHOULD_PREFIX)
20- #define GUNIT_SHOULD_PREFIX " should "
21- #endif
22-
2319namespace testing {
2420inline namespace v1 {
2521namespace detail {
2622
27- struct TestCaseInfo {
28- bool disabled = false ;
29- std::string symbol;
30- std::string type;
31- std::string name;
32- std::string file;
33- int line = 0 ;
34- std::string should;
35-
36- bool operator ==(const TestCaseInfo& ti) const { return symbol == ti.symbol ; }
37- bool operator !=(const TestCaseInfo& ti) const { return symbol != ti.symbol ; }
38- bool operator <(const TestCaseInfo& ti) const { return symbol < ti.symbol ; }
39- bool operator >(const TestCaseInfo& ti) const { return symbol > ti.symbol ; }
40- };
23+ bool PatternMatchesString (const char *pattern,
24+ const char *str) {
25+ switch (*pattern) {
26+ case ' \0 ' :
27+ case ' :' : // Either ':' or '\0' marks the end of the pattern.
28+ return *str == ' \0 ' ;
29+ case ' ?' : // Matches any single character.
30+ return *str != ' \0 ' && PatternMatchesString (pattern + 1 , str + 1 );
31+ case ' *' : // Matches any string (possibly empty) of characters.
32+ return (*str != ' \0 ' && PatternMatchesString (pattern, str + 1 )) ||
33+ PatternMatchesString (pattern + 1 , str);
34+ default : // Non-special character. Matches itself.
35+ return *pattern == *str &&
36+ PatternMatchesString (pattern + 1 , str + 1 );
37+ }
38+ }
4139
42- struct TestCaseInfoParser {
43- using type = TestCaseInfo;
44-
45- static auto parse (const std::string& line) {
46- TestCaseInfo ti;
47- ti.symbol = line;
48- const auto str = std::string{" >()::shouldRegister" };
49- ti.symbol .replace (ti.symbol .find (str), str.length (), " |" );
50- std::string token;
51- std::istringstream stream (ti.symbol );
52-
53- const auto parseString = [&](std::string& result, char end = ' >' ) {
54- std::getline (stream, token, end);
55- if (token.find (" ::detail::string" ) != std::string::npos) {
56- if (token.find (" )" ) != std::string::npos) {
57- std::istringstream istream (token);
58- while (std::getline (istream, token, ' ,' )) {
59- const auto begin = token.find (' )' );
60- result += static_cast <char >(std::atoi (token.substr (begin + 1 ).c_str ()));
61- }
62- }
63- } else {
64- detail::trim (token);
65- result = token;
66- }
67- std::getline (stream, token, ' ,' );
68- };
69-
70- std::getline (stream, token, ' <' );
71- std::getline (stream, token, ' ,' );
72- ti.disabled = token == " true" ;
73- parseString (ti.name );
74- parseString (ti.file );
75- std::getline (stream, token, ' ,' );
76- ti.line = std::atoi (token.c_str ());
77- parseString (ti.should );
78- parseString (ti.type , ' |' );
79- if (!ti.type .empty () && ti.type [0 ] == ' "' && ti.type [ti.type .length () - 2 ] == ' "' ) {
80- ti.type = ti.type .substr (1 , ti.type .length () - 3 );
40+ bool MatchesFilter ( const std::string& name, const char * filter) {
41+ const char *cur_pattern = filter;
42+ for (;;) {
43+ if (PatternMatchesString (cur_pattern, name.c_str ())) {
44+ return true ;
8145 }
82- return ti;
46+
47+ // Finds the next pattern in the filter.
48+ cur_pattern = strchr (cur_pattern, ' :' );
49+
50+ // Returns if no more pattern can be found.
51+ if (cur_pattern == NULL ) {
52+ return false ;
53+ }
54+
55+ // Skips the pattern separater (the ':' character).
56+ cur_pattern++;
8357 }
84- };
58+ }
8559
86- inline auto & tests () {
87- static auto ts = symbols<TestCaseInfoParser>(" _ZZN7testing2v16detail21SHOULD_REGISTER_GTEST" );
88- return ts;
60+ bool FilterMatchesShould (const std::string& name, const std::string &should) {
61+ // Split --gtest_filter at '-', if there is one, to separate into
62+ // positive filter and negative filter portions
63+ const char * const p = should.c_str ();
64+ const char * const dash = strchr (p, ' -' );
65+ std::string positive;
66+ std::string negative;
67+ if (dash == NULL ) {
68+ positive = should.c_str (); // Whole string is a positive filter
69+ negative = " " ;
70+ } else {
71+ positive = std::string (p, dash); // Everything up to the dash
72+ negative = std::string (dash + 1 ); // Everything after the dash
73+ if (positive.empty ()) {
74+ // Treat '-test1' as the same as '*-test1'
75+ positive = " *" ;
76+ }
77+ }
78+
79+ return (MatchesFilter (name, positive.c_str ()) && !MatchesFilter (name, negative.c_str ()));
8980}
9081
82+ struct TestRun {
83+ std::string should = GetShouldParam();
84+ bool once = false ;
85+
86+ static std::string GetShouldParam () {
87+ const std::string filter = " --should=" ;
88+ for (auto i = 0u ; i < internal::GetArgvs ().size (); ++i) {
89+ if (internal::GetArgvs ()[i].find (filter) != std::string::npos) {
90+ return internal::GetArgvs ()[i].substr (filter.length ());
91+ }
92+ }
93+ return " *" ;
94+ }
95+
96+ bool run (const std::string& name, int line) {
97+ if (once) {
98+ return false ;
99+ }
100+ const auto result = line > test_line && FilterMatchesShould (name, should);
101+ if (result) {
102+ std::cout << " [ SHOULD ] " << name << std::endl;
103+ }
104+ test_line = line;
105+ once = true ;
106+ return result;
107+ }
108+
109+ int test_line = 0 ;
110+ };
111+
91112template <bool DISABLED, class T >
92113class GTestAutoRegister {
93114 static auto IsDisabled (bool disabled) { return DISABLED || disabled ? " DISABLED_" : " " ; }
94115
95- void MakeAndRegisterTestInfo (const TestCaseInfo& ti ,
116+ void MakeAndRegisterTestInfo (bool disabled, const std::string& type, const std::string& name, const std::string& /* file */ , int /* line */ ,
96117 detail::type<TestInfo*(const char *, const char *, const char *, const char *, const void *,
97118 void (*)(), void (*)(), internal::TestFactoryBase*)>) {
98- if (ti.should .empty ()) {
99- internal::MakeAndRegisterTestInfo ((IsDisabled (ti.disabled ) + ti.type ).c_str (), ti.name .c_str (), nullptr , nullptr ,
100- internal::GetTestTypeId (), Test::SetUpTestCase, Test::TearDownTestCase,
101- new internal::TestFactoryImpl<T>{});
102- } else {
103- internal::MakeAndRegisterTestInfo ((IsDisabled (ti.disabled ) + ti.type + ti.name ).c_str (),
104- (std::string{GUNIT_SHOULD_PREFIX} + ti.should ).c_str (), nullptr , nullptr ,
119+ internal::MakeAndRegisterTestInfo ((IsDisabled (disabled) + type).c_str (), name.c_str (), nullptr , nullptr ,
105120 internal::GetTestTypeId (), Test::SetUpTestCase, Test::TearDownTestCase,
106121 new internal::TestFactoryImpl<T>{});
107- }
108122 }
109123
110124 template <class ... Ts>
111- void MakeAndRegisterTestInfo (const TestCaseInfo& ti, detail::type<TestInfo*(Ts...)>) {
112- if (ti.should .empty ()) {
113- internal::MakeAndRegisterTestInfo ((IsDisabled (ti.disabled ) + ti.type ).c_str (), ti.name .c_str (), nullptr , nullptr ,
114- {ti.file .c_str (), ti.line }, internal::GetTestTypeId (), Test::SetUpTestCase,
115- Test::TearDownTestCase, new internal::TestFactoryImpl<T>{});
116- } else {
117- internal::MakeAndRegisterTestInfo ((IsDisabled (ti.disabled ) + ti.type + ti.name ).c_str (),
118- (std::string{GUNIT_SHOULD_PREFIX} + ti.should ).c_str (), nullptr , nullptr ,
119- {ti.file .c_str (), ti.line }, internal::GetTestTypeId (), Test::SetUpTestCase,
120- Test::TearDownTestCase, new internal::TestFactoryImpl<T>{});
121- }
125+ void MakeAndRegisterTestInfo (bool disabled, const std::string& type, const std::string& name, const std::string& file, int line, detail::type<TestInfo*(Ts...)>) {
126+ internal::MakeAndRegisterTestInfo ((IsDisabled (disabled) + type).c_str (), name.c_str (), nullptr , nullptr ,
127+ {file.c_str (), line},
128+ internal::GetTestTypeId (), Test::SetUpTestCase, Test::TearDownTestCase,
129+ new internal::TestFactoryImpl<T>{});
122130 }
123131
124132 template <class TestType >
@@ -133,61 +141,48 @@ class GTestAutoRegister {
133141 return str;
134142 }
135143
136- bool RegisterShouldTestCase () {
137- auto registered = false ;
138- for (const auto & ti : tests ()) {
139- if (GetTypeName (detail::type<typename T::TEST_TYPE>{}) == ti.type && T::TEST_NAME::c_str () == ti.name ) {
140- MakeAndRegisterTestInfo (ti, detail::type<decltype (internal::MakeAndRegisterTestInfo)>{});
141- registered = true ;
142- }
143- }
144- return registered;
145- }
146-
147- bool RegisterShouldParamTestCase () {
148- auto registered = false ;
149- for (const auto & ti : tests ()) {
150- if (GetTypeName (detail::type<typename T::TEST_TYPE>{}) == ti.type && T::TEST_NAME::c_str () == ti.name ) {
151- UnitTest::GetInstance ()
152- ->parameterized_test_registry ()
153- .GetTestCasePatternHolder <T>(ti.type .c_str (), {ti.file , ti.line })
154- ->AddTestPattern ((IsDisabled (ti.disabled ) + ti.type ).c_str (), std::string{GUNIT_SHOULD_PREFIX + ti.should }.c_str (),
155- new internal::TestMetaFactory<T>());
156- registered = true ;
157- }
158- }
159- return registered;
160- }
144+ // bool RegisterShouldParamTestCase() {
145+ // auto registered = false;
146+ // for (const auto& ti : tests()) {
147+ // if (GetTypeName(detail::type<typename T::TEST_TYPE>{}) == ti.type && T::TEST_NAME::c_str() == ti.name) {
148+ // UnitTest::GetInstance()
149+ // ->parameterized_test_registry()
150+ // .GetTestCasePatternHolder<T>(ti.type.c_str(), {ti.file, ti.line})
151+ // ->AddTestPattern((IsDisabled(ti.disabled) + ti.type).c_str(), std::string{GUNIT_SHOULD_PREFIX + ti.should}.c_str(),
152+ // new internal::TestMetaFactory<T>());
153+ // registered = true;
154+ // }
155+ // }
156+ // return registered;
157+ // }
161158
162159 public:
163160 GTestAutoRegister () {
164- if (!RegisterShouldTestCase ()) {
165- MakeAndRegisterTestInfo ({DISABLED,
166- {},
167- GetTypeName (detail::type<typename T::TEST_TYPE>{}),
168- T::TEST_NAME::c_str (),
169- T::TEST_FILE,
170- T::TEST_LINE,
171- {}},
161+ MakeAndRegisterTestInfo (DISABLED,
162+ GetTypeName (detail::type<typename T::TEST_TYPE>{}),
163+ T::TEST_NAME::c_str (),
164+ T::TEST_FILE,
165+ T::TEST_LINE,
172166 detail::type<decltype (internal::MakeAndRegisterTestInfo)>{});
173- }
174167 }
175168
176169 template <class TEval , class TGenerateNames >
177- explicit GTestAutoRegister (const TEval& eval, const TGenerateNames& genNames) {
178- if (!RegisterShouldParamTestCase ()) {
179- UnitTest::GetInstance ()
180- ->parameterized_test_registry ()
181- .GetTestCasePatternHolder <T>(GetTypeName (detail::type<typename T::TEST_TYPE>{}), {T::TEST_FILE, T::TEST_LINE})
182- ->AddTestPattern (GetTypeName (detail::type<typename T::TEST_TYPE>{}),
183- GetTypeName (detail::type<typename T::TEST_TYPE>{}), new internal::TestMetaFactory<T>());
184- }
185-
186- UnitTest::GetInstance ()
187- ->parameterized_test_registry ()
188- .GetTestCasePatternHolder <T>(GetTypeName (detail::type<typename T::TEST_TYPE>{}), {T::TEST_FILE, T::TEST_LINE})
189- ->AddTestCaseInstantiation ((std::string{IsDisabled (DISABLED)} + T::TEST_NAME::c_str ()).c_str (), eval, genNames,
190- T::TEST_FILE, T::TEST_LINE);
170+ GTestAutoRegister (const TEval& eval, const TGenerateNames& genNames) {
171+ (void )eval;
172+ (void )genNames;
173+ // if (!RegisterShouldParamTestCase()) {
174+ // UnitTest::GetInstance()
175+ // ->parameterized_test_registry()
176+ // .GetTestCasePatternHolder<T>(GetTypeName(detail::type<typename T::TEST_TYPE>{}), {T::TEST_FILE, T::TEST_LINE})
177+ // ->AddTestPattern(GetTypeName(detail::type<typename T::TEST_TYPE>{}),
178+ // GetTypeName(detail::type<typename T::TEST_TYPE>{}), new internal::TestMetaFactory<T>());
179+ // }
180+
181+ // UnitTest::GetInstance()
182+ // ->parameterized_test_registry()
183+ // .GetTestCasePatternHolder<T>(GetTypeName(detail::type<typename T::TEST_TYPE>{}), {T::TEST_FILE, T::TEST_LINE})
184+ // ->AddTestCaseInstantiation((std::string{IsDisabled(DISABLED)} + T::TEST_NAME::c_str()).c_str(), eval, genNames,
185+ // T::TEST_FILE, T::TEST_LINE);
191186 }
192187};
193188
@@ -224,11 +219,6 @@ class GTest<T, TParamType, std::false_type, TAny> : public Test {
224219template <class T , class TParamType >
225220class GTest <T, TParamType, std::true_type, std::true_type> : public T {};
226221
227- template <bool Disabled, class Name , class File , int Line, class Should , class T >
228- bool SHOULD_REGISTER_GTEST () {
229- static auto shouldRegister = true ;
230- return shouldRegister;
231- }
232222} // detail
233223
234224template <class T = detail::none_t , class TParamType = void >
@@ -253,14 +243,20 @@ class GTest : public detail::GTest<T, TParamType> {};
253243 ::testing::detail::apply_t <std::common_type_t , decltype (PARAMS)>> { \
254244 using TEST_TYPE = __GUNIT_CAT(GTEST_TYPE_, __LINE__); \
255245 using TEST_NAME = NAME; \
256- \
257246 static constexpr auto TEST_FILE = __FILE__; \
258247 static constexpr auto TEST_LINE = __LINE__; \
259- void TestBody (); \
248+ void TestBodyImpl (::testing::detail::TestRun&); \
249+ void TestBody () {\
250+ ::testing::detail::TestRun tr; \
251+ while (tr.once ) {\
252+ tr.once = false ; \
253+ TestBodyImpl (tr);\
254+ }; \
255+ } \
260256 }; \
261257 static ::testing::detail::GTestAutoRegister<DISABLED, GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__), NAME>> __GUNIT_CAT ( \
262258 ar, __LINE__){__VA_ARGS__}; \
263- void GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__), NAME>::TestBody( )
259+ void GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__), NAME>::TestBodyImpl(::testing::detail::TestRun& __attribute__ ((unused)) tr_gtest )
264260
265261#define __GTEST_IMPL_1 (DISABLED, TYPE ) \
266262 __GTEST_IMPL (DISABLED, TYPE, ::testing::detail::string<>, ::testing::detail::type<void >{}, )
@@ -285,13 +281,7 @@ class GTest : public detail::GTest<T, TParamType> {};
285281#define DISABLED_GTEST (...) __GUNIT_CAT(__GTEST_IMPL_, __GUNIT_SIZE(__VA_ARGS__))(true , __VA_ARGS__)
286282
287283#define SHOULD (NAME ) \
288- if (::testing::detail::SHOULD_REGISTER_GTEST<false , TEST_NAME, decltype (__GUNIT_CAT(__FILE__, _gtest_string)), __LINE__, \
289- decltype (__GUNIT_CAT(NAME, _gtest_string)), TEST_TYPE>() && \
290- std::string{::testing::UnitTest::GetInstance ()->current_test_info ()->name ()}.find(std::string{GUNIT_SHOULD_PREFIX} + \
291- NAME) != std::string::npos)
284+ if (tr_gtest.run(NAME, __LINE__))
292285
293286#define DISABLED_SHOULD (NAME ) \
294- if (::testing::detail::SHOULD_REGISTER_GTEST<true , TEST_NAME, decltype (__GUNIT_CAT(__FILE__, _gtest_string)), __LINE__, \
295- decltype (__GUNIT_CAT(NAME, _gtest_string)), TEST_TYPE>() && \
296- std::string{::testing::UnitTest::GetInstance ()->current_test_info ()->name ()}.find(std::string{GUNIT_SHOULD_PREFIX} + \
297- NAME) != std::string::npos)
287+ if (false )
0 commit comments