• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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