Skip to content

Commit 8414147

Browse files
committed
[GTest] support for GTEST("name") or GTEST(type)
1 parent 6091099 commit 8414147

File tree

4 files changed

+84
-35
lines changed

4 files changed

+84
-35
lines changed

include/GUnit/Detail/Utility.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ struct string {
5454
}
5555
};
5656

57+
template <class TStr, std::size_t N, char... Chrs>
58+
struct make_string : make_string<TStr, N - 1, TStr().chrs[N - 1], Chrs...> {};
59+
60+
template <class TStr, char... Chrs>
61+
struct make_string<TStr, 0, Chrs...> {
62+
using type = string<Chrs...>;
63+
};
64+
5765
namespace operators {
5866

5967
#if defined(__clang__)

include/GUnit/GTest.h

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,22 @@ class GTestAutoRegister {
118118
}
119119
}
120120

121+
template <class TestType>
122+
static auto GetTypeName(detail::type<TestType>) {
123+
return get_type_name<TestType>();
124+
}
125+
126+
template <char Quote, char... Chrs>
127+
static auto GetTypeName(detail::type<string<Quote, Chrs...>>) {
128+
static char str[] = {Chrs...};
129+
str[sizeof...(Chrs) - 2] = 0; // last quote
130+
return str;
131+
}
132+
121133
bool RegisterShouldTestCase() {
122134
auto registered = false;
123135
for (const auto& ti : tests()) {
124-
if (get_type_name<typename T::TEST_TYPE>() == ti.type && T::TEST_NAME::c_str() == ti.name) {
136+
if (GetTypeName(detail::type<typename T::TEST_TYPE>{}) == ti.type && T::TEST_NAME::c_str() == ti.name) {
125137
MakeAndRegisterTestInfo(ti, detail::type<decltype(::testing::internal::MakeAndRegisterTestInfo)>{});
126138
registered = true;
127139
}
@@ -133,7 +145,7 @@ class GTestAutoRegister {
133145
GTestAutoRegister() {
134146
if (!RegisterShouldTestCase()) {
135147
MakeAndRegisterTestInfo(
136-
{{}, get_type_name<typename T::TEST_TYPE>(), T::TEST_NAME::c_str(), T::TEST_FILE, T::TEST_LINE, {}},
148+
{{}, GetTypeName(detail::type<typename T::TEST_TYPE>{}), T::TEST_NAME::c_str(), T::TEST_FILE, T::TEST_LINE, {}},
137149
detail::type<decltype(::testing::internal::MakeAndRegisterTestInfo)>{});
138150
}
139151
}
@@ -187,35 +199,52 @@ class GTest : public detail::GTest<T> {};
187199

188200
#define GTEST(...) __GUNIT_CAT(GTEST_IMPL_, __GUNIT_SIZE(__VA_ARGS__))(__VA_ARGS__)
189201

190-
#define GTEST_IMPL_1(TYPE) \
191-
template <class...> \
192-
struct GTEST; \
193-
template <> \
194-
struct GTEST<TYPE> : ::testing::detail::GTest<TYPE> { \
195-
using TEST_TYPE = TYPE; \
196-
using TEST_NAME = ::testing::detail::string<>; \
197-
static constexpr auto TEST_FILE = __FILE__; \
198-
static constexpr auto TEST_LINE = __LINE__; \
199-
void test(); \
200-
}; \
201-
::testing::detail::GTestAutoRegister<GTEST<TYPE>> __GUNIT_CAT(ar, __LINE__){}; \
202-
void GTEST<TYPE>::test()
203-
204-
#define GTEST_IMPL_2(TYPE, NAME) \
205-
auto __GUNIT_CAT(GTESET_IMPL_TEST_NAME, __LINE__)() { return __GUNIT_CAT(NAME, _gtest_string); } \
206-
template <class...> \
207-
struct GTEST; \
208-
template <> \
209-
struct GTEST<TYPE, decltype(__GUNIT_CAT(GTESET_IMPL_TEST_NAME, __LINE__))> : ::testing::detail::GTest<TYPE> { \
210-
using TEST_TYPE = TYPE; \
211-
using TEST_NAME = decltype(__GUNIT_CAT(GTESET_IMPL_TEST_NAME, __LINE__)()); \
212-
static constexpr auto TEST_FILE = __FILE__; \
213-
static constexpr auto TEST_LINE = __LINE__; \
214-
void test(); \
215-
}; \
216-
::testing::detail::GTestAutoRegister<GTEST<TYPE, decltype(__GUNIT_CAT(GTESET_IMPL_TEST_NAME, __LINE__))>> __GUNIT_CAT( \
217-
ar, __LINE__){}; \
218-
void GTEST<TYPE, decltype(__GUNIT_CAT(GTESET_IMPL_TEST_NAME, __LINE__))>::test()
202+
#define GTEST_IMPL_1(TYPE) \
203+
struct __GUNIT_CAT(GTEST_STRING_, __LINE__) { \
204+
const char* chrs = #TYPE; \
205+
}; \
206+
using __GUNIT_CAT(GTEST_TYPE_, __LINE__) = \
207+
std::conditional_t<#TYPE[(0)] == '"', decltype(::testing::detail::make_string<__GUNIT_CAT(GTEST_STRING_, __LINE__), \
208+
sizeof(#TYPE)>::type()), \
209+
__typeof__(TYPE)>; \
210+
template <class...> \
211+
struct GTEST; \
212+
template <> \
213+
struct GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__)> : ::testing::detail::GTest<__GUNIT_CAT(GTEST_TYPE_, __LINE__)> { \
214+
using TEST_TYPE = __GUNIT_CAT(GTEST_TYPE_, __LINE__); \
215+
using TEST_NAME = ::testing::detail::string<>; \
216+
\
217+
static constexpr auto TEST_FILE = __FILE__; \
218+
static constexpr auto TEST_LINE = __LINE__; \
219+
void test(); \
220+
}; \
221+
::testing::detail::GTestAutoRegister<GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__)>> __GUNIT_CAT(ar, __LINE__){}; \
222+
void GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__)>::test()
223+
224+
#define GTEST_IMPL_2(TYPE, NAME) \
225+
struct __GUNIT_CAT(GTEST_STRING_, __LINE__) { \
226+
const char* chrs = #TYPE; \
227+
}; \
228+
using __GUNIT_CAT(GTEST_TYPE_, __LINE__) = \
229+
std::conditional_t<#TYPE[(0)] == '"', decltype(::testing::detail::make_string<__GUNIT_CAT(GTEST_STRING_, __LINE__), \
230+
sizeof(#TYPE)>::type()), \
231+
__typeof__(TYPE)>; \
232+
auto __GUNIT_CAT(GTEST_TEST_NAME, __LINE__)() { return __GUNIT_CAT(NAME, _gtest_string); } \
233+
template <class...> \
234+
struct GTEST; \
235+
template <> \
236+
struct GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__), decltype(__GUNIT_CAT(GTEST_TEST_NAME, __LINE__))> \
237+
: ::testing::detail::GTest<__GUNIT_CAT(GTEST_TYPE_, __LINE__)> { \
238+
using TEST_TYPE = __GUNIT_CAT(GTEST_TYPE_, __LINE__); \
239+
using TEST_NAME = decltype(__GUNIT_CAT(GTEST_TEST_NAME, __LINE__)()); \
240+
static constexpr auto TEST_FILE = __FILE__; \
241+
static constexpr auto TEST_LINE = __LINE__; \
242+
void test(); \
243+
}; \
244+
::testing::detail::GTestAutoRegister< \
245+
GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__), decltype(__GUNIT_CAT(GTEST_TEST_NAME, __LINE__))>> \
246+
__GUNIT_CAT(ar, __LINE__){}; \
247+
void GTEST<__GUNIT_CAT(GTEST_TYPE_, __LINE__), decltype(__GUNIT_CAT(GTEST_TEST_NAME, __LINE__))>::test()
219248

220249
#define SHOULD(NAME) \
221250
if (::testing::detail::SHOULD_REGISTER_GTEST<TEST_TYPE, TEST_NAME, decltype(__GUNIT_CAT(__FILE__, _gtest_string)), __LINE__, \

test/Detail/Utility.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ TEST(Utility, ShouldAdd2Strings) {
3232
}
3333
}
3434

35+
TEST(Utility, ShouldMakeString) {
36+
using namespace operators;
37+
static_assert(std::is_same<string<>, decltype(""_gtest_string)>::value, "");
38+
static_assert(std::is_same<string<'a', 'b', 'c'>, decltype("abc"_gtest_string)>::value, "");
39+
40+
struct String {
41+
const char* chrs = "abcd";
42+
};
43+
44+
static_assert(std::is_same<string<'a', 'b', 'c', 'd', 0>, decltype(make_string<String, sizeof("abcd")>::type())>::value, "");
45+
}
46+
3547
struct n {};
3648

3749
TEST(Utility, ShouldGetTypeName) {

test/GTest.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ GTEST(example, "[should create sut with a mock]") {
790790
}
791791
}
792792

793-
GTEST(class MakeWithMocks) {
793+
GTEST("Make with mocks") {
794794
SHOULD("make complex example with default and custom mocks") {
795795
using namespace testing;
796796
using SUT = std::unique_ptr<complex_example>;
@@ -804,11 +804,11 @@ GTEST(class MakeWithMocks) {
804804
}
805805
}
806806

807-
GTEST(class ExampleTest, "[Example]") {
807+
GTEST("Example Test", "[Example]") {
808808
SHOULD("expect true") { EXPECT_TRUE(true); }
809809
}
810810

811-
GTEST(class ExampleTest, "[OtherExample]") {
811+
GTEST("Example Test", "[OtherExample]") {
812812
SHOULD("expect false") { EXPECT_FALSE(false); }
813813
}
814814

@@ -828,7 +828,7 @@ GTEST(MyTest, "[Custom Test]") {
828828
}
829829
}
830830

831-
GTEST(class TestWithoutShould, "Should Register the test case itself") { EXPECT_TRUE(true); }
831+
GTEST("Test without should", "Should Register the test case itself") { EXPECT_TRUE(true); }
832832

833833
#if __has_include(<boost / di.hpp>)
834834
class di_example {

0 commit comments

Comments
 (0)