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_WORKER_THREAD_DESTRUCTOR()
68 PROXY_METHOD0(void, VoidMethod0)
69 PROXY_METHOD0(std::string, Method0)
70 PROXY_CONSTMETHOD0(std::string, ConstMethod0)
71 PROXY_WORKER_METHOD1(std::string, Method1, std::string)
72 PROXY_CONSTMETHOD1(std::string, ConstMethod1, std::string)
73 PROXY_WORKER_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_SIGNALING_PROXY_MAP(Fake)
80 PROXY_SIGNALING_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_SIGNALING_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