1 /*
2  *  Copyright 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "api/proxy.h"
12 
13 #include <memory>
14 #include <string>
15 
16 #include "rtc_base/gunit.h"
17 #include "rtc_base/ref_count.h"
18 #include "test/gmock.h"
19 
20 using ::testing::_;
21 using ::testing::DoAll;
22 using ::testing::Exactly;
23 using ::testing::InvokeWithoutArgs;
24 using ::testing::Return;
25 
26 namespace webrtc {
27 
28 // Interface used for testing here.
29 class FakeInterface : public rtc::RefCountInterface {
30  public:
31   virtual void VoidMethod0() = 0;
32   virtual std::string Method0() = 0;
33   virtual std::string ConstMethod0() const = 0;
34   virtual std::string Method1(std::string s) = 0;
35   virtual std::string ConstMethod1(std::string s) const = 0;
36   virtual std::string Method2(std::string s1, std::string s2) = 0;
37 
38  protected:
~FakeInterface()39   virtual ~FakeInterface() {}
40 };
41 
42 // Implementation of the test interface.
43 class Fake : public FakeInterface {
44  public:
Create()45   static rtc::scoped_refptr<Fake> Create() {
46     return new rtc::RefCountedObject<Fake>();
47   }
48   // Used to verify destructor is called on the correct thread.
49   MOCK_METHOD(void, Destroy, ());
50 
51   MOCK_METHOD(void, VoidMethod0, (), (override));
52   MOCK_METHOD(std::string, Method0, (), (override));
53   MOCK_METHOD(std::string, ConstMethod0, (), (const, override));
54 
55   MOCK_METHOD(std::string, Method1, (std::string), (override));
56   MOCK_METHOD(std::string, ConstMethod1, (std::string), (const, override));
57 
58   MOCK_METHOD(std::string, Method2, (std::string, std::string), (override));
59 
60  protected:
Fake()61   Fake() {}
~Fake()62   ~Fake() { Destroy(); }
63 };
64 
65 // Proxies for the test interface.
66 BEGIN_PROXY_MAP(Fake)
67 PROXY_SECONDARY_THREAD_DESTRUCTOR()
68 PROXY_METHOD0(void, VoidMethod0)
69 PROXY_METHOD0(std::string, Method0)
70 PROXY_CONSTMETHOD0(std::string, ConstMethod0)
71 PROXY_SECONDARY_METHOD1(std::string, Method1, std::string)
72 PROXY_CONSTMETHOD1(std::string, ConstMethod1, std::string)
73 PROXY_SECONDARY_METHOD2(std::string, Method2, std::string, std::string)
74 END_PROXY_MAP()
75 
76 // Preprocessor hack to get a proxy class a name different than FakeProxy.
77 #define FakeProxy FakeSignalingProxy
78 #define FakeProxyWithInternal FakeSignalingProxyWithInternal
79 BEGIN_PRIMARY_PROXY_MAP(Fake)
80 PROXY_PRIMARY_THREAD_DESTRUCTOR()
81 PROXY_METHOD0(void, VoidMethod0)
82 PROXY_METHOD0(std::string, Method0)
83 PROXY_CONSTMETHOD0(std::string, ConstMethod0)
84 PROXY_METHOD1(std::string, Method1, std::string)
85 PROXY_CONSTMETHOD1(std::string, ConstMethod1, std::string)
86 PROXY_METHOD2(std::string, Method2, std::string, std::string)
87 END_PROXY_MAP()
88 #undef FakeProxy
89 
90 class SignalingProxyTest : public ::testing::Test {
91  public:
92   // Checks that the functions are called on the right thread.
CheckSignalingThread()93   void CheckSignalingThread() { EXPECT_TRUE(signaling_thread_->IsCurrent()); }
94 
95  protected:
SetUp()96   void SetUp() override {
97     signaling_thread_ = rtc::Thread::Create();
98     ASSERT_TRUE(signaling_thread_->Start());
99     fake_ = Fake::Create();
100     fake_signaling_proxy_ =
101         FakeSignalingProxy::Create(signaling_thread_.get(), fake_.get());
102   }
103 
104  protected:
105   std::unique_ptr<rtc::Thread> signaling_thread_;
106   rtc::scoped_refptr<FakeInterface> fake_signaling_proxy_;
107   rtc::scoped_refptr<Fake> fake_;
108 };
109 
TEST_F(SignalingProxyTest,SignalingThreadDestructor)110 TEST_F(SignalingProxyTest, SignalingThreadDestructor) {
111   EXPECT_CALL(*fake_, Destroy())
112       .Times(Exactly(1))
113       .WillOnce(
114           InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread));
115   fake_ = nullptr;
116   fake_signaling_proxy_ = nullptr;
117 }
118 
TEST_F(SignalingProxyTest,VoidMethod0)119 TEST_F(SignalingProxyTest, VoidMethod0) {
120   EXPECT_CALL(*fake_, VoidMethod0())
121       .Times(Exactly(1))
122       .WillOnce(
123           InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread));
124   fake_signaling_proxy_->VoidMethod0();
125 }
126 
TEST_F(SignalingProxyTest,Method0)127 TEST_F(SignalingProxyTest, Method0) {
128   EXPECT_CALL(*fake_, Method0())
129       .Times(Exactly(1))
130       .WillOnce(DoAll(
131           InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
132           Return("Method0")));
133   EXPECT_EQ("Method0", fake_signaling_proxy_->Method0());
134 }
135 
TEST_F(SignalingProxyTest,ConstMethod0)136 TEST_F(SignalingProxyTest, ConstMethod0) {
137   EXPECT_CALL(*fake_, ConstMethod0())
138       .Times(Exactly(1))
139       .WillOnce(DoAll(
140           InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
141           Return("ConstMethod0")));
142   EXPECT_EQ("ConstMethod0", fake_signaling_proxy_->ConstMethod0());
143 }
144 
TEST_F(SignalingProxyTest,Method1)145 TEST_F(SignalingProxyTest, Method1) {
146   const std::string arg1 = "arg1";
147   EXPECT_CALL(*fake_, Method1(arg1))
148       .Times(Exactly(1))
149       .WillOnce(DoAll(
150           InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
151           Return("Method1")));
152   EXPECT_EQ("Method1", fake_signaling_proxy_->Method1(arg1));
153 }
154 
TEST_F(SignalingProxyTest,ConstMethod1)155 TEST_F(SignalingProxyTest, ConstMethod1) {
156   const std::string arg1 = "arg1";
157   EXPECT_CALL(*fake_, ConstMethod1(arg1))
158       .Times(Exactly(1))
159       .WillOnce(DoAll(
160           InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
161           Return("ConstMethod1")));
162   EXPECT_EQ("ConstMethod1", fake_signaling_proxy_->ConstMethod1(arg1));
163 }
164 
TEST_F(SignalingProxyTest,Method2)165 TEST_F(SignalingProxyTest, Method2) {
166   const std::string arg1 = "arg1";
167   const std::string arg2 = "arg2";
168   EXPECT_CALL(*fake_, Method2(arg1, arg2))
169       .Times(Exactly(1))
170       .WillOnce(DoAll(
171           InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
172           Return("Method2")));
173   EXPECT_EQ("Method2", fake_signaling_proxy_->Method2(arg1, arg2));
174 }
175 
176 class ProxyTest : public ::testing::Test {
177  public:
178   // Checks that the functions are called on the right thread.
CheckSignalingThread()179   void CheckSignalingThread() { EXPECT_TRUE(signaling_thread_->IsCurrent()); }
CheckWorkerThread()180   void CheckWorkerThread() { EXPECT_TRUE(worker_thread_->IsCurrent()); }
181 
182  protected:
SetUp()183   void SetUp() override {
184     signaling_thread_ = rtc::Thread::Create();
185     worker_thread_ = rtc::Thread::Create();
186     ASSERT_TRUE(signaling_thread_->Start());
187     ASSERT_TRUE(worker_thread_->Start());
188     fake_ = Fake::Create();
189     fake_proxy_ = FakeProxy::Create(signaling_thread_.get(),
190                                     worker_thread_.get(), fake_.get());
191   }
192 
193  protected:
194   std::unique_ptr<rtc::Thread> signaling_thread_;
195   std::unique_ptr<rtc::Thread> worker_thread_;
196   rtc::scoped_refptr<FakeInterface> fake_proxy_;
197   rtc::scoped_refptr<Fake> fake_;
198 };
199 
TEST_F(ProxyTest,WorkerThreadDestructor)200 TEST_F(ProxyTest, WorkerThreadDestructor) {
201   EXPECT_CALL(*fake_, Destroy())
202       .Times(Exactly(1))
203       .WillOnce(InvokeWithoutArgs(this, &ProxyTest::CheckWorkerThread));
204   fake_ = nullptr;
205   fake_proxy_ = nullptr;
206 }
207 
TEST_F(ProxyTest,VoidMethod0)208 TEST_F(ProxyTest, VoidMethod0) {
209   EXPECT_CALL(*fake_, VoidMethod0())
210       .Times(Exactly(1))
211       .WillOnce(InvokeWithoutArgs(this, &ProxyTest::CheckSignalingThread));
212   fake_proxy_->VoidMethod0();
213 }
214 
TEST_F(ProxyTest,Method0)215 TEST_F(ProxyTest, Method0) {
216   EXPECT_CALL(*fake_, Method0())
217       .Times(Exactly(1))
218       .WillOnce(DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckSignalingThread),
219                       Return("Method0")));
220   EXPECT_EQ("Method0", fake_proxy_->Method0());
221 }
222 
TEST_F(ProxyTest,ConstMethod0)223 TEST_F(ProxyTest, ConstMethod0) {
224   EXPECT_CALL(*fake_, ConstMethod0())
225       .Times(Exactly(1))
226       .WillOnce(DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckSignalingThread),
227                       Return("ConstMethod0")));
228   EXPECT_EQ("ConstMethod0", fake_proxy_->ConstMethod0());
229 }
230 
TEST_F(ProxyTest,WorkerMethod1)231 TEST_F(ProxyTest, WorkerMethod1) {
232   const std::string arg1 = "arg1";
233   EXPECT_CALL(*fake_, Method1(arg1))
234       .Times(Exactly(1))
235       .WillOnce(DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckWorkerThread),
236                       Return("Method1")));
237   EXPECT_EQ("Method1", fake_proxy_->Method1(arg1));
238 }
239 
TEST_F(ProxyTest,ConstMethod1)240 TEST_F(ProxyTest, ConstMethod1) {
241   const std::string arg1 = "arg1";
242   EXPECT_CALL(*fake_, ConstMethod1(arg1))
243       .Times(Exactly(1))
244       .WillOnce(DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckSignalingThread),
245                       Return("ConstMethod1")));
246   EXPECT_EQ("ConstMethod1", fake_proxy_->ConstMethod1(arg1));
247 }
248 
TEST_F(ProxyTest,WorkerMethod2)249 TEST_F(ProxyTest, WorkerMethod2) {
250   const std::string arg1 = "arg1";
251   const std::string arg2 = "arg2";
252   EXPECT_CALL(*fake_, Method2(arg1, arg2))
253       .Times(Exactly(1))
254       .WillOnce(DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckWorkerThread),
255                       Return("Method2")));
256   EXPECT_EQ("Method2", fake_proxy_->Method2(arg1, arg2));
257 }
258 
259 // Interface for testing OWNED_PROXY_MAP.
260 class FooInterface {
261  public:
~FooInterface()262   virtual ~FooInterface() {}
263   virtual void Bar() = 0;
264 };
265 
266 class Foo : public FooInterface {
267  public:
Foo()268   Foo() {}
269   MOCK_METHOD(void, Bar, (), (override));
270 };
271 
272 BEGIN_OWNED_PROXY_MAP(Foo)
273 PROXY_PRIMARY_THREAD_DESTRUCTOR()
274 PROXY_METHOD0(void, Bar)
275 END_PROXY_MAP()
276 
277 class OwnedProxyTest : public ::testing::Test {
278  public:
OwnedProxyTest()279   OwnedProxyTest()
280       : signaling_thread_(rtc::Thread::Create()),
281         worker_thread_(rtc::Thread::Create()),
282         foo_(new Foo()),
283         foo_proxy_(FooProxy::Create(signaling_thread_.get(),
284                                     worker_thread_.get(),
285                                     std::unique_ptr<FooInterface>(foo_))) {
286     signaling_thread_->Start();
287     worker_thread_->Start();
288   }
289 
CheckSignalingThread()290   void CheckSignalingThread() { EXPECT_TRUE(signaling_thread_->IsCurrent()); }
CheckWorkerThread()291   void CheckWorkerThread() { EXPECT_TRUE(worker_thread_->IsCurrent()); }
292 
293  protected:
294   std::unique_ptr<rtc::Thread> signaling_thread_;
295   std::unique_ptr<rtc::Thread> worker_thread_;
296   Foo* foo_;  // Owned by foo_proxy_, not this class.
297   std::unique_ptr<FooInterface> foo_proxy_;
298 };
299 
300 // Just tests that a method can be invoked using an "owned proxy" (as opposed
301 // to normal ref-counted version).
TEST_F(OwnedProxyTest,BasicTest)302 TEST_F(OwnedProxyTest, BasicTest) {
303   EXPECT_CALL(*foo_, Bar())
304       .Times(Exactly(1))
305       .WillOnce(InvokeWithoutArgs(this, &OwnedProxyTest::CheckSignalingThread));
306   foo_proxy_->Bar();
307 }
308 
309 }  // namespace webrtc
310