Merge lp:~3v1n0/unity/testing-friend into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Rejected
Rejected by: Andrea Azzarone
Proposed branch: lp:~3v1n0/unity/testing-friend
Merge into: lp:unity
Prerequisite: lp:~3v1n0/unity/launcher-controller-ensure-new
Diff against target: 569 lines (+275/-76)
7 files modified
launcher/EdgeBarrierController.cpp (+1/-41)
launcher/EdgeBarrierController.h (+3/-3)
launcher/EdgeBarrierControllerPrivate.h (+68/-0)
launcher/LauncherController.h (+2/-2)
tests/test_edge_barrier_controller.cpp (+34/-28)
tests/test_launcher_controller.cpp (+12/-2)
unity-shared/TestingFriend.h (+155/-0)
To merge this branch: bzr merge lp:~3v1n0/unity/testing-friend
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Disapprove
Brandon Schaefer (community) Needs Fixing
Francis Ginther Abstain
jenkins (community) continuous-integration Needs Fixing
Review via email: mp+116783@code.launchpad.net

Commit message

TestingFriend: added testing friend, a tool that will (hopefully) help you in testing!

Description of the change

Added the unity::tests::Friend class definition and some utility macros that can be used to easily test private members of classes without great refactoring.

Basically it's only needed that the class(es) you're testing is friend of unity::tests::Friend and then on the testing side you can implement that Friend function with the proxy functions you need to access to private members.
I've added some macros that allow this definition easier. This is needed since in C++ the friendship is not transitive.

I know that the same could have been achieved just by adding a different friend class for each class that is then implemented as inheriting from ::testing::Test (as done in lp:~3v1n0/unity/launcher-controller-ensure-new for LauncherController), but I didn't like this for two reasons:
1) it would have allowed to access to all members from the tests, without any explicit control on it
2) it would have not allowed to test interactions between classes without defining friends around

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

Don't you have to make sure that the unit::tests::Friend class is in an anonymous namespace in the test source file to make sure you don't get linking errors?

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> Don't you have to make sure that the unit::tests::Friend class is in an
> anonymous namespace in the test source file to make sure you don't get linking
> errors?

If I add it to an anonymous namespace, it won't work since it won't be considered friend of the class I've added to.

Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Martin Mrazik (mrazik) wrote :

Sorry for the jenkins failure. I'm looking into this.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Ah, and Tim... I see no link errors here even when defining it multiple times (actually it's defined twice). Is that maybe because the definition is actually inline?

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> Ah, and Tim... I see no link errors here even when defining it multiple times
> (actually it's defined twice). Is that maybe because the definition is
> actually inline?

Looking at the standard, it also seems caused by the fact that these tests::Friend classes are defined in different translation units, and this will be always true (until you don't play too much with tests), so we should be and we actually are safe from linking errors.

Revision history for this message
Francis Ginther (fginther) wrote :

Review was claimed by accident, please ignore.

review: Abstain
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

In file included from /home/bschaefer/src/unity/tests/test_launcher_controller.cpp:24:0:
/home/bschaefer/src/unity/launcher/LauncherController.h: In member function ‘unity::launcher::LauncherModel::Ptr unity::launcher::TestLauncherController::GetLauncherModel()’:
/home/bschaefer/src/unity/launcher/LauncherController.h:91:25: error: ‘std::unique_ptr<unity::launcher::Controller::Impl> unity::launcher::Controller::pimpl’ is private
/home/bschaefer/src/unity/tests/test_launcher_controller.cpp:96:15: error: within this context

Also should merge with trunk as it still has the old dependency for libutouch-geis

review: Needs Fixing
Revision history for this message
Andrea Azzarone (azzar1) :
review: Disapprove

Unmerged revisions

2558. By Marco Trevisan (Treviño) on 2012-07-25

Merging with lp:~3v1n0/unity/launcher-controller-ensure-new (and trunk)

2557. By Marco Trevisan (Treviño) on 2012-07-25

test_edge_barrier_controller: use tests::Friend

2556. By Marco Trevisan (Treviño) on 2012-07-25

EdgeBarrierController: move the definition of ::Impl in EdgeBarrierControllerPrivate

For testing purposes...

2555. By Marco Trevisan (Treviño) on 2012-07-25

LauncherController: use unity::tests::Friend to access to pimpl!

2554. By Marco Trevisan (Treviño) on 2012-07-25

TestingFriend: added testing friend, a tool that will help you in testing!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'launcher/EdgeBarrierController.cpp'
--- launcher/EdgeBarrierController.cpp 2012-07-25 23:45:28 +0000
+++ launcher/EdgeBarrierController.cpp 2012-07-25 23:45:28 +0000
@@ -18,47 +18,12 @@
18 * Marco Trevisan <marco.trevisan@canonical.com>18 * Marco Trevisan <marco.trevisan@canonical.com>
19 */19 */
2020
21#include "EdgeBarrierController.h"21#include "EdgeBarrierControllerPrivate.h"
22#include "Decaymulator.h"
23#include "unity-shared/UScreen.h"22#include "unity-shared/UScreen.h"
24#include "UnityCore/GLibSource.h"
2523
26namespace unity {24namespace unity {
27namespace ui {25namespace ui {
2826
29struct EdgeBarrierController::Impl
30{
31 Impl(EdgeBarrierController *parent);
32
33 void ResizeBarrierList(std::vector<nux::Geometry> const& layout);
34 void SetupBarriers(std::vector<nux::Geometry> const& layout);
35
36 void OnPointerBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event);
37 void BarrierRelease(PointerBarrierWrapper* owner, int event);
38
39 bool StickyEdgeSetter(bool const& new_val)
40 {
41 if (parent_->options() && new_val != parent_->options()->edge_resist())
42 {
43 parent_->options()->edge_resist = new_val;
44 return true;
45 }
46 return false;
47 }
48
49 bool StickyEdgeGetter()
50 {
51 return parent_->options() ? parent_->options()->edge_resist() : false;
52 }
53
54 std::vector<PointerBarrierWrapper::Ptr> barriers_;
55 std::vector<EdgeBarrierSubscriber*> subscribers_;
56 Decaymulator decaymulator_;
57 glib::Source::UniquePtr release_timeout_;
58 float edge_overcome_pressure_;
59 EdgeBarrierController* parent_;
60};
61
62EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent)27EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent)
63 : edge_overcome_pressure_(0)28 : edge_overcome_pressure_(0)
64 , parent_(parent)29 , parent_(parent)
@@ -235,10 +200,5 @@
235 return pimpl->subscribers_[monitor];200 return pimpl->subscribers_[monitor];
236}201}
237202
238void EdgeBarrierController::ProcessBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event)
239{
240 pimpl->OnPointerBarrierEvent(owner, event);
241}
242
243}203}
244}204}
245205
=== modified file 'launcher/EdgeBarrierController.h'
--- launcher/EdgeBarrierController.h 2012-07-25 23:45:28 +0000
+++ launcher/EdgeBarrierController.h 2012-07-25 23:45:28 +0000
@@ -22,6 +22,7 @@
2222
23#include "PointerBarrier.h"23#include "PointerBarrier.h"
24#include "LauncherOptions.h"24#include "LauncherOptions.h"
25#include "unity-shared/TestingFriend.h"
2526
26namespace unity {27namespace unity {
27namespace ui {28namespace ui {
@@ -45,12 +46,11 @@
45 void Unsubscribe(EdgeBarrierSubscriber* subscriber, unsigned int monitor);46 void Unsubscribe(EdgeBarrierSubscriber* subscriber, unsigned int monitor);
46 EdgeBarrierSubscriber* GetSubscriber(unsigned int monitor);47 EdgeBarrierSubscriber* GetSubscriber(unsigned int monitor);
4748
48protected:
49 void ProcessBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event);
50
51private:49private:
52 struct Impl;50 struct Impl;
53 std::unique_ptr<Impl> pimpl;51 std::unique_ptr<Impl> pimpl;
52
53 friend class tests::Friend;
54};54};
5555
56}56}
5757
=== added file 'launcher/EdgeBarrierControllerPrivate.h'
--- launcher/EdgeBarrierControllerPrivate.h 1970-01-01 00:00:00 +0000
+++ launcher/EdgeBarrierControllerPrivate.h 2012-07-25 23:45:28 +0000
@@ -0,0 +1,68 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * version 3 along with this program. If not, see
15 * <http://www.gnu.org/licenses/>
16 *
17 * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
18 * Jason Smith <jason.smith@canonical.com>
19 *
20 */
21
22#ifndef UNITY_EDGE_BARRIER_CONTROLLER_PRIVATE_H
23#define UNITY_EDGE_BARRIER_CONTROLLER_PRIVATE_H
24
25#include "EdgeBarrierController.h"
26#include "Decaymulator.h"
27#include "UnityCore/GLibSource.h"
28
29namespace unity {
30namespace ui {
31
32struct EdgeBarrierController::Impl
33{
34 Impl(EdgeBarrierController *parent);
35
36 void ResizeBarrierList(std::vector<nux::Geometry> const& layout);
37 void SetupBarriers(std::vector<nux::Geometry> const& layout);
38
39 void OnPointerBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event);
40 void BarrierRelease(PointerBarrierWrapper* owner, int event);
41
42 bool StickyEdgeSetter(bool const& new_val)
43 {
44 if (parent_->options() && new_val != parent_->options()->edge_resist())
45 {
46 parent_->options()->edge_resist = new_val;
47 return true;
48 }
49 return false;
50 }
51
52 bool StickyEdgeGetter()
53 {
54 return parent_->options() ? parent_->options()->edge_resist() : false;
55 }
56
57 std::vector<PointerBarrierWrapper::Ptr> barriers_;
58 std::vector<EdgeBarrierSubscriber*> subscribers_;
59 Decaymulator decaymulator_;
60 glib::Source::UniquePtr release_timeout_;
61 float edge_overcome_pressure_;
62 EdgeBarrierController* parent_;
63};
64
65} // namespace ui
66} // namespace unity
67
68#endif
069
=== modified file 'launcher/LauncherController.h'
--- launcher/LauncherController.h 2012-07-25 23:45:28 +0000
+++ launcher/LauncherController.h 2012-07-25 23:45:28 +0000
@@ -27,6 +27,7 @@
2727
28#include "LauncherOptions.h"28#include "LauncherOptions.h"
29#include "SoftwareCenterLauncherIcon.h"29#include "SoftwareCenterLauncherIcon.h"
30#include "unity-shared/TestingFriend.h"
3031
31namespace unity32namespace unity
32{33{
@@ -35,7 +36,6 @@
35class AbstractLauncherIcon;36class AbstractLauncherIcon;
36class Launcher;37class Launcher;
37class LauncherModel;38class LauncherModel;
38class TestLauncherController;
3939
40class Controller : public unity::debug::Introspectable, public sigc::trackable40class Controller : public unity::debug::Introspectable, public sigc::trackable
41{41{
@@ -87,9 +87,9 @@
87 void AddProperties(GVariantBuilder* builder);87 void AddProperties(GVariantBuilder* builder);
8888
89private:89private:
90 friend class TestLauncherController;
91 class Impl;90 class Impl;
92 std::unique_ptr<Impl> pimpl;91 std::unique_ptr<Impl> pimpl;
92 friend class tests::Friend;
93};93};
9494
95}95}
9696
=== modified file 'tests/test_edge_barrier_controller.cpp'
--- tests/test_edge_barrier_controller.cpp 2012-07-25 23:45:28 +0000
+++ tests/test_edge_barrier_controller.cpp 2012-07-25 23:45:28 +0000
@@ -22,7 +22,7 @@
22#include "test_utils.h"22#include "test_utils.h"
23#include "test_uscreen_mock.h"23#include "test_uscreen_mock.h"
2424
25#include "EdgeBarrierController.h"25#include "EdgeBarrierControllerPrivate.h"
2626
27using namespace unity;27using namespace unity;
28using namespace unity::ui;28using namespace unity::ui;
@@ -46,20 +46,6 @@
46 MOCK_METHOD1(ReleaseBarrier, void(int));46 MOCK_METHOD1(ReleaseBarrier, void(int));
47};47};
4848
49class MockEdgeBarrierController : public EdgeBarrierController
50{
51public:
52 void ProcessBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event)
53 {
54 EdgeBarrierController::ProcessBarrierEvent(owner, event);
55 }
56
57 EdgeBarrierSubscriber* GetSubscriber(unsigned int monitor)
58 {
59 return EdgeBarrierController::GetSubscriber(monitor);
60 }
61};
62
63class TestBarrierSubscriber : public EdgeBarrierSubscriber49class TestBarrierSubscriber : public EdgeBarrierSubscriber
64{50{
65public:51public:
@@ -75,7 +61,21 @@
75 bool handles_;61 bool handles_;
76};62};
7763
78class TestEdgeBarrierController : public Test64}
65
66namespace unity
67{
68namespace tests
69{
70// Implementing unity::tests::Friend, see TestingFriend.h
71class Friend : public ::testing::Test
72{
73public:
74 PRIVATE_PIMPL_METHOD_CALLER(pimpl, OnPointerBarrierEvent);
75 PRIVATE_PIMPL_MEMBER_GETTER(pimpl, subscribers_);
76};
77
78class TestEdgeBarrierController : public Friend
79{79{
80public:80public:
81 virtual void SetUp()81 virtual void SetUp()
@@ -93,6 +93,11 @@
93 }93 }
94 }94 }
9595
96 void ProcessBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event)
97 {
98 CallPrivatepimplOnPointerBarrierEvent<EdgeBarrierController, void, PointerBarrierWrapper*, BarrierEvent::Ptr>(bc, owner, event);
99 }
100
96 BarrierEvent::Ptr MakeBarrierEvent(int id, bool breaker)101 BarrierEvent::Ptr MakeBarrierEvent(int id, bool breaker)
97 {102 {
98 int velocity = breaker ? std::numeric_limits<int>::max() : bc.options()->edge_overcome_pressure() - 1;103 int velocity = breaker ? std::numeric_limits<int>::max() : bc.options()->edge_overcome_pressure() - 1;
@@ -101,7 +106,7 @@
101106
102 TestBarrierSubscriber subscribers_[max_num_monitors];107 TestBarrierSubscriber subscribers_[max_num_monitors];
103 MockUScreen uscreen;108 MockUScreen uscreen;
104 MockEdgeBarrierController bc;109 EdgeBarrierController bc;
105};110};
106111
107TEST_F(TestEdgeBarrierController, Construction)112TEST_F(TestEdgeBarrierController, Construction)
@@ -145,7 +150,7 @@
145 auto breaking_barrier_event = MakeBarrierEvent(0, true);150 auto breaking_barrier_event = MakeBarrierEvent(0, true);
146151
147 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);152 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);
148 bc.ProcessBarrierEvent(&owner, breaking_barrier_event);153 ProcessBarrierEvent(&owner, breaking_barrier_event);
149}154}
150155
151TEST_F(TestEdgeBarrierController, ProcessHandledEventOnReleasedBarrier)156TEST_F(TestEdgeBarrierController, ProcessHandledEventOnReleasedBarrier)
@@ -159,7 +164,7 @@
159 auto breaking_barrier_event = MakeBarrierEvent(0, true);164 auto breaking_barrier_event = MakeBarrierEvent(0, true);
160165
161 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);166 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);
162 bc.ProcessBarrierEvent(&owner, breaking_barrier_event);167 ProcessBarrierEvent(&owner, breaking_barrier_event);
163}168}
164169
165TEST_F(TestEdgeBarrierController, ProcessUnHandledEventBreakingBarrier)170TEST_F(TestEdgeBarrierController, ProcessUnHandledEventBreakingBarrier)
@@ -171,7 +176,7 @@
171 auto breaking_barrier_event = MakeBarrierEvent(breaking_id, true);176 auto breaking_barrier_event = MakeBarrierEvent(breaking_id, true);
172177
173 EXPECT_CALL(owner, ReleaseBarrier(breaking_id));178 EXPECT_CALL(owner, ReleaseBarrier(breaking_id));
174 bc.ProcessBarrierEvent(&owner, breaking_barrier_event);179 ProcessBarrierEvent(&owner, breaking_barrier_event);
175}180}
176181
177TEST_F(TestEdgeBarrierController, ProcessUnHandledEventBreakingBarrierOnMaxMonitor)182TEST_F(TestEdgeBarrierController, ProcessUnHandledEventBreakingBarrierOnMaxMonitor)
@@ -185,7 +190,7 @@
185 // you can reproduce this repeating this test multiple times using the190 // you can reproduce this repeating this test multiple times using the
186 // --gtest_repeat=X command line191 // --gtest_repeat=X command line
187 EXPECT_CALL(owner, ReleaseBarrier(_));192 EXPECT_CALL(owner, ReleaseBarrier(_));
188 bc.ProcessBarrierEvent(&owner, breaking_barrier_event);193 ProcessBarrierEvent(&owner, breaking_barrier_event);
189}194}
190195
191TEST_F(TestEdgeBarrierController, ProcessUnHandledEventNotBreakingBarrier)196TEST_F(TestEdgeBarrierController, ProcessUnHandledEventNotBreakingBarrier)
@@ -197,7 +202,7 @@
197 auto not_breaking_barrier_event = MakeBarrierEvent(not_breaking_id, false);202 auto not_breaking_barrier_event = MakeBarrierEvent(not_breaking_id, false);
198203
199 EXPECT_CALL(owner, ReleaseBarrier(not_breaking_id)).Times(0);204 EXPECT_CALL(owner, ReleaseBarrier(not_breaking_id)).Times(0);
200 bc.ProcessBarrierEvent(&owner, not_breaking_barrier_event);205 ProcessBarrierEvent(&owner, not_breaking_barrier_event);
201}206}
202207
203TEST_F(TestEdgeBarrierController, ProcessUnHandledEventOnReleasedBarrier)208TEST_F(TestEdgeBarrierController, ProcessUnHandledEventOnReleasedBarrier)
@@ -209,7 +214,7 @@
209 auto not_breaking_barrier_event = MakeBarrierEvent(not_breaking_id, false);214 auto not_breaking_barrier_event = MakeBarrierEvent(not_breaking_id, false);
210215
211 EXPECT_CALL(owner, ReleaseBarrier(not_breaking_id));216 EXPECT_CALL(owner, ReleaseBarrier(not_breaking_id));
212 bc.ProcessBarrierEvent(&owner, not_breaking_barrier_event);217 ProcessBarrierEvent(&owner, not_breaking_barrier_event);
213}218}
214219
215TEST_F(TestEdgeBarrierController, BreakingEdgeTemporaryReleasesBarrier)220TEST_F(TestEdgeBarrierController, BreakingEdgeTemporaryReleasesBarrier)
@@ -217,7 +222,7 @@
217 MockPointerBarrier owner;222 MockPointerBarrier owner;
218223
219 EXPECT_CALL(owner, ReleaseBarrier(1));224 EXPECT_CALL(owner, ReleaseBarrier(1));
220 bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(1, true));225 ProcessBarrierEvent(&owner, MakeBarrierEvent(1, true));
221 ASSERT_TRUE(owner.released());226 ASSERT_TRUE(owner.released());
222227
223 Utils::WaitForTimeoutMSec(bc.options()->edge_passed_disabled_ms);228 Utils::WaitForTimeoutMSec(bc.options()->edge_passed_disabled_ms);
@@ -231,12 +236,12 @@
231 subscribers_[monitor].handles_ = false;236 subscribers_[monitor].handles_ = false;
232237
233 EXPECT_CALL(owner, ReleaseBarrier(5));238 EXPECT_CALL(owner, ReleaseBarrier(5));
234 bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(5, true));239 ProcessBarrierEvent(&owner, MakeBarrierEvent(5, true));
235 ASSERT_TRUE(owner.released());240 ASSERT_TRUE(owner.released());
236241
237 subscribers_[monitor].handles_ = false;242 subscribers_[monitor].handles_ = false;
238 EXPECT_CALL(owner, ReleaseBarrier(6));243 EXPECT_CALL(owner, ReleaseBarrier(6));
239 bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(6, false));244 ProcessBarrierEvent(&owner, MakeBarrierEvent(6, false));
240}245}
241246
242TEST_F(TestEdgeBarrierController, BreakingEdgeDontReleasesBarrierForHandledEvents)247TEST_F(TestEdgeBarrierController, BreakingEdgeDontReleasesBarrierForHandledEvents)
@@ -246,12 +251,12 @@
246 subscribers_[monitor].handles_ = false;251 subscribers_[monitor].handles_ = false;
247252
248 EXPECT_CALL(owner, ReleaseBarrier(5));253 EXPECT_CALL(owner, ReleaseBarrier(5));
249 bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(5, true));254 ProcessBarrierEvent(&owner, MakeBarrierEvent(5, true));
250 ASSERT_TRUE(owner.released());255 ASSERT_TRUE(owner.released());
251256
252 subscribers_[monitor].handles_ = true;257 subscribers_[monitor].handles_ = true;
253 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);258 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);
254 bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(6, true));259 ProcessBarrierEvent(&owner, MakeBarrierEvent(6, true));
255}260}
256261
257TEST_F(TestEdgeBarrierController, StickyEdgePropertyProxiesLauncherOption)262TEST_F(TestEdgeBarrierController, StickyEdgePropertyProxiesLauncherOption)
@@ -270,3 +275,4 @@
270}275}
271276
272}277}
278}
273279
=== modified file 'tests/test_launcher_controller.cpp'
--- tests/test_launcher_controller.cpp 2012-07-25 23:45:28 +0000
+++ tests/test_launcher_controller.cpp 2012-07-25 23:45:28 +0000
@@ -32,6 +32,16 @@
32namespace unity32namespace unity
33{33{
3434
35// Implementing unity::tests::Friend, see TestingFriend.h
36namespace tests
37{
38 class Friend : public ::testing::Test
39 {
40 public:
41 PRIVATE_PIMPL_MEMBER_GETTER(pimpl, edge_barriers_)
42 };
43}
44
35class MockFavoriteStore : public FavoriteStore45class MockFavoriteStore : public FavoriteStore
36{46{
37public:47public:
@@ -51,7 +61,7 @@
5161
52namespace launcher62namespace launcher
53{63{
54class TestLauncherController : public testing::Test64class TestLauncherController : public tests::Friend
55{65{
56public:66public:
57 TestLauncherController()67 TestLauncherController()
@@ -67,7 +77,7 @@
67protected:77protected:
68 ui::EdgeBarrierController &GetBarrierController()78 ui::EdgeBarrierController &GetBarrierController()
69 {79 {
70 return lc.pimpl->edge_barriers_;80 return *get_private_pimpl_edge_barriers_<launcher::Controller, ui::EdgeBarrierController>(lc);
71 }81 }
7282
73 MockUScreen uscreen;83 MockUScreen uscreen;
7484
=== added file 'unity-shared/TestingFriend.h'
--- unity-shared/TestingFriend.h 1970-01-01 00:00:00 +0000
+++ unity-shared/TestingFriend.h 2012-07-25 23:45:28 +0000
@@ -0,0 +1,155 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * version 3 along with this program. If not, see
15 * <http://www.gnu.org/licenses/>
16 *
17 * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
18 */
19
20#ifndef TESTING_FRIEND_H
21#define TESTING_FRIEND_H
22
23namespace unity
24{
25namespace tests
26{
27/*
28* This is a class without definition that is meant to be used as a friend
29* in the classes that we want to test accessing to private members.
30* The definition of this must be done in the testing file.
31*/
32class Friend;
33
34#define PRIVATE_MEMBER_GETTER(member) \
35 template <typename T, typename R> R* get_private_##member(T& cl) { return &(cl.member); }
36#define PRIVATE_PIMPL_MEMBER_GETTER(pimpl, sub) \
37 template <typename T, typename R> R* get_private_##pimpl##_##sub(T& cl) { return &(cl.pimpl->sub); }
38#define PRIVATE_METHOD_CALLER(Method) \
39 template <typename T, typename R, typename... Ts> R CallPrivate##Method(T& cl, Ts... vars) { return cl.Method(vars...); }
40#define PRIVATE_PIMPL_METHOD_CALLER(pimpl, Method) \
41 template <typename T, typename R, typename... Ts> R CallPrivate##pimpl##Method(T& cl, Ts... vars) { return cl.pimpl->Method(vars...); }
42
43/*
44 * Example:
45
46// This should go in FooTestMe.h
47
48#include "TestingFriend.h"
49
50class FooTestMe
51{
52public:
53 //...
54protected:
55 void virtual VirtualMethod() {}
56
57private:
58 void Method() { VirtualMethod(); }
59 double MethodWithValues(int a, bool b) { priv_value_ = b ? a+1 : a-1; return priv_value_;}
60
61 double priv_value_;
62
63 friend class unity::tests::Friend;
64};
65
66 * At this point in each test file you want to use this feature, you need to
67 * define the Friend class, inheriting from Google tests' testing::Test
68 * now, this class can access to all the private members of all the unity
69 * classes that have been defined as friend of unity::tests::Friend, but this
70 * is not enough to give the tests access to the private data (since we want to
71 * inherit from it on tests).
72 *
73 * So, to achieve this you can both write proxy functions and use the macros
74 * defined above to generate template functions that allow the access to the
75 * private data or methods.
76
77// This should go in test_foo_test_me.cpp
78
79#include <gtest/gtest.h>
80#include "FooTestMe.h"
81
82namespace unity
83{
84namespace tests
85{
86 class Friend : public ::testing::Test
87 {
88 public:
89 // Generates void CallPrivateMethod(T const& cl)
90 PRIVATE_METHOD_CALLER(Method)
91
92 // Generates int CallPrivateMethodWithValues(T const& cl, int a, bool b)
93 PRIVATE_METHOD_CALLER(MethodWithValues)
94
95 // Generates int* get_private_priv_value_(T const& cl)
96 PRIVATE_MEMBER_GETTER(priv_value_)
97
98 // Otherwise you can still do
99 double CallMethodWithValues(FooTestMe& foo_test_me, int a, int b)
100 {
101 return foo_test_me.MethodWithValues(a, b);
102 }
103 };
104}
105}
106
107 * It' also possible to mock the function to test, if needed.
108
109// Optional Mocking
110class FooTestMeMock : public FooTestMe
111{
112public:
113 MOCK_METHOD0(VirtualMethod, void());
114};
115
116 * This is the actual class used by gtest as testing class
117
118namespace
119{
120class TestFooTestMe : public unity::tests::Friend
121{
122public:
123 virtual void SetUp()
124 {}
125
126 // Just use FooTestMe if you don't need mocking
127 FooTestMeMock test_me;
128};
129
130 * In the test functions you can access the private members, just using the
131 * functions that have been generated into unity::tests::Friend to get access
132 * to the tested class.
133
134TEST_F(TestFooTestMe, Methods)
135{
136 EXPECT_CALL(test_me, VirtualMethod());
137 CallPrivateMethod<FooTestMe, void>(test_me);
138
139 double val = CallPrivateMethodWithValues<FooTestMe, double, int, bool>(test_me, 9, true);
140 EXPECT_EQ(val, 10.0);
141
142 double* priv_value = get_private_priv_value_<FooTestMe, double>(test_me);
143 EXPECT_EQ(*priv_value, 10.0);
144
145 EXPECT_EQ(11.0, CallMethodWithValues(test_me, 10, true));
146}
147}
148
149*
150*/
151
152} // namespace testing
153} // namespace unity
154
155#endif