blob: 7ed43267249491bbd1b1a516eb07a83fa79b75c7 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2004 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/asyncinvoker.h"
12#include "webrtc/base/asyncudpsocket.h"
13#include "webrtc/base/event.h"
14#include "webrtc/base/gunit.h"
15#include "webrtc/base/physicalsocketserver.h"
16#include "webrtc/base/socketaddress.h"
17#include "webrtc/base/thread.h"
18
19#if defined(WEBRTC_WIN)
20#include <comdef.h> // NOLINT
21#endif
22
23using namespace rtc;
24
25// Generates a sequence of numbers (collaboratively).
26class TestGenerator {
27 public:
28 TestGenerator() : last(0), count(0) {}
29
30 int Next(int prev) {
31 int result = prev + last;
32 last = result;
33 count += 1;
34 return result;
35 }
36
37 int last;
38 int count;
39};
40
41struct TestMessage : public MessageData {
42 explicit TestMessage(int v) : value(v) {}
43 virtual ~TestMessage() {}
44
45 int value;
46};
47
48// Receives on a socket and sends by posting messages.
49class SocketClient : public TestGenerator, public sigslot::has_slots<> {
50 public:
51 SocketClient(AsyncSocket* socket, const SocketAddress& addr,
52 Thread* post_thread, MessageHandler* phandler)
53 : socket_(AsyncUDPSocket::Create(socket, addr)),
54 post_thread_(post_thread),
55 post_handler_(phandler) {
56 socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
57 }
58
59 ~SocketClient() {
60 delete socket_;
61 }
62
63 SocketAddress address() const { return socket_->GetLocalAddress(); }
64
65 void OnPacket(AsyncPacketSocket* socket, const char* buf, size_t size,
66 const SocketAddress& remote_addr,
67 const PacketTime& packet_time) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020068 EXPECT_EQ(size, sizeof(uint32_t));
69 uint32_t prev = reinterpret_cast<const uint32_t*>(buf)[0];
70 uint32_t result = Next(prev);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000071
72 post_thread_->PostDelayed(200, post_handler_, 0, new TestMessage(result));
73 }
74
75 private:
76 AsyncUDPSocket* socket_;
77 Thread* post_thread_;
78 MessageHandler* post_handler_;
79};
80
81// Receives messages and sends on a socket.
82class MessageClient : public MessageHandler, public TestGenerator {
83 public:
84 MessageClient(Thread* pth, Socket* socket)
85 : socket_(socket) {
86 }
87
88 virtual ~MessageClient() {
89 delete socket_;
90 }
91
92 virtual void OnMessage(Message *pmsg) {
93 TestMessage* msg = static_cast<TestMessage*>(pmsg->pdata);
94 int result = Next(msg->value);
95 EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
96 delete msg;
97 }
98
99 private:
100 Socket* socket_;
101};
102
103class CustomThread : public rtc::Thread {
104 public:
105 CustomThread() {}
106 virtual ~CustomThread() { Stop(); }
107 bool Start() { return false; }
jiayl@webrtc.orgba737cb2014-09-18 16:45:21 +0000108
109 bool WrapCurrent() {
110 return Thread::WrapCurrent();
111 }
112 void UnwrapCurrent() {
113 Thread::UnwrapCurrent();
114 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000115};
116
117
118// A thread that does nothing when it runs and signals an event
119// when it is destroyed.
120class SignalWhenDestroyedThread : public Thread {
121 public:
122 SignalWhenDestroyedThread(Event* event)
123 : event_(event) {
124 }
125
126 virtual ~SignalWhenDestroyedThread() {
127 Stop();
128 event_->Set();
129 }
130
131 virtual void Run() {
132 // Do nothing.
133 }
134
135 private:
136 Event* event_;
137};
138
nissed9b75be2015-11-16 00:54:07 -0800139// A bool wrapped in a mutex, to avoid data races. Using a volatile
140// bool should be sufficient for correct code ("eventual consistency"
141// between caches is sufficient), but we can't tell the compiler about
142// that, and then tsan complains about a data race.
143
144// See also discussion at
145// http://stackoverflow.com/questions/7223164/is-mutex-needed-to-synchronize-a-simple-flag-between-pthreads
146
147// Using std::atomic<bool> or std::atomic_flag in C++11 is probably
148// the right thing to do, but those features are not yet allowed. Or
149// rtc::AtomicInt, if/when that is added. Since the use isn't
150// performance critical, use a plain critical section for the time
151// being.
152
153class AtomicBool {
154 public:
155 explicit AtomicBool(bool value = false) : flag_(value) {}
156 AtomicBool& operator=(bool value) {
157 CritScope scoped_lock(&cs_);
158 flag_ = value;
159 return *this;
160 }
161 bool get() const {
162 CritScope scoped_lock(&cs_);
163 return flag_;
164 }
165
166 private:
167 mutable CriticalSection cs_;
168 bool flag_;
169};
170
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000171// Function objects to test Thread::Invoke.
172struct FunctorA {
173 int operator()() { return 42; }
174};
175class FunctorB {
176 public:
nissed9b75be2015-11-16 00:54:07 -0800177 explicit FunctorB(AtomicBool* flag) : flag_(flag) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000178 void operator()() { if (flag_) *flag_ = true; }
179 private:
nissed9b75be2015-11-16 00:54:07 -0800180 AtomicBool* flag_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000181};
182struct FunctorC {
183 int operator()() {
184 Thread::Current()->ProcessMessages(50);
185 return 24;
186 }
187};
188
189// See: https://code.google.com/p/webrtc/issues/detail?id=2409
190TEST(ThreadTest, DISABLED_Main) {
191 const SocketAddress addr("127.0.0.1", 0);
192
193 // Create the messaging client on its own thread.
194 Thread th1;
195 Socket* socket = th1.socketserver()->CreateAsyncSocket(addr.family(),
196 SOCK_DGRAM);
197 MessageClient msg_client(&th1, socket);
198
199 // Create the socket client on its own thread.
200 Thread th2;
201 AsyncSocket* asocket =
202 th2.socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
203 SocketClient sock_client(asocket, addr, &th1, &msg_client);
204
205 socket->Connect(sock_client.address());
206
207 th1.Start();
208 th2.Start();
209
210 // Get the messages started.
211 th1.PostDelayed(100, &msg_client, 0, new TestMessage(1));
212
213 // Give the clients a little while to run.
214 // Messages will be processed at 100, 300, 500, 700, 900.
215 Thread* th_main = Thread::Current();
216 th_main->ProcessMessages(1000);
217
218 // Stop the sending client. Give the receiver a bit longer to run, in case
219 // it is running on a machine that is under load (e.g. the build machine).
220 th1.Stop();
221 th_main->ProcessMessages(200);
222 th2.Stop();
223
224 // Make sure the results were correct
225 EXPECT_EQ(5, msg_client.count);
226 EXPECT_EQ(34, msg_client.last);
227 EXPECT_EQ(5, sock_client.count);
228 EXPECT_EQ(55, sock_client.last);
229}
230
231// Test that setting thread names doesn't cause a malfunction.
232// There's no easy way to verify the name was set properly at this time.
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000233TEST(ThreadTest, Names) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000234 // Default name
235 Thread *thread;
236 thread = new Thread();
237 EXPECT_TRUE(thread->Start());
238 thread->Stop();
239 delete thread;
240 thread = new Thread();
241 // Name with no object parameter
242 EXPECT_TRUE(thread->SetName("No object", NULL));
243 EXPECT_TRUE(thread->Start());
244 thread->Stop();
245 delete thread;
246 // Really long name
247 thread = new Thread();
248 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
249 EXPECT_TRUE(thread->Start());
250 thread->Stop();
251 delete thread;
252}
253
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000254TEST(ThreadTest, Wrap) {
255 Thread* current_thread = Thread::Current();
256 current_thread->UnwrapCurrent();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000257 CustomThread* cthread = new CustomThread();
258 EXPECT_TRUE(cthread->WrapCurrent());
fischman@webrtc.orge5063b12014-05-23 17:28:50 +0000259 EXPECT_TRUE(cthread->RunningForTest());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000260 EXPECT_FALSE(cthread->IsOwned());
261 cthread->UnwrapCurrent();
fischman@webrtc.orge5063b12014-05-23 17:28:50 +0000262 EXPECT_FALSE(cthread->RunningForTest());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000263 delete cthread;
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000264 current_thread->WrapCurrent();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000265}
266
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000267TEST(ThreadTest, Invoke) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000268 // Create and start the thread.
269 Thread thread;
270 thread.Start();
271 // Try calling functors.
272 EXPECT_EQ(42, thread.Invoke<int>(FunctorA()));
nissed9b75be2015-11-16 00:54:07 -0800273 AtomicBool called;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000274 FunctorB f2(&called);
275 thread.Invoke<void>(f2);
nissed9b75be2015-11-16 00:54:07 -0800276 EXPECT_TRUE(called.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000277 // Try calling bare functions.
278 struct LocalFuncs {
279 static int Func1() { return 999; }
280 static void Func2() {}
281 };
282 EXPECT_EQ(999, thread.Invoke<int>(&LocalFuncs::Func1));
283 thread.Invoke<void>(&LocalFuncs::Func2);
284}
285
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000286// Verifies that two threads calling Invoke on each other at the same time does
287// not deadlock.
288TEST(ThreadTest, TwoThreadsInvokeNoDeadlock) {
289 AutoThread thread;
290 Thread* current_thread = Thread::Current();
291 ASSERT_TRUE(current_thread != NULL);
292
293 Thread other_thread;
294 other_thread.Start();
295
296 struct LocalFuncs {
297 static void Set(bool* out) { *out = true; }
298 static void InvokeSet(Thread* thread, bool* out) {
299 thread->Invoke<void>(Bind(&Set, out));
300 }
301 };
302
303 bool called = false;
304 other_thread.Invoke<void>(
305 Bind(&LocalFuncs::InvokeSet, current_thread, &called));
306
307 EXPECT_TRUE(called);
308}
309
310// Verifies that if thread A invokes a call on thread B and thread C is trying
311// to invoke A at the same time, thread A does not handle C's invoke while
312// invoking B.
313TEST(ThreadTest, ThreeThreadsInvoke) {
314 AutoThread thread;
315 Thread* thread_a = Thread::Current();
316 Thread thread_b, thread_c;
317 thread_b.Start();
318 thread_c.Start();
319
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000320 class LockedBool {
321 public:
322 explicit LockedBool(bool value) : value_(value) {}
323
324 void Set(bool value) {
325 CritScope lock(&crit_);
326 value_ = value;
327 }
328
329 bool Get() {
330 CritScope lock(&crit_);
331 return value_;
332 }
333
334 private:
335 CriticalSection crit_;
336 bool value_ GUARDED_BY(crit_);
337 };
338
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000339 struct LocalFuncs {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000340 static void Set(LockedBool* out) { out->Set(true); }
341 static void InvokeSet(Thread* thread, LockedBool* out) {
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000342 thread->Invoke<void>(Bind(&Set, out));
343 }
344
345 // Set |out| true and call InvokeSet on |thread|.
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000346 static void SetAndInvokeSet(LockedBool* out,
347 Thread* thread,
348 LockedBool* out_inner) {
349 out->Set(true);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000350 InvokeSet(thread, out_inner);
351 }
352
353 // Asynchronously invoke SetAndInvokeSet on |thread1| and wait until
354 // |thread1| starts the call.
355 static void AsyncInvokeSetAndWait(
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000356 Thread* thread1, Thread* thread2, LockedBool* out) {
357 CriticalSection crit;
358 LockedBool async_invoked(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000359
360 AsyncInvoker invoker;
361 invoker.AsyncInvoke<void>(
362 thread1, Bind(&SetAndInvokeSet, &async_invoked, thread2, out));
363
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000364 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000365 }
366 };
367
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000368 LockedBool thread_a_called(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000369
370 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
371 // Thread B returns when C receives the call and C should be blocked until A
372 // starts to process messages.
373 thread_b.Invoke<void>(Bind(&LocalFuncs::AsyncInvokeSetAndWait,
374 &thread_c, thread_a, &thread_a_called));
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000375 EXPECT_FALSE(thread_a_called.Get());
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000376
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000377 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000378}
379
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000380class AsyncInvokeTest : public testing::Test {
381 public:
382 void IntCallback(int value) {
383 EXPECT_EQ(expected_thread_, Thread::Current());
384 int_value_ = value;
385 }
386 void AsyncInvokeIntCallback(AsyncInvoker* invoker, Thread* thread) {
387 expected_thread_ = thread;
388 invoker->AsyncInvoke(thread, FunctorC(),
389 &AsyncInvokeTest::IntCallback,
390 static_cast<AsyncInvokeTest*>(this));
391 invoke_started_.Set();
392 }
393 void SetExpectedThreadForIntCallback(Thread* thread) {
394 expected_thread_ = thread;
395 }
396
397 protected:
398 enum { kWaitTimeout = 1000 };
399 AsyncInvokeTest()
400 : int_value_(0),
401 invoke_started_(true, false),
402 expected_thread_(NULL) {}
403
404 int int_value_;
405 Event invoke_started_;
406 Thread* expected_thread_;
407};
408
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000409TEST_F(AsyncInvokeTest, FireAndForget) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000410 AsyncInvoker invoker;
411 // Create and start the thread.
412 Thread thread;
413 thread.Start();
414 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800415 AtomicBool called;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000416 invoker.AsyncInvoke<void>(&thread, FunctorB(&called));
nissed9b75be2015-11-16 00:54:07 -0800417 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000418}
419
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000420TEST_F(AsyncInvokeTest, WithCallback) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000421 AsyncInvoker invoker;
422 // Create and start the thread.
423 Thread thread;
424 thread.Start();
425 // Try calling functor.
426 SetExpectedThreadForIntCallback(Thread::Current());
427 invoker.AsyncInvoke(&thread, FunctorA(),
428 &AsyncInvokeTest::IntCallback,
429 static_cast<AsyncInvokeTest*>(this));
430 EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
431}
432
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000433TEST_F(AsyncInvokeTest, CancelInvoker) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000434 // Create and start the thread.
435 Thread thread;
436 thread.Start();
437 // Try destroying invoker during call.
438 {
439 AsyncInvoker invoker;
440 invoker.AsyncInvoke(&thread, FunctorC(),
441 &AsyncInvokeTest::IntCallback,
442 static_cast<AsyncInvokeTest*>(this));
443 }
444 // With invoker gone, callback should be cancelled.
445 Thread::Current()->ProcessMessages(kWaitTimeout);
446 EXPECT_EQ(0, int_value_);
447}
448
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000449TEST_F(AsyncInvokeTest, CancelCallingThread) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000450 AsyncInvoker invoker;
451 { // Create and start the thread.
452 Thread thread;
453 thread.Start();
454 // Try calling functor.
455 thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
456 static_cast<AsyncInvokeTest*>(this),
457 &invoker, Thread::Current()));
458 // Wait for the call to begin.
459 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
460 }
461 // Calling thread is gone. Return message shouldn't happen.
462 Thread::Current()->ProcessMessages(kWaitTimeout);
463 EXPECT_EQ(0, int_value_);
464}
465
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000466TEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000467 Thread thread;
468 thread.Start();
469 {
470 AsyncInvoker invoker;
471 // Try calling functor.
472 thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
473 static_cast<AsyncInvokeTest*>(this),
474 &invoker, Thread::Current()));
475 // Wait for the call to begin.
476 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
477 }
478 // Invoker is destroyed. Function should not execute.
479 Thread::Current()->ProcessMessages(kWaitTimeout);
480 EXPECT_EQ(0, int_value_);
481}
482
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000483TEST_F(AsyncInvokeTest, Flush) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000484 AsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800485 AtomicBool flag1;
486 AtomicBool flag2;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000487 // Queue two async calls to the current thread.
488 invoker.AsyncInvoke<void>(Thread::Current(),
489 FunctorB(&flag1));
490 invoker.AsyncInvoke<void>(Thread::Current(),
491 FunctorB(&flag2));
492 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800493 EXPECT_FALSE(flag1.get());
494 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000495 // Force them to run now.
496 invoker.Flush(Thread::Current());
nissed9b75be2015-11-16 00:54:07 -0800497 EXPECT_TRUE(flag1.get());
498 EXPECT_TRUE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000499}
500
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000501TEST_F(AsyncInvokeTest, FlushWithIds) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000502 AsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800503 AtomicBool flag1;
504 AtomicBool flag2;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000505 // Queue two async calls to the current thread, one with a message id.
506 invoker.AsyncInvoke<void>(Thread::Current(),
507 FunctorB(&flag1),
508 5);
509 invoker.AsyncInvoke<void>(Thread::Current(),
510 FunctorB(&flag2));
511 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800512 EXPECT_FALSE(flag1.get());
513 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000514 // Execute pending calls with id == 5.
515 invoker.Flush(Thread::Current(), 5);
nissed9b75be2015-11-16 00:54:07 -0800516 EXPECT_TRUE(flag1.get());
517 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000518 flag1 = false;
519 // Execute all pending calls. The id == 5 call should not execute again.
520 invoker.Flush(Thread::Current());
nissed9b75be2015-11-16 00:54:07 -0800521 EXPECT_FALSE(flag1.get());
522 EXPECT_TRUE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000523}
524
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200525class GuardedAsyncInvokeTest : public testing::Test {
526 public:
527 void IntCallback(int value) {
528 EXPECT_EQ(expected_thread_, Thread::Current());
529 int_value_ = value;
530 }
531 void AsyncInvokeIntCallback(GuardedAsyncInvoker* invoker, Thread* thread) {
532 expected_thread_ = thread;
533 invoker->AsyncInvoke(FunctorC(), &GuardedAsyncInvokeTest::IntCallback,
534 static_cast<GuardedAsyncInvokeTest*>(this));
535 invoke_started_.Set();
536 }
537 void SetExpectedThreadForIntCallback(Thread* thread) {
538 expected_thread_ = thread;
539 }
540
541 protected:
542 const static int kWaitTimeout = 1000;
543 GuardedAsyncInvokeTest()
544 : int_value_(0),
545 invoke_started_(true, false),
546 expected_thread_(nullptr) {}
547
548 int int_value_;
549 Event invoke_started_;
550 Thread* expected_thread_;
551};
552
553// Functor for creating an invoker.
554struct CreateInvoker {
555 CreateInvoker(scoped_ptr<GuardedAsyncInvoker>* invoker) : invoker_(invoker) {}
556 void operator()() { invoker_->reset(new GuardedAsyncInvoker()); }
557 scoped_ptr<GuardedAsyncInvoker>* invoker_;
558};
559
560// Test that we can call AsyncInvoke<void>() after the thread died.
561TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) {
562 // Create and start the thread.
563 scoped_ptr<Thread> thread(new Thread());
564 thread->Start();
565 scoped_ptr<GuardedAsyncInvoker> invoker;
566 // Create the invoker on |thread|.
567 thread->Invoke<void>(CreateInvoker(&invoker));
568 // Kill |thread|.
569 thread = nullptr;
570 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800571 AtomicBool called;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200572 EXPECT_FALSE(invoker->AsyncInvoke<void>(FunctorB(&called)));
573 // With thread gone, nothing should happen.
nissed9b75be2015-11-16 00:54:07 -0800574 WAIT(called.get(), kWaitTimeout);
575 EXPECT_FALSE(called.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200576}
577
578// Test that we can call AsyncInvoke with callback after the thread died.
579TEST_F(GuardedAsyncInvokeTest, KillThreadWithCallback) {
580 // Create and start the thread.
581 scoped_ptr<Thread> thread(new Thread());
582 thread->Start();
583 scoped_ptr<GuardedAsyncInvoker> invoker;
584 // Create the invoker on |thread|.
585 thread->Invoke<void>(CreateInvoker(&invoker));
586 // Kill |thread|.
587 thread = nullptr;
588 // Try calling functor.
589 EXPECT_FALSE(
590 invoker->AsyncInvoke(FunctorC(), &GuardedAsyncInvokeTest::IntCallback,
591 static_cast<GuardedAsyncInvokeTest*>(this)));
592 // With thread gone, callback should be cancelled.
593 Thread::Current()->ProcessMessages(kWaitTimeout);
594 EXPECT_EQ(0, int_value_);
595}
596
597// The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker
598// when Thread is still alive.
599TEST_F(GuardedAsyncInvokeTest, FireAndForget) {
600 GuardedAsyncInvoker invoker;
601 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800602 AtomicBool called;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200603 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&called)));
nissed9b75be2015-11-16 00:54:07 -0800604 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200605}
606
607TEST_F(GuardedAsyncInvokeTest, WithCallback) {
608 GuardedAsyncInvoker invoker;
609 // Try calling functor.
610 SetExpectedThreadForIntCallback(Thread::Current());
611 EXPECT_TRUE(invoker.AsyncInvoke(FunctorA(),
612 &GuardedAsyncInvokeTest::IntCallback,
613 static_cast<GuardedAsyncInvokeTest*>(this)));
614 EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
615}
616
617TEST_F(GuardedAsyncInvokeTest, CancelInvoker) {
618 // Try destroying invoker during call.
619 {
620 GuardedAsyncInvoker invoker;
621 EXPECT_TRUE(
622 invoker.AsyncInvoke(FunctorC(), &GuardedAsyncInvokeTest::IntCallback,
623 static_cast<GuardedAsyncInvokeTest*>(this)));
624 }
625 // With invoker gone, callback should be cancelled.
626 Thread::Current()->ProcessMessages(kWaitTimeout);
627 EXPECT_EQ(0, int_value_);
628}
629
630TEST_F(GuardedAsyncInvokeTest, CancelCallingThread) {
631 GuardedAsyncInvoker invoker;
632 // Try destroying calling thread during call.
633 {
634 Thread thread;
635 thread.Start();
636 // Try calling functor.
637 thread.Invoke<void>(Bind(&GuardedAsyncInvokeTest::AsyncInvokeIntCallback,
638 static_cast<GuardedAsyncInvokeTest*>(this),
639 &invoker, Thread::Current()));
640 // Wait for the call to begin.
641 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
642 }
643 // Calling thread is gone. Return message shouldn't happen.
644 Thread::Current()->ProcessMessages(kWaitTimeout);
645 EXPECT_EQ(0, int_value_);
646}
647
648TEST_F(GuardedAsyncInvokeTest, KillInvokerBeforeExecute) {
649 Thread thread;
650 thread.Start();
651 {
652 GuardedAsyncInvoker invoker;
653 // Try calling functor.
654 thread.Invoke<void>(Bind(&GuardedAsyncInvokeTest::AsyncInvokeIntCallback,
655 static_cast<GuardedAsyncInvokeTest*>(this),
656 &invoker, Thread::Current()));
657 // Wait for the call to begin.
658 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
659 }
660 // Invoker is destroyed. Function should not execute.
661 Thread::Current()->ProcessMessages(kWaitTimeout);
662 EXPECT_EQ(0, int_value_);
663}
664
665TEST_F(GuardedAsyncInvokeTest, Flush) {
666 GuardedAsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800667 AtomicBool flag1;
668 AtomicBool flag2;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200669 // Queue two async calls to the current thread.
670 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1)));
671 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2)));
672 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800673 EXPECT_FALSE(flag1.get());
674 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200675 // Force them to run now.
676 EXPECT_TRUE(invoker.Flush());
nissed9b75be2015-11-16 00:54:07 -0800677 EXPECT_TRUE(flag1.get());
678 EXPECT_TRUE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200679}
680
681TEST_F(GuardedAsyncInvokeTest, FlushWithIds) {
682 GuardedAsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800683 AtomicBool flag1;
684 AtomicBool flag2;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200685 // Queue two async calls to the current thread, one with a message id.
686 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1), 5));
687 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2)));
688 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800689 EXPECT_FALSE(flag1.get());
690 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200691 // Execute pending calls with id == 5.
692 EXPECT_TRUE(invoker.Flush(5));
nissed9b75be2015-11-16 00:54:07 -0800693 EXPECT_TRUE(flag1.get());
694 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200695 flag1 = false;
696 // Execute all pending calls. The id == 5 call should not execute again.
697 EXPECT_TRUE(invoker.Flush());
nissed9b75be2015-11-16 00:54:07 -0800698 EXPECT_FALSE(flag1.get());
699 EXPECT_TRUE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200700}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000701
702#if defined(WEBRTC_WIN)
703class ComThreadTest : public testing::Test, public MessageHandler {
704 public:
705 ComThreadTest() : done_(false) {}
706 protected:
707 virtual void OnMessage(Message* message) {
708 HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
709 // S_FALSE means the thread was already inited for a multithread apartment.
710 EXPECT_EQ(S_FALSE, hr);
711 if (SUCCEEDED(hr)) {
712 CoUninitialize();
713 }
714 done_ = true;
715 }
716 bool done_;
717};
718
719TEST_F(ComThreadTest, ComInited) {
720 Thread* thread = new ComThread();
721 EXPECT_TRUE(thread->Start());
722 thread->Post(this, 0);
723 EXPECT_TRUE_WAIT(done_, 1000);
724 delete thread;
725}
726#endif