blob: a888534a19b2f2690c5a8627ad64a3f7e44de951 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "rtc_base/thread.h"
12
kwibergbfefb032016-05-01 14:53:46 -070013#include <memory>
14
Ali Tofigh4b681942022-08-23 12:57:16 +020015#include "api/field_trials_view.h"
Danil Chapovalov912b3b82019-11-22 15:52:40 +010016#include "api/task_queue/task_queue_factory.h"
17#include "api/task_queue/task_queue_test.h"
Danil Chapovalov4bcf8092022-07-06 19:42:34 +020018#include "api/units/time_delta.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "rtc_base/async_udp_socket.h"
Mirko Bonadei481e3452021-07-30 13:57:25 +020020#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/event.h"
Danil Chapovalov207f8532022-08-24 12:19:46 +020022#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/gunit.h"
Mirko Bonadeie5f4c6b2021-01-15 10:41:01 +010024#include "rtc_base/internal/default_socket_server.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/null_socket_server.h"
26#include "rtc_base/physical_socket_server.h"
Danil Chapovalov16242932022-09-02 11:10:24 +020027#include "rtc_base/ref_counted_object.h"
Steve Anton10542f22019-01-11 09:11:00 -080028#include "rtc_base/socket_address.h"
Markus Handell4ab7dde2020-07-10 13:23:25 +020029#include "rtc_base/synchronization/mutex.h"
Artem Titove41c4332018-07-25 15:04:28 +020030#include "rtc_base/third_party/sigslot/sigslot.h"
Danil Chapovalov207f8532022-08-24 12:19:46 +020031#include "test/gmock.h"
Sebastian Janssonda7267a2020-03-03 10:48:05 +010032#include "test/testsupport/rtc_expect_death.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000033
34#if defined(WEBRTC_WIN)
35#include <comdef.h> // NOLINT
Markus Handell4ab7dde2020-07-10 13:23:25 +020036
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000037#endif
38
Mirko Bonadeie10b1632018-12-11 18:43:40 +010039namespace rtc {
40namespace {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000041
Danil Chapovalov207f8532022-08-24 12:19:46 +020042using ::testing::ElementsAre;
Danil Chapovalov4bcf8092022-07-06 19:42:34 +020043using ::webrtc::TimeDelta;
Sebastian Jansson73387822020-01-16 11:15:35 +010044
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000045// Generates a sequence of numbers (collaboratively).
46class TestGenerator {
47 public:
48 TestGenerator() : last(0), count(0) {}
49
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
Danil Chapovalov1e6965a2022-09-05 11:27:57 +020061// Receives messages and sends on a socket.
62class MessageClient : public TestGenerator {
63 public:
64 MessageClient(Thread* pth, Socket* socket) : socket_(socket) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000065
Danil Chapovalov1e6965a2022-09-05 11:27:57 +020066 ~MessageClient() { delete socket_; }
67
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_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000075};
76
77// Receives on a socket and sends by posting messages.
78class SocketClient : public TestGenerator, public sigslot::has_slots<> {
79 public:
Niels Möllerd0b88792021-08-12 10:32:30 +020080 SocketClient(Socket* socket,
Yves Gerey665174f2018-06-19 15:03:05 +020081 const SocketAddress& addr,
82 Thread* post_thread,
Danil Chapovalov1e6965a2022-09-05 11:27:57 +020083 MessageClient* phandler)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000084 : socket_(AsyncUDPSocket::Create(socket, addr)),
85 post_thread_(post_thread),
86 post_handler_(phandler) {
87 socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
88 }
89
Steve Anton9de3aac2017-10-24 10:08:26 -070090 ~SocketClient() override { delete socket_; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000091
92 SocketAddress address() const { return socket_->GetLocalAddress(); }
93
Yves Gerey665174f2018-06-19 15:03:05 +020094 void OnPacket(AsyncPacketSocket* socket,
95 const char* buf,
96 size_t size,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000097 const SocketAddress& remote_addr,
Niels Möllere6933812018-11-05 13:01:41 +010098 const int64_t& packet_time_us) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020099 EXPECT_EQ(size, sizeof(uint32_t));
100 uint32_t prev = reinterpret_cast<const uint32_t*>(buf)[0];
101 uint32_t result = Next(prev);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000102
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200103 post_thread_->PostDelayedTask([post_handler_ = post_handler_,
104 result] { post_handler_->OnValue(result); },
105 TimeDelta::Millis(200));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000106 }
107
108 private:
109 AsyncUDPSocket* socket_;
110 Thread* post_thread_;
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200111 MessageClient* post_handler_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000112};
113
deadbeefaea92932017-05-23 12:55:03 -0700114class CustomThread : public rtc::Thread {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000115 public:
tommie7251592017-07-14 14:44:46 -0700116 CustomThread()
117 : Thread(std::unique_ptr<SocketServer>(new rtc::NullSocketServer())) {}
Steve Anton9de3aac2017-10-24 10:08:26 -0700118 ~CustomThread() override { Stop(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000119 bool Start() { return false; }
jiayl@webrtc.orgba737cb2014-09-18 16:45:21 +0000120
Yves Gerey665174f2018-06-19 15:03:05 +0200121 bool WrapCurrent() { return Thread::WrapCurrent(); }
122 void UnwrapCurrent() { Thread::UnwrapCurrent(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000123};
124
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000125// A thread that does nothing when it runs and signals an event
126// when it is destroyed.
127class SignalWhenDestroyedThread : public Thread {
128 public:
129 SignalWhenDestroyedThread(Event* event)
tommie7251592017-07-14 14:44:46 -0700130 : Thread(std::unique_ptr<SocketServer>(new NullSocketServer())),
131 event_(event) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000132
Steve Anton9de3aac2017-10-24 10:08:26 -0700133 ~SignalWhenDestroyedThread() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000134 Stop();
135 event_->Set();
136 }
137
Steve Anton9de3aac2017-10-24 10:08:26 -0700138 void Run() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000139 // Do nothing.
140 }
141
142 private:
143 Event* event_;
144};
145
nissed9b75be2015-11-16 00:54:07 -0800146// A bool wrapped in a mutex, to avoid data races. Using a volatile
147// bool should be sufficient for correct code ("eventual consistency"
148// between caches is sufficient), but we can't tell the compiler about
149// that, and then tsan complains about a data race.
150
151// See also discussion at
152// http://stackoverflow.com/questions/7223164/is-mutex-needed-to-synchronize-a-simple-flag-between-pthreads
153
154// Using std::atomic<bool> or std::atomic_flag in C++11 is probably
155// the right thing to do, but those features are not yet allowed. Or
deadbeefaea92932017-05-23 12:55:03 -0700156// rtc::AtomicInt, if/when that is added. Since the use isn't
nissed9b75be2015-11-16 00:54:07 -0800157// performance critical, use a plain critical section for the time
158// being.
159
160class AtomicBool {
161 public:
162 explicit AtomicBool(bool value = false) : flag_(value) {}
163 AtomicBool& operator=(bool value) {
Markus Handell4ab7dde2020-07-10 13:23:25 +0200164 webrtc::MutexLock scoped_lock(&mutex_);
nissed9b75be2015-11-16 00:54:07 -0800165 flag_ = value;
166 return *this;
167 }
168 bool get() const {
Markus Handell4ab7dde2020-07-10 13:23:25 +0200169 webrtc::MutexLock scoped_lock(&mutex_);
nissed9b75be2015-11-16 00:54:07 -0800170 return flag_;
171 }
172
173 private:
Markus Handell4ab7dde2020-07-10 13:23:25 +0200174 mutable webrtc::Mutex mutex_;
nissed9b75be2015-11-16 00:54:07 -0800175 bool flag_;
176};
177
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000178// Function objects to test Thread::Invoke.
179struct FunctorA {
180 int operator()() { return 42; }
181};
182class FunctorB {
183 public:
nissed9b75be2015-11-16 00:54:07 -0800184 explicit FunctorB(AtomicBool* flag) : flag_(flag) {}
Yves Gerey665174f2018-06-19 15:03:05 +0200185 void operator()() {
186 if (flag_)
187 *flag_ = true;
188 }
189
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000190 private:
nissed9b75be2015-11-16 00:54:07 -0800191 AtomicBool* flag_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000192};
193struct FunctorC {
194 int operator()() {
195 Thread::Current()->ProcessMessages(50);
196 return 24;
197 }
198};
Cameron Pickettd132ce12018-03-12 16:07:37 -0700199struct FunctorD {
200 public:
201 explicit FunctorD(AtomicBool* flag) : flag_(flag) {}
202 FunctorD(FunctorD&&) = default;
Byoungchan Lee14af7622022-01-12 05:24:58 +0900203
204 FunctorD(const FunctorD&) = delete;
205 FunctorD& operator=(const FunctorD&) = delete;
206
Cameron Pickettd132ce12018-03-12 16:07:37 -0700207 FunctorD& operator=(FunctorD&&) = default;
Yves Gerey665174f2018-06-19 15:03:05 +0200208 void operator()() {
209 if (flag_)
210 *flag_ = true;
211 }
212
Cameron Pickettd132ce12018-03-12 16:07:37 -0700213 private:
214 AtomicBool* flag_;
Cameron Pickettd132ce12018-03-12 16:07:37 -0700215};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000216
217// See: https://code.google.com/p/webrtc/issues/detail?id=2409
218TEST(ThreadTest, DISABLED_Main) {
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200219 rtc::AutoThread main_thread;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000220 const SocketAddress addr("127.0.0.1", 0);
221
222 // Create the messaging client on its own thread.
tommie7251592017-07-14 14:44:46 -0700223 auto th1 = Thread::CreateWithSocketServer();
Niels Möllerd0b88792021-08-12 10:32:30 +0200224 Socket* socket = th1->socketserver()->CreateSocket(addr.family(), SOCK_DGRAM);
tommie7251592017-07-14 14:44:46 -0700225 MessageClient msg_client(th1.get(), socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000226
227 // Create the socket client on its own thread.
tommie7251592017-07-14 14:44:46 -0700228 auto th2 = Thread::CreateWithSocketServer();
Niels Möllerd0b88792021-08-12 10:32:30 +0200229 Socket* asocket =
230 th2->socketserver()->CreateSocket(addr.family(), SOCK_DGRAM);
tommie7251592017-07-14 14:44:46 -0700231 SocketClient sock_client(asocket, addr, th1.get(), &msg_client);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000232
233 socket->Connect(sock_client.address());
234
tommie7251592017-07-14 14:44:46 -0700235 th1->Start();
236 th2->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000237
238 // Get the messages started.
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200239 th1->PostDelayedTask([&msg_client] { msg_client.OnValue(1); },
240 TimeDelta::Millis(100));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000241
242 // Give the clients a little while to run.
243 // Messages will be processed at 100, 300, 500, 700, 900.
244 Thread* th_main = Thread::Current();
245 th_main->ProcessMessages(1000);
246
247 // Stop the sending client. Give the receiver a bit longer to run, in case
248 // it is running on a machine that is under load (e.g. the build machine).
tommie7251592017-07-14 14:44:46 -0700249 th1->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000250 th_main->ProcessMessages(200);
tommie7251592017-07-14 14:44:46 -0700251 th2->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000252
253 // Make sure the results were correct
254 EXPECT_EQ(5, msg_client.count);
255 EXPECT_EQ(34, msg_client.last);
256 EXPECT_EQ(5, sock_client.count);
257 EXPECT_EQ(55, sock_client.last);
258}
259
Tommife041642021-04-07 10:08:28 +0200260TEST(ThreadTest, CountBlockingCalls) {
Niels Möller83830f32022-05-20 09:12:57 +0200261 rtc::AutoThread current;
262
Tommife041642021-04-07 10:08:28 +0200263 // When the test runs, this will print out:
264 // (thread_unittest.cc:262): Blocking TestBody: total=2 (actual=1, could=1)
265 RTC_LOG_THREAD_BLOCK_COUNT();
266#if RTC_DCHECK_IS_ON
Tommife041642021-04-07 10:08:28 +0200267 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
268 [&](uint32_t actual_block, uint32_t could_block) {
269 EXPECT_EQ(1u, actual_block);
270 EXPECT_EQ(1u, could_block);
271 });
272
273 EXPECT_EQ(0u, blocked_calls.GetBlockingCallCount());
274 EXPECT_EQ(0u, blocked_calls.GetCouldBeBlockingCallCount());
275 EXPECT_EQ(0u, blocked_calls.GetTotalBlockedCallCount());
276
277 // Test invoking on the current thread. This should not count as an 'actual'
278 // invoke, but should still count as an invoke that could block since we
279 // that the call to Invoke serves a purpose in some configurations (and should
280 // not be used a general way to call methods on the same thread).
Niels Möller83830f32022-05-20 09:12:57 +0200281 current.Invoke<void>(RTC_FROM_HERE, []() {});
Tommife041642021-04-07 10:08:28 +0200282 EXPECT_EQ(0u, blocked_calls.GetBlockingCallCount());
283 EXPECT_EQ(1u, blocked_calls.GetCouldBeBlockingCallCount());
284 EXPECT_EQ(1u, blocked_calls.GetTotalBlockedCallCount());
285
286 // Create a new thread to invoke on.
287 auto thread = Thread::CreateWithSocketServer();
288 thread->Start();
289 EXPECT_EQ(42, thread->Invoke<int>(RTC_FROM_HERE, []() { return 42; }));
290 EXPECT_EQ(1u, blocked_calls.GetBlockingCallCount());
291 EXPECT_EQ(1u, blocked_calls.GetCouldBeBlockingCallCount());
292 EXPECT_EQ(2u, blocked_calls.GetTotalBlockedCallCount());
293 thread->Stop();
294 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
295#else
296 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);
297 RTC_LOG(LS_INFO) << "Test not active in this config";
298#endif
299}
300
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200301#if RTC_DCHECK_IS_ON
302TEST(ThreadTest, CountBlockingCallsOneCallback) {
Niels Möller83830f32022-05-20 09:12:57 +0200303 rtc::AutoThread current;
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200304 bool was_called_back = false;
305 {
306 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
307 [&](uint32_t actual_block, uint32_t could_block) {
308 was_called_back = true;
309 });
Niels Möller83830f32022-05-20 09:12:57 +0200310 current.Invoke<void>(RTC_FROM_HERE, []() {});
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200311 }
312 EXPECT_TRUE(was_called_back);
313}
314
315TEST(ThreadTest, CountBlockingCallsSkipCallback) {
Niels Möller83830f32022-05-20 09:12:57 +0200316 rtc::AutoThread current;
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200317 bool was_called_back = false;
318 {
319 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
320 [&](uint32_t actual_block, uint32_t could_block) {
321 was_called_back = true;
322 });
323 // Changed `blocked_calls` to not issue the callback if there are 1 or
324 // fewer blocking calls (i.e. we set the minimum required number to 2).
325 blocked_calls.set_minimum_call_count_for_callback(2);
Niels Möller83830f32022-05-20 09:12:57 +0200326 current.Invoke<void>(RTC_FROM_HERE, []() {});
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200327 }
328 // We should not have gotten a call back.
329 EXPECT_FALSE(was_called_back);
330}
331#endif
332
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000333// Test that setting thread names doesn't cause a malfunction.
334// There's no easy way to verify the name was set properly at this time.
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000335TEST(ThreadTest, Names) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000336 // Default name
tommie7251592017-07-14 14:44:46 -0700337 auto thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000338 EXPECT_TRUE(thread->Start());
339 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000340 // Name with no object parameter
tommie7251592017-07-14 14:44:46 -0700341 thread = Thread::CreateWithSocketServer();
deadbeef37f5ecf2017-02-27 14:06:41 -0800342 EXPECT_TRUE(thread->SetName("No object", nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000343 EXPECT_TRUE(thread->Start());
344 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000345 // Really long name
tommie7251592017-07-14 14:44:46 -0700346 thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000347 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
348 EXPECT_TRUE(thread->Start());
349 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000350}
351
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000352TEST(ThreadTest, Wrap) {
353 Thread* current_thread = Thread::Current();
Niels Möller5a8f8602019-06-12 11:30:59 +0200354 ThreadManager::Instance()->SetCurrentThread(nullptr);
355
356 {
357 CustomThread cthread;
358 EXPECT_TRUE(cthread.WrapCurrent());
359 EXPECT_EQ(&cthread, Thread::Current());
360 EXPECT_TRUE(cthread.RunningForTest());
361 EXPECT_FALSE(cthread.IsOwned());
362 cthread.UnwrapCurrent();
363 EXPECT_FALSE(cthread.RunningForTest());
364 }
365 ThreadManager::Instance()->SetCurrentThread(current_thread);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000366}
367
Mirko Bonadei481e3452021-07-30 13:57:25 +0200368#if (!defined(NDEBUG) || RTC_DCHECK_IS_ON)
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200369TEST(ThreadTest, InvokeToThreadAllowedReturnsTrueWithoutPolicies) {
Niels Möller83830f32022-05-20 09:12:57 +0200370 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200371 // Create and start the thread.
372 auto thread1 = Thread::CreateWithSocketServer();
373 auto thread2 = Thread::CreateWithSocketServer();
374
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200375 thread1->PostTask(
376 [&]() { EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 09:12:57 +0200377 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200378}
379
380TEST(ThreadTest, InvokeAllowedWhenThreadsAdded) {
Niels Möller83830f32022-05-20 09:12:57 +0200381 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200382 // Create and start the thread.
383 auto thread1 = Thread::CreateWithSocketServer();
384 auto thread2 = Thread::CreateWithSocketServer();
385 auto thread3 = Thread::CreateWithSocketServer();
386 auto thread4 = Thread::CreateWithSocketServer();
387
388 thread1->AllowInvokesToThread(thread2.get());
389 thread1->AllowInvokesToThread(thread3.get());
390
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200391 thread1->PostTask([&]() {
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200392 EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get()));
393 EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread3.get()));
394 EXPECT_FALSE(thread1->IsInvokeToThreadAllowed(thread4.get()));
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200395 });
Niels Möller83830f32022-05-20 09:12:57 +0200396 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200397}
398
399TEST(ThreadTest, InvokesDisallowedWhenDisallowAllInvokes) {
Niels Möller83830f32022-05-20 09:12:57 +0200400 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200401 // Create and start the thread.
402 auto thread1 = Thread::CreateWithSocketServer();
403 auto thread2 = Thread::CreateWithSocketServer();
404
405 thread1->DisallowAllInvokes();
406
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200407 thread1->PostTask(
408 [&]() { EXPECT_FALSE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 09:12:57 +0200409 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200410}
Mirko Bonadei481e3452021-07-30 13:57:25 +0200411#endif // (!defined(NDEBUG) || RTC_DCHECK_IS_ON)
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200412
413TEST(ThreadTest, InvokesAllowedByDefault) {
Niels Möller83830f32022-05-20 09:12:57 +0200414 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200415 // Create and start the thread.
416 auto thread1 = Thread::CreateWithSocketServer();
417 auto thread2 = Thread::CreateWithSocketServer();
418
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200419 thread1->PostTask(
420 [&]() { EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 09:12:57 +0200421 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200422}
423
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000424TEST(ThreadTest, Invoke) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000425 // Create and start the thread.
tommie7251592017-07-14 14:44:46 -0700426 auto thread = Thread::CreateWithSocketServer();
427 thread->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000428 // Try calling functors.
tommie7251592017-07-14 14:44:46 -0700429 EXPECT_EQ(42, thread->Invoke<int>(RTC_FROM_HERE, FunctorA()));
nissed9b75be2015-11-16 00:54:07 -0800430 AtomicBool called;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000431 FunctorB f2(&called);
tommie7251592017-07-14 14:44:46 -0700432 thread->Invoke<void>(RTC_FROM_HERE, f2);
nissed9b75be2015-11-16 00:54:07 -0800433 EXPECT_TRUE(called.get());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000434 // Try calling bare functions.
435 struct LocalFuncs {
436 static int Func1() { return 999; }
437 static void Func2() {}
438 };
tommie7251592017-07-14 14:44:46 -0700439 EXPECT_EQ(999, thread->Invoke<int>(RTC_FROM_HERE, &LocalFuncs::Func1));
440 thread->Invoke<void>(RTC_FROM_HERE, &LocalFuncs::Func2);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000441}
442
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000443// Verifies that two threads calling Invoke on each other at the same time does
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100444// not deadlock but crash.
445#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
446TEST(ThreadTest, TwoThreadsInvokeDeathTest) {
Mirko Bonadei386b5c32021-07-28 08:55:52 +0200447 GTEST_FLAG_SET(death_test_style, "threadsafe");
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000448 AutoThread thread;
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100449 Thread* main_thread = Thread::Current();
tommie7251592017-07-14 14:44:46 -0700450 auto other_thread = Thread::CreateWithSocketServer();
451 other_thread->Start();
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100452 other_thread->Invoke<void>(RTC_FROM_HERE, [main_thread] {
453 RTC_EXPECT_DEATH(main_thread->Invoke<void>(RTC_FROM_HERE, [] {}), "loop");
454 });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000455}
456
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100457TEST(ThreadTest, ThreeThreadsInvokeDeathTest) {
Mirko Bonadei386b5c32021-07-28 08:55:52 +0200458 GTEST_FLAG_SET(death_test_style, "threadsafe");
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100459 AutoThread thread;
460 Thread* first = Thread::Current();
461
462 auto second = Thread::Create();
463 second->Start();
464 auto third = Thread::Create();
465 third->Start();
466
467 second->Invoke<void>(RTC_FROM_HERE, [&] {
468 third->Invoke<void>(RTC_FROM_HERE, [&] {
469 RTC_EXPECT_DEATH(first->Invoke<void>(RTC_FROM_HERE, [] {}), "loop");
470 });
471 });
472}
473
474#endif
475
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000476// Verifies that if thread A invokes a call on thread B and thread C is trying
477// to invoke A at the same time, thread A does not handle C's invoke while
478// invoking B.
479TEST(ThreadTest, ThreeThreadsInvoke) {
480 AutoThread thread;
481 Thread* thread_a = Thread::Current();
tommie7251592017-07-14 14:44:46 -0700482 auto thread_b = Thread::CreateWithSocketServer();
483 auto thread_c = Thread::CreateWithSocketServer();
484 thread_b->Start();
485 thread_c->Start();
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000486
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000487 class LockedBool {
488 public:
489 explicit LockedBool(bool value) : value_(value) {}
490
491 void Set(bool value) {
Markus Handell4ab7dde2020-07-10 13:23:25 +0200492 webrtc::MutexLock lock(&mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000493 value_ = value;
494 }
495
496 bool Get() {
Markus Handell4ab7dde2020-07-10 13:23:25 +0200497 webrtc::MutexLock lock(&mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000498 return value_;
499 }
500
501 private:
Markus Handell4ab7dde2020-07-10 13:23:25 +0200502 webrtc::Mutex mutex_;
503 bool value_ RTC_GUARDED_BY(mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000504 };
505
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000506 struct LocalFuncs {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000507 static void Set(LockedBool* out) { out->Set(true); }
508 static void InvokeSet(Thread* thread, LockedBool* out) {
Niels Möller1a29a5d2021-01-18 11:35:23 +0100509 thread->Invoke<void>(RTC_FROM_HERE, [out] { Set(out); });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000510 }
511
Artem Titov96e3b992021-07-26 16:03:14 +0200512 // Set `out` true and call InvokeSet on `thread`.
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000513 static void SetAndInvokeSet(LockedBool* out,
514 Thread* thread,
515 LockedBool* out_inner) {
516 out->Set(true);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000517 InvokeSet(thread, out_inner);
518 }
519
Artem Titov96e3b992021-07-26 16:03:14 +0200520 // Asynchronously invoke SetAndInvokeSet on `thread1` and wait until
521 // `thread1` starts the call.
Danil Chapovalov16242932022-09-02 11:10:24 +0200522 static void AsyncInvokeSetAndWait(Thread* thread1,
deadbeef162cb532017-02-23 17:10:07 -0800523 Thread* thread2,
524 LockedBool* out) {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000525 LockedBool async_invoked(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000526
Danil Chapovalov16242932022-09-02 11:10:24 +0200527 thread1->PostTask([&async_invoked, thread2, out] {
528 SetAndInvokeSet(&async_invoked, thread2, out);
529 });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000530
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000531 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000532 }
533 };
534
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000535 LockedBool thread_a_called(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000536
537 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
538 // Thread B returns when C receives the call and C should be blocked until A
539 // starts to process messages.
Niels Möller1a29a5d2021-01-18 11:35:23 +0100540 Thread* thread_c_ptr = thread_c.get();
Danil Chapovalov16242932022-09-02 11:10:24 +0200541 thread_b->Invoke<void>(RTC_FROM_HERE, [thread_c_ptr, thread_a,
542 &thread_a_called] {
543 LocalFuncs::AsyncInvokeSetAndWait(thread_c_ptr, thread_a, &thread_a_called);
544 });
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000545 EXPECT_FALSE(thread_a_called.Get());
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000546
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000547 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000548}
549
Danil Chapovalov207f8532022-08-24 12:19:46 +0200550static void DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(
551 FakeClock& clock,
552 Thread& q) {
553 std::vector<int> run_order;
554
555 Event done;
Sebastian Jansson73387822020-01-16 11:15:35 +0100556 int64_t now = TimeMillis();
Danil Chapovalov207f8532022-08-24 12:19:46 +0200557 q.PostDelayedTask([&] { run_order.push_back(3); }, TimeDelta::Millis(3));
558 q.PostDelayedTask([&] { run_order.push_back(0); }, TimeDelta::Millis(1));
559 q.PostDelayedTask([&] { run_order.push_back(1); }, TimeDelta::Millis(2));
560 q.PostDelayedTask([&] { run_order.push_back(4); }, TimeDelta::Millis(3));
561 q.PostDelayedTask([&] { run_order.push_back(2); }, TimeDelta::Millis(2));
562 q.PostDelayedTask([&] { done.Set(); }, TimeDelta::Millis(4));
563 // Validate time was frozen while tasks were posted.
564 RTC_DCHECK_EQ(TimeMillis(), now);
Sebastian Jansson73387822020-01-16 11:15:35 +0100565
Danil Chapovalov207f8532022-08-24 12:19:46 +0200566 // Change time to make all tasks ready to run and wait for them.
567 clock.AdvanceTime(TimeDelta::Millis(4));
568 ASSERT_TRUE(done.Wait(TimeDelta::Seconds(1)));
Sebastian Jansson73387822020-01-16 11:15:35 +0100569
Danil Chapovalov207f8532022-08-24 12:19:46 +0200570 EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
Sebastian Jansson73387822020-01-16 11:15:35 +0100571}
572
Danil Chapovalov71cf2d02022-08-26 11:49:14 +0200573TEST(ThreadTest, DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder) {
Danil Chapovalov207f8532022-08-24 12:19:46 +0200574 ScopedBaseFakeClock clock;
Mirko Bonadeie5f4c6b2021-01-15 10:41:01 +0100575 Thread q(CreateDefaultSocketServer(), true);
Danil Chapovalov207f8532022-08-24 12:19:46 +0200576 q.Start();
577 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(clock, q);
Sebastian Jansson73387822020-01-16 11:15:35 +0100578
579 NullSocketServer nullss;
580 Thread q_nullss(&nullss, true);
Danil Chapovalov207f8532022-08-24 12:19:46 +0200581 q_nullss.Start();
582 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(clock, q_nullss);
Sebastian Jansson73387822020-01-16 11:15:35 +0100583}
584
Sebastian Jansson73387822020-01-16 11:15:35 +0100585// Ensure that ProcessAllMessageQueues does its essential function; process
586// all messages (both delayed and non delayed) up until the current time, on
587// all registered message queues.
588TEST(ThreadManager, ProcessAllMessageQueues) {
Niels Möller83830f32022-05-20 09:12:57 +0200589 rtc::AutoThread main_thread;
Sebastian Jansson73387822020-01-16 11:15:35 +0100590 Event entered_process_all_message_queues(true, false);
591 auto a = Thread::CreateWithSocketServer();
592 auto b = Thread::CreateWithSocketServer();
593 a->Start();
594 b->Start();
595
Niels Möller7a669002022-06-27 09:47:02 +0200596 std::atomic<int> messages_processed(0);
Sebastian Jansson73387822020-01-16 11:15:35 +0100597 auto incrementer = [&messages_processed,
598 &entered_process_all_message_queues] {
599 // Wait for event as a means to ensure Increment doesn't occur outside
600 // of ProcessAllMessageQueues. The event is set by a message posted to
601 // the main thread, which is guaranteed to be handled inside
602 // ProcessAllMessageQueues.
603 entered_process_all_message_queues.Wait(Event::kForever);
Niels Möller7a669002022-06-27 09:47:02 +0200604 messages_processed.fetch_add(1);
Sebastian Jansson73387822020-01-16 11:15:35 +0100605 };
606 auto event_signaler = [&entered_process_all_message_queues] {
607 entered_process_all_message_queues.Set();
608 };
609
610 // Post messages (both delayed and non delayed) to both threads.
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200611 a->PostTask(incrementer);
612 b->PostTask(incrementer);
613 a->PostDelayedTask(incrementer, TimeDelta::Zero());
614 b->PostDelayedTask(incrementer, TimeDelta::Zero());
615 main_thread.PostTask(event_signaler);
Sebastian Jansson73387822020-01-16 11:15:35 +0100616
617 ThreadManager::ProcessAllMessageQueuesForTesting();
Niels Möller7a669002022-06-27 09:47:02 +0200618 EXPECT_EQ(4, messages_processed.load(std::memory_order_acquire));
Sebastian Jansson73387822020-01-16 11:15:35 +0100619}
620
621// Test that ProcessAllMessageQueues doesn't hang if a thread is quitting.
622TEST(ThreadManager, ProcessAllMessageQueuesWithQuittingThread) {
623 auto t = Thread::CreateWithSocketServer();
624 t->Start();
625 t->Quit();
626 ThreadManager::ProcessAllMessageQueuesForTesting();
627}
628
629// Test that ProcessAllMessageQueues doesn't hang if a queue clears its
630// messages.
631TEST(ThreadManager, ProcessAllMessageQueuesWithClearedQueue) {
Niels Möller83830f32022-05-20 09:12:57 +0200632 rtc::AutoThread main_thread;
Sebastian Jansson73387822020-01-16 11:15:35 +0100633 Event entered_process_all_message_queues(true, false);
634 auto t = Thread::CreateWithSocketServer();
635 t->Start();
636
637 auto clearer = [&entered_process_all_message_queues] {
638 // Wait for event as a means to ensure Clear doesn't occur outside of
639 // ProcessAllMessageQueues. The event is set by a message posted to the
640 // main thread, which is guaranteed to be handled inside
641 // ProcessAllMessageQueues.
642 entered_process_all_message_queues.Wait(Event::kForever);
643 rtc::Thread::Current()->Clear(nullptr);
644 };
645 auto event_signaler = [&entered_process_all_message_queues] {
646 entered_process_all_message_queues.Set();
647 };
648
649 // Post messages (both delayed and non delayed) to both threads.
Henrik Boström2deee4b2022-01-20 11:58:05 +0100650 t->PostTask(clearer);
Niels Möller83830f32022-05-20 09:12:57 +0200651 main_thread.PostTask(event_signaler);
Sebastian Jansson73387822020-01-16 11:15:35 +0100652 ThreadManager::ProcessAllMessageQueuesForTesting();
653}
654
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200655class RefCountedHandler : public MessageHandler, public rtc::RefCountInterface {
Sebastian Jansson73387822020-01-16 11:15:35 +0100656 public:
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200657 ~RefCountedHandler() override { ThreadManager::Clear(this); }
658
Sebastian Jansson73387822020-01-16 11:15:35 +0100659 void OnMessage(Message* msg) override {}
660};
661
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200662class EmptyHandler : public MessageHandler {
Sebastian Jansson73387822020-01-16 11:15:35 +0100663 public:
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200664 ~EmptyHandler() override { ThreadManager::Clear(this); }
665
Sebastian Jansson73387822020-01-16 11:15:35 +0100666 void OnMessage(Message* msg) override {}
667};
668
669TEST(ThreadManager, ClearReentrant) {
670 std::unique_ptr<Thread> t(Thread::Create());
671 EmptyHandler handler;
672 RefCountedHandler* inner_handler(
673 new rtc::RefCountedObject<RefCountedHandler>());
674 // When the empty handler is destroyed, it will clear messages queued for
675 // itself. The message to be cleared itself wraps a MessageHandler object
676 // (RefCountedHandler) so this will cause the message queue to be cleared
677 // again in a re-entrant fashion, which previously triggered a DCHECK.
678 // The inner handler will be removed in a re-entrant fashion from the
679 // message queue of the thread while the outer handler is removed, verifying
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200680 // that the iterator is not invalidated in "Thread::Clear".
Sebastian Jansson73387822020-01-16 11:15:35 +0100681 t->Post(RTC_FROM_HERE, inner_handler, 0);
682 t->Post(RTC_FROM_HERE, &handler, 0,
683 new ScopedRefMessageData<RefCountedHandler>(inner_handler));
684}
685
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100686void WaitAndSetEvent(Event* wait_event, Event* set_event) {
687 wait_event->Wait(Event::kForever);
688 set_event->Set();
689}
690
691// A functor that keeps track of the number of copies and moves.
692class LifeCycleFunctor {
693 public:
694 struct Stats {
695 size_t copy_count = 0;
696 size_t move_count = 0;
697 };
698
699 LifeCycleFunctor(Stats* stats, Event* event) : stats_(stats), event_(event) {}
700 LifeCycleFunctor(const LifeCycleFunctor& other) { *this = other; }
701 LifeCycleFunctor(LifeCycleFunctor&& other) { *this = std::move(other); }
702
703 LifeCycleFunctor& operator=(const LifeCycleFunctor& other) {
704 stats_ = other.stats_;
705 event_ = other.event_;
706 ++stats_->copy_count;
707 return *this;
708 }
709
710 LifeCycleFunctor& operator=(LifeCycleFunctor&& other) {
711 stats_ = other.stats_;
712 event_ = other.event_;
713 ++stats_->move_count;
714 return *this;
715 }
716
717 void operator()() { event_->Set(); }
718
719 private:
720 Stats* stats_;
721 Event* event_;
722};
723
724// A functor that verifies the thread it was destroyed on.
725class DestructionFunctor {
726 public:
727 DestructionFunctor(Thread* thread, bool* thread_was_current, Event* event)
728 : thread_(thread),
729 thread_was_current_(thread_was_current),
730 event_(event) {}
731 ~DestructionFunctor() {
732 // Only signal the event if this was the functor that was invoked to avoid
733 // the event being signaled due to the destruction of temporary/moved
734 // versions of this object.
735 if (was_invoked_) {
736 *thread_was_current_ = thread_->IsCurrent();
737 event_->Set();
738 }
739 }
740
741 void operator()() { was_invoked_ = true; }
742
743 private:
744 Thread* thread_;
745 bool* thread_was_current_;
746 Event* event_;
747 bool was_invoked_ = false;
748};
749
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100750TEST(ThreadPostTaskTest, InvokesWithLambda) {
751 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
752 background_thread->Start();
753
754 Event event;
Henrik Boström595f6882022-01-24 09:57:03 +0100755 background_thread->PostTask([&event] { event.Set(); });
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100756 event.Wait(Event::kForever);
757}
758
759TEST(ThreadPostTaskTest, InvokesWithCopiedFunctor) {
760 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
761 background_thread->Start();
762
763 LifeCycleFunctor::Stats stats;
764 Event event;
765 LifeCycleFunctor functor(&stats, &event);
Henrik Boström595f6882022-01-24 09:57:03 +0100766 background_thread->PostTask(functor);
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100767 event.Wait(Event::kForever);
768
769 EXPECT_EQ(1u, stats.copy_count);
770 EXPECT_EQ(0u, stats.move_count);
771}
772
773TEST(ThreadPostTaskTest, InvokesWithMovedFunctor) {
774 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
775 background_thread->Start();
776
777 LifeCycleFunctor::Stats stats;
778 Event event;
779 LifeCycleFunctor functor(&stats, &event);
Henrik Boström595f6882022-01-24 09:57:03 +0100780 background_thread->PostTask(std::move(functor));
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100781 event.Wait(Event::kForever);
782
783 EXPECT_EQ(0u, stats.copy_count);
784 EXPECT_EQ(1u, stats.move_count);
785}
786
787TEST(ThreadPostTaskTest, InvokesWithReferencedFunctorShouldCopy) {
788 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
789 background_thread->Start();
790
791 LifeCycleFunctor::Stats stats;
792 Event event;
793 LifeCycleFunctor functor(&stats, &event);
794 LifeCycleFunctor& functor_ref = functor;
Henrik Boström595f6882022-01-24 09:57:03 +0100795 background_thread->PostTask(functor_ref);
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100796 event.Wait(Event::kForever);
797
798 EXPECT_EQ(1u, stats.copy_count);
799 EXPECT_EQ(0u, stats.move_count);
800}
801
802TEST(ThreadPostTaskTest, InvokesWithCopiedFunctorDestroyedOnTargetThread) {
803 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
804 background_thread->Start();
805
806 Event event;
807 bool was_invoked_on_background_thread = false;
808 DestructionFunctor functor(background_thread.get(),
809 &was_invoked_on_background_thread, &event);
Henrik Boström595f6882022-01-24 09:57:03 +0100810 background_thread->PostTask(functor);
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100811 event.Wait(Event::kForever);
812
813 EXPECT_TRUE(was_invoked_on_background_thread);
814}
815
816TEST(ThreadPostTaskTest, InvokesWithMovedFunctorDestroyedOnTargetThread) {
817 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
818 background_thread->Start();
819
820 Event event;
821 bool was_invoked_on_background_thread = false;
822 DestructionFunctor functor(background_thread.get(),
823 &was_invoked_on_background_thread, &event);
Henrik Boström595f6882022-01-24 09:57:03 +0100824 background_thread->PostTask(std::move(functor));
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100825 event.Wait(Event::kForever);
826
827 EXPECT_TRUE(was_invoked_on_background_thread);
828}
829
830TEST(ThreadPostTaskTest,
831 InvokesWithReferencedFunctorShouldCopyAndDestroyedOnTargetThread) {
832 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
833 background_thread->Start();
834
835 Event event;
836 bool was_invoked_on_background_thread = false;
837 DestructionFunctor functor(background_thread.get(),
838 &was_invoked_on_background_thread, &event);
839 DestructionFunctor& functor_ref = functor;
Henrik Boström595f6882022-01-24 09:57:03 +0100840 background_thread->PostTask(functor_ref);
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100841 event.Wait(Event::kForever);
842
843 EXPECT_TRUE(was_invoked_on_background_thread);
844}
845
846TEST(ThreadPostTaskTest, InvokesOnBackgroundThread) {
847 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
848 background_thread->Start();
849
850 Event event;
851 bool was_invoked_on_background_thread = false;
Niels Möller1a29a5d2021-01-18 11:35:23 +0100852 Thread* background_thread_ptr = background_thread.get();
Henrik Boström595f6882022-01-24 09:57:03 +0100853 background_thread->PostTask(
Niels Möller1a29a5d2021-01-18 11:35:23 +0100854 [background_thread_ptr, &was_invoked_on_background_thread, &event] {
855 was_invoked_on_background_thread = background_thread_ptr->IsCurrent();
856 event.Set();
857 });
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100858 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;
Henrik Boström595f6882022-01-24 09:57:03 +0100871 background_thread->PostTask(
Henrik Boström2deee4b2022-01-20 11:58:05 +0100872 [&event_set_by_test_thread, &event_set_by_background_thread] {
873 WaitAndSetEvent(&event_set_by_test_thread,
874 &event_set_by_background_thread);
875 });
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100876 event_set_by_test_thread.Set();
877 event_set_by_background_thread.Wait(Event::kForever);
878}
879
880TEST(ThreadPostTaskTest, InvokesInPostedOrder) {
881 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
882 background_thread->Start();
883
884 Event first;
885 Event second;
886 Event third;
887 Event fourth;
888
Henrik Boström595f6882022-01-24 09:57:03 +0100889 background_thread->PostTask(
890 [&first, &second] { WaitAndSetEvent(&first, &second); });
891 background_thread->PostTask(
892 [&second, &third] { WaitAndSetEvent(&second, &third); });
893 background_thread->PostTask(
894 [&third, &fourth] { WaitAndSetEvent(&third, &fourth); });
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100895
896 // All tasks have been posted before the first one is unblocked.
897 first.Set();
898 // Only if the chain is invoked in posted order will the last event be set.
899 fourth.Wait(Event::kForever);
900}
901
Steve Antonbcc1a762019-12-11 11:21:53 -0800902TEST(ThreadPostDelayedTaskTest, InvokesAsynchronously) {
903 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
904 background_thread->Start();
905
906 // The first event ensures that SendSingleMessage() is not blocking this
907 // thread. The second event ensures that the message is processed.
908 Event event_set_by_test_thread;
909 Event event_set_by_background_thread;
Henrik Boström595f6882022-01-24 09:57:03 +0100910 background_thread->PostDelayedTask(
Niels Möller1a29a5d2021-01-18 11:35:23 +0100911 [&event_set_by_test_thread, &event_set_by_background_thread] {
912 WaitAndSetEvent(&event_set_by_test_thread,
913 &event_set_by_background_thread);
914 },
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200915 TimeDelta::Millis(10));
Steve Antonbcc1a762019-12-11 11:21:53 -0800916 event_set_by_test_thread.Set();
917 event_set_by_background_thread.Wait(Event::kForever);
918}
919
920TEST(ThreadPostDelayedTaskTest, InvokesInDelayOrder) {
Steve Anton094396f2019-12-16 00:56:02 -0800921 ScopedFakeClock clock;
Steve Antonbcc1a762019-12-11 11:21:53 -0800922 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
923 background_thread->Start();
924
925 Event first;
926 Event second;
927 Event third;
928 Event fourth;
929
Henrik Boström595f6882022-01-24 09:57:03 +0100930 background_thread->PostDelayedTask(
931 [&third, &fourth] { WaitAndSetEvent(&third, &fourth); },
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200932 TimeDelta::Millis(11));
Henrik Boström595f6882022-01-24 09:57:03 +0100933 background_thread->PostDelayedTask(
934 [&first, &second] { WaitAndSetEvent(&first, &second); },
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200935 TimeDelta::Millis(9));
Henrik Boström595f6882022-01-24 09:57:03 +0100936 background_thread->PostDelayedTask(
937 [&second, &third] { WaitAndSetEvent(&second, &third); },
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200938 TimeDelta::Millis(10));
Steve Antonbcc1a762019-12-11 11:21:53 -0800939
940 // All tasks have been posted before the first one is unblocked.
941 first.Set();
Steve Anton094396f2019-12-16 00:56:02 -0800942 // Only if the chain is invoked in delay order will the last event be set.
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200943 clock.AdvanceTime(TimeDelta::Millis(11));
Markus Handell2cfc1af2022-08-19 08:16:48 +0000944 EXPECT_TRUE(fourth.Wait(TimeDelta::Zero()));
Steve Antonbcc1a762019-12-11 11:21:53 -0800945}
946
Tommi6866dc72020-05-15 10:11:56 +0200947TEST(ThreadPostDelayedTaskTest, IsCurrentTaskQueue) {
948 auto current_tq = webrtc::TaskQueueBase::Current();
949 {
950 std::unique_ptr<rtc::Thread> thread(rtc::Thread::Create());
951 thread->WrapCurrent();
952 EXPECT_EQ(webrtc::TaskQueueBase::Current(),
953 static_cast<webrtc::TaskQueueBase*>(thread.get()));
954 thread->UnwrapCurrent();
955 }
956 EXPECT_EQ(webrtc::TaskQueueBase::Current(), current_tq);
957}
958
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100959class ThreadFactory : public webrtc::TaskQueueFactory {
960 public:
961 std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
962 CreateTaskQueue(absl::string_view /* name */,
963 Priority /*priority*/) const override {
964 std::unique_ptr<Thread> thread = Thread::Create();
965 thread->Start();
966 return std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>(
967 thread.release());
968 }
969};
970
Ali Tofigh4b681942022-08-23 12:57:16 +0200971std::unique_ptr<webrtc::TaskQueueFactory> CreateDefaultThreadFactory(
972 const webrtc::FieldTrialsView*) {
973 return std::make_unique<ThreadFactory>();
974}
975
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100976using ::webrtc::TaskQueueTest;
977
978INSTANTIATE_TEST_SUITE_P(RtcThread,
979 TaskQueueTest,
Ali Tofigh4b681942022-08-23 12:57:16 +0200980 ::testing::Values(CreateDefaultThreadFactory));
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100981
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100982} // namespace
983} // namespace rtc