1 /*
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 "rtc_base/thread.h"
12
13 #include <memory>
14
15 #include "api/field_trials_view.h"
16 #include "api/task_queue/task_queue_factory.h"
17 #include "api/task_queue/task_queue_test.h"
18 #include "api/units/time_delta.h"
19 #include "rtc_base/async_udp_socket.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/event.h"
22 #include "rtc_base/fake_clock.h"
23 #include "rtc_base/gunit.h"
24 #include "rtc_base/internal/default_socket_server.h"
25 #include "rtc_base/null_socket_server.h"
26 #include "rtc_base/physical_socket_server.h"
27 #include "rtc_base/ref_counted_object.h"
28 #include "rtc_base/socket_address.h"
29 #include "rtc_base/synchronization/mutex.h"
30 #include "rtc_base/third_party/sigslot/sigslot.h"
31 #include "test/gmock.h"
32 #include "test/testsupport/rtc_expect_death.h"
33
34 #if defined(WEBRTC_WIN)
35 #include <comdef.h> // NOLINT
36
37 #endif
38
39 namespace rtc {
40 namespace {
41
42 using ::testing::ElementsAre;
43 using ::webrtc::TimeDelta;
44
45 // Generates a sequence of numbers (collaboratively).
46 class TestGenerator {
47 public:
TestGenerator()48 TestGenerator() : last(0), count(0) {}
49
Next(int prev)50 int Next(int prev) {
51 int result = prev + last;
52 last = result;
53 count += 1;
54 return result;
55 }
56
57 int last;
58 int count;
59 };
60
61 // Receives messages and sends on a socket.
62 class MessageClient : public TestGenerator {
63 public:
MessageClient(Thread * pth,Socket * socket)64 MessageClient(Thread* pth, Socket* socket) : socket_(socket) {}
65
~MessageClient()66 ~MessageClient() { delete socket_; }
67
OnValue(int value)68 void OnValue(int value) {
69 int result = Next(value);
70 EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
71 }
72
73 private:
74 Socket* socket_;
75 };
76
77 // Receives on a socket and sends by posting messages.
78 class SocketClient : public TestGenerator, public sigslot::has_slots<> {
79 public:
SocketClient(Socket * socket,const SocketAddress & addr,Thread * post_thread,MessageClient * phandler)80 SocketClient(Socket* socket,
81 const SocketAddress& addr,
82 Thread* post_thread,
83 MessageClient* phandler)
84 : socket_(AsyncUDPSocket::Create(socket, addr)),
85 post_thread_(post_thread),
86 post_handler_(phandler) {
87 socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
88 }
89
~SocketClient()90 ~SocketClient() override { delete socket_; }
91
address() const92 SocketAddress address() const { return socket_->GetLocalAddress(); }
93
OnPacket(AsyncPacketSocket * socket,const char * buf,size_t size,const SocketAddress & remote_addr,const int64_t & packet_time_us)94 void OnPacket(AsyncPacketSocket* socket,
95 const char* buf,
96 size_t size,
97 const SocketAddress& remote_addr,
98 const int64_t& packet_time_us) {
99 EXPECT_EQ(size, sizeof(uint32_t));
100 uint32_t prev = reinterpret_cast<const uint32_t*>(buf)[0];
101 uint32_t result = Next(prev);
102
103 post_thread_->PostDelayedTask([post_handler_ = post_handler_,
104 result] { post_handler_->OnValue(result); },
105 TimeDelta::Millis(200));
106 }
107
108 private:
109 AsyncUDPSocket* socket_;
110 Thread* post_thread_;
111 MessageClient* post_handler_;
112 };
113
114 class CustomThread : public rtc::Thread {
115 public:
CustomThread()116 CustomThread()
117 : Thread(std::unique_ptr<SocketServer>(new rtc::NullSocketServer())) {}
~CustomThread()118 ~CustomThread() override { Stop(); }
Start()119 bool Start() { return false; }
120
WrapCurrent()121 bool WrapCurrent() { return Thread::WrapCurrent(); }
UnwrapCurrent()122 void UnwrapCurrent() { Thread::UnwrapCurrent(); }
123 };
124
125 // A thread that does nothing when it runs and signals an event
126 // when it is destroyed.
127 class SignalWhenDestroyedThread : public Thread {
128 public:
SignalWhenDestroyedThread(Event * event)129 SignalWhenDestroyedThread(Event* event)
130 : Thread(std::unique_ptr<SocketServer>(new NullSocketServer())),
131 event_(event) {}
132
~SignalWhenDestroyedThread()133 ~SignalWhenDestroyedThread() override {
134 Stop();
135 event_->Set();
136 }
137
Run()138 void Run() override {
139 // Do nothing.
140 }
141
142 private:
143 Event* event_;
144 };
145
146 // See: https://code.google.com/p/webrtc/issues/detail?id=2409
TEST(ThreadTest,DISABLED_Main)147 TEST(ThreadTest, DISABLED_Main) {
148 rtc::AutoThread main_thread;
149 const SocketAddress addr("127.0.0.1", 0);
150
151 // Create the messaging client on its own thread.
152 auto th1 = Thread::CreateWithSocketServer();
153 Socket* socket = th1->socketserver()->CreateSocket(addr.family(), SOCK_DGRAM);
154 MessageClient msg_client(th1.get(), socket);
155
156 // Create the socket client on its own thread.
157 auto th2 = Thread::CreateWithSocketServer();
158 Socket* asocket =
159 th2->socketserver()->CreateSocket(addr.family(), SOCK_DGRAM);
160 SocketClient sock_client(asocket, addr, th1.get(), &msg_client);
161
162 socket->Connect(sock_client.address());
163
164 th1->Start();
165 th2->Start();
166
167 // Get the messages started.
168 th1->PostDelayedTask([&msg_client] { msg_client.OnValue(1); },
169 TimeDelta::Millis(100));
170
171 // Give the clients a little while to run.
172 // Messages will be processed at 100, 300, 500, 700, 900.
173 Thread* th_main = Thread::Current();
174 th_main->ProcessMessages(1000);
175
176 // Stop the sending client. Give the receiver a bit longer to run, in case
177 // it is running on a machine that is under load (e.g. the build machine).
178 th1->Stop();
179 th_main->ProcessMessages(200);
180 th2->Stop();
181
182 // Make sure the results were correct
183 EXPECT_EQ(5, msg_client.count);
184 EXPECT_EQ(34, msg_client.last);
185 EXPECT_EQ(5, sock_client.count);
186 EXPECT_EQ(55, sock_client.last);
187 }
188
TEST(ThreadTest,CountBlockingCalls)189 TEST(ThreadTest, CountBlockingCalls) {
190 rtc::AutoThread current;
191
192 // When the test runs, this will print out:
193 // (thread_unittest.cc:262): Blocking TestBody: total=2 (actual=1, could=1)
194 RTC_LOG_THREAD_BLOCK_COUNT();
195 #if RTC_DCHECK_IS_ON
196 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
197 [&](uint32_t actual_block, uint32_t could_block) {
198 EXPECT_EQ(1u, actual_block);
199 EXPECT_EQ(1u, could_block);
200 });
201
202 EXPECT_EQ(0u, blocked_calls.GetBlockingCallCount());
203 EXPECT_EQ(0u, blocked_calls.GetCouldBeBlockingCallCount());
204 EXPECT_EQ(0u, blocked_calls.GetTotalBlockedCallCount());
205
206 // Test invoking on the current thread. This should not count as an 'actual'
207 // invoke, but should still count as an invoke that could block since we
208 // that the call to `BlockingCall` serves a purpose in some configurations
209 // (and should not be used a general way to call methods on the same thread).
210 current.BlockingCall([]() {});
211 EXPECT_EQ(0u, blocked_calls.GetBlockingCallCount());
212 EXPECT_EQ(1u, blocked_calls.GetCouldBeBlockingCallCount());
213 EXPECT_EQ(1u, blocked_calls.GetTotalBlockedCallCount());
214
215 // Create a new thread to invoke on.
216 auto thread = Thread::CreateWithSocketServer();
217 thread->Start();
218 EXPECT_EQ(42, thread->BlockingCall([]() { return 42; }));
219 EXPECT_EQ(1u, blocked_calls.GetBlockingCallCount());
220 EXPECT_EQ(1u, blocked_calls.GetCouldBeBlockingCallCount());
221 EXPECT_EQ(2u, blocked_calls.GetTotalBlockedCallCount());
222 thread->Stop();
223 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
224 #else
225 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);
226 RTC_LOG(LS_INFO) << "Test not active in this config";
227 #endif
228 }
229
230 #if RTC_DCHECK_IS_ON
TEST(ThreadTest,CountBlockingCallsOneCallback)231 TEST(ThreadTest, CountBlockingCallsOneCallback) {
232 rtc::AutoThread current;
233 bool was_called_back = false;
234 {
235 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
236 [&](uint32_t actual_block, uint32_t could_block) {
237 was_called_back = true;
238 });
239 current.BlockingCall([]() {});
240 }
241 EXPECT_TRUE(was_called_back);
242 }
243
TEST(ThreadTest,CountBlockingCallsSkipCallback)244 TEST(ThreadTest, CountBlockingCallsSkipCallback) {
245 rtc::AutoThread current;
246 bool was_called_back = false;
247 {
248 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
249 [&](uint32_t actual_block, uint32_t could_block) {
250 was_called_back = true;
251 });
252 // Changed `blocked_calls` to not issue the callback if there are 1 or
253 // fewer blocking calls (i.e. we set the minimum required number to 2).
254 blocked_calls.set_minimum_call_count_for_callback(2);
255 current.BlockingCall([]() {});
256 }
257 // We should not have gotten a call back.
258 EXPECT_FALSE(was_called_back);
259 }
260 #endif
261
262 // Test that setting thread names doesn't cause a malfunction.
263 // There's no easy way to verify the name was set properly at this time.
TEST(ThreadTest,Names)264 TEST(ThreadTest, Names) {
265 // Default name
266 auto thread = Thread::CreateWithSocketServer();
267 EXPECT_TRUE(thread->Start());
268 thread->Stop();
269 // Name with no object parameter
270 thread = Thread::CreateWithSocketServer();
271 EXPECT_TRUE(thread->SetName("No object", nullptr));
272 EXPECT_TRUE(thread->Start());
273 thread->Stop();
274 // Really long name
275 thread = Thread::CreateWithSocketServer();
276 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
277 EXPECT_TRUE(thread->Start());
278 thread->Stop();
279 }
280
TEST(ThreadTest,Wrap)281 TEST(ThreadTest, Wrap) {
282 Thread* current_thread = Thread::Current();
283 ThreadManager::Instance()->SetCurrentThread(nullptr);
284
285 {
286 CustomThread cthread;
287 EXPECT_TRUE(cthread.WrapCurrent());
288 EXPECT_EQ(&cthread, Thread::Current());
289 EXPECT_TRUE(cthread.RunningForTest());
290 EXPECT_FALSE(cthread.IsOwned());
291 cthread.UnwrapCurrent();
292 EXPECT_FALSE(cthread.RunningForTest());
293 }
294 ThreadManager::Instance()->SetCurrentThread(current_thread);
295 }
296
297 #if (!defined(NDEBUG) || RTC_DCHECK_IS_ON)
TEST(ThreadTest,InvokeToThreadAllowedReturnsTrueWithoutPolicies)298 TEST(ThreadTest, InvokeToThreadAllowedReturnsTrueWithoutPolicies) {
299 rtc::AutoThread main_thread;
300 // Create and start the thread.
301 auto thread1 = Thread::CreateWithSocketServer();
302 auto thread2 = Thread::CreateWithSocketServer();
303
304 thread1->PostTask(
305 [&]() { EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
306 main_thread.ProcessMessages(100);
307 }
308
TEST(ThreadTest,InvokeAllowedWhenThreadsAdded)309 TEST(ThreadTest, InvokeAllowedWhenThreadsAdded) {
310 rtc::AutoThread main_thread;
311 // Create and start the thread.
312 auto thread1 = Thread::CreateWithSocketServer();
313 auto thread2 = Thread::CreateWithSocketServer();
314 auto thread3 = Thread::CreateWithSocketServer();
315 auto thread4 = Thread::CreateWithSocketServer();
316
317 thread1->AllowInvokesToThread(thread2.get());
318 thread1->AllowInvokesToThread(thread3.get());
319
320 thread1->PostTask([&]() {
321 EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get()));
322 EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread3.get()));
323 EXPECT_FALSE(thread1->IsInvokeToThreadAllowed(thread4.get()));
324 });
325 main_thread.ProcessMessages(100);
326 }
327
TEST(ThreadTest,InvokesDisallowedWhenDisallowAllInvokes)328 TEST(ThreadTest, InvokesDisallowedWhenDisallowAllInvokes) {
329 rtc::AutoThread main_thread;
330 // Create and start the thread.
331 auto thread1 = Thread::CreateWithSocketServer();
332 auto thread2 = Thread::CreateWithSocketServer();
333
334 thread1->DisallowAllInvokes();
335
336 thread1->PostTask(
337 [&]() { EXPECT_FALSE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
338 main_thread.ProcessMessages(100);
339 }
340 #endif // (!defined(NDEBUG) || RTC_DCHECK_IS_ON)
341
TEST(ThreadTest,InvokesAllowedByDefault)342 TEST(ThreadTest, InvokesAllowedByDefault) {
343 rtc::AutoThread main_thread;
344 // Create and start the thread.
345 auto thread1 = Thread::CreateWithSocketServer();
346 auto thread2 = Thread::CreateWithSocketServer();
347
348 thread1->PostTask(
349 [&]() { EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
350 main_thread.ProcessMessages(100);
351 }
352
TEST(ThreadTest,BlockingCall)353 TEST(ThreadTest, BlockingCall) {
354 // Create and start the thread.
355 auto thread = Thread::CreateWithSocketServer();
356 thread->Start();
357 // Try calling functors.
358 EXPECT_EQ(42, thread->BlockingCall([] { return 42; }));
359 bool called = false;
360 thread->BlockingCall([&] { called = true; });
361 EXPECT_TRUE(called);
362
363 // Try calling bare functions.
364 struct LocalFuncs {
365 static int Func1() { return 999; }
366 static void Func2() {}
367 };
368 EXPECT_EQ(999, thread->BlockingCall(&LocalFuncs::Func1));
369 thread->BlockingCall(&LocalFuncs::Func2);
370 }
371
372 // Verifies that two threads calling Invoke on each other at the same time does
373 // not deadlock but crash.
374 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(ThreadTest,TwoThreadsInvokeDeathTest)375 TEST(ThreadTest, TwoThreadsInvokeDeathTest) {
376 GTEST_FLAG_SET(death_test_style, "threadsafe");
377 AutoThread thread;
378 Thread* main_thread = Thread::Current();
379 auto other_thread = Thread::CreateWithSocketServer();
380 other_thread->Start();
381 other_thread->BlockingCall([main_thread] {
382 RTC_EXPECT_DEATH(main_thread->BlockingCall([] {}), "loop");
383 });
384 }
385
TEST(ThreadTest,ThreeThreadsInvokeDeathTest)386 TEST(ThreadTest, ThreeThreadsInvokeDeathTest) {
387 GTEST_FLAG_SET(death_test_style, "threadsafe");
388 AutoThread thread;
389 Thread* first = Thread::Current();
390
391 auto second = Thread::Create();
392 second->Start();
393 auto third = Thread::Create();
394 third->Start();
395
396 second->BlockingCall([&] {
397 third->BlockingCall(
398 [&] { RTC_EXPECT_DEATH(first->BlockingCall([] {}), "loop"); });
399 });
400 }
401
402 #endif
403
404 // Verifies that if thread A invokes a call on thread B and thread C is trying
405 // to invoke A at the same time, thread A does not handle C's invoke while
406 // invoking B.
TEST(ThreadTest,ThreeThreadsBlockingCall)407 TEST(ThreadTest, ThreeThreadsBlockingCall) {
408 AutoThread thread;
409 Thread* thread_a = Thread::Current();
410 auto thread_b = Thread::CreateWithSocketServer();
411 auto thread_c = Thread::CreateWithSocketServer();
412 thread_b->Start();
413 thread_c->Start();
414
415 class LockedBool {
416 public:
417 explicit LockedBool(bool value) : value_(value) {}
418
419 void Set(bool value) {
420 webrtc::MutexLock lock(&mutex_);
421 value_ = value;
422 }
423
424 bool Get() {
425 webrtc::MutexLock lock(&mutex_);
426 return value_;
427 }
428
429 private:
430 webrtc::Mutex mutex_;
431 bool value_ RTC_GUARDED_BY(mutex_);
432 };
433
434 struct LocalFuncs {
435 static void Set(LockedBool* out) { out->Set(true); }
436 static void InvokeSet(Thread* thread, LockedBool* out) {
437 thread->BlockingCall([out] { Set(out); });
438 }
439
440 // Set `out` true and call InvokeSet on `thread`.
441 static void SetAndInvokeSet(LockedBool* out,
442 Thread* thread,
443 LockedBool* out_inner) {
444 out->Set(true);
445 InvokeSet(thread, out_inner);
446 }
447
448 // Asynchronously invoke SetAndInvokeSet on `thread1` and wait until
449 // `thread1` starts the call.
450 static void AsyncInvokeSetAndWait(Thread* thread1,
451 Thread* thread2,
452 LockedBool* out) {
453 LockedBool async_invoked(false);
454
455 thread1->PostTask([&async_invoked, thread2, out] {
456 SetAndInvokeSet(&async_invoked, thread2, out);
457 });
458
459 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
460 }
461 };
462
463 LockedBool thread_a_called(false);
464
465 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
466 // Thread B returns when C receives the call and C should be blocked until A
467 // starts to process messages.
468 Thread* thread_c_ptr = thread_c.get();
469 thread_b->BlockingCall([thread_c_ptr, thread_a, &thread_a_called] {
470 LocalFuncs::AsyncInvokeSetAndWait(thread_c_ptr, thread_a, &thread_a_called);
471 });
472 EXPECT_FALSE(thread_a_called.Get());
473
474 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
475 }
476
DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(FakeClock & clock,Thread & q)477 static void DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(
478 FakeClock& clock,
479 Thread& q) {
480 std::vector<int> run_order;
481
482 Event done;
483 int64_t now = TimeMillis();
484 q.PostDelayedTask([&] { run_order.push_back(3); }, TimeDelta::Millis(3));
485 q.PostDelayedTask([&] { run_order.push_back(0); }, TimeDelta::Millis(1));
486 q.PostDelayedTask([&] { run_order.push_back(1); }, TimeDelta::Millis(2));
487 q.PostDelayedTask([&] { run_order.push_back(4); }, TimeDelta::Millis(3));
488 q.PostDelayedTask([&] { run_order.push_back(2); }, TimeDelta::Millis(2));
489 q.PostDelayedTask([&] { done.Set(); }, TimeDelta::Millis(4));
490 // Validate time was frozen while tasks were posted.
491 RTC_DCHECK_EQ(TimeMillis(), now);
492
493 // Change time to make all tasks ready to run and wait for them.
494 clock.AdvanceTime(TimeDelta::Millis(4));
495 ASSERT_TRUE(done.Wait(TimeDelta::Seconds(1)));
496
497 EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
498 }
499
TEST(ThreadTest,DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder)500 TEST(ThreadTest, DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder) {
501 ScopedBaseFakeClock clock;
502 Thread q(CreateDefaultSocketServer(), true);
503 q.Start();
504 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(clock, q);
505
506 NullSocketServer nullss;
507 Thread q_nullss(&nullss, true);
508 q_nullss.Start();
509 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(clock, q_nullss);
510 }
511
512 // Ensure that ProcessAllMessageQueues does its essential function; process
513 // all messages (both delayed and non delayed) up until the current time, on
514 // all registered message queues.
TEST(ThreadManager,ProcessAllMessageQueues)515 TEST(ThreadManager, ProcessAllMessageQueues) {
516 rtc::AutoThread main_thread;
517 Event entered_process_all_message_queues(true, false);
518 auto a = Thread::CreateWithSocketServer();
519 auto b = Thread::CreateWithSocketServer();
520 a->Start();
521 b->Start();
522
523 std::atomic<int> messages_processed(0);
524 auto incrementer = [&messages_processed,
525 &entered_process_all_message_queues] {
526 // Wait for event as a means to ensure Increment doesn't occur outside
527 // of ProcessAllMessageQueues. The event is set by a message posted to
528 // the main thread, which is guaranteed to be handled inside
529 // ProcessAllMessageQueues.
530 entered_process_all_message_queues.Wait(Event::kForever);
531 messages_processed.fetch_add(1);
532 };
533 auto event_signaler = [&entered_process_all_message_queues] {
534 entered_process_all_message_queues.Set();
535 };
536
537 // Post messages (both delayed and non delayed) to both threads.
538 a->PostTask(incrementer);
539 b->PostTask(incrementer);
540 a->PostDelayedTask(incrementer, TimeDelta::Zero());
541 b->PostDelayedTask(incrementer, TimeDelta::Zero());
542 main_thread.PostTask(event_signaler);
543
544 ThreadManager::ProcessAllMessageQueuesForTesting();
545 EXPECT_EQ(4, messages_processed.load(std::memory_order_acquire));
546 }
547
548 // Test that ProcessAllMessageQueues doesn't hang if a thread is quitting.
TEST(ThreadManager,ProcessAllMessageQueuesWithQuittingThread)549 TEST(ThreadManager, ProcessAllMessageQueuesWithQuittingThread) {
550 auto t = Thread::CreateWithSocketServer();
551 t->Start();
552 t->Quit();
553 ThreadManager::ProcessAllMessageQueuesForTesting();
554 }
555
WaitAndSetEvent(Event * wait_event,Event * set_event)556 void WaitAndSetEvent(Event* wait_event, Event* set_event) {
557 wait_event->Wait(Event::kForever);
558 set_event->Set();
559 }
560
561 // A functor that keeps track of the number of copies and moves.
562 class LifeCycleFunctor {
563 public:
564 struct Stats {
565 size_t copy_count = 0;
566 size_t move_count = 0;
567 };
568
LifeCycleFunctor(Stats * stats,Event * event)569 LifeCycleFunctor(Stats* stats, Event* event) : stats_(stats), event_(event) {}
LifeCycleFunctor(const LifeCycleFunctor & other)570 LifeCycleFunctor(const LifeCycleFunctor& other) { *this = other; }
LifeCycleFunctor(LifeCycleFunctor && other)571 LifeCycleFunctor(LifeCycleFunctor&& other) { *this = std::move(other); }
572
operator =(const LifeCycleFunctor & other)573 LifeCycleFunctor& operator=(const LifeCycleFunctor& other) {
574 stats_ = other.stats_;
575 event_ = other.event_;
576 ++stats_->copy_count;
577 return *this;
578 }
579
operator =(LifeCycleFunctor && other)580 LifeCycleFunctor& operator=(LifeCycleFunctor&& other) {
581 stats_ = other.stats_;
582 event_ = other.event_;
583 ++stats_->move_count;
584 return *this;
585 }
586
operator ()()587 void operator()() { event_->Set(); }
588
589 private:
590 Stats* stats_;
591 Event* event_;
592 };
593
594 // A functor that verifies the thread it was destroyed on.
595 class DestructionFunctor {
596 public:
DestructionFunctor(Thread * thread,bool * thread_was_current,Event * event)597 DestructionFunctor(Thread* thread, bool* thread_was_current, Event* event)
598 : thread_(thread),
599 thread_was_current_(thread_was_current),
600 event_(event) {}
~DestructionFunctor()601 ~DestructionFunctor() {
602 // Only signal the event if this was the functor that was invoked to avoid
603 // the event being signaled due to the destruction of temporary/moved
604 // versions of this object.
605 if (was_invoked_) {
606 *thread_was_current_ = thread_->IsCurrent();
607 event_->Set();
608 }
609 }
610
operator ()()611 void operator()() { was_invoked_ = true; }
612
613 private:
614 Thread* thread_;
615 bool* thread_was_current_;
616 Event* event_;
617 bool was_invoked_ = false;
618 };
619
TEST(ThreadPostTaskTest,InvokesWithLambda)620 TEST(ThreadPostTaskTest, InvokesWithLambda) {
621 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
622 background_thread->Start();
623
624 Event event;
625 background_thread->PostTask([&event] { event.Set(); });
626 event.Wait(Event::kForever);
627 }
628
TEST(ThreadPostTaskTest,InvokesWithCopiedFunctor)629 TEST(ThreadPostTaskTest, InvokesWithCopiedFunctor) {
630 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
631 background_thread->Start();
632
633 LifeCycleFunctor::Stats stats;
634 Event event;
635 LifeCycleFunctor functor(&stats, &event);
636 background_thread->PostTask(functor);
637 event.Wait(Event::kForever);
638
639 EXPECT_EQ(1u, stats.copy_count);
640 EXPECT_EQ(0u, stats.move_count);
641 }
642
TEST(ThreadPostTaskTest,InvokesWithMovedFunctor)643 TEST(ThreadPostTaskTest, InvokesWithMovedFunctor) {
644 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
645 background_thread->Start();
646
647 LifeCycleFunctor::Stats stats;
648 Event event;
649 LifeCycleFunctor functor(&stats, &event);
650 background_thread->PostTask(std::move(functor));
651 event.Wait(Event::kForever);
652
653 EXPECT_EQ(0u, stats.copy_count);
654 EXPECT_EQ(1u, stats.move_count);
655 }
656
TEST(ThreadPostTaskTest,InvokesWithReferencedFunctorShouldCopy)657 TEST(ThreadPostTaskTest, InvokesWithReferencedFunctorShouldCopy) {
658 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
659 background_thread->Start();
660
661 LifeCycleFunctor::Stats stats;
662 Event event;
663 LifeCycleFunctor functor(&stats, &event);
664 LifeCycleFunctor& functor_ref = functor;
665 background_thread->PostTask(functor_ref);
666 event.Wait(Event::kForever);
667
668 EXPECT_EQ(1u, stats.copy_count);
669 EXPECT_EQ(0u, stats.move_count);
670 }
671
TEST(ThreadPostTaskTest,InvokesWithCopiedFunctorDestroyedOnTargetThread)672 TEST(ThreadPostTaskTest, InvokesWithCopiedFunctorDestroyedOnTargetThread) {
673 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
674 background_thread->Start();
675
676 Event event;
677 bool was_invoked_on_background_thread = false;
678 DestructionFunctor functor(background_thread.get(),
679 &was_invoked_on_background_thread, &event);
680 background_thread->PostTask(functor);
681 event.Wait(Event::kForever);
682
683 EXPECT_TRUE(was_invoked_on_background_thread);
684 }
685
TEST(ThreadPostTaskTest,InvokesWithMovedFunctorDestroyedOnTargetThread)686 TEST(ThreadPostTaskTest, InvokesWithMovedFunctorDestroyedOnTargetThread) {
687 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
688 background_thread->Start();
689
690 Event event;
691 bool was_invoked_on_background_thread = false;
692 DestructionFunctor functor(background_thread.get(),
693 &was_invoked_on_background_thread, &event);
694 background_thread->PostTask(std::move(functor));
695 event.Wait(Event::kForever);
696
697 EXPECT_TRUE(was_invoked_on_background_thread);
698 }
699
TEST(ThreadPostTaskTest,InvokesWithReferencedFunctorShouldCopyAndDestroyedOnTargetThread)700 TEST(ThreadPostTaskTest,
701 InvokesWithReferencedFunctorShouldCopyAndDestroyedOnTargetThread) {
702 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
703 background_thread->Start();
704
705 Event event;
706 bool was_invoked_on_background_thread = false;
707 DestructionFunctor functor(background_thread.get(),
708 &was_invoked_on_background_thread, &event);
709 DestructionFunctor& functor_ref = functor;
710 background_thread->PostTask(functor_ref);
711 event.Wait(Event::kForever);
712
713 EXPECT_TRUE(was_invoked_on_background_thread);
714 }
715
TEST(ThreadPostTaskTest,InvokesOnBackgroundThread)716 TEST(ThreadPostTaskTest, InvokesOnBackgroundThread) {
717 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
718 background_thread->Start();
719
720 Event event;
721 bool was_invoked_on_background_thread = false;
722 Thread* background_thread_ptr = background_thread.get();
723 background_thread->PostTask(
724 [background_thread_ptr, &was_invoked_on_background_thread, &event] {
725 was_invoked_on_background_thread = background_thread_ptr->IsCurrent();
726 event.Set();
727 });
728 event.Wait(Event::kForever);
729
730 EXPECT_TRUE(was_invoked_on_background_thread);
731 }
732
TEST(ThreadPostTaskTest,InvokesAsynchronously)733 TEST(ThreadPostTaskTest, InvokesAsynchronously) {
734 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
735 background_thread->Start();
736
737 // The first event ensures that SendSingleMessage() is not blocking this
738 // thread. The second event ensures that the message is processed.
739 Event event_set_by_test_thread;
740 Event event_set_by_background_thread;
741 background_thread->PostTask(
742 [&event_set_by_test_thread, &event_set_by_background_thread] {
743 WaitAndSetEvent(&event_set_by_test_thread,
744 &event_set_by_background_thread);
745 });
746 event_set_by_test_thread.Set();
747 event_set_by_background_thread.Wait(Event::kForever);
748 }
749
TEST(ThreadPostTaskTest,InvokesInPostedOrder)750 TEST(ThreadPostTaskTest, InvokesInPostedOrder) {
751 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
752 background_thread->Start();
753
754 Event first;
755 Event second;
756 Event third;
757 Event fourth;
758
759 background_thread->PostTask(
760 [&first, &second] { WaitAndSetEvent(&first, &second); });
761 background_thread->PostTask(
762 [&second, &third] { WaitAndSetEvent(&second, &third); });
763 background_thread->PostTask(
764 [&third, &fourth] { WaitAndSetEvent(&third, &fourth); });
765
766 // All tasks have been posted before the first one is unblocked.
767 first.Set();
768 // Only if the chain is invoked in posted order will the last event be set.
769 fourth.Wait(Event::kForever);
770 }
771
TEST(ThreadPostDelayedTaskTest,InvokesAsynchronously)772 TEST(ThreadPostDelayedTaskTest, InvokesAsynchronously) {
773 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
774 background_thread->Start();
775
776 // The first event ensures that SendSingleMessage() is not blocking this
777 // thread. The second event ensures that the message is processed.
778 Event event_set_by_test_thread;
779 Event event_set_by_background_thread;
780 background_thread->PostDelayedTask(
781 [&event_set_by_test_thread, &event_set_by_background_thread] {
782 WaitAndSetEvent(&event_set_by_test_thread,
783 &event_set_by_background_thread);
784 },
785 TimeDelta::Millis(10));
786 event_set_by_test_thread.Set();
787 event_set_by_background_thread.Wait(Event::kForever);
788 }
789
TEST(ThreadPostDelayedTaskTest,InvokesInDelayOrder)790 TEST(ThreadPostDelayedTaskTest, InvokesInDelayOrder) {
791 ScopedFakeClock clock;
792 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
793 background_thread->Start();
794
795 Event first;
796 Event second;
797 Event third;
798 Event fourth;
799
800 background_thread->PostDelayedTask(
801 [&third, &fourth] { WaitAndSetEvent(&third, &fourth); },
802 TimeDelta::Millis(11));
803 background_thread->PostDelayedTask(
804 [&first, &second] { WaitAndSetEvent(&first, &second); },
805 TimeDelta::Millis(9));
806 background_thread->PostDelayedTask(
807 [&second, &third] { WaitAndSetEvent(&second, &third); },
808 TimeDelta::Millis(10));
809
810 // All tasks have been posted before the first one is unblocked.
811 first.Set();
812 // Only if the chain is invoked in delay order will the last event be set.
813 clock.AdvanceTime(TimeDelta::Millis(11));
814 EXPECT_TRUE(fourth.Wait(TimeDelta::Zero()));
815 }
816
TEST(ThreadPostDelayedTaskTest,IsCurrentTaskQueue)817 TEST(ThreadPostDelayedTaskTest, IsCurrentTaskQueue) {
818 auto current_tq = webrtc::TaskQueueBase::Current();
819 {
820 std::unique_ptr<rtc::Thread> thread(rtc::Thread::Create());
821 thread->WrapCurrent();
822 EXPECT_EQ(webrtc::TaskQueueBase::Current(),
823 static_cast<webrtc::TaskQueueBase*>(thread.get()));
824 thread->UnwrapCurrent();
825 }
826 EXPECT_EQ(webrtc::TaskQueueBase::Current(), current_tq);
827 }
828
829 class ThreadFactory : public webrtc::TaskQueueFactory {
830 public:
831 std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
CreateTaskQueue(absl::string_view,Priority) const832 CreateTaskQueue(absl::string_view /* name */,
833 Priority /*priority*/) const override {
834 std::unique_ptr<Thread> thread = Thread::Create();
835 thread->Start();
836 return std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>(
837 thread.release());
838 }
839 };
840
CreateDefaultThreadFactory(const webrtc::FieldTrialsView *)841 std::unique_ptr<webrtc::TaskQueueFactory> CreateDefaultThreadFactory(
842 const webrtc::FieldTrialsView*) {
843 return std::make_unique<ThreadFactory>();
844 }
845
846 using ::webrtc::TaskQueueTest;
847
848 INSTANTIATE_TEST_SUITE_P(RtcThread,
849 TaskQueueTest,
850 ::testing::Values(CreateDefaultThreadFactory));
851
852 } // namespace
853 } // namespace rtc
854