blob: c4b6143ee0287e0a6ccccea7a4b5d84fda48184c [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
kwibergbfefb032016-05-01 14:53:46 -070011#include <memory>
12
Niels Möller5a96a0e2019-04-30 11:45:58 +020013#include "absl/memory/memory.h"
Steve Anton10542f22019-01-11 09:11:00 -080014#include "rtc_base/async_invoker.h"
15#include "rtc_base/async_udp_socket.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "rtc_base/event.h"
17#include "rtc_base/gunit.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "rtc_base/null_socket_server.h"
19#include "rtc_base/physical_socket_server.h"
20#include "rtc_base/socket_address.h"
Artem Titove41c4332018-07-25 15:04:28 +020021#include "rtc_base/third_party/sigslot/sigslot.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "rtc_base/thread.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000023
24#if defined(WEBRTC_WIN)
25#include <comdef.h> // NOLINT
26#endif
27
Mirko Bonadeie10b1632018-12-11 18:43:40 +010028namespace rtc {
29namespace {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030
31// Generates a sequence of numbers (collaboratively).
32class TestGenerator {
33 public:
34 TestGenerator() : last(0), count(0) {}
35
36 int Next(int prev) {
37 int result = prev + last;
38 last = result;
39 count += 1;
40 return result;
41 }
42
43 int last;
44 int count;
45};
46
47struct TestMessage : public MessageData {
48 explicit TestMessage(int v) : value(v) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000049
50 int value;
51};
52
53// Receives on a socket and sends by posting messages.
54class SocketClient : public TestGenerator, public sigslot::has_slots<> {
55 public:
Yves Gerey665174f2018-06-19 15:03:05 +020056 SocketClient(AsyncSocket* socket,
57 const SocketAddress& addr,
58 Thread* post_thread,
59 MessageHandler* phandler)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000060 : socket_(AsyncUDPSocket::Create(socket, addr)),
61 post_thread_(post_thread),
62 post_handler_(phandler) {
63 socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
64 }
65
Steve Anton9de3aac2017-10-24 10:08:26 -070066 ~SocketClient() override { delete socket_; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000067
68 SocketAddress address() const { return socket_->GetLocalAddress(); }
69
Yves Gerey665174f2018-06-19 15:03:05 +020070 void OnPacket(AsyncPacketSocket* socket,
71 const char* buf,
72 size_t size,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000073 const SocketAddress& remote_addr,
Niels Möllere6933812018-11-05 13:01:41 +010074 const int64_t& packet_time_us) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020075 EXPECT_EQ(size, sizeof(uint32_t));
76 uint32_t prev = reinterpret_cast<const uint32_t*>(buf)[0];
77 uint32_t result = Next(prev);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000078
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070079 post_thread_->PostDelayed(RTC_FROM_HERE, 200, post_handler_, 0,
80 new TestMessage(result));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000081 }
82
83 private:
84 AsyncUDPSocket* socket_;
85 Thread* post_thread_;
86 MessageHandler* post_handler_;
87};
88
89// Receives messages and sends on a socket.
90class MessageClient : public MessageHandler, public TestGenerator {
91 public:
Yves Gerey665174f2018-06-19 15:03:05 +020092 MessageClient(Thread* pth, Socket* socket) : socket_(socket) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000093
Steve Anton9de3aac2017-10-24 10:08:26 -070094 ~MessageClient() override { delete socket_; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000095
Steve Anton9de3aac2017-10-24 10:08:26 -070096 void OnMessage(Message* pmsg) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000097 TestMessage* msg = static_cast<TestMessage*>(pmsg->pdata);
98 int result = Next(msg->value);
99 EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
100 delete msg;
101 }
102
103 private:
104 Socket* socket_;
105};
106
deadbeefaea92932017-05-23 12:55:03 -0700107class CustomThread : public rtc::Thread {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000108 public:
tommie7251592017-07-14 14:44:46 -0700109 CustomThread()
110 : Thread(std::unique_ptr<SocketServer>(new rtc::NullSocketServer())) {}
Steve Anton9de3aac2017-10-24 10:08:26 -0700111 ~CustomThread() override { Stop(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000112 bool Start() { return false; }
jiayl@webrtc.orgba737cb2014-09-18 16:45:21 +0000113
Yves Gerey665174f2018-06-19 15:03:05 +0200114 bool WrapCurrent() { return Thread::WrapCurrent(); }
115 void UnwrapCurrent() { Thread::UnwrapCurrent(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000116};
117
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000118// 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)
tommie7251592017-07-14 14:44:46 -0700123 : Thread(std::unique_ptr<SocketServer>(new NullSocketServer())),
124 event_(event) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000125
Steve Anton9de3aac2017-10-24 10:08:26 -0700126 ~SignalWhenDestroyedThread() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000127 Stop();
128 event_->Set();
129 }
130
Steve Anton9de3aac2017-10-24 10:08:26 -0700131 void Run() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000132 // 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
deadbeefaea92932017-05-23 12:55:03 -0700149// rtc::AtomicInt, if/when that is added. Since the use isn't
nissed9b75be2015-11-16 00:54:07 -0800150// 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:
pbos5ad935c2016-01-25 03:52:44 -0800167 CriticalSection cs_;
nissed9b75be2015-11-16 00:54:07 -0800168 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) {}
Yves Gerey665174f2018-06-19 15:03:05 +0200178 void operator()() {
179 if (flag_)
180 *flag_ = true;
181 }
182
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000183 private:
nissed9b75be2015-11-16 00:54:07 -0800184 AtomicBool* flag_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000185};
186struct FunctorC {
187 int operator()() {
188 Thread::Current()->ProcessMessages(50);
189 return 24;
190 }
191};
Cameron Pickettd132ce12018-03-12 16:07:37 -0700192struct FunctorD {
193 public:
194 explicit FunctorD(AtomicBool* flag) : flag_(flag) {}
195 FunctorD(FunctorD&&) = default;
196 FunctorD& operator=(FunctorD&&) = default;
Yves Gerey665174f2018-06-19 15:03:05 +0200197 void operator()() {
198 if (flag_)
199 *flag_ = true;
200 }
201
Cameron Pickettd132ce12018-03-12 16:07:37 -0700202 private:
203 AtomicBool* flag_;
204 RTC_DISALLOW_COPY_AND_ASSIGN(FunctorD);
205};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000206
207// See: https://code.google.com/p/webrtc/issues/detail?id=2409
208TEST(ThreadTest, DISABLED_Main) {
209 const SocketAddress addr("127.0.0.1", 0);
210
211 // Create the messaging client on its own thread.
tommie7251592017-07-14 14:44:46 -0700212 auto th1 = Thread::CreateWithSocketServer();
213 Socket* socket =
214 th1->socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
215 MessageClient msg_client(th1.get(), socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000216
217 // Create the socket client on its own thread.
tommie7251592017-07-14 14:44:46 -0700218 auto th2 = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000219 AsyncSocket* asocket =
tommie7251592017-07-14 14:44:46 -0700220 th2->socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
221 SocketClient sock_client(asocket, addr, th1.get(), &msg_client);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000222
223 socket->Connect(sock_client.address());
224
tommie7251592017-07-14 14:44:46 -0700225 th1->Start();
226 th2->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000227
228 // Get the messages started.
tommie7251592017-07-14 14:44:46 -0700229 th1->PostDelayed(RTC_FROM_HERE, 100, &msg_client, 0, new TestMessage(1));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000230
231 // Give the clients a little while to run.
232 // Messages will be processed at 100, 300, 500, 700, 900.
233 Thread* th_main = Thread::Current();
234 th_main->ProcessMessages(1000);
235
236 // Stop the sending client. Give the receiver a bit longer to run, in case
237 // it is running on a machine that is under load (e.g. the build machine).
tommie7251592017-07-14 14:44:46 -0700238 th1->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000239 th_main->ProcessMessages(200);
tommie7251592017-07-14 14:44:46 -0700240 th2->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000241
242 // Make sure the results were correct
243 EXPECT_EQ(5, msg_client.count);
244 EXPECT_EQ(34, msg_client.last);
245 EXPECT_EQ(5, sock_client.count);
246 EXPECT_EQ(55, sock_client.last);
247}
248
249// Test that setting thread names doesn't cause a malfunction.
250// There's no easy way to verify the name was set properly at this time.
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000251TEST(ThreadTest, Names) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000252 // Default name
tommie7251592017-07-14 14:44:46 -0700253 auto thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000254 EXPECT_TRUE(thread->Start());
255 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000256 // Name with no object parameter
tommie7251592017-07-14 14:44:46 -0700257 thread = Thread::CreateWithSocketServer();
deadbeef37f5ecf2017-02-27 14:06:41 -0800258 EXPECT_TRUE(thread->SetName("No object", nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000259 EXPECT_TRUE(thread->Start());
260 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000261 // Really long name
tommie7251592017-07-14 14:44:46 -0700262 thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000263 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
264 EXPECT_TRUE(thread->Start());
265 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000266}
267
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000268TEST(ThreadTest, Wrap) {
269 Thread* current_thread = Thread::Current();
Niels Moller9d1840c2019-05-21 07:26:37 +0000270 current_thread->UnwrapCurrent();
271 CustomThread* cthread = new CustomThread();
272 EXPECT_TRUE(cthread->WrapCurrent());
273 EXPECT_TRUE(cthread->RunningForTest());
274 EXPECT_FALSE(cthread->IsOwned());
275 cthread->UnwrapCurrent();
276 EXPECT_FALSE(cthread->RunningForTest());
277 delete cthread;
278 current_thread->WrapCurrent();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000279}
280
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000281TEST(ThreadTest, Invoke) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000282 // Create and start the thread.
tommie7251592017-07-14 14:44:46 -0700283 auto thread = Thread::CreateWithSocketServer();
284 thread->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000285 // Try calling functors.
tommie7251592017-07-14 14:44:46 -0700286 EXPECT_EQ(42, thread->Invoke<int>(RTC_FROM_HERE, FunctorA()));
nissed9b75be2015-11-16 00:54:07 -0800287 AtomicBool called;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000288 FunctorB f2(&called);
tommie7251592017-07-14 14:44:46 -0700289 thread->Invoke<void>(RTC_FROM_HERE, f2);
nissed9b75be2015-11-16 00:54:07 -0800290 EXPECT_TRUE(called.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000291 // Try calling bare functions.
292 struct LocalFuncs {
293 static int Func1() { return 999; }
294 static void Func2() {}
295 };
tommie7251592017-07-14 14:44:46 -0700296 EXPECT_EQ(999, thread->Invoke<int>(RTC_FROM_HERE, &LocalFuncs::Func1));
297 thread->Invoke<void>(RTC_FROM_HERE, &LocalFuncs::Func2);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000298}
299
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000300// Verifies that two threads calling Invoke on each other at the same time does
301// not deadlock.
302TEST(ThreadTest, TwoThreadsInvokeNoDeadlock) {
303 AutoThread thread;
304 Thread* current_thread = Thread::Current();
deadbeef37f5ecf2017-02-27 14:06:41 -0800305 ASSERT_TRUE(current_thread != nullptr);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000306
tommie7251592017-07-14 14:44:46 -0700307 auto other_thread = Thread::CreateWithSocketServer();
308 other_thread->Start();
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000309
310 struct LocalFuncs {
311 static void Set(bool* out) { *out = true; }
312 static void InvokeSet(Thread* thread, bool* out) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700313 thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out));
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000314 }
315 };
316
317 bool called = false;
tommie7251592017-07-14 14:44:46 -0700318 other_thread->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700319 RTC_FROM_HERE, Bind(&LocalFuncs::InvokeSet, current_thread, &called));
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000320
321 EXPECT_TRUE(called);
322}
323
324// Verifies that if thread A invokes a call on thread B and thread C is trying
325// to invoke A at the same time, thread A does not handle C's invoke while
326// invoking B.
327TEST(ThreadTest, ThreeThreadsInvoke) {
328 AutoThread thread;
329 Thread* thread_a = Thread::Current();
tommie7251592017-07-14 14:44:46 -0700330 auto thread_b = Thread::CreateWithSocketServer();
331 auto thread_c = Thread::CreateWithSocketServer();
332 thread_b->Start();
333 thread_c->Start();
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000334
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000335 class LockedBool {
336 public:
337 explicit LockedBool(bool value) : value_(value) {}
338
339 void Set(bool value) {
340 CritScope lock(&crit_);
341 value_ = value;
342 }
343
344 bool Get() {
345 CritScope lock(&crit_);
346 return value_;
347 }
348
349 private:
350 CriticalSection crit_;
danilchap3c6abd22017-09-06 05:46:29 -0700351 bool value_ RTC_GUARDED_BY(crit_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000352 };
353
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000354 struct LocalFuncs {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000355 static void Set(LockedBool* out) { out->Set(true); }
356 static void InvokeSet(Thread* thread, LockedBool* out) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700357 thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out));
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000358 }
359
360 // Set |out| true and call InvokeSet on |thread|.
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000361 static void SetAndInvokeSet(LockedBool* out,
362 Thread* thread,
363 LockedBool* out_inner) {
364 out->Set(true);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000365 InvokeSet(thread, out_inner);
366 }
367
368 // Asynchronously invoke SetAndInvokeSet on |thread1| and wait until
369 // |thread1| starts the call.
deadbeef162cb532017-02-23 17:10:07 -0800370 static void AsyncInvokeSetAndWait(AsyncInvoker* invoker,
371 Thread* thread1,
372 Thread* thread2,
373 LockedBool* out) {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000374 CriticalSection crit;
375 LockedBool async_invoked(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000376
deadbeef162cb532017-02-23 17:10:07 -0800377 invoker->AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700378 RTC_FROM_HERE, thread1,
379 Bind(&SetAndInvokeSet, &async_invoked, thread2, out));
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000380
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000381 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000382 }
383 };
384
deadbeef162cb532017-02-23 17:10:07 -0800385 AsyncInvoker invoker;
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000386 LockedBool thread_a_called(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000387
388 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
389 // Thread B returns when C receives the call and C should be blocked until A
390 // starts to process messages.
tommie7251592017-07-14 14:44:46 -0700391 thread_b->Invoke<void>(RTC_FROM_HERE,
392 Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker,
393 thread_c.get(), thread_a, &thread_a_called));
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000394 EXPECT_FALSE(thread_a_called.Get());
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000395
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000396 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000397}
398
jbauch25d1f282016-02-05 00:25:02 -0800399// Set the name on a thread when the underlying QueueDestroyed signal is
400// triggered. This causes an error if the object is already partially
401// destroyed.
402class SetNameOnSignalQueueDestroyedTester : public sigslot::has_slots<> {
403 public:
404 SetNameOnSignalQueueDestroyedTester(Thread* thread) : thread_(thread) {
405 thread->SignalQueueDestroyed.connect(
406 this, &SetNameOnSignalQueueDestroyedTester::OnQueueDestroyed);
407 }
408
409 void OnQueueDestroyed() {
410 // Makes sure that if we access the Thread while it's being destroyed, that
411 // it doesn't cause a problem because the vtable has been modified.
412 thread_->SetName("foo", nullptr);
413 }
414
415 private:
416 Thread* thread_;
417};
418
419TEST(ThreadTest, SetNameOnSignalQueueDestroyed) {
tommie7251592017-07-14 14:44:46 -0700420 auto thread1 = Thread::CreateWithSocketServer();
421 SetNameOnSignalQueueDestroyedTester tester1(thread1.get());
422 thread1.reset();
jbauch25d1f282016-02-05 00:25:02 -0800423
424 Thread* thread2 = new AutoThread();
425 SetNameOnSignalQueueDestroyedTester tester2(thread2);
426 delete thread2;
jbauch25d1f282016-02-05 00:25:02 -0800427}
428
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200429class AsyncInvokeTest : public ::testing::Test {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000430 public:
431 void IntCallback(int value) {
432 EXPECT_EQ(expected_thread_, Thread::Current());
433 int_value_ = value;
434 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000435 void SetExpectedThreadForIntCallback(Thread* thread) {
436 expected_thread_ = thread;
437 }
438
439 protected:
440 enum { kWaitTimeout = 1000 };
Yves Gerey665174f2018-06-19 15:03:05 +0200441 AsyncInvokeTest() : int_value_(0), expected_thread_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000442
443 int int_value_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000444 Thread* expected_thread_;
445};
446
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000447TEST_F(AsyncInvokeTest, FireAndForget) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000448 AsyncInvoker invoker;
449 // Create and start the thread.
tommie7251592017-07-14 14:44:46 -0700450 auto thread = Thread::CreateWithSocketServer();
451 thread->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000452 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800453 AtomicBool called;
tommie7251592017-07-14 14:44:46 -0700454 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), FunctorB(&called));
nissed9b75be2015-11-16 00:54:07 -0800455 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
tommie7251592017-07-14 14:44:46 -0700456 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000457}
458
Cameron Pickettd132ce12018-03-12 16:07:37 -0700459TEST_F(AsyncInvokeTest, NonCopyableFunctor) {
460 AsyncInvoker invoker;
461 // Create and start the thread.
462 auto thread = Thread::CreateWithSocketServer();
463 thread->Start();
464 // Try calling functor.
465 AtomicBool called;
466 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), FunctorD(&called));
467 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
468 thread->Stop();
469}
470
deadbeef162cb532017-02-23 17:10:07 -0800471TEST_F(AsyncInvokeTest, KillInvokerDuringExecute) {
472 // Use these events to get in a state where the functor is in the middle of
473 // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE"
474 // is run.
Niels Möllerc572ff32018-11-07 08:43:50 +0100475 Event functor_started;
476 Event functor_continue;
477 Event functor_finished;
deadbeef162cb532017-02-23 17:10:07 -0800478
tommie7251592017-07-14 14:44:46 -0700479 auto thread = Thread::CreateWithSocketServer();
480 thread->Start();
deadbeef162cb532017-02-23 17:10:07 -0800481 volatile bool invoker_destroyed = false;
482 {
deadbeef3af63b02017-08-08 17:59:47 -0700483 auto functor = [&functor_started, &functor_continue, &functor_finished,
484 &invoker_destroyed] {
485 functor_started.Set();
486 functor_continue.Wait(Event::kForever);
487 rtc::Thread::Current()->SleepMs(kWaitTimeout);
488 EXPECT_FALSE(invoker_destroyed);
489 functor_finished.Set();
490 };
deadbeef162cb532017-02-23 17:10:07 -0800491 AsyncInvoker invoker;
deadbeef3af63b02017-08-08 17:59:47 -0700492 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), functor);
deadbeef162cb532017-02-23 17:10:07 -0800493 functor_started.Wait(Event::kForever);
deadbeefaea92932017-05-23 12:55:03 -0700494
deadbeef3af63b02017-08-08 17:59:47 -0700495 // Destroy the invoker while the functor is still executing (doing
496 // SleepMs).
deadbeefaea92932017-05-23 12:55:03 -0700497 functor_continue.Set();
deadbeef162cb532017-02-23 17:10:07 -0800498 }
499
500 // If the destructor DIDN'T wait for the functor to finish executing, it will
501 // hit the EXPECT_FALSE(invoker_destroyed) after it finishes sleeping for a
502 // second.
503 invoker_destroyed = true;
504 functor_finished.Wait(Event::kForever);
505}
506
deadbeef3af63b02017-08-08 17:59:47 -0700507// Variant of the above test where the async-invoked task calls AsyncInvoke
508// *again*, for the thread on which the AsyncInvoker is currently being
509// destroyed. This shouldn't deadlock or crash; this second invocation should
510// just be ignored.
511TEST_F(AsyncInvokeTest, KillInvokerDuringExecuteWithReentrantInvoke) {
Niels Möllerc572ff32018-11-07 08:43:50 +0100512 Event functor_started;
deadbeef3af63b02017-08-08 17:59:47 -0700513 // Flag used to verify that the recursively invoked task never actually runs.
514 bool reentrant_functor_run = false;
515
516 Thread* main = Thread::Current();
Niels Möller5a96a0e2019-04-30 11:45:58 +0200517 Thread thread(absl::make_unique<NullSocketServer>());
deadbeef3af63b02017-08-08 17:59:47 -0700518 thread.Start();
519 {
520 AsyncInvoker invoker;
521 auto reentrant_functor = [&reentrant_functor_run] {
522 reentrant_functor_run = true;
523 };
524 auto functor = [&functor_started, &invoker, main, reentrant_functor] {
525 functor_started.Set();
526 Thread::Current()->SleepMs(kWaitTimeout);
527 invoker.AsyncInvoke<void>(RTC_FROM_HERE, main, reentrant_functor);
528 };
529 // This queues a task on |thread| to sleep for |kWaitTimeout| then queue a
530 // task on |main|. But this second queued task should never run, since the
531 // destructor will be entered before it's even invoked.
532 invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread, functor);
533 functor_started.Wait(Event::kForever);
534 }
535 EXPECT_FALSE(reentrant_functor_run);
536}
537
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000538TEST_F(AsyncInvokeTest, Flush) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000539 AsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800540 AtomicBool flag1;
541 AtomicBool flag2;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000542 // Queue two async calls to the current thread.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700543 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1));
544 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000545 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800546 EXPECT_FALSE(flag1.get());
547 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000548 // Force them to run now.
549 invoker.Flush(Thread::Current());
nissed9b75be2015-11-16 00:54:07 -0800550 EXPECT_TRUE(flag1.get());
551 EXPECT_TRUE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000552}
553
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000554TEST_F(AsyncInvokeTest, FlushWithIds) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000555 AsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800556 AtomicBool flag1;
557 AtomicBool flag2;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000558 // Queue two async calls to the current thread, one with a message id.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700559 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000560 5);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700561 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000562 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800563 EXPECT_FALSE(flag1.get());
564 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000565 // Execute pending calls with id == 5.
566 invoker.Flush(Thread::Current(), 5);
nissed9b75be2015-11-16 00:54:07 -0800567 EXPECT_TRUE(flag1.get());
568 EXPECT_FALSE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000569 flag1 = false;
570 // Execute all pending calls. The id == 5 call should not execute again.
571 invoker.Flush(Thread::Current());
nissed9b75be2015-11-16 00:54:07 -0800572 EXPECT_FALSE(flag1.get());
573 EXPECT_TRUE(flag2.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000574}
575
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200576class GuardedAsyncInvokeTest : public ::testing::Test {
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200577 public:
578 void IntCallback(int value) {
579 EXPECT_EQ(expected_thread_, Thread::Current());
580 int_value_ = value;
581 }
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200582 void SetExpectedThreadForIntCallback(Thread* thread) {
583 expected_thread_ = thread;
584 }
585
586 protected:
587 const static int kWaitTimeout = 1000;
Yves Gerey665174f2018-06-19 15:03:05 +0200588 GuardedAsyncInvokeTest() : int_value_(0), expected_thread_(nullptr) {}
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200589
590 int int_value_;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200591 Thread* expected_thread_;
592};
593
594// Functor for creating an invoker.
595struct CreateInvoker {
jbauch555604a2016-04-26 03:13:22 -0700596 CreateInvoker(std::unique_ptr<GuardedAsyncInvoker>* invoker)
597 : invoker_(invoker) {}
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200598 void operator()() { invoker_->reset(new GuardedAsyncInvoker()); }
jbauch555604a2016-04-26 03:13:22 -0700599 std::unique_ptr<GuardedAsyncInvoker>* invoker_;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200600};
601
602// Test that we can call AsyncInvoke<void>() after the thread died.
603TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) {
604 // Create and start the thread.
tommie7251592017-07-14 14:44:46 -0700605 std::unique_ptr<Thread> thread(Thread::Create());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200606 thread->Start();
jbauch555604a2016-04-26 03:13:22 -0700607 std::unique_ptr<GuardedAsyncInvoker> invoker;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200608 // Create the invoker on |thread|.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700609 thread->Invoke<void>(RTC_FROM_HERE, CreateInvoker(&invoker));
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200610 // Kill |thread|.
611 thread = nullptr;
612 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800613 AtomicBool called;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700614 EXPECT_FALSE(invoker->AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&called)));
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200615 // With thread gone, nothing should happen.
nissed9b75be2015-11-16 00:54:07 -0800616 WAIT(called.get(), kWaitTimeout);
617 EXPECT_FALSE(called.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200618}
619
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200620// The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker
621// when Thread is still alive.
622TEST_F(GuardedAsyncInvokeTest, FireAndForget) {
623 GuardedAsyncInvoker invoker;
624 // Try calling functor.
nissed9b75be2015-11-16 00:54:07 -0800625 AtomicBool called;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700626 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&called)));
nissed9b75be2015-11-16 00:54:07 -0800627 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200628}
629
Cameron Pickettd132ce12018-03-12 16:07:37 -0700630TEST_F(GuardedAsyncInvokeTest, NonCopyableFunctor) {
631 GuardedAsyncInvoker invoker;
632 // Try calling functor.
633 AtomicBool called;
634 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorD(&called)));
635 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
636}
637
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200638TEST_F(GuardedAsyncInvokeTest, Flush) {
639 GuardedAsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800640 AtomicBool flag1;
641 AtomicBool flag2;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200642 // Queue two async calls to the current thread.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700643 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag1)));
644 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag2)));
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200645 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800646 EXPECT_FALSE(flag1.get());
647 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200648 // Force them to run now.
649 EXPECT_TRUE(invoker.Flush());
nissed9b75be2015-11-16 00:54:07 -0800650 EXPECT_TRUE(flag1.get());
651 EXPECT_TRUE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200652}
653
654TEST_F(GuardedAsyncInvokeTest, FlushWithIds) {
655 GuardedAsyncInvoker invoker;
nissed9b75be2015-11-16 00:54:07 -0800656 AtomicBool flag1;
657 AtomicBool flag2;
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200658 // Queue two async calls to the current thread, one with a message id.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700659 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag1), 5));
660 EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag2)));
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200661 // Because we haven't pumped messages, these should not have run yet.
nissed9b75be2015-11-16 00:54:07 -0800662 EXPECT_FALSE(flag1.get());
663 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200664 // Execute pending calls with id == 5.
665 EXPECT_TRUE(invoker.Flush(5));
nissed9b75be2015-11-16 00:54:07 -0800666 EXPECT_TRUE(flag1.get());
667 EXPECT_FALSE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200668 flag1 = false;
669 // Execute all pending calls. The id == 5 call should not execute again.
670 EXPECT_TRUE(invoker.Flush());
nissed9b75be2015-11-16 00:54:07 -0800671 EXPECT_FALSE(flag1.get());
672 EXPECT_TRUE(flag2.get());
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200673}
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100674
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100675void ThreadIsCurrent(Thread* thread, bool* result, Event* event) {
676 *result = thread->IsCurrent();
677 event->Set();
678}
679
680void WaitAndSetEvent(Event* wait_event, Event* set_event) {
681 wait_event->Wait(Event::kForever);
682 set_event->Set();
683}
684
685// A functor that keeps track of the number of copies and moves.
686class LifeCycleFunctor {
687 public:
688 struct Stats {
689 size_t copy_count = 0;
690 size_t move_count = 0;
691 };
692
693 LifeCycleFunctor(Stats* stats, Event* event) : stats_(stats), event_(event) {}
694 LifeCycleFunctor(const LifeCycleFunctor& other) { *this = other; }
695 LifeCycleFunctor(LifeCycleFunctor&& other) { *this = std::move(other); }
696
697 LifeCycleFunctor& operator=(const LifeCycleFunctor& other) {
698 stats_ = other.stats_;
699 event_ = other.event_;
700 ++stats_->copy_count;
701 return *this;
702 }
703
704 LifeCycleFunctor& operator=(LifeCycleFunctor&& other) {
705 stats_ = other.stats_;
706 event_ = other.event_;
707 ++stats_->move_count;
708 return *this;
709 }
710
711 void operator()() { event_->Set(); }
712
713 private:
714 Stats* stats_;
715 Event* event_;
716};
717
718// A functor that verifies the thread it was destroyed on.
719class DestructionFunctor {
720 public:
721 DestructionFunctor(Thread* thread, bool* thread_was_current, Event* event)
722 : thread_(thread),
723 thread_was_current_(thread_was_current),
724 event_(event) {}
725 ~DestructionFunctor() {
726 // Only signal the event if this was the functor that was invoked to avoid
727 // the event being signaled due to the destruction of temporary/moved
728 // versions of this object.
729 if (was_invoked_) {
730 *thread_was_current_ = thread_->IsCurrent();
731 event_->Set();
732 }
733 }
734
735 void operator()() { was_invoked_ = true; }
736
737 private:
738 Thread* thread_;
739 bool* thread_was_current_;
740 Event* event_;
741 bool was_invoked_ = false;
742};
743
744TEST(ThreadPostTaskTest, InvokesWithBind) {
745 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
746 background_thread->Start();
747
748 Event event;
749 background_thread->PostTask(RTC_FROM_HERE, Bind(&Event::Set, &event));
750 event.Wait(Event::kForever);
751}
752
753TEST(ThreadPostTaskTest, InvokesWithLambda) {
754 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
755 background_thread->Start();
756
757 Event event;
758 background_thread->PostTask(RTC_FROM_HERE, [&event] { event.Set(); });
759 event.Wait(Event::kForever);
760}
761
762TEST(ThreadPostTaskTest, InvokesWithCopiedFunctor) {
763 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
764 background_thread->Start();
765
766 LifeCycleFunctor::Stats stats;
767 Event event;
768 LifeCycleFunctor functor(&stats, &event);
769 background_thread->PostTask(RTC_FROM_HERE, functor);
770 event.Wait(Event::kForever);
771
772 EXPECT_EQ(1u, stats.copy_count);
773 EXPECT_EQ(0u, stats.move_count);
774}
775
776TEST(ThreadPostTaskTest, InvokesWithMovedFunctor) {
777 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
778 background_thread->Start();
779
780 LifeCycleFunctor::Stats stats;
781 Event event;
782 LifeCycleFunctor functor(&stats, &event);
783 background_thread->PostTask(RTC_FROM_HERE, std::move(functor));
784 event.Wait(Event::kForever);
785
786 EXPECT_EQ(0u, stats.copy_count);
787 EXPECT_EQ(1u, stats.move_count);
788}
789
790TEST(ThreadPostTaskTest, InvokesWithReferencedFunctorShouldCopy) {
791 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
792 background_thread->Start();
793
794 LifeCycleFunctor::Stats stats;
795 Event event;
796 LifeCycleFunctor functor(&stats, &event);
797 LifeCycleFunctor& functor_ref = functor;
798 background_thread->PostTask(RTC_FROM_HERE, functor_ref);
799 event.Wait(Event::kForever);
800
801 EXPECT_EQ(1u, stats.copy_count);
802 EXPECT_EQ(0u, stats.move_count);
803}
804
805TEST(ThreadPostTaskTest, InvokesWithCopiedFunctorDestroyedOnTargetThread) {
806 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
807 background_thread->Start();
808
809 Event event;
810 bool was_invoked_on_background_thread = false;
811 DestructionFunctor functor(background_thread.get(),
812 &was_invoked_on_background_thread, &event);
813 background_thread->PostTask(RTC_FROM_HERE, functor);
814 event.Wait(Event::kForever);
815
816 EXPECT_TRUE(was_invoked_on_background_thread);
817}
818
819TEST(ThreadPostTaskTest, InvokesWithMovedFunctorDestroyedOnTargetThread) {
820 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
821 background_thread->Start();
822
823 Event event;
824 bool was_invoked_on_background_thread = false;
825 DestructionFunctor functor(background_thread.get(),
826 &was_invoked_on_background_thread, &event);
827 background_thread->PostTask(RTC_FROM_HERE, std::move(functor));
828 event.Wait(Event::kForever);
829
830 EXPECT_TRUE(was_invoked_on_background_thread);
831}
832
833TEST(ThreadPostTaskTest,
834 InvokesWithReferencedFunctorShouldCopyAndDestroyedOnTargetThread) {
835 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
836 background_thread->Start();
837
838 Event event;
839 bool was_invoked_on_background_thread = false;
840 DestructionFunctor functor(background_thread.get(),
841 &was_invoked_on_background_thread, &event);
842 DestructionFunctor& functor_ref = functor;
843 background_thread->PostTask(RTC_FROM_HERE, functor_ref);
844 event.Wait(Event::kForever);
845
846 EXPECT_TRUE(was_invoked_on_background_thread);
847}
848
849TEST(ThreadPostTaskTest, InvokesOnBackgroundThread) {
850 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
851 background_thread->Start();
852
853 Event event;
854 bool was_invoked_on_background_thread = false;
855 background_thread->PostTask(RTC_FROM_HERE,
856 Bind(&ThreadIsCurrent, background_thread.get(),
857 &was_invoked_on_background_thread, &event));
858 event.Wait(Event::kForever);
859
860 EXPECT_TRUE(was_invoked_on_background_thread);
861}
862
863TEST(ThreadPostTaskTest, InvokesAsynchronously) {
864 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
865 background_thread->Start();
866
867 // The first event ensures that SendSingleMessage() is not blocking this
868 // thread. The second event ensures that the message is processed.
869 Event event_set_by_test_thread;
870 Event event_set_by_background_thread;
871 background_thread->PostTask(RTC_FROM_HERE,
872 Bind(&WaitAndSetEvent, &event_set_by_test_thread,
873 &event_set_by_background_thread));
874 event_set_by_test_thread.Set();
875 event_set_by_background_thread.Wait(Event::kForever);
876}
877
878TEST(ThreadPostTaskTest, InvokesInPostedOrder) {
879 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
880 background_thread->Start();
881
882 Event first;
883 Event second;
884 Event third;
885 Event fourth;
886
887 background_thread->PostTask(RTC_FROM_HERE,
888 Bind(&WaitAndSetEvent, &first, &second));
889 background_thread->PostTask(RTC_FROM_HERE,
890 Bind(&WaitAndSetEvent, &second, &third));
891 background_thread->PostTask(RTC_FROM_HERE,
892 Bind(&WaitAndSetEvent, &third, &fourth));
893
894 // All tasks have been posted before the first one is unblocked.
895 first.Set();
896 // Only if the chain is invoked in posted order will the last event be set.
897 fourth.Wait(Event::kForever);
898}
899
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100900} // namespace
901} // namespace rtc