blob: 0e04fae3f8cdc8f08bed17f0f716a86e40a37098 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "rtc_base/thread.h"
12
kwibergbfefb032016-05-01 14:53:46 -070013#include <memory>
14
Danil Chapovalov912b3b82019-11-22 15:52:40 +010015#include "api/task_queue/task_queue_factory.h"
16#include "api/task_queue/task_queue_test.h"
Steve Anton10542f22019-01-11 09:11:00 -080017#include "rtc_base/async_invoker.h"
18#include "rtc_base/async_udp_socket.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/event.h"
20#include "rtc_base/gunit.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "rtc_base/null_socket_server.h"
22#include "rtc_base/physical_socket_server.h"
23#include "rtc_base/socket_address.h"
Artem Titove41c4332018-07-25 15:04:28 +020024#include "rtc_base/third_party/sigslot/sigslot.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000025
26#if defined(WEBRTC_WIN)
27#include <comdef.h> // NOLINT
28#endif
29
Mirko Bonadeie10b1632018-12-11 18:43:40 +010030namespace rtc {
31namespace {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032
33// Generates a sequence of numbers (collaboratively).
34class TestGenerator {
35 public:
36 TestGenerator() : last(0), count(0) {}
37
38 int Next(int prev) {
39 int result = prev + last;
40 last = result;
41 count += 1;
42 return result;
43 }
44
45 int last;
46 int count;
47};
48
49struct TestMessage : public MessageData {
50 explicit TestMessage(int v) : value(v) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000051
52 int value;
53};
54
55// Receives on a socket and sends by posting messages.
56class SocketClient : public TestGenerator, public sigslot::has_slots<> {
57 public:
Yves Gerey665174f2018-06-19 15:03:05 +020058 SocketClient(AsyncSocket* socket,
59 const SocketAddress& addr,
60 Thread* post_thread,
61 MessageHandler* phandler)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062 : socket_(AsyncUDPSocket::Create(socket, addr)),
63 post_thread_(post_thread),
64 post_handler_(phandler) {
65 socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
66 }
67
Steve Anton9de3aac2017-10-24 10:08:26 -070068 ~SocketClient() override { delete socket_; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000069
70 SocketAddress address() const { return socket_->GetLocalAddress(); }
71
Yves Gerey665174f2018-06-19 15:03:05 +020072 void OnPacket(AsyncPacketSocket* socket,
73 const char* buf,
74 size_t size,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000075 const SocketAddress& remote_addr,
Niels Möllere6933812018-11-05 13:01:41 +010076 const int64_t& packet_time_us) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020077 EXPECT_EQ(size, sizeof(uint32_t));
78 uint32_t prev = reinterpret_cast<const uint32_t*>(buf)[0];
79 uint32_t result = Next(prev);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000080
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070081 post_thread_->PostDelayed(RTC_FROM_HERE, 200, post_handler_, 0,
82 new TestMessage(result));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000083 }
84
85 private:
86 AsyncUDPSocket* socket_;
87 Thread* post_thread_;
88 MessageHandler* post_handler_;
89};
90
91// Receives messages and sends on a socket.
92class MessageClient : public MessageHandler, public TestGenerator {
93 public:
Yves Gerey665174f2018-06-19 15:03:05 +020094 MessageClient(Thread* pth, Socket* socket) : socket_(socket) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000095
Steve Anton9de3aac2017-10-24 10:08:26 -070096 ~MessageClient() override { delete socket_; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000097
Steve Anton9de3aac2017-10-24 10:08:26 -070098 void OnMessage(Message* pmsg) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000099 TestMessage* msg = static_cast<TestMessage*>(pmsg->pdata);
100 int result = Next(msg->value);
101 EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
102 delete msg;
103 }
104
105 private:
106 Socket* socket_;
107};
108
deadbeefaea92932017-05-23 12:55:03 -0700109class CustomThread : public rtc::Thread {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000110 public:
tommie7251592017-07-14 14:44:46 -0700111 CustomThread()
112 : Thread(std::unique_ptr<SocketServer>(new rtc::NullSocketServer())) {}
Steve Anton9de3aac2017-10-24 10:08:26 -0700113 ~CustomThread() override { Stop(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000114 bool Start() { return false; }
jiayl@webrtc.orgba737cb2014-09-18 16:45:21 +0000115
Yves Gerey665174f2018-06-19 15:03:05 +0200116 bool WrapCurrent() { return Thread::WrapCurrent(); }
117 void UnwrapCurrent() { Thread::UnwrapCurrent(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000118};
119
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000120// A thread that does nothing when it runs and signals an event
121// when it is destroyed.
122class SignalWhenDestroyedThread : public Thread {
123 public:
124 SignalWhenDestroyedThread(Event* event)
tommie7251592017-07-14 14:44:46 -0700125 : Thread(std::unique_ptr<SocketServer>(new NullSocketServer())),
126 event_(event) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000127
Steve Anton9de3aac2017-10-24 10:08:26 -0700128 ~SignalWhenDestroyedThread() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000129 Stop();
130 event_->Set();
131 }
132
Steve Anton9de3aac2017-10-24 10:08:26 -0700133 void Run() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000134 // Do nothing.
135 }
136
137 private:
138 Event* event_;
139};
140
nissed9b75be2015-11-16 00:54:07 -0800141// A bool wrapped in a mutex, to avoid data races. Using a volatile
142// bool should be sufficient for correct code ("eventual consistency"
143// between caches is sufficient), but we can't tell the compiler about
144// that, and then tsan complains about a data race.
145
146// See also discussion at
147// http://stackoverflow.com/questions/7223164/is-mutex-needed-to-synchronize-a-simple-flag-between-pthreads
148
149// Using std::atomic<bool> or std::atomic_flag in C++11 is probably
150// the right thing to do, but those features are not yet allowed. Or
deadbeefaea92932017-05-23 12:55:03 -0700151// rtc::AtomicInt, if/when that is added. Since the use isn't
nissed9b75be2015-11-16 00:54:07 -0800152// performance critical, use a plain critical section for the time
153// being.
154
155class AtomicBool {
156 public:
157 explicit AtomicBool(bool value = false) : flag_(value) {}
158 AtomicBool& operator=(bool value) {
159 CritScope scoped_lock(&cs_);
160 flag_ = value;
161 return *this;
162 }
163 bool get() const {
164 CritScope scoped_lock(&cs_);
165 return flag_;
166 }
167
168 private:
pbos5ad935c2016-01-25 03:52:44 -0800169 CriticalSection cs_;
nissed9b75be2015-11-16 00:54:07 -0800170 bool flag_;
171};
172
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000173// Function objects to test Thread::Invoke.
174struct FunctorA {
175 int operator()() { return 42; }
176};
177class FunctorB {
178 public:
nissed9b75be2015-11-16 00:54:07 -0800179 explicit FunctorB(AtomicBool* flag) : flag_(flag) {}
Yves Gerey665174f2018-06-19 15:03:05 +0200180 void operator()() {
181 if (flag_)
182 *flag_ = true;
183 }
184
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000185 private:
nissed9b75be2015-11-16 00:54:07 -0800186 AtomicBool* flag_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000187};
188struct FunctorC {
189 int operator()() {
190 Thread::Current()->ProcessMessages(50);
191 return 24;
192 }
193};
Cameron Pickettd132ce12018-03-12 16:07:37 -0700194struct FunctorD {
195 public:
196 explicit FunctorD(AtomicBool* flag) : flag_(flag) {}
197 FunctorD(FunctorD&&) = default;
198 FunctorD& operator=(FunctorD&&) = default;
Yves Gerey665174f2018-06-19 15:03:05 +0200199 void operator()() {
200 if (flag_)
201 *flag_ = true;
202 }
203
Cameron Pickettd132ce12018-03-12 16:07:37 -0700204 private:
205 AtomicBool* flag_;
206 RTC_DISALLOW_COPY_AND_ASSIGN(FunctorD);
207};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000208
209// See: https://code.google.com/p/webrtc/issues/detail?id=2409
210TEST(ThreadTest, DISABLED_Main) {
211 const SocketAddress addr("127.0.0.1", 0);
212
213 // Create the messaging client on its own thread.
tommie7251592017-07-14 14:44:46 -0700214 auto th1 = Thread::CreateWithSocketServer();
215 Socket* socket =
216 th1->socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
217 MessageClient msg_client(th1.get(), socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000218
219 // Create the socket client on its own thread.
tommie7251592017-07-14 14:44:46 -0700220 auto th2 = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000221 AsyncSocket* asocket =
tommie7251592017-07-14 14:44:46 -0700222 th2->socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
223 SocketClient sock_client(asocket, addr, th1.get(), &msg_client);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000224
225 socket->Connect(sock_client.address());
226
tommie7251592017-07-14 14:44:46 -0700227 th1->Start();
228 th2->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000229
230 // Get the messages started.
tommie7251592017-07-14 14:44:46 -0700231 th1->PostDelayed(RTC_FROM_HERE, 100, &msg_client, 0, new TestMessage(1));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000232
233 // Give the clients a little while to run.
234 // Messages will be processed at 100, 300, 500, 700, 900.
235 Thread* th_main = Thread::Current();
236 th_main->ProcessMessages(1000);
237
238 // Stop the sending client. Give the receiver a bit longer to run, in case
239 // it is running on a machine that is under load (e.g. the build machine).
tommie7251592017-07-14 14:44:46 -0700240 th1->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000241 th_main->ProcessMessages(200);
tommie7251592017-07-14 14:44:46 -0700242 th2->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000243
244 // Make sure the results were correct
245 EXPECT_EQ(5, msg_client.count);
246 EXPECT_EQ(34, msg_client.last);
247 EXPECT_EQ(5, sock_client.count);
248 EXPECT_EQ(55, sock_client.last);
249}
250
251// Test that setting thread names doesn't cause a malfunction.
252// There's no easy way to verify the name was set properly at this time.
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000253TEST(ThreadTest, Names) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000254 // Default name
tommie7251592017-07-14 14:44:46 -0700255 auto thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000256 EXPECT_TRUE(thread->Start());
257 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000258 // Name with no object parameter
tommie7251592017-07-14 14:44:46 -0700259 thread = Thread::CreateWithSocketServer();
deadbeef37f5ecf2017-02-27 14:06:41 -0800260 EXPECT_TRUE(thread->SetName("No object", nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000261 EXPECT_TRUE(thread->Start());
262 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000263 // Really long name
tommie7251592017-07-14 14:44:46 -0700264 thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000265 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
266 EXPECT_TRUE(thread->Start());
267 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000268}
269
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000270TEST(ThreadTest, Wrap) {
271 Thread* current_thread = Thread::Current();
Niels Möller5a8f8602019-06-12 11:30:59 +0200272 ThreadManager::Instance()->SetCurrentThread(nullptr);
273
274 {
275 CustomThread cthread;
276 EXPECT_TRUE(cthread.WrapCurrent());
277 EXPECT_EQ(&cthread, Thread::Current());
278 EXPECT_TRUE(cthread.RunningForTest());
279 EXPECT_FALSE(cthread.IsOwned());
280 cthread.UnwrapCurrent();
281 EXPECT_FALSE(cthread.RunningForTest());
282 }
283 ThreadManager::Instance()->SetCurrentThread(current_thread);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000284}
285
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000286TEST(ThreadTest, Invoke) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000287 // Create and start the thread.
tommie7251592017-07-14 14:44:46 -0700288 auto thread = Thread::CreateWithSocketServer();
289 thread->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000290 // Try calling functors.
tommie7251592017-07-14 14:44:46 -0700291 EXPECT_EQ(42, thread->Invoke<int>(RTC_FROM_HERE, FunctorA()));
nissed9b75be2015-11-16 00:54:07 -0800292 AtomicBool called;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000293 FunctorB f2(&called);
tommie7251592017-07-14 14:44:46 -0700294 thread->Invoke<void>(RTC_FROM_HERE, f2);
nissed9b75be2015-11-16 00:54:07 -0800295 EXPECT_TRUE(called.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000296 // Try calling bare functions.
297 struct LocalFuncs {
298 static int Func1() { return 999; }
299 static void Func2() {}
300 };
tommie7251592017-07-14 14:44:46 -0700301 EXPECT_EQ(999, thread->Invoke<int>(RTC_FROM_HERE, &LocalFuncs::Func1));
302 thread->Invoke<void>(RTC_FROM_HERE, &LocalFuncs::Func2);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000303}
304
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000305// Verifies that two threads calling Invoke on each other at the same time does
306// not deadlock.
307TEST(ThreadTest, TwoThreadsInvokeNoDeadlock) {
308 AutoThread thread;
309 Thread* current_thread = Thread::Current();
deadbeef37f5ecf2017-02-27 14:06:41 -0800310 ASSERT_TRUE(current_thread != nullptr);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000311
tommie7251592017-07-14 14:44:46 -0700312 auto other_thread = Thread::CreateWithSocketServer();
313 other_thread->Start();
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000314
315 struct LocalFuncs {
316 static void Set(bool* out) { *out = true; }
317 static void InvokeSet(Thread* thread, bool* out) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700318 thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out));
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000319 }
320 };
321
322 bool called = false;
tommie7251592017-07-14 14:44:46 -0700323 other_thread->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700324 RTC_FROM_HERE, Bind(&LocalFuncs::InvokeSet, current_thread, &called));
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000325
326 EXPECT_TRUE(called);
327}
328
329// Verifies that if thread A invokes a call on thread B and thread C is trying
330// to invoke A at the same time, thread A does not handle C's invoke while
331// invoking B.
332TEST(ThreadTest, ThreeThreadsInvoke) {
333 AutoThread thread;
334 Thread* thread_a = Thread::Current();
tommie7251592017-07-14 14:44:46 -0700335 auto thread_b = Thread::CreateWithSocketServer();
336 auto thread_c = Thread::CreateWithSocketServer();
337 thread_b->Start();
338 thread_c->Start();
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000339
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000340 class LockedBool {
341 public:
342 explicit LockedBool(bool value) : value_(value) {}
343
344 void Set(bool value) {
345 CritScope lock(&crit_);
346 value_ = value;
347 }
348
349 bool Get() {
350 CritScope lock(&crit_);
351 return value_;
352 }
353
354 private:
355 CriticalSection crit_;
danilchap3c6abd22017-09-06 05:46:29 -0700356 bool value_ RTC_GUARDED_BY(crit_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000357 };
358
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000359 struct LocalFuncs {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000360 static void Set(LockedBool* out) { out->Set(true); }
361 static void InvokeSet(Thread* thread, LockedBool* out) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700362 thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out));
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000363 }
364
365 // Set |out| true and call InvokeSet on |thread|.
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000366 static void SetAndInvokeSet(LockedBool* out,
367 Thread* thread,
368 LockedBool* out_inner) {
369 out->Set(true);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000370 InvokeSet(thread, out_inner);
371 }
372
373 // Asynchronously invoke SetAndInvokeSet on |thread1| and wait until
374 // |thread1| starts the call.
deadbeef162cb532017-02-23 17:10:07 -0800375 static void AsyncInvokeSetAndWait(AsyncInvoker* invoker,
376 Thread* thread1,
377 Thread* thread2,
378 LockedBool* out) {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000379 CriticalSection crit;
380 LockedBool async_invoked(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000381
deadbeef162cb532017-02-23 17:10:07 -0800382 invoker->AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700383 RTC_FROM_HERE, thread1,
384 Bind(&SetAndInvokeSet, &async_invoked, thread2, out));
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000385
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000386 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000387 }
388 };
389
deadbeef162cb532017-02-23 17:10:07 -0800390 AsyncInvoker invoker;
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000391 LockedBool thread_a_called(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000392
393 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
394 // Thread B returns when C receives the call and C should be blocked until A
395 // starts to process messages.
tommie7251592017-07-14 14:44:46 -0700396 thread_b->Invoke<void>(RTC_FROM_HERE,
397 Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker,
398 thread_c.get(), thread_a, &thread_a_called));
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000399 EXPECT_FALSE(thread_a_called.Get());
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000400
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000401 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000402}
403
jbauch25d1f282016-02-05 00:25:02 -0800404// Set the name on a thread when the underlying QueueDestroyed signal is
405// triggered. This causes an error if the object is already partially
406// destroyed.
407class SetNameOnSignalQueueDestroyedTester : public sigslot::has_slots<> {
408 public:
409 SetNameOnSignalQueueDestroyedTester(Thread* thread) : thread_(thread) {
410 thread->SignalQueueDestroyed.connect(
411 this, &SetNameOnSignalQueueDestroyedTester::OnQueueDestroyed);
412 }
413
414 void OnQueueDestroyed() {
415 // Makes sure that if we access the Thread while it's being destroyed, that
416 // it doesn't cause a problem because the vtable has been modified.
417 thread_->SetName("foo", nullptr);
418 }
419
420 private:
421 Thread* thread_;
422};
423
424TEST(ThreadTest, SetNameOnSignalQueueDestroyed) {
tommie7251592017-07-14 14:44:46 -0700425 auto thread1 = Thread::CreateWithSocketServer();
426 SetNameOnSignalQueueDestroyedTester tester1(thread1.get());
427 thread1.reset();
jbauch25d1f282016-02-05 00:25:02 -0800428
429 Thread* thread2 = new AutoThread();
430 SetNameOnSignalQueueDestroyedTester tester2(thread2);
431 delete thread2;
jbauch25d1f282016-02-05 00:25:02 -0800432}
433
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200434class AsyncInvokeTest : public ::testing::Test {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000435 public:
436 void IntCallback(int value) {
437 EXPECT_EQ(expected_thread_, Thread::Current());
438 int_value_ = value;
439 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000440 void SetExpectedThreadForIntCallback(Thread* thread) {
441 expected_thread_ = thread;
442 }
443
444 protected:
445 enum { kWaitTimeout = 1000 };
Yves Gerey665174f2018-06-19 15:03:05 +0200446 AsyncInvokeTest() : int_value_(0), expected_thread_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000447
448 int int_value_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000449 Thread* expected_thread_;
450};
451
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000452TEST_F(AsyncInvokeTest, FireAndForget) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000453 AsyncInvoker invoker;
454 // Create and start the thread.
tommie7251592017-07-14 14:44:46 -0700455 auto thread = Thread::CreateWithSocketServer();
456 thread->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000457 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800458 AtomicBool called;
tommie7251592017-07-14 14:44:46 -0700459 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), FunctorB(&called));
nissed9b75be2015-11-16 00:54:07 -0800460 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
tommie7251592017-07-14 14:44:46 -0700461 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000462}
463
Cameron Pickettd132ce12018-03-12 16:07:37 -0700464TEST_F(AsyncInvokeTest, NonCopyableFunctor) {
465 AsyncInvoker invoker;
466 // Create and start the thread.
467 auto thread = Thread::CreateWithSocketServer();
468 thread->Start();
469 // Try calling functor.
470 AtomicBool called;
471 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), FunctorD(&called));
472 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
473 thread->Stop();
474}
475
deadbeef162cb532017-02-23 17:10:07 -0800476TEST_F(AsyncInvokeTest, KillInvokerDuringExecute) {
477 // Use these events to get in a state where the functor is in the middle of
478 // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE"
479 // is run.
Niels Möllerc572ff32018-11-07 08:43:50 +0100480 Event functor_started;
481 Event functor_continue;
482 Event functor_finished;
deadbeef162cb532017-02-23 17:10:07 -0800483
tommie7251592017-07-14 14:44:46 -0700484 auto thread = Thread::CreateWithSocketServer();
485 thread->Start();
deadbeef162cb532017-02-23 17:10:07 -0800486 volatile bool invoker_destroyed = false;
487 {
deadbeef3af63b02017-08-08 17:59:47 -0700488 auto functor = [&functor_started, &functor_continue, &functor_finished,
489 &invoker_destroyed] {
490 functor_started.Set();
491 functor_continue.Wait(Event::kForever);
492 rtc::Thread::Current()->SleepMs(kWaitTimeout);
493 EXPECT_FALSE(invoker_destroyed);
494 functor_finished.Set();
495 };
deadbeef162cb532017-02-23 17:10:07 -0800496 AsyncInvoker invoker;
deadbeef3af63b02017-08-08 17:59:47 -0700497 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), functor);
deadbeef162cb532017-02-23 17:10:07 -0800498 functor_started.Wait(Event::kForever);
deadbeefaea92932017-05-23 12:55:03 -0700499
deadbeef3af63b02017-08-08 17:59:47 -0700500 // Destroy the invoker while the functor is still executing (doing
501 // SleepMs).
deadbeefaea92932017-05-23 12:55:03 -0700502 functor_continue.Set();
deadbeef162cb532017-02-23 17:10:07 -0800503 }
504
505 // If the destructor DIDN'T wait for the functor to finish executing, it will
506 // hit the EXPECT_FALSE(invoker_destroyed) after it finishes sleeping for a
507 // second.
508 invoker_destroyed = true;
509 functor_finished.Wait(Event::kForever);
510}
511
deadbeef3af63b02017-08-08 17:59:47 -0700512// Variant of the above test where the async-invoked task calls AsyncInvoke
513// *again*, for the thread on which the AsyncInvoker is currently being
514// destroyed. This shouldn't deadlock or crash; this second invocation should
515// just be ignored.
516TEST_F(AsyncInvokeTest, KillInvokerDuringExecuteWithReentrantInvoke) {
Niels Möllerc572ff32018-11-07 08:43:50 +0100517 Event functor_started;
deadbeef3af63b02017-08-08 17:59:47 -0700518 // Flag used to verify that the recursively invoked task never actually runs.
519 bool reentrant_functor_run = false;
520
521 Thread* main = Thread::Current();
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200522 Thread thread(std::make_unique<NullSocketServer>());
deadbeef3af63b02017-08-08 17:59:47 -0700523 thread.Start();
524 {
525 AsyncInvoker invoker;
526 auto reentrant_functor = [&reentrant_functor_run] {
527 reentrant_functor_run = true;
528 };
529 auto functor = [&functor_started, &invoker, main, reentrant_functor] {
530 functor_started.Set();
531 Thread::Current()->SleepMs(kWaitTimeout);
532 invoker.AsyncInvoke<void>(RTC_FROM_HERE, main, reentrant_functor);
533 };
534 // This queues a task on |thread| to sleep for |kWaitTimeout| then queue a
535 // task on |main|. But this second queued task should never run, since the
536 // destructor will be entered before it's even invoked.
537 invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread, functor);
538 functor_started.Wait(Event::kForever);
539 }
540 EXPECT_FALSE(reentrant_functor_run);
541}
542
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000543TEST_F(AsyncInvokeTest, Flush) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000544 AsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800545 AtomicBool flag1;
546 AtomicBool flag2;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000547 // Queue two async calls to the current thread.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700548 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1));
549 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000550 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800551 EXPECT_FALSE(flag1.get());
552 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000553 // Force them to run now.
554 invoker.Flush(Thread::Current());
nissed9b75be2015-11-16 00:54:07 -0800555 EXPECT_TRUE(flag1.get());
556 EXPECT_TRUE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000557}
558
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000559TEST_F(AsyncInvokeTest, FlushWithIds) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000560 AsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800561 AtomicBool flag1;
562 AtomicBool flag2;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000563 // Queue two async calls to the current thread, one with a message id.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700564 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000565 5);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700566 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000567 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800568 EXPECT_FALSE(flag1.get());
569 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000570 // Execute pending calls with id == 5.
571 invoker.Flush(Thread::Current(), 5);
nissed9b75be2015-11-16 00:54:07 -0800572 EXPECT_TRUE(flag1.get());
573 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000574 flag1 = false;
575 // Execute all pending calls. The id == 5 call should not execute again.
576 invoker.Flush(Thread::Current());
nissed9b75be2015-11-16 00:54:07 -0800577 EXPECT_FALSE(flag1.get());
578 EXPECT_TRUE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000579}
580
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200581class GuardedAsyncInvokeTest : public ::testing::Test {
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200582 public:
583 void IntCallback(int value) {
584 EXPECT_EQ(expected_thread_, Thread::Current());
585 int_value_ = value;
586 }
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200587 void SetExpectedThreadForIntCallback(Thread* thread) {
588 expected_thread_ = thread;
589 }
590
591 protected:
592 const static int kWaitTimeout = 1000;
Yves Gerey665174f2018-06-19 15:03:05 +0200593 GuardedAsyncInvokeTest() : int_value_(0), expected_thread_(nullptr) {}
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200594
595 int int_value_;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200596 Thread* expected_thread_;
597};
598
599// Functor for creating an invoker.
600struct CreateInvoker {
jbauch555604a2016-04-26 03:13:22 -0700601 CreateInvoker(std::unique_ptr<GuardedAsyncInvoker>* invoker)
602 : invoker_(invoker) {}
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200603 void operator()() { invoker_->reset(new GuardedAsyncInvoker()); }
jbauch555604a2016-04-26 03:13:22 -0700604 std::unique_ptr<GuardedAsyncInvoker>* invoker_;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200605};
606
607// Test that we can call AsyncInvoke<void>() after the thread died.
608TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) {
609 // Create and start the thread.
tommie7251592017-07-14 14:44:46 -0700610 std::unique_ptr<Thread> thread(Thread::Create());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200611 thread->Start();
jbauch555604a2016-04-26 03:13:22 -0700612 std::unique_ptr<GuardedAsyncInvoker> invoker;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200613 // Create the invoker on |thread|.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700614 thread->Invoke<void>(RTC_FROM_HERE, CreateInvoker(&invoker));
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200615 // Kill |thread|.
616 thread = nullptr;
617 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800618 AtomicBool called;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700619 EXPECT_FALSE(invoker->AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&called)));
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200620 // With thread gone, nothing should happen.
nissed9b75be2015-11-16 00:54:07 -0800621 WAIT(called.get(), kWaitTimeout);
622 EXPECT_FALSE(called.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200623}
624
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200625// The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker
626// when Thread is still alive.
627TEST_F(GuardedAsyncInvokeTest, FireAndForget) {
628 GuardedAsyncInvoker invoker;
629 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800630 AtomicBool called;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700631 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&called)));
nissed9b75be2015-11-16 00:54:07 -0800632 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200633}
634
Cameron Pickettd132ce12018-03-12 16:07:37 -0700635TEST_F(GuardedAsyncInvokeTest, NonCopyableFunctor) {
636 GuardedAsyncInvoker invoker;
637 // Try calling functor.
638 AtomicBool called;
639 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorD(&called)));
640 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
641}
642
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200643TEST_F(GuardedAsyncInvokeTest, Flush) {
644 GuardedAsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800645 AtomicBool flag1;
646 AtomicBool flag2;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200647 // Queue two async calls to the current thread.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700648 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag1)));
649 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag2)));
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200650 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800651 EXPECT_FALSE(flag1.get());
652 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200653 // Force them to run now.
654 EXPECT_TRUE(invoker.Flush());
nissed9b75be2015-11-16 00:54:07 -0800655 EXPECT_TRUE(flag1.get());
656 EXPECT_TRUE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200657}
658
659TEST_F(GuardedAsyncInvokeTest, FlushWithIds) {
660 GuardedAsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800661 AtomicBool flag1;
662 AtomicBool flag2;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200663 // Queue two async calls to the current thread, one with a message id.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700664 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag1), 5));
665 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag2)));
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200666 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800667 EXPECT_FALSE(flag1.get());
668 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200669 // Execute pending calls with id == 5.
670 EXPECT_TRUE(invoker.Flush(5));
nissed9b75be2015-11-16 00:54:07 -0800671 EXPECT_TRUE(flag1.get());
672 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200673 flag1 = false;
674 // Execute all pending calls. The id == 5 call should not execute again.
675 EXPECT_TRUE(invoker.Flush());
nissed9b75be2015-11-16 00:54:07 -0800676 EXPECT_FALSE(flag1.get());
677 EXPECT_TRUE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200678}
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100679
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100680void ThreadIsCurrent(Thread* thread, bool* result, Event* event) {
681 *result = thread->IsCurrent();
682 event->Set();
683}
684
685void WaitAndSetEvent(Event* wait_event, Event* set_event) {
686 wait_event->Wait(Event::kForever);
687 set_event->Set();
688}
689
690// A functor that keeps track of the number of copies and moves.
691class LifeCycleFunctor {
692 public:
693 struct Stats {
694 size_t copy_count = 0;
695 size_t move_count = 0;
696 };
697
698 LifeCycleFunctor(Stats* stats, Event* event) : stats_(stats), event_(event) {}
699 LifeCycleFunctor(const LifeCycleFunctor& other) { *this = other; }
700 LifeCycleFunctor(LifeCycleFunctor&& other) { *this = std::move(other); }
701
702 LifeCycleFunctor& operator=(const LifeCycleFunctor& other) {
703 stats_ = other.stats_;
704 event_ = other.event_;
705 ++stats_->copy_count;
706 return *this;
707 }
708
709 LifeCycleFunctor& operator=(LifeCycleFunctor&& other) {
710 stats_ = other.stats_;
711 event_ = other.event_;
712 ++stats_->move_count;
713 return *this;
714 }
715
716 void operator()() { event_->Set(); }
717
718 private:
719 Stats* stats_;
720 Event* event_;
721};
722
723// A functor that verifies the thread it was destroyed on.
724class DestructionFunctor {
725 public:
726 DestructionFunctor(Thread* thread, bool* thread_was_current, Event* event)
727 : thread_(thread),
728 thread_was_current_(thread_was_current),
729 event_(event) {}
730 ~DestructionFunctor() {
731 // Only signal the event if this was the functor that was invoked to avoid
732 // the event being signaled due to the destruction of temporary/moved
733 // versions of this object.
734 if (was_invoked_) {
735 *thread_was_current_ = thread_->IsCurrent();
736 event_->Set();
737 }
738 }
739
740 void operator()() { was_invoked_ = true; }
741
742 private:
743 Thread* thread_;
744 bool* thread_was_current_;
745 Event* event_;
746 bool was_invoked_ = false;
747};
748
749TEST(ThreadPostTaskTest, InvokesWithBind) {
750 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
751 background_thread->Start();
752
753 Event event;
754 background_thread->PostTask(RTC_FROM_HERE, Bind(&Event::Set, &event));
755 event.Wait(Event::kForever);
756}
757
758TEST(ThreadPostTaskTest, InvokesWithLambda) {
759 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
760 background_thread->Start();
761
762 Event event;
763 background_thread->PostTask(RTC_FROM_HERE, [&event] { event.Set(); });
764 event.Wait(Event::kForever);
765}
766
767TEST(ThreadPostTaskTest, InvokesWithCopiedFunctor) {
768 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
769 background_thread->Start();
770
771 LifeCycleFunctor::Stats stats;
772 Event event;
773 LifeCycleFunctor functor(&stats, &event);
774 background_thread->PostTask(RTC_FROM_HERE, functor);
775 event.Wait(Event::kForever);
776
777 EXPECT_EQ(1u, stats.copy_count);
778 EXPECT_EQ(0u, stats.move_count);
779}
780
781TEST(ThreadPostTaskTest, InvokesWithMovedFunctor) {
782 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
783 background_thread->Start();
784
785 LifeCycleFunctor::Stats stats;
786 Event event;
787 LifeCycleFunctor functor(&stats, &event);
788 background_thread->PostTask(RTC_FROM_HERE, std::move(functor));
789 event.Wait(Event::kForever);
790
791 EXPECT_EQ(0u, stats.copy_count);
792 EXPECT_EQ(1u, stats.move_count);
793}
794
795TEST(ThreadPostTaskTest, InvokesWithReferencedFunctorShouldCopy) {
796 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
797 background_thread->Start();
798
799 LifeCycleFunctor::Stats stats;
800 Event event;
801 LifeCycleFunctor functor(&stats, &event);
802 LifeCycleFunctor& functor_ref = functor;
803 background_thread->PostTask(RTC_FROM_HERE, functor_ref);
804 event.Wait(Event::kForever);
805
806 EXPECT_EQ(1u, stats.copy_count);
807 EXPECT_EQ(0u, stats.move_count);
808}
809
810TEST(ThreadPostTaskTest, InvokesWithCopiedFunctorDestroyedOnTargetThread) {
811 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
812 background_thread->Start();
813
814 Event event;
815 bool was_invoked_on_background_thread = false;
816 DestructionFunctor functor(background_thread.get(),
817 &was_invoked_on_background_thread, &event);
818 background_thread->PostTask(RTC_FROM_HERE, functor);
819 event.Wait(Event::kForever);
820
821 EXPECT_TRUE(was_invoked_on_background_thread);
822}
823
824TEST(ThreadPostTaskTest, InvokesWithMovedFunctorDestroyedOnTargetThread) {
825 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
826 background_thread->Start();
827
828 Event event;
829 bool was_invoked_on_background_thread = false;
830 DestructionFunctor functor(background_thread.get(),
831 &was_invoked_on_background_thread, &event);
832 background_thread->PostTask(RTC_FROM_HERE, std::move(functor));
833 event.Wait(Event::kForever);
834
835 EXPECT_TRUE(was_invoked_on_background_thread);
836}
837
838TEST(ThreadPostTaskTest,
839 InvokesWithReferencedFunctorShouldCopyAndDestroyedOnTargetThread) {
840 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
841 background_thread->Start();
842
843 Event event;
844 bool was_invoked_on_background_thread = false;
845 DestructionFunctor functor(background_thread.get(),
846 &was_invoked_on_background_thread, &event);
847 DestructionFunctor& functor_ref = functor;
848 background_thread->PostTask(RTC_FROM_HERE, functor_ref);
849 event.Wait(Event::kForever);
850
851 EXPECT_TRUE(was_invoked_on_background_thread);
852}
853
854TEST(ThreadPostTaskTest, InvokesOnBackgroundThread) {
855 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
856 background_thread->Start();
857
858 Event event;
859 bool was_invoked_on_background_thread = false;
860 background_thread->PostTask(RTC_FROM_HERE,
861 Bind(&ThreadIsCurrent, background_thread.get(),
862 &was_invoked_on_background_thread, &event));
863 event.Wait(Event::kForever);
864
865 EXPECT_TRUE(was_invoked_on_background_thread);
866}
867
868TEST(ThreadPostTaskTest, InvokesAsynchronously) {
869 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
870 background_thread->Start();
871
872 // The first event ensures that SendSingleMessage() is not blocking this
873 // thread. The second event ensures that the message is processed.
874 Event event_set_by_test_thread;
875 Event event_set_by_background_thread;
876 background_thread->PostTask(RTC_FROM_HERE,
877 Bind(&WaitAndSetEvent, &event_set_by_test_thread,
878 &event_set_by_background_thread));
879 event_set_by_test_thread.Set();
880 event_set_by_background_thread.Wait(Event::kForever);
881}
882
883TEST(ThreadPostTaskTest, InvokesInPostedOrder) {
884 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
885 background_thread->Start();
886
887 Event first;
888 Event second;
889 Event third;
890 Event fourth;
891
892 background_thread->PostTask(RTC_FROM_HERE,
893 Bind(&WaitAndSetEvent, &first, &second));
894 background_thread->PostTask(RTC_FROM_HERE,
895 Bind(&WaitAndSetEvent, &second, &third));
896 background_thread->PostTask(RTC_FROM_HERE,
897 Bind(&WaitAndSetEvent, &third, &fourth));
898
899 // All tasks have been posted before the first one is unblocked.
900 first.Set();
901 // Only if the chain is invoked in posted order will the last event be set.
902 fourth.Wait(Event::kForever);
903}
904
Steve Antonbcc1a762019-12-11 11:21:53 -0800905TEST(ThreadPostDelayedTaskTest, InvokesAsynchronously) {
906 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
907 background_thread->Start();
908
909 // The first event ensures that SendSingleMessage() is not blocking this
910 // thread. The second event ensures that the message is processed.
911 Event event_set_by_test_thread;
912 Event event_set_by_background_thread;
913 background_thread->PostDelayedTask(
914 RTC_FROM_HERE,
915 Bind(&WaitAndSetEvent, &event_set_by_test_thread,
916 &event_set_by_background_thread),
917 /*milliseconds=*/10);
918 event_set_by_test_thread.Set();
919 event_set_by_background_thread.Wait(Event::kForever);
920}
921
922TEST(ThreadPostDelayedTaskTest, InvokesInDelayOrder) {
Steve Anton094396f2019-12-16 00:56:02 -0800923 ScopedFakeClock clock;
Steve Antonbcc1a762019-12-11 11:21:53 -0800924 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
925 background_thread->Start();
926
927 Event first;
928 Event second;
929 Event third;
930 Event fourth;
931
932 background_thread->PostDelayedTask(RTC_FROM_HERE,
933 Bind(&WaitAndSetEvent, &third, &fourth),
934 /*milliseconds=*/11);
935 background_thread->PostDelayedTask(RTC_FROM_HERE,
936 Bind(&WaitAndSetEvent, &first, &second),
937 /*milliseconds=*/9);
938 background_thread->PostDelayedTask(RTC_FROM_HERE,
939 Bind(&WaitAndSetEvent, &second, &third),
940 /*milliseconds=*/10);
941
942 // All tasks have been posted before the first one is unblocked.
943 first.Set();
Steve Anton094396f2019-12-16 00:56:02 -0800944 // Only if the chain is invoked in delay order will the last event be set.
945 clock.AdvanceTime(webrtc::TimeDelta::ms(11));
946 EXPECT_TRUE(fourth.Wait(0));
Steve Antonbcc1a762019-12-11 11:21:53 -0800947}
948
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100949class ThreadFactory : public webrtc::TaskQueueFactory {
950 public:
951 std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
952 CreateTaskQueue(absl::string_view /* name */,
953 Priority /*priority*/) const override {
954 std::unique_ptr<Thread> thread = Thread::Create();
955 thread->Start();
956 return std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>(
957 thread.release());
958 }
959};
960
961using ::webrtc::TaskQueueTest;
962
963INSTANTIATE_TEST_SUITE_P(RtcThread,
964 TaskQueueTest,
965 ::testing::Values(std::make_unique<ThreadFactory>));
966
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100967} // namespace
968} // namespace rtc