Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(765)

Side by Side Diff: webrtc/base/sigslot_unittest.cc

Issue 2877023002: Move webrtc/{base => rtc_base} (Closed)
Patch Set: update presubmit.py and DEPS include rules Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/base/sigslot.cc ('k') | webrtc/base/sigslottester.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2012 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 "webrtc/base/sigslot.h"
12
13 #include "webrtc/base/gunit.h"
14
15 // This function, when passed a has_slots or signalx, will break the build if
16 // its threading requirement is not single threaded
17 static bool TemplateIsST(const sigslot::single_threaded* p) {
18 return true;
19 }
20 // This function, when passed a has_slots or signalx, will break the build if
21 // its threading requirement is not multi threaded
22 static bool TemplateIsMT(const sigslot::multi_threaded_local* p) {
23 return true;
24 }
25
26 class SigslotDefault : public testing::Test, public sigslot::has_slots<> {
27 protected:
28 sigslot::signal0<> signal_;
29 };
30
31 template<class slot_policy = sigslot::single_threaded,
32 class signal_policy = sigslot::single_threaded>
33 class SigslotReceiver : public sigslot::has_slots<slot_policy> {
34 public:
35 SigslotReceiver() : signal_(nullptr), signal_count_(0) {}
36 ~SigslotReceiver() {
37 }
38
39 // Provide copy constructor so that tests can exercise the has_slots copy
40 // constructor.
41 SigslotReceiver(const SigslotReceiver&) = default;
42
43 void Connect(sigslot::signal0<signal_policy>* signal) {
44 if (!signal) return;
45 Disconnect();
46 signal_ = signal;
47 signal->connect(this,
48 &SigslotReceiver<slot_policy, signal_policy>::OnSignal);
49 }
50 void Disconnect() {
51 if (!signal_) return;
52 signal_->disconnect(this);
53 signal_ = nullptr;
54 }
55 void OnSignal() {
56 ++signal_count_;
57 }
58 int signal_count() { return signal_count_; }
59
60 private:
61 sigslot::signal0<signal_policy>* signal_;
62 int signal_count_;
63 };
64
65 template<class slot_policy = sigslot::single_threaded,
66 class mt_signal_policy = sigslot::multi_threaded_local>
67 class SigslotSlotTest : public testing::Test {
68 protected:
69 SigslotSlotTest() {
70 mt_signal_policy mt_policy;
71 TemplateIsMT(&mt_policy);
72 }
73
74 virtual void SetUp() {
75 Connect();
76 }
77 virtual void TearDown() {
78 Disconnect();
79 }
80
81 void Disconnect() {
82 st_receiver_.Disconnect();
83 mt_receiver_.Disconnect();
84 }
85
86 void Connect() {
87 st_receiver_.Connect(&SignalSTLoopback);
88 mt_receiver_.Connect(&SignalMTLoopback);
89 }
90
91 int st_loop_back_count() { return st_receiver_.signal_count(); }
92 int mt_loop_back_count() { return mt_receiver_.signal_count(); }
93
94 sigslot::signal0<> SignalSTLoopback;
95 SigslotReceiver<slot_policy, sigslot::single_threaded> st_receiver_;
96 sigslot::signal0<mt_signal_policy> SignalMTLoopback;
97 SigslotReceiver<slot_policy, mt_signal_policy> mt_receiver_;
98 };
99
100 typedef SigslotSlotTest<> SigslotSTSlotTest;
101 typedef SigslotSlotTest<sigslot::multi_threaded_local,
102 sigslot::multi_threaded_local> SigslotMTSlotTest;
103
104 class multi_threaded_local_fake : public sigslot::multi_threaded_local {
105 public:
106 multi_threaded_local_fake() : lock_count_(0), unlock_count_(0) {
107 }
108
109 void lock() { ++lock_count_; }
110 void unlock() { ++unlock_count_; }
111
112 int lock_count() { return lock_count_; }
113
114 bool InCriticalSection() { return lock_count_ != unlock_count_; }
115
116 protected:
117 int lock_count_;
118 int unlock_count_;
119 };
120
121 typedef SigslotSlotTest<multi_threaded_local_fake,
122 multi_threaded_local_fake> SigslotMTLockBase;
123
124 class SigslotMTLockTest : public SigslotMTLockBase {
125 protected:
126 SigslotMTLockTest() {}
127
128 virtual void SetUp() {
129 EXPECT_EQ(0, SlotLockCount());
130 SigslotMTLockBase::SetUp();
131 // Connects to two signals (ST and MT). However,
132 // SlotLockCount() only gets the count for the
133 // MT signal (there are two separate SigslotReceiver which
134 // keep track of their own count).
135 EXPECT_EQ(1, SlotLockCount());
136 }
137 virtual void TearDown() {
138 const int previous_lock_count = SlotLockCount();
139 SigslotMTLockBase::TearDown();
140 // Disconnects from two signals. Note analogous to SetUp().
141 EXPECT_EQ(previous_lock_count + 1, SlotLockCount());
142 }
143
144 int SlotLockCount() { return mt_receiver_.lock_count(); }
145 void Signal() { SignalMTLoopback(); }
146 int SignalLockCount() { return SignalMTLoopback.lock_count(); }
147 int signal_count() { return mt_loop_back_count(); }
148 bool InCriticalSection() { return SignalMTLoopback.InCriticalSection(); }
149 };
150
151 // This test will always succeed. However, if the default template instantiation
152 // changes from single threaded to multi threaded it will break the build here.
153 TEST_F(SigslotDefault, DefaultIsST) {
154 EXPECT_TRUE(TemplateIsST(this));
155 EXPECT_TRUE(TemplateIsST(&signal_));
156 }
157
158 // ST slot, ST signal
159 TEST_F(SigslotSTSlotTest, STLoopbackTest) {
160 SignalSTLoopback();
161 EXPECT_EQ(1, st_loop_back_count());
162 EXPECT_EQ(0, mt_loop_back_count());
163 }
164
165 // ST slot, MT signal
166 TEST_F(SigslotSTSlotTest, MTLoopbackTest) {
167 SignalMTLoopback();
168 EXPECT_EQ(1, mt_loop_back_count());
169 EXPECT_EQ(0, st_loop_back_count());
170 }
171
172 // ST slot, both ST and MT (separate) signal
173 TEST_F(SigslotSTSlotTest, AllLoopbackTest) {
174 SignalSTLoopback();
175 SignalMTLoopback();
176 EXPECT_EQ(1, mt_loop_back_count());
177 EXPECT_EQ(1, st_loop_back_count());
178 }
179
180 TEST_F(SigslotSTSlotTest, Reconnect) {
181 SignalSTLoopback();
182 SignalMTLoopback();
183 EXPECT_EQ(1, mt_loop_back_count());
184 EXPECT_EQ(1, st_loop_back_count());
185 Disconnect();
186 SignalSTLoopback();
187 SignalMTLoopback();
188 EXPECT_EQ(1, mt_loop_back_count());
189 EXPECT_EQ(1, st_loop_back_count());
190 Connect();
191 SignalSTLoopback();
192 SignalMTLoopback();
193 EXPECT_EQ(2, mt_loop_back_count());
194 EXPECT_EQ(2, st_loop_back_count());
195 }
196
197 // MT slot, ST signal
198 TEST_F(SigslotMTSlotTest, STLoopbackTest) {
199 SignalSTLoopback();
200 EXPECT_EQ(1, st_loop_back_count());
201 EXPECT_EQ(0, mt_loop_back_count());
202 }
203
204 // MT slot, MT signal
205 TEST_F(SigslotMTSlotTest, MTLoopbackTest) {
206 SignalMTLoopback();
207 EXPECT_EQ(1, mt_loop_back_count());
208 EXPECT_EQ(0, st_loop_back_count());
209 }
210
211 // MT slot, both ST and MT (separate) signal
212 TEST_F(SigslotMTSlotTest, AllLoopbackTest) {
213 SignalMTLoopback();
214 SignalSTLoopback();
215 EXPECT_EQ(1, st_loop_back_count());
216 EXPECT_EQ(1, mt_loop_back_count());
217 }
218
219 // Test that locks are acquired and released correctly.
220 TEST_F(SigslotMTLockTest, LockSanity) {
221 const int lock_count = SignalLockCount();
222 Signal();
223 EXPECT_FALSE(InCriticalSection());
224 EXPECT_EQ(lock_count + 1, SignalLockCount());
225 EXPECT_EQ(1, signal_count());
226 }
227
228 // Destroy signal and slot in different orders.
229 TEST(SigslotDestructionOrder, SignalFirst) {
230 sigslot::signal0<>* signal = new sigslot::signal0<>;
231 SigslotReceiver<>* receiver = new SigslotReceiver<>();
232 receiver->Connect(signal);
233 (*signal)();
234 EXPECT_EQ(1, receiver->signal_count());
235 delete signal;
236 delete receiver;
237 }
238
239 TEST(SigslotDestructionOrder, SlotFirst) {
240 sigslot::signal0<>* signal = new sigslot::signal0<>;
241 SigslotReceiver<>* receiver = new SigslotReceiver<>();
242 receiver->Connect(signal);
243 (*signal)();
244 EXPECT_EQ(1, receiver->signal_count());
245
246 delete receiver;
247 (*signal)();
248 delete signal;
249 }
250
251 // Test that if a signal is copied, its slot connections are copied as well.
252 TEST(SigslotTest, CopyConnectedSignal) {
253 sigslot::signal<> signal;
254 SigslotReceiver<> receiver;
255 receiver.Connect(&signal);
256
257 // Fire the copied signal, expecting the receiver to be notified.
258 sigslot::signal<> copied_signal(signal);
259 copied_signal();
260 EXPECT_EQ(1, receiver.signal_count());
261 }
262
263 // Test that if a slot is copied, its signal connections are copied as well.
264 TEST(SigslotTest, CopyConnectedSlot) {
265 sigslot::signal<> signal;
266 SigslotReceiver<> receiver;
267 receiver.Connect(&signal);
268
269 // Fire the signal after copying the receiver, expecting the copied receiver
270 // to be notified.
271 SigslotReceiver<> copied_receiver(receiver);
272 signal();
273 EXPECT_EQ(1, copied_receiver.signal_count());
274 }
275
276 // Just used for the test below.
277 class Disconnector : public sigslot::has_slots<> {
278 public:
279 Disconnector(SigslotReceiver<>* receiver1, SigslotReceiver<>* receiver2)
280 : receiver1_(receiver1), receiver2_(receiver2) {}
281
282 void Connect(sigslot::signal<>* signal) {
283 signal_ = signal;
284 signal->connect(this, &Disconnector::Disconnect);
285 }
286
287 private:
288 void Disconnect() {
289 receiver1_->Disconnect();
290 receiver2_->Disconnect();
291 signal_->disconnect(this);
292 }
293
294 sigslot::signal<>* signal_;
295 SigslotReceiver<>* receiver1_;
296 SigslotReceiver<>* receiver2_;
297 };
298
299 // Test that things work as expected if a signal is disconnected from a slot
300 // while it's firing.
301 TEST(SigslotTest, DisconnectFromSignalWhileFiring) {
302 sigslot::signal<> signal;
303 SigslotReceiver<> receiver1;
304 SigslotReceiver<> receiver2;
305 SigslotReceiver<> receiver3;
306 Disconnector disconnector(&receiver1, &receiver2);
307
308 // From this ordering, receiver1 should receive the signal, then the
309 // disconnector will be invoked, causing receiver2 to be disconnected before
310 // it receives the signal. And receiver3 should also receive the signal,
311 // since it was never disconnected.
312 receiver1.Connect(&signal);
313 disconnector.Connect(&signal);
314 receiver2.Connect(&signal);
315 receiver3.Connect(&signal);
316 signal();
317
318 EXPECT_EQ(1, receiver1.signal_count());
319 EXPECT_EQ(0, receiver2.signal_count());
320 EXPECT_EQ(1, receiver3.signal_count());
321 }
322
323 // Uses disconnect_all instead of disconnect.
324 class Disconnector2 : public sigslot::has_slots<> {
325 public:
326 void Connect(sigslot::signal<>* signal) {
327 signal_ = signal;
328 signal->connect(this, &Disconnector2::Disconnect);
329 }
330
331 private:
332 void Disconnect() {
333 signal_->disconnect_all();
334 }
335
336 sigslot::signal<>* signal_;
337 };
338
339 // Test that things work as expected if a signal is disconnected from a slot
340 // while it's firing using disconnect_all.
341 TEST(SigslotTest, CallDisconnectAllWhileSignalFiring) {
342 sigslot::signal<> signal;
343 SigslotReceiver<> receiver1;
344 SigslotReceiver<> receiver2;
345 Disconnector2 disconnector;
346
347 // From this ordering, receiver1 should receive the signal, then the
348 // disconnector will be invoked, causing receiver2 to be disconnected before
349 // it receives the signal.
350 receiver1.Connect(&signal);
351 disconnector.Connect(&signal);
352 receiver2.Connect(&signal);
353 signal();
354
355 EXPECT_EQ(1, receiver1.signal_count());
356 EXPECT_EQ(0, receiver2.signal_count());
357 }
OLDNEW
« no previous file with comments | « webrtc/base/sigslot.cc ('k') | webrtc/base/sigslottester.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698