blob: d5b467c1f2a21d756d9ed7468b6b471e529fbb5c [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
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000146// See: https://code.google.com/p/webrtc/issues/detail?id=2409
147TEST(ThreadTest, DISABLED_Main) {
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200148 rtc::AutoThread main_thread;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000149 const SocketAddress addr("127.0.0.1", 0);
150
151 // Create the messaging client on its own thread.
tommie7251592017-07-14 14:44:46 -0700152 auto th1 = Thread::CreateWithSocketServer();
Niels Möllerd0b88792021-08-12 10:32:30 +0200153 Socket* socket = th1->socketserver()->CreateSocket(addr.family(), SOCK_DGRAM);
tommie7251592017-07-14 14:44:46 -0700154 MessageClient msg_client(th1.get(), socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000155
156 // Create the socket client on its own thread.
tommie7251592017-07-14 14:44:46 -0700157 auto th2 = Thread::CreateWithSocketServer();
Niels Möllerd0b88792021-08-12 10:32:30 +0200158 Socket* asocket =
159 th2->socketserver()->CreateSocket(addr.family(), SOCK_DGRAM);
tommie7251592017-07-14 14:44:46 -0700160 SocketClient sock_client(asocket, addr, th1.get(), &msg_client);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000161
162 socket->Connect(sock_client.address());
163
tommie7251592017-07-14 14:44:46 -0700164 th1->Start();
165 th2->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000166
167 // Get the messages started.
Danil Chapovalov1e6965a2022-09-05 11:27:57 +0200168 th1->PostDelayedTask([&msg_client] { msg_client.OnValue(1); },
169 TimeDelta::Millis(100));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000170
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).
tommie7251592017-07-14 14:44:46 -0700178 th1->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000179 th_main->ProcessMessages(200);
tommie7251592017-07-14 14:44:46 -0700180 th2->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000181
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
Tommife041642021-04-07 10:08:28 +0200189TEST(ThreadTest, CountBlockingCalls) {
Niels Möller83830f32022-05-20 09:12:57 +0200190 rtc::AutoThread current;
191
Tommife041642021-04-07 10:08:28 +0200192 // 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
Tommife041642021-04-07 10:08:28 +0200196 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
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200208 // 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([]() {});
Tommife041642021-04-07 10:08:28 +0200211 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();
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200218 EXPECT_EQ(42, thread->BlockingCall([]() { return 42; }));
Tommife041642021-04-07 10:08:28 +0200219 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
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200230#if RTC_DCHECK_IS_ON
231TEST(ThreadTest, CountBlockingCallsOneCallback) {
Niels Möller83830f32022-05-20 09:12:57 +0200232 rtc::AutoThread current;
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200233 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 });
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200239 current.BlockingCall([]() {});
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200240 }
241 EXPECT_TRUE(was_called_back);
242}
243
244TEST(ThreadTest, CountBlockingCallsSkipCallback) {
Niels Möller83830f32022-05-20 09:12:57 +0200245 rtc::AutoThread current;
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200246 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);
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200255 current.BlockingCall([]() {});
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200256 }
257 // We should not have gotten a call back.
258 EXPECT_FALSE(was_called_back);
259}
260#endif
261
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000262// 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.
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000264TEST(ThreadTest, Names) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000265 // Default name
tommie7251592017-07-14 14:44:46 -0700266 auto thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000267 EXPECT_TRUE(thread->Start());
268 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000269 // Name with no object parameter
tommie7251592017-07-14 14:44:46 -0700270 thread = Thread::CreateWithSocketServer();
deadbeef37f5ecf2017-02-27 14:06:41 -0800271 EXPECT_TRUE(thread->SetName("No object", nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000272 EXPECT_TRUE(thread->Start());
273 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000274 // Really long name
tommie7251592017-07-14 14:44:46 -0700275 thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000276 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
277 EXPECT_TRUE(thread->Start());
278 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000279}
280
henrike@webrtc.orge30dab72014-10-09 15:41:40 +0000281TEST(ThreadTest, Wrap) {
282 Thread* current_thread = Thread::Current();
Niels Möller5a8f8602019-06-12 11:30:59 +0200283 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);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000295}
296
Mirko Bonadei481e3452021-07-30 13:57:25 +0200297#if (!defined(NDEBUG) || RTC_DCHECK_IS_ON)
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200298TEST(ThreadTest, InvokeToThreadAllowedReturnsTrueWithoutPolicies) {
Niels Möller83830f32022-05-20 09:12:57 +0200299 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200300 // Create and start the thread.
301 auto thread1 = Thread::CreateWithSocketServer();
302 auto thread2 = Thread::CreateWithSocketServer();
303
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200304 thread1->PostTask(
305 [&]() { EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 09:12:57 +0200306 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200307}
308
309TEST(ThreadTest, InvokeAllowedWhenThreadsAdded) {
Niels Möller83830f32022-05-20 09:12:57 +0200310 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200311 // 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
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200320 thread1->PostTask([&]() {
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200321 EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get()));
322 EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread3.get()));
323 EXPECT_FALSE(thread1->IsInvokeToThreadAllowed(thread4.get()));
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200324 });
Niels Möller83830f32022-05-20 09:12:57 +0200325 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200326}
327
328TEST(ThreadTest, InvokesDisallowedWhenDisallowAllInvokes) {
Niels Möller83830f32022-05-20 09:12:57 +0200329 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200330 // Create and start the thread.
331 auto thread1 = Thread::CreateWithSocketServer();
332 auto thread2 = Thread::CreateWithSocketServer();
333
334 thread1->DisallowAllInvokes();
335
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200336 thread1->PostTask(
337 [&]() { EXPECT_FALSE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 09:12:57 +0200338 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200339}
Mirko Bonadei481e3452021-07-30 13:57:25 +0200340#endif // (!defined(NDEBUG) || RTC_DCHECK_IS_ON)
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200341
342TEST(ThreadTest, InvokesAllowedByDefault) {
Niels Möller83830f32022-05-20 09:12:57 +0200343 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200344 // Create and start the thread.
345 auto thread1 = Thread::CreateWithSocketServer();
346 auto thread2 = Thread::CreateWithSocketServer();
347
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200348 thread1->PostTask(
349 [&]() { EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 09:12:57 +0200350 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200351}
352
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200353TEST(ThreadTest, BlockingCall) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000354 // Create and start the thread.
tommie7251592017-07-14 14:44:46 -0700355 auto thread = Thread::CreateWithSocketServer();
356 thread->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000357 // Try calling functors.
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200358 EXPECT_EQ(42, thread->BlockingCall([] { return 42; }));
359 bool called = false;
360 thread->BlockingCall([&] { called = true; });
361 EXPECT_TRUE(called);
362
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000363 // Try calling bare functions.
364 struct LocalFuncs {
365 static int Func1() { return 999; }
366 static void Func2() {}
367 };
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200368 EXPECT_EQ(999, thread->BlockingCall(&LocalFuncs::Func1));
369 thread->BlockingCall(&LocalFuncs::Func2);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000370}
371
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000372// Verifies that two threads calling Invoke on each other at the same time does
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100373// not deadlock but crash.
374#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
375TEST(ThreadTest, TwoThreadsInvokeDeathTest) {
Mirko Bonadei386b5c32021-07-28 08:55:52 +0200376 GTEST_FLAG_SET(death_test_style, "threadsafe");
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000377 AutoThread thread;
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100378 Thread* main_thread = Thread::Current();
tommie7251592017-07-14 14:44:46 -0700379 auto other_thread = Thread::CreateWithSocketServer();
380 other_thread->Start();
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200381 other_thread->BlockingCall([main_thread] {
382 RTC_EXPECT_DEATH(main_thread->BlockingCall([] {}), "loop");
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100383 });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000384}
385
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100386TEST(ThreadTest, ThreeThreadsInvokeDeathTest) {
Mirko Bonadei386b5c32021-07-28 08:55:52 +0200387 GTEST_FLAG_SET(death_test_style, "threadsafe");
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100388 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
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200396 second->BlockingCall([&] {
397 third->BlockingCall(
398 [&] { RTC_EXPECT_DEATH(first->BlockingCall([] {}), "loop"); });
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100399 });
400}
401
402#endif
403
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000404// 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.
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200407TEST(ThreadTest, ThreeThreadsBlockingCall) {
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000408 AutoThread thread;
409 Thread* thread_a = Thread::Current();
tommie7251592017-07-14 14:44:46 -0700410 auto thread_b = Thread::CreateWithSocketServer();
411 auto thread_c = Thread::CreateWithSocketServer();
412 thread_b->Start();
413 thread_c->Start();
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000414
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000415 class LockedBool {
416 public:
417 explicit LockedBool(bool value) : value_(value) {}
418
419 void Set(bool value) {
Markus Handell4ab7dde2020-07-10 13:23:25 +0200420 webrtc::MutexLock lock(&mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000421 value_ = value;
422 }
423
424 bool Get() {
Markus Handell4ab7dde2020-07-10 13:23:25 +0200425 webrtc::MutexLock lock(&mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000426 return value_;
427 }
428
429 private:
Markus Handell4ab7dde2020-07-10 13:23:25 +0200430 webrtc::Mutex mutex_;
431 bool value_ RTC_GUARDED_BY(mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000432 };
433
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000434 struct LocalFuncs {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000435 static void Set(LockedBool* out) { out->Set(true); }
436 static void InvokeSet(Thread* thread, LockedBool* out) {
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200437 thread->BlockingCall([out] { Set(out); });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000438 }
439
Artem Titov96e3b992021-07-26 16:03:14 +0200440 // Set `out` true and call InvokeSet on `thread`.
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000441 static void SetAndInvokeSet(LockedBool* out,
442 Thread* thread,
443 LockedBool* out_inner) {
444 out->Set(true);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000445 InvokeSet(thread, out_inner);
446 }
447
Artem Titov96e3b992021-07-26 16:03:14 +0200448 // Asynchronously invoke SetAndInvokeSet on `thread1` and wait until
449 // `thread1` starts the call.
Danil Chapovalov16242932022-09-02 11:10:24 +0200450 static void AsyncInvokeSetAndWait(Thread* thread1,
deadbeef162cb532017-02-23 17:10:07 -0800451 Thread* thread2,
452 LockedBool* out) {
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000453 LockedBool async_invoked(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000454
Danil Chapovalov16242932022-09-02 11:10:24 +0200455 thread1->PostTask([&async_invoked, thread2, out] {
456 SetAndInvokeSet(&async_invoked, thread2, out);
457 });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000458
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000459 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000460 }
461 };
462
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000463 LockedBool thread_a_called(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000464
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.
Niels Möller1a29a5d2021-01-18 11:35:23 +0100468 Thread* thread_c_ptr = thread_c.get();
Danil Chapovalov7c323ad2022-09-08 13:13:53 +0200469 thread_b->BlockingCall([thread_c_ptr, thread_a, &thread_a_called] {
Danil Chapovalov16242932022-09-02 11:10:24 +0200470 LocalFuncs::AsyncInvokeSetAndWait(thread_c_ptr, thread_a, &thread_a_called);
471 });
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000472 EXPECT_FALSE(thread_a_called.Get());
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000473
pbos@webrtc.orge93cbd12014-10-15 14:54:56 +0000474 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05 +0000475}
476
Danil Chapovalov207f8532022-08-24 12:19:46 +0200477static void DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(
478 FakeClock& clock,
479 Thread& q) {
480 std::vector<int> run_order;
481
482 Event done;
Sebastian Jansson73387822020-01-16 11:15:35 +0100483 int64_t now = TimeMillis();
Danil Chapovalov207f8532022-08-24 12:19:46 +0200484 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);
Sebastian Jansson73387822020-01-16 11:15:35 +0100492
Danil Chapovalov207f8532022-08-24 12:19:46 +0200493 // 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)));
Sebastian Jansson73387822020-01-16 11:15:35 +0100496
Danil Chapovalov207f8532022-08-24 12:19:46 +0200497 EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
Sebastian Jansson73387822020-01-16 11:15:35 +0100498}
499
Danil Chapovalov71cf2d02022-08-26 11:49:14 +0200500TEST(ThreadTest, DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder) {
Danil Chapovalov207f8532022-08-24 12:19:46 +0200501 ScopedBaseFakeClock clock;
Mirko Bonadeie5f4c6b2021-01-15 10:41:01 +0100502 Thread q(CreateDefaultSocketServer(), true);
Danil Chapovalov207f8532022-08-24 12:19:46 +0200503 q.Start();
504 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(clock, q);
Sebastian Jansson73387822020-01-16 11:15:35 +0100505
506 NullSocketServer nullss;
507 Thread q_nullss(&nullss, true);
Danil Chapovalov207f8532022-08-24 12:19:46 +0200508 q_nullss.Start();
509 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(clock, q_nullss);
Sebastian Jansson73387822020-01-16 11:15:35 +0100510}
511
Sebastian Jansson73387822020-01-16 11:15:35 +0100512// 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.
515TEST(ThreadManager, ProcessAllMessageQueues) {
Niels Möller83830f32022-05-20 09:12:57 +0200516 rtc::AutoThread main_thread;
Sebastian Jansson73387822020-01-16 11:15:35 +0100517 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
Niels Möller7a669002022-06-27 09:47:02 +0200523 std::atomic<int> messages_processed(0);
Sebastian Jansson73387822020-01-16 11:15:35 +0100524 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);
Niels Möller7a669002022-06-27 09:47:02 +0200531 messages_processed.fetch_add(1);
Sebastian Jansson73387822020-01-16 11:15:35 +0100532 };
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.
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200538 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);
Sebastian Jansson73387822020-01-16 11:15:35 +0100543
544 ThreadManager::ProcessAllMessageQueuesForTesting();
Niels Möller7a669002022-06-27 09:47:02 +0200545 EXPECT_EQ(4, messages_processed.load(std::memory_order_acquire));
Sebastian Jansson73387822020-01-16 11:15:35 +0100546}
547
548// Test that ProcessAllMessageQueues doesn't hang if a thread is quitting.
549TEST(ThreadManager, ProcessAllMessageQueuesWithQuittingThread) {
550 auto t = Thread::CreateWithSocketServer();
551 t->Start();
552 t->Quit();
553 ThreadManager::ProcessAllMessageQueuesForTesting();
554}
555
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100556void 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.
562class LifeCycleFunctor {
563 public:
564 struct Stats {
565 size_t copy_count = 0;
566 size_t move_count = 0;
567 };
568
569 LifeCycleFunctor(Stats* stats, Event* event) : stats_(stats), event_(event) {}
570 LifeCycleFunctor(const LifeCycleFunctor& other) { *this = other; }
571 LifeCycleFunctor(LifeCycleFunctor&& other) { *this = std::move(other); }
572
573 LifeCycleFunctor& operator=(const LifeCycleFunctor& other) {
574 stats_ = other.stats_;
575 event_ = other.event_;
576 ++stats_->copy_count;
577 return *this;
578 }
579
580 LifeCycleFunctor& operator=(LifeCycleFunctor&& other) {
581 stats_ = other.stats_;
582 event_ = other.event_;
583 ++stats_->move_count;
584 return *this;
585 }
586
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.
595class DestructionFunctor {
596 public:
597 DestructionFunctor(Thread* thread, bool* thread_was_current, Event* event)
598 : thread_(thread),
599 thread_was_current_(thread_was_current),
600 event_(event) {}
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
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
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100620TEST(ThreadPostTaskTest, InvokesWithLambda) {
621 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
622 background_thread->Start();
623
624 Event event;
Henrik Boström595f6882022-01-24 09:57:03 +0100625 background_thread->PostTask([&event] { event.Set(); });
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100626 event.Wait(Event::kForever);
627}
628
629TEST(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);
Henrik Boström595f6882022-01-24 09:57:03 +0100636 background_thread->PostTask(functor);
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100637 event.Wait(Event::kForever);
638
639 EXPECT_EQ(1u, stats.copy_count);
640 EXPECT_EQ(0u, stats.move_count);
641}
642
643TEST(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);
Henrik Boström595f6882022-01-24 09:57:03 +0100650 background_thread->PostTask(std::move(functor));
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100651 event.Wait(Event::kForever);
652
653 EXPECT_EQ(0u, stats.copy_count);
654 EXPECT_EQ(1u, stats.move_count);
655}
656
657TEST(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;
Henrik Boström595f6882022-01-24 09:57:03 +0100665 background_thread->PostTask(functor_ref);
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100666 event.Wait(Event::kForever);
667
668 EXPECT_EQ(1u, stats.copy_count);
669 EXPECT_EQ(0u, stats.move_count);
670}
671
672TEST(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);
Henrik Boström595f6882022-01-24 09:57:03 +0100680 background_thread->PostTask(functor);
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100681 event.Wait(Event::kForever);
682
683 EXPECT_TRUE(was_invoked_on_background_thread);
684}
685
686TEST(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);
Henrik Boström595f6882022-01-24 09:57:03 +0100694 background_thread->PostTask(std::move(functor));
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100695 event.Wait(Event::kForever);
696
697 EXPECT_TRUE(was_invoked_on_background_thread);
698}
699
700TEST(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;
Henrik Boström595f6882022-01-24 09:57:03 +0100710 background_thread->PostTask(functor_ref);
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100711 event.Wait(Event::kForever);
712
713 EXPECT_TRUE(was_invoked_on_background_thread);
714}
715
716TEST(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;
Niels Möller1a29a5d2021-01-18 11:35:23 +0100722 Thread* background_thread_ptr = background_thread.get();
Henrik Boström595f6882022-01-24 09:57:03 +0100723 background_thread->PostTask(
Niels Möller1a29a5d2021-01-18 11:35:23 +0100724 [background_thread_ptr, &was_invoked_on_background_thread, &event] {
725 was_invoked_on_background_thread = background_thread_ptr->IsCurrent();
726 event.Set();
727 });
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100728 event.Wait(Event::kForever);
729
730 EXPECT_TRUE(was_invoked_on_background_thread);
731}
732
733TEST(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;
Henrik Boström595f6882022-01-24 09:57:03 +0100741 background_thread->PostTask(
Henrik Boström2deee4b2022-01-20 11:58:05 +0100742 [&event_set_by_test_thread, &event_set_by_background_thread] {
743 WaitAndSetEvent(&event_set_by_test_thread,
744 &event_set_by_background_thread);
745 });
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100746 event_set_by_test_thread.Set();
747 event_set_by_background_thread.Wait(Event::kForever);
748}
749
750TEST(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
Henrik Boström595f6882022-01-24 09:57:03 +0100759 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); });
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100765
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
Steve Antonbcc1a762019-12-11 11:21:53 -0800772TEST(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;
Henrik Boström595f6882022-01-24 09:57:03 +0100780 background_thread->PostDelayedTask(
Niels Möller1a29a5d2021-01-18 11:35:23 +0100781 [&event_set_by_test_thread, &event_set_by_background_thread] {
782 WaitAndSetEvent(&event_set_by_test_thread,
783 &event_set_by_background_thread);
784 },
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200785 TimeDelta::Millis(10));
Steve Antonbcc1a762019-12-11 11:21:53 -0800786 event_set_by_test_thread.Set();
787 event_set_by_background_thread.Wait(Event::kForever);
788}
789
790TEST(ThreadPostDelayedTaskTest, InvokesInDelayOrder) {
Steve Anton094396f2019-12-16 00:56:02 -0800791 ScopedFakeClock clock;
Steve Antonbcc1a762019-12-11 11:21:53 -0800792 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
Henrik Boström595f6882022-01-24 09:57:03 +0100800 background_thread->PostDelayedTask(
801 [&third, &fourth] { WaitAndSetEvent(&third, &fourth); },
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200802 TimeDelta::Millis(11));
Henrik Boström595f6882022-01-24 09:57:03 +0100803 background_thread->PostDelayedTask(
804 [&first, &second] { WaitAndSetEvent(&first, &second); },
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200805 TimeDelta::Millis(9));
Henrik Boström595f6882022-01-24 09:57:03 +0100806 background_thread->PostDelayedTask(
807 [&second, &third] { WaitAndSetEvent(&second, &third); },
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200808 TimeDelta::Millis(10));
Steve Antonbcc1a762019-12-11 11:21:53 -0800809
810 // All tasks have been posted before the first one is unblocked.
811 first.Set();
Steve Anton094396f2019-12-16 00:56:02 -0800812 // Only if the chain is invoked in delay order will the last event be set.
Danil Chapovalov4bcf8092022-07-06 19:42:34 +0200813 clock.AdvanceTime(TimeDelta::Millis(11));
Markus Handell2cfc1af2022-08-19 08:16:48 +0000814 EXPECT_TRUE(fourth.Wait(TimeDelta::Zero()));
Steve Antonbcc1a762019-12-11 11:21:53 -0800815}
816
Tommi6866dc72020-05-15 10:11:56 +0200817TEST(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
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100829class ThreadFactory : public webrtc::TaskQueueFactory {
830 public:
831 std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
832 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
Ali Tofigh4b681942022-08-23 12:57:16 +0200841std::unique_ptr<webrtc::TaskQueueFactory> CreateDefaultThreadFactory(
842 const webrtc::FieldTrialsView*) {
843 return std::make_unique<ThreadFactory>();
844}
845
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100846using ::webrtc::TaskQueueTest;
847
848INSTANTIATE_TEST_SUITE_P(RtcThread,
849 TaskQueueTest,
Ali Tofigh4b681942022-08-23 12:57:16 +0200850 ::testing::Values(CreateDefaultThreadFactory));
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100851
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100852} // namespace
853} // namespace rtc