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.
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?

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.

jenkins (martin-mrazik+qa) wrote :
review: Needs Fixing (continuous-integration)
Martin Mrazik (mrazik) wrote :

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

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?

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.

Francis Ginther (fginther) wrote :

Review was claimed by accident, please ignore.

review: Abstain
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
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
1=== modified file 'launcher/EdgeBarrierController.cpp'
2--- launcher/EdgeBarrierController.cpp 2012-07-25 23:45:28 +0000
3+++ launcher/EdgeBarrierController.cpp 2012-07-25 23:45:28 +0000
4@@ -18,47 +18,12 @@
5 * Marco Trevisan <marco.trevisan@canonical.com>
6 */
7
8-#include "EdgeBarrierController.h"
9-#include "Decaymulator.h"
10+#include "EdgeBarrierControllerPrivate.h"
11 #include "unity-shared/UScreen.h"
12-#include "UnityCore/GLibSource.h"
13
14 namespace unity {
15 namespace ui {
16
17-struct EdgeBarrierController::Impl
18-{
19- Impl(EdgeBarrierController *parent);
20-
21- void ResizeBarrierList(std::vector<nux::Geometry> const& layout);
22- void SetupBarriers(std::vector<nux::Geometry> const& layout);
23-
24- void OnPointerBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event);
25- void BarrierRelease(PointerBarrierWrapper* owner, int event);
26-
27- bool StickyEdgeSetter(bool const& new_val)
28- {
29- if (parent_->options() && new_val != parent_->options()->edge_resist())
30- {
31- parent_->options()->edge_resist = new_val;
32- return true;
33- }
34- return false;
35- }
36-
37- bool StickyEdgeGetter()
38- {
39- return parent_->options() ? parent_->options()->edge_resist() : false;
40- }
41-
42- std::vector<PointerBarrierWrapper::Ptr> barriers_;
43- std::vector<EdgeBarrierSubscriber*> subscribers_;
44- Decaymulator decaymulator_;
45- glib::Source::UniquePtr release_timeout_;
46- float edge_overcome_pressure_;
47- EdgeBarrierController* parent_;
48-};
49-
50 EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent)
51 : edge_overcome_pressure_(0)
52 , parent_(parent)
53@@ -235,10 +200,5 @@
54 return pimpl->subscribers_[monitor];
55 }
56
57-void EdgeBarrierController::ProcessBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event)
58-{
59- pimpl->OnPointerBarrierEvent(owner, event);
60-}
61-
62 }
63 }
64
65=== modified file 'launcher/EdgeBarrierController.h'
66--- launcher/EdgeBarrierController.h 2012-07-25 23:45:28 +0000
67+++ launcher/EdgeBarrierController.h 2012-07-25 23:45:28 +0000
68@@ -22,6 +22,7 @@
69
70 #include "PointerBarrier.h"
71 #include "LauncherOptions.h"
72+#include "unity-shared/TestingFriend.h"
73
74 namespace unity {
75 namespace ui {
76@@ -45,12 +46,11 @@
77 void Unsubscribe(EdgeBarrierSubscriber* subscriber, unsigned int monitor);
78 EdgeBarrierSubscriber* GetSubscriber(unsigned int monitor);
79
80-protected:
81- void ProcessBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event);
82-
83 private:
84 struct Impl;
85 std::unique_ptr<Impl> pimpl;
86+
87+ friend class tests::Friend;
88 };
89
90 }
91
92=== added file 'launcher/EdgeBarrierControllerPrivate.h'
93--- launcher/EdgeBarrierControllerPrivate.h 1970-01-01 00:00:00 +0000
94+++ launcher/EdgeBarrierControllerPrivate.h 2012-07-25 23:45:28 +0000
95@@ -0,0 +1,68 @@
96+/*
97+ * Copyright 2012 Canonical Ltd.
98+ *
99+ * This program is free software: you can redistribute it and/or modify it
100+ * under the terms of the GNU General Public License version 3, as published
101+ * by the Free Software Foundation.
102+ *
103+ * This program is distributed in the hope that it will be useful, but
104+ * WITHOUT ANY WARRANTY; without even the implied warranties of
105+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
106+ * PURPOSE. See the GNU General Public License for more details.
107+ *
108+ * You should have received a copy of the GNU General Public License
109+ * version 3 along with this program. If not, see
110+ * <http://www.gnu.org/licenses/>
111+ *
112+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
113+ * Jason Smith <jason.smith@canonical.com>
114+ *
115+ */
116+
117+#ifndef UNITY_EDGE_BARRIER_CONTROLLER_PRIVATE_H
118+#define UNITY_EDGE_BARRIER_CONTROLLER_PRIVATE_H
119+
120+#include "EdgeBarrierController.h"
121+#include "Decaymulator.h"
122+#include "UnityCore/GLibSource.h"
123+
124+namespace unity {
125+namespace ui {
126+
127+struct EdgeBarrierController::Impl
128+{
129+ Impl(EdgeBarrierController *parent);
130+
131+ void ResizeBarrierList(std::vector<nux::Geometry> const& layout);
132+ void SetupBarriers(std::vector<nux::Geometry> const& layout);
133+
134+ void OnPointerBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event);
135+ void BarrierRelease(PointerBarrierWrapper* owner, int event);
136+
137+ bool StickyEdgeSetter(bool const& new_val)
138+ {
139+ if (parent_->options() && new_val != parent_->options()->edge_resist())
140+ {
141+ parent_->options()->edge_resist = new_val;
142+ return true;
143+ }
144+ return false;
145+ }
146+
147+ bool StickyEdgeGetter()
148+ {
149+ return parent_->options() ? parent_->options()->edge_resist() : false;
150+ }
151+
152+ std::vector<PointerBarrierWrapper::Ptr> barriers_;
153+ std::vector<EdgeBarrierSubscriber*> subscribers_;
154+ Decaymulator decaymulator_;
155+ glib::Source::UniquePtr release_timeout_;
156+ float edge_overcome_pressure_;
157+ EdgeBarrierController* parent_;
158+};
159+
160+} // namespace ui
161+} // namespace unity
162+
163+#endif
164
165=== modified file 'launcher/LauncherController.h'
166--- launcher/LauncherController.h 2012-07-25 23:45:28 +0000
167+++ launcher/LauncherController.h 2012-07-25 23:45:28 +0000
168@@ -27,6 +27,7 @@
169
170 #include "LauncherOptions.h"
171 #include "SoftwareCenterLauncherIcon.h"
172+#include "unity-shared/TestingFriend.h"
173
174 namespace unity
175 {
176@@ -35,7 +36,6 @@
177 class AbstractLauncherIcon;
178 class Launcher;
179 class LauncherModel;
180-class TestLauncherController;
181
182 class Controller : public unity::debug::Introspectable, public sigc::trackable
183 {
184@@ -87,9 +87,9 @@
185 void AddProperties(GVariantBuilder* builder);
186
187 private:
188- friend class TestLauncherController;
189 class Impl;
190 std::unique_ptr<Impl> pimpl;
191+ friend class tests::Friend;
192 };
193
194 }
195
196=== modified file 'tests/test_edge_barrier_controller.cpp'
197--- tests/test_edge_barrier_controller.cpp 2012-07-25 23:45:28 +0000
198+++ tests/test_edge_barrier_controller.cpp 2012-07-25 23:45:28 +0000
199@@ -22,7 +22,7 @@
200 #include "test_utils.h"
201 #include "test_uscreen_mock.h"
202
203-#include "EdgeBarrierController.h"
204+#include "EdgeBarrierControllerPrivate.h"
205
206 using namespace unity;
207 using namespace unity::ui;
208@@ -46,20 +46,6 @@
209 MOCK_METHOD1(ReleaseBarrier, void(int));
210 };
211
212-class MockEdgeBarrierController : public EdgeBarrierController
213-{
214-public:
215- void ProcessBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event)
216- {
217- EdgeBarrierController::ProcessBarrierEvent(owner, event);
218- }
219-
220- EdgeBarrierSubscriber* GetSubscriber(unsigned int monitor)
221- {
222- return EdgeBarrierController::GetSubscriber(monitor);
223- }
224-};
225-
226 class TestBarrierSubscriber : public EdgeBarrierSubscriber
227 {
228 public:
229@@ -75,7 +61,21 @@
230 bool handles_;
231 };
232
233-class TestEdgeBarrierController : public Test
234+}
235+
236+namespace unity
237+{
238+namespace tests
239+{
240+// Implementing unity::tests::Friend, see TestingFriend.h
241+class Friend : public ::testing::Test
242+{
243+public:
244+ PRIVATE_PIMPL_METHOD_CALLER(pimpl, OnPointerBarrierEvent);
245+ PRIVATE_PIMPL_MEMBER_GETTER(pimpl, subscribers_);
246+};
247+
248+class TestEdgeBarrierController : public Friend
249 {
250 public:
251 virtual void SetUp()
252@@ -93,6 +93,11 @@
253 }
254 }
255
256+ void ProcessBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event)
257+ {
258+ CallPrivatepimplOnPointerBarrierEvent<EdgeBarrierController, void, PointerBarrierWrapper*, BarrierEvent::Ptr>(bc, owner, event);
259+ }
260+
261 BarrierEvent::Ptr MakeBarrierEvent(int id, bool breaker)
262 {
263 int velocity = breaker ? std::numeric_limits<int>::max() : bc.options()->edge_overcome_pressure() - 1;
264@@ -101,7 +106,7 @@
265
266 TestBarrierSubscriber subscribers_[max_num_monitors];
267 MockUScreen uscreen;
268- MockEdgeBarrierController bc;
269+ EdgeBarrierController bc;
270 };
271
272 TEST_F(TestEdgeBarrierController, Construction)
273@@ -145,7 +150,7 @@
274 auto breaking_barrier_event = MakeBarrierEvent(0, true);
275
276 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);
277- bc.ProcessBarrierEvent(&owner, breaking_barrier_event);
278+ ProcessBarrierEvent(&owner, breaking_barrier_event);
279 }
280
281 TEST_F(TestEdgeBarrierController, ProcessHandledEventOnReleasedBarrier)
282@@ -159,7 +164,7 @@
283 auto breaking_barrier_event = MakeBarrierEvent(0, true);
284
285 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);
286- bc.ProcessBarrierEvent(&owner, breaking_barrier_event);
287+ ProcessBarrierEvent(&owner, breaking_barrier_event);
288 }
289
290 TEST_F(TestEdgeBarrierController, ProcessUnHandledEventBreakingBarrier)
291@@ -171,7 +176,7 @@
292 auto breaking_barrier_event = MakeBarrierEvent(breaking_id, true);
293
294 EXPECT_CALL(owner, ReleaseBarrier(breaking_id));
295- bc.ProcessBarrierEvent(&owner, breaking_barrier_event);
296+ ProcessBarrierEvent(&owner, breaking_barrier_event);
297 }
298
299 TEST_F(TestEdgeBarrierController, ProcessUnHandledEventBreakingBarrierOnMaxMonitor)
300@@ -185,7 +190,7 @@
301 // you can reproduce this repeating this test multiple times using the
302 // --gtest_repeat=X command line
303 EXPECT_CALL(owner, ReleaseBarrier(_));
304- bc.ProcessBarrierEvent(&owner, breaking_barrier_event);
305+ ProcessBarrierEvent(&owner, breaking_barrier_event);
306 }
307
308 TEST_F(TestEdgeBarrierController, ProcessUnHandledEventNotBreakingBarrier)
309@@ -197,7 +202,7 @@
310 auto not_breaking_barrier_event = MakeBarrierEvent(not_breaking_id, false);
311
312 EXPECT_CALL(owner, ReleaseBarrier(not_breaking_id)).Times(0);
313- bc.ProcessBarrierEvent(&owner, not_breaking_barrier_event);
314+ ProcessBarrierEvent(&owner, not_breaking_barrier_event);
315 }
316
317 TEST_F(TestEdgeBarrierController, ProcessUnHandledEventOnReleasedBarrier)
318@@ -209,7 +214,7 @@
319 auto not_breaking_barrier_event = MakeBarrierEvent(not_breaking_id, false);
320
321 EXPECT_CALL(owner, ReleaseBarrier(not_breaking_id));
322- bc.ProcessBarrierEvent(&owner, not_breaking_barrier_event);
323+ ProcessBarrierEvent(&owner, not_breaking_barrier_event);
324 }
325
326 TEST_F(TestEdgeBarrierController, BreakingEdgeTemporaryReleasesBarrier)
327@@ -217,7 +222,7 @@
328 MockPointerBarrier owner;
329
330 EXPECT_CALL(owner, ReleaseBarrier(1));
331- bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(1, true));
332+ ProcessBarrierEvent(&owner, MakeBarrierEvent(1, true));
333 ASSERT_TRUE(owner.released());
334
335 Utils::WaitForTimeoutMSec(bc.options()->edge_passed_disabled_ms);
336@@ -231,12 +236,12 @@
337 subscribers_[monitor].handles_ = false;
338
339 EXPECT_CALL(owner, ReleaseBarrier(5));
340- bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(5, true));
341+ ProcessBarrierEvent(&owner, MakeBarrierEvent(5, true));
342 ASSERT_TRUE(owner.released());
343
344 subscribers_[monitor].handles_ = false;
345 EXPECT_CALL(owner, ReleaseBarrier(6));
346- bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(6, false));
347+ ProcessBarrierEvent(&owner, MakeBarrierEvent(6, false));
348 }
349
350 TEST_F(TestEdgeBarrierController, BreakingEdgeDontReleasesBarrierForHandledEvents)
351@@ -246,12 +251,12 @@
352 subscribers_[monitor].handles_ = false;
353
354 EXPECT_CALL(owner, ReleaseBarrier(5));
355- bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(5, true));
356+ ProcessBarrierEvent(&owner, MakeBarrierEvent(5, true));
357 ASSERT_TRUE(owner.released());
358
359 subscribers_[monitor].handles_ = true;
360 EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);
361- bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(6, true));
362+ ProcessBarrierEvent(&owner, MakeBarrierEvent(6, true));
363 }
364
365 TEST_F(TestEdgeBarrierController, StickyEdgePropertyProxiesLauncherOption)
366@@ -270,3 +275,4 @@
367 }
368
369 }
370+}
371
372=== modified file 'tests/test_launcher_controller.cpp'
373--- tests/test_launcher_controller.cpp 2012-07-25 23:45:28 +0000
374+++ tests/test_launcher_controller.cpp 2012-07-25 23:45:28 +0000
375@@ -32,6 +32,16 @@
376 namespace unity
377 {
378
379+// Implementing unity::tests::Friend, see TestingFriend.h
380+namespace tests
381+{
382+ class Friend : public ::testing::Test
383+ {
384+ public:
385+ PRIVATE_PIMPL_MEMBER_GETTER(pimpl, edge_barriers_)
386+ };
387+}
388+
389 class MockFavoriteStore : public FavoriteStore
390 {
391 public:
392@@ -51,7 +61,7 @@
393
394 namespace launcher
395 {
396-class TestLauncherController : public testing::Test
397+class TestLauncherController : public tests::Friend
398 {
399 public:
400 TestLauncherController()
401@@ -67,7 +77,7 @@
402 protected:
403 ui::EdgeBarrierController &GetBarrierController()
404 {
405- return lc.pimpl->edge_barriers_;
406+ return *get_private_pimpl_edge_barriers_<launcher::Controller, ui::EdgeBarrierController>(lc);
407 }
408
409 MockUScreen uscreen;
410
411=== added file 'unity-shared/TestingFriend.h'
412--- unity-shared/TestingFriend.h 1970-01-01 00:00:00 +0000
413+++ unity-shared/TestingFriend.h 2012-07-25 23:45:28 +0000
414@@ -0,0 +1,155 @@
415+/*
416+ * Copyright 2012 Canonical Ltd.
417+ *
418+ * This program is free software: you can redistribute it and/or modify it
419+ * under the terms of the GNU General Public License version 3, as published
420+ * by the Free Software Foundation.
421+ *
422+ * This program is distributed in the hope that it will be useful, but
423+ * WITHOUT ANY WARRANTY; without even the implied warranties of
424+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
425+ * PURPOSE. See the GNU General Public License for more details.
426+ *
427+ * You should have received a copy of the GNU General Public License
428+ * version 3 along with this program. If not, see
429+ * <http://www.gnu.org/licenses/>
430+ *
431+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
432+ */
433+
434+#ifndef TESTING_FRIEND_H
435+#define TESTING_FRIEND_H
436+
437+namespace unity
438+{
439+namespace tests
440+{
441+/*
442+* This is a class without definition that is meant to be used as a friend
443+* in the classes that we want to test accessing to private members.
444+* The definition of this must be done in the testing file.
445+*/
446+class Friend;
447+
448+#define PRIVATE_MEMBER_GETTER(member) \
449+ template <typename T, typename R> R* get_private_##member(T& cl) { return &(cl.member); }
450+#define PRIVATE_PIMPL_MEMBER_GETTER(pimpl, sub) \
451+ template <typename T, typename R> R* get_private_##pimpl##_##sub(T& cl) { return &(cl.pimpl->sub); }
452+#define PRIVATE_METHOD_CALLER(Method) \
453+ template <typename T, typename R, typename... Ts> R CallPrivate##Method(T& cl, Ts... vars) { return cl.Method(vars...); }
454+#define PRIVATE_PIMPL_METHOD_CALLER(pimpl, Method) \
455+ template <typename T, typename R, typename... Ts> R CallPrivate##pimpl##Method(T& cl, Ts... vars) { return cl.pimpl->Method(vars...); }
456+
457+/*
458+ * Example:
459+
460+// This should go in FooTestMe.h
461+
462+#include "TestingFriend.h"
463+
464+class FooTestMe
465+{
466+public:
467+ //...
468+protected:
469+ void virtual VirtualMethod() {}
470+
471+private:
472+ void Method() { VirtualMethod(); }
473+ double MethodWithValues(int a, bool b) { priv_value_ = b ? a+1 : a-1; return priv_value_;}
474+
475+ double priv_value_;
476+
477+ friend class unity::tests::Friend;
478+};
479+
480+ * At this point in each test file you want to use this feature, you need to
481+ * define the Friend class, inheriting from Google tests' testing::Test
482+ * now, this class can access to all the private members of all the unity
483+ * classes that have been defined as friend of unity::tests::Friend, but this
484+ * is not enough to give the tests access to the private data (since we want to
485+ * inherit from it on tests).
486+ *
487+ * So, to achieve this you can both write proxy functions and use the macros
488+ * defined above to generate template functions that allow the access to the
489+ * private data or methods.
490+
491+// This should go in test_foo_test_me.cpp
492+
493+#include <gtest/gtest.h>
494+#include "FooTestMe.h"
495+
496+namespace unity
497+{
498+namespace tests
499+{
500+ class Friend : public ::testing::Test
501+ {
502+ public:
503+ // Generates void CallPrivateMethod(T const& cl)
504+ PRIVATE_METHOD_CALLER(Method)
505+
506+ // Generates int CallPrivateMethodWithValues(T const& cl, int a, bool b)
507+ PRIVATE_METHOD_CALLER(MethodWithValues)
508+
509+ // Generates int* get_private_priv_value_(T const& cl)
510+ PRIVATE_MEMBER_GETTER(priv_value_)
511+
512+ // Otherwise you can still do
513+ double CallMethodWithValues(FooTestMe& foo_test_me, int a, int b)
514+ {
515+ return foo_test_me.MethodWithValues(a, b);
516+ }
517+ };
518+}
519+}
520+
521+ * It' also possible to mock the function to test, if needed.
522+
523+// Optional Mocking
524+class FooTestMeMock : public FooTestMe
525+{
526+public:
527+ MOCK_METHOD0(VirtualMethod, void());
528+};
529+
530+ * This is the actual class used by gtest as testing class
531+
532+namespace
533+{
534+class TestFooTestMe : public unity::tests::Friend
535+{
536+public:
537+ virtual void SetUp()
538+ {}
539+
540+ // Just use FooTestMe if you don't need mocking
541+ FooTestMeMock test_me;
542+};
543+
544+ * In the test functions you can access the private members, just using the
545+ * functions that have been generated into unity::tests::Friend to get access
546+ * to the tested class.
547+
548+TEST_F(TestFooTestMe, Methods)
549+{
550+ EXPECT_CALL(test_me, VirtualMethod());
551+ CallPrivateMethod<FooTestMe, void>(test_me);
552+
553+ double val = CallPrivateMethodWithValues<FooTestMe, double, int, bool>(test_me, 9, true);
554+ EXPECT_EQ(val, 10.0);
555+
556+ double* priv_value = get_private_priv_value_<FooTestMe, double>(test_me);
557+ EXPECT_EQ(*priv_value, 10.0);
558+
559+ EXPECT_EQ(11.0, CallMethodWithValues(test_me, 10, true));
560+}
561+}
562+
563+*
564+*/
565+
566+} // namespace testing
567+} // namespace unity
568+
569+#endif