Skip to content

Commit da27ab2

Browse files
committed
[GTest] create sut and mocks automatically when they are creatable
1 parent 483b557 commit da27ab2

File tree

9 files changed

+68
-21
lines changed

9 files changed

+68
-21
lines changed

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ struct BenchmarkTest : testing::Test { |
121121
void SetUp() override { |
122122
sut = std::make_unique<example>(m1, m2, m3); |
123123
} |
124-
| // setup is NOT NEEDED!
124+
| // set-up is NOT NEEDED!
125125
mock_i1 m1; |
126126
mock_i2 m2; |
127127
mock_i3 m3; |
@@ -130,29 +130,27 @@ struct BenchmarkTest : testing::Test { |
130130
```
131131

132132
```cpp
133-
TEST_F(BenchmarkTest, ShouldCallF1) { |GTEST(example) {
133+
TEST_F(BenchmarkTest, ShouldCallF1) { |GTEST(example) { // set-up
134134
using namespace testing; | using namespace testing;
135135
|
136136
EXPECT_CALL(m1,f1(_)).WillOnce(Return(true)); | SHOULD("call f1") {
137137
EXPECT_CALL(m2,f2_1()).Times(1); | EXPECT_CALL(mock<i1>(),(f1)(_)).WillOnce(Return(true));
138138
EXPECT_CALL(m3,f3(0, 1, 2)).Times(1); | EXPECT_CALL(mock<i2>(),(f2_1)()).Times(1);
139139
| EXPECT_CALL(mock<i3>(),(f3)(0, 1, 2)).Times(1);
140140
sut->test(); |
141-
} | sut->test(); // sut and mocks created automatically
142-
| }
141+
} | sut->test(); // sut and mocks were
142+
| } // created automatically
143143
TEST_F(BenchmarkTest, ShouldCallF2) { |
144144
using namespace testing; | SHOULD("call f2") {
145145
| EXPECT_CALL(mock<i1>(),(f1)(_)).WillOnce(Return(false));
146146
EXPECT_CALL(m1,f1(_)).WillOnce(Return(false)); | EXPECT_CALL(mock<i2>(),(f2_2)()).Times(1);
147147
EXPECT_CALL(m2,f2_2()).Times(1); | EXPECT_CALL(mock<i3>(),(f3)(0, 1, 2)).Times(1);
148148
EXPECT_CALL(m3,f3(0, 1, 2)).Times(1); |
149149
| sut->test();
150-
sut->test(); | }
150+
sut->test(); | } // tear-down
151151
} |}
152152
```
153153
154-
> Note: GUnit deduces constructor parameters automatically!
155-
156154
#GUnit
157155
* Header only library
158156
* Based on top of GoogleTest/GoogleMock

example/GMock.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
// http://www.boost.org/LICENSE_1_0.txt)
77
//
88
#include "GUnit/GMock.h"
9-
#include "GUnit/GMake.h"
109
#include <gtest/gtest.h>
1110
#include <stdexcept>
11+
#include "GUnit/GMake.h"
1212

1313
class interface {
1414
public:

include/GUnit/Detail/Preprocessor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#define __GUNIT_IBP_IS_VARIADIC_R_1 1,
2121
#define __GUNIT_IBP_IS_VARIADIC_R___GUNIT_IBP_IS_VARIADIC_C 0,
2222
#define __GUNIT_IBP(...) __GUNIT_IBP_SPLIT(0, __GUNIT_CAT(__GUNIT_IBP_IS_VARIADIC_R_, __GUNIT_IBP_IS_VARIADIC_C __VA_ARGS__))
23-
#define __GUNIT_IS_EMPTY(...) \
23+
#define __GUNIT_IS_EMPTY(...) \
2424
__GUNIT_IS_EMPTY_IIF(__GUNIT_IBP(__VA_ARGS__)) \
2525
(__GUNIT_IS_EMPTY_GEN_ZERO, __GUNIT_IS_EMPTY_PROCESS)(__VA_ARGS__)
2626
#define __GUNIT_IS_EMPTY_PRIMITIVE_CAT(a, b) a##b

include/GUnit/GMake.h

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,24 @@ struct resolve_size {
186186
operator const T &() const;
187187
};
188188

189+
template <std::size_t, class T>
190+
using resolve_size_t = resolve_size<T>;
191+
192+
template <class TParent>
193+
struct resolve_creatable {
194+
template <class T, GUNIT_REQUIRES(!is_copy_ctor<TParent, T>::value && detail::is_abstract<deref_t<T>>::value)>
195+
operator T();
196+
197+
template <class T, GUNIT_REQUIRES(!is_copy_ctor<TParent, T>::value && detail::is_abstract<deref_t<T>>::value)>
198+
operator T &() const;
199+
200+
template <class T, GUNIT_REQUIRES(!is_copy_ctor<TParent, T>::value && detail::is_abstract<deref_t<T>>::value)>
201+
operator const T &() const;
202+
};
203+
204+
template <std::size_t, class T>
205+
using resolve_creatable_t = resolve_creatable<T>;
206+
189207
template <class TParent, template <class> class TMock, class TArgs = std::tuple<>>
190208
class resolve {
191209
public:
@@ -254,9 +272,6 @@ class resolve {
254272
template <std::size_t, class T, template <class> class TMock, class TArgs = std::tuple<>>
255273
using resolve_t = resolve<T, TMock, TArgs>;
256274

257-
template <std::size_t, class T>
258-
using resolve_size_t = resolve_size<T>;
259-
260275
template <class, class = std::make_index_sequence<GUNIT_MAX_CTOR_SIZE>>
261276
struct ctor_size;
262277

@@ -284,7 +299,16 @@ auto make_impl(detail::identity<T>, mocks_t &mocks, std::tuple<TArgs...> &args,
284299
return T(resolve_t<Ns, detail::deref_t<T>, TMock, std::tuple<TArgs...>>{mocks, args}...);
285300
}
286301

287-
} // detail
302+
template <class, class>
303+
struct is_creatable_impl;
304+
305+
template <class T, std::size_t... Ns>
306+
struct is_creatable_impl<T, std::index_sequence<Ns...>> : std::is_constructible<T, resolve_creatable_t<Ns, T>...> {};
307+
308+
template <class T>
309+
using is_creatable = is_creatable_impl<T, std::make_index_sequence<ctor_size<T>::value>>;
310+
311+
} // detail
288312

289313
template <class T, class... TArgs>
290314
auto make(TArgs &&... args) {

include/GUnit/GMock.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
namespace testing {
2727
inline namespace v1 {
2828
namespace detail {
29-
3029
static auto gmock_ready = true;
3130

3231
// clang-format off
@@ -164,7 +163,7 @@ class vtable {
164163
};
165164
} // detail
166165

167-
template <class T>
166+
template <class T, class = detail::is_complete<T>>
168167
class GMock {
169168
static_assert(detail::is_abstract<T>::value, "T has to be an abstract type");
170169
static_assert(std::has_virtual_destructor<T>::value, "T has to have a virtual destructor");
@@ -390,7 +389,7 @@ inline auto ByRef(NiceGMock<T> &x) {
390389
#define __GMOCK_OVERLOAD_CAST_IMPL_1(obj, call)
391390
#define __GMOCK_OVERLOAD_CAST_IMPL_2(obj, call) \
392391
(::testing::detail::function_type_t<std::decay_t<decltype(obj)>::type, __GMOCK_FUNCTION call>)
393-
#define __GMOCK_INTERNAL(...) \
392+
#define __GMOCK_INTERNAL(...) \
394393
__GUNIT_IF(__GUNIT_IS_EMPTY(__VA_ARGS__)) \
395394
(__GUNIT_IGNORE, __GUNIT_COMMA)() __VA_ARGS__
396395
#define __GMOCK_CALL(...) __GMOCK_INTERNAL

include/GUnit/GTest.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ class GTestAutoRegister {
5757
class ScopedVisibility {
5858
public:
5959
ScopedVisibility() { gmock_ready = false; }
60-
6160
~ScopedVisibility() { gmock_ready = true; }
6261

6362
private:
@@ -78,6 +77,12 @@ class GTest {
7877
protected:
7978
using SUT = std::unique_ptr<T>;
8079

80+
explicit GTest(std::false_type) {}
81+
explicit GTest(std::true_type) { std::tie(sut, mocks) = make<SUT, StrictGMock>(); }
82+
83+
public:
84+
GTest() : GTest(is_creatable<T>{}) {}
85+
8186
template <class TMock>
8287
decltype(auto) mock() {
8388
return mocks.mock<TMock>();
@@ -90,7 +95,7 @@ class GTest {
9095
template <class T>
9196
class GTest<T, std::false_type> {};
9297

93-
} // detail
98+
} // detail
9499

95100
template <class T>
96101
class GTest : public detail::GTest<T>, public Test {};

test/GMake.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
// http://www.boost.org/LICENSE_1_0.txt)
77
//
88
#include "GUnit/GMake.h"
9-
#include "GUnit/GMock.h"
109
#include <gtest/gtest.h>
10+
#include "GUnit/GMock.h"
1111

1212
struct interface {
1313
virtual ~interface() = default;

test/GMock.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,6 @@ TEST(GMock, ShouldAllowDeletingMock) {
521521
}
522522
}
523523

524-
525524
TEST(GMock, ShouldHandleByRef) {
526525
using namespace testing;
527526
auto i = std::make_shared<GMock<interface>>();

test/GTest.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,12 @@ GTEST(longest_ctor) {
697697

698698
GTEST(longest_ctor_force) {
699699
using namespace testing;
700+
701+
SHOULD("not create sut and mocks") {
702+
EXPECT_FALSE((detail::is_creatable<longest_ctor_force>::value));
703+
EXPECT_FALSE(sut.get());
704+
}
705+
700706
std::tie(sut, mocks) = testing::make<SUT, testing::NaggyGMock>(short{42}, 77.0);
701707

702708
SHOULD("take injected, longest ctor") {
@@ -710,8 +716,13 @@ GTEST(longest_ctor_force) {
710716
GTEST(complex_example) {
711717
using namespace testing;
712718

719+
SHOULD("create sut and mocks") {
720+
EXPECT_TRUE((detail::is_creatable<complex_example>::value));
721+
EXPECT_TRUE(sut.get());
722+
}
723+
713724
SHOULD("make complex example with strict mocks") {
714-
std::tie(sut, mocks) = testing::make<SUT, testing::StrictGMock, NiceGMock<interface_dtor>>();
725+
std::tie(sut, mocks) = testing::make<SUT, StrictGMock, NiceGMock<interface_dtor>>();
715726
EXPECT_CALL(mock<interface>(), (get)(_)).WillOnce(Return(123));
716727
EXPECT_CALL(mock<interface2>(), (f1)(77.0)).Times(1);
717728
EXPECT_CALL(mock<interface4>(), (f2)(_)).Times(1);
@@ -731,6 +742,17 @@ GTEST(complex_example) {
731742
}
732743
}
733744

745+
struct is_default_constructible {};
746+
747+
GTEST(is_default_constructible) {
748+
using namespace testing;
749+
750+
SHOULD("create a default constructible type") {
751+
EXPECT_TRUE((detail::is_creatable<is_default_constructible>::value));
752+
EXPECT_TRUE(sut.get());
753+
}
754+
}
755+
734756
GTEST(class MakeWithMocks) {
735757
SHOULD("make complex example with default and custom mocks") {
736758
using namespace testing;

0 commit comments

Comments
 (0)