thread_unittest.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/threading/thread.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/debug/leak_annotations.h"
  11. #include "base/logging.h"
  12. #include "base/memory/ptr_util.h"
  13. #include "base/memory/raw_ptr.h"
  14. #include "base/run_loop.h"
  15. #include "base/synchronization/waitable_event.h"
  16. #include "base/task/current_thread.h"
  17. #include "base/task/sequence_manager/sequence_manager_impl.h"
  18. #include "base/task/single_thread_task_runner.h"
  19. #include "base/task/task_executor.h"
  20. #include "base/test/bind.h"
  21. #include "base/test/gtest_util.h"
  22. #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
  23. #include "base/threading/platform_thread.h"
  24. #include "base/time/time.h"
  25. #include "build/build_config.h"
  26. #include "testing/gmock/include/gmock/gmock.h"
  27. #include "testing/gtest/include/gtest/gtest.h"
  28. #include "testing/platform_test.h"
  29. using base::Thread;
  30. using ::testing::NotNull;
  31. typedef PlatformTest ThreadTest;
  32. namespace {
  33. void ToggleValue(bool* value) {
  34. ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean "
  35. "in base/thread_unittest");
  36. *value = !*value;
  37. }
  38. class SleepInsideInitThread : public Thread {
  39. public:
  40. SleepInsideInitThread() : Thread("none") {
  41. init_called_ = false;
  42. ANNOTATE_BENIGN_RACE(
  43. this, "Benign test-only data race on vptr - http://crbug.com/98219");
  44. }
  45. SleepInsideInitThread(const SleepInsideInitThread&) = delete;
  46. SleepInsideInitThread& operator=(const SleepInsideInitThread&) = delete;
  47. ~SleepInsideInitThread() override { Stop(); }
  48. void Init() override {
  49. base::PlatformThread::Sleep(base::Milliseconds(500));
  50. init_called_ = true;
  51. }
  52. bool InitCalled() { return init_called_; }
  53. private:
  54. bool init_called_;
  55. };
  56. enum ThreadEvent {
  57. // Thread::Init() was called.
  58. THREAD_EVENT_INIT = 0,
  59. // The MessageLoop for the thread was deleted.
  60. THREAD_EVENT_MESSAGE_LOOP_DESTROYED,
  61. // Thread::CleanUp() was called.
  62. THREAD_EVENT_CLEANUP,
  63. // Keep at end of list.
  64. THREAD_NUM_EVENTS
  65. };
  66. typedef std::vector<ThreadEvent> EventList;
  67. class CaptureToEventList : public Thread {
  68. public:
  69. // This Thread pushes events into the vector |event_list| to show
  70. // the order they occured in. |event_list| must remain valid for the
  71. // lifetime of this thread.
  72. explicit CaptureToEventList(EventList* event_list)
  73. : Thread("none"),
  74. event_list_(event_list) {
  75. }
  76. CaptureToEventList(const CaptureToEventList&) = delete;
  77. CaptureToEventList& operator=(const CaptureToEventList&) = delete;
  78. ~CaptureToEventList() override { Stop(); }
  79. void Init() override { event_list_->push_back(THREAD_EVENT_INIT); }
  80. void CleanUp() override { event_list_->push_back(THREAD_EVENT_CLEANUP); }
  81. private:
  82. raw_ptr<EventList> event_list_;
  83. };
  84. // Observer that writes a value into |event_list| when a message loop has been
  85. // destroyed.
  86. class CapturingDestructionObserver
  87. : public base::CurrentThread::DestructionObserver {
  88. public:
  89. // |event_list| must remain valid throughout the observer's lifetime.
  90. explicit CapturingDestructionObserver(EventList* event_list)
  91. : event_list_(event_list) {
  92. }
  93. CapturingDestructionObserver(const CapturingDestructionObserver&) = delete;
  94. CapturingDestructionObserver& operator=(const CapturingDestructionObserver&) =
  95. delete;
  96. // DestructionObserver implementation:
  97. void WillDestroyCurrentMessageLoop() override {
  98. event_list_->push_back(THREAD_EVENT_MESSAGE_LOOP_DESTROYED);
  99. event_list_ = nullptr;
  100. }
  101. private:
  102. raw_ptr<EventList> event_list_;
  103. };
  104. // Task that adds a destruction observer to the current message loop.
  105. void RegisterDestructionObserver(
  106. base::CurrentThread::DestructionObserver* observer) {
  107. base::CurrentThread::Get()->AddDestructionObserver(observer);
  108. }
  109. // Task that calls GetThreadId() of |thread|, stores the result into |id|, then
  110. // signal |event|.
  111. void ReturnThreadId(base::Thread* thread,
  112. base::PlatformThreadId* id,
  113. base::WaitableEvent* event) {
  114. *id = thread->GetThreadId();
  115. event->Signal();
  116. }
  117. } // namespace
  118. TEST_F(ThreadTest, StartWithOptions_StackSize) {
  119. Thread a("StartWithStackSize");
  120. // Ensure that the thread can work with only 12 kb and still process a
  121. // message. At the same time, we should scale with the bitness of the system
  122. // where 12 kb is definitely not enough.
  123. // 12 kb = 3072 Slots on a 32-bit system, so we'll scale based off of that.
  124. Thread::Options options;
  125. #if defined(ADDRESS_SANITIZER) || !defined(NDEBUG)
  126. // ASan bloats the stack variables and overflows the 3072 slot stack. Some
  127. // debug builds also grow the stack too much.
  128. options.stack_size = 2 * 3072 * sizeof(uintptr_t);
  129. #else
  130. options.stack_size = 3072 * sizeof(uintptr_t);
  131. #endif
  132. EXPECT_TRUE(a.StartWithOptions(std::move(options)));
  133. EXPECT_TRUE(a.task_runner());
  134. EXPECT_TRUE(a.IsRunning());
  135. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
  136. base::WaitableEvent::InitialState::NOT_SIGNALED);
  137. a.task_runner()->PostTask(
  138. FROM_HERE,
  139. base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)));
  140. event.Wait();
  141. }
  142. // Intentional test-only race for otherwise untestable code, won't fix.
  143. // https://crbug.com/634383
  144. #if !defined(THREAD_SANITIZER)
  145. TEST_F(ThreadTest, StartWithOptions_NonJoinable) {
  146. Thread* a = new Thread("StartNonJoinable");
  147. // Non-joinable threads have to be leaked for now (see
  148. // Thread::Options::joinable for details).
  149. ANNOTATE_LEAKING_OBJECT_PTR(a);
  150. Thread::Options options;
  151. options.joinable = false;
  152. EXPECT_TRUE(a->StartWithOptions(std::move(options)));
  153. EXPECT_TRUE(a->task_runner());
  154. EXPECT_TRUE(a->IsRunning());
  155. // Without this call this test is racy. The above IsRunning() succeeds because
  156. // of an early-return condition while between Start() and StopSoon(), after
  157. // invoking StopSoon() below this early-return condition is no longer
  158. // satisfied and the real |is_running_| bit has to be checked. It could still
  159. // be false if the message loop hasn't started for real in practice. This is
  160. // only a requirement for this test because the non-joinable property forces
  161. // it to use StopSoon() and not wait for a complete Stop().
  162. EXPECT_TRUE(a->WaitUntilThreadStarted());
  163. // Make the thread block until |block_event| is signaled.
  164. base::WaitableEvent block_event(
  165. base::WaitableEvent::ResetPolicy::AUTOMATIC,
  166. base::WaitableEvent::InitialState::NOT_SIGNALED);
  167. a->task_runner()->PostTask(FROM_HERE,
  168. base::BindOnce(&base::WaitableEvent::Wait,
  169. base::Unretained(&block_event)));
  170. a->StopSoon();
  171. EXPECT_TRUE(a->IsRunning());
  172. // Unblock the task and give a bit of extra time to unwind QuitWhenIdle().
  173. block_event.Signal();
  174. base::PlatformThread::Sleep(base::Milliseconds(20));
  175. // The thread should now have stopped on its own.
  176. EXPECT_FALSE(a->IsRunning());
  177. }
  178. #endif
  179. TEST_F(ThreadTest, TwoTasksOnJoinableThread) {
  180. bool was_invoked = false;
  181. {
  182. Thread a("TwoTasksOnJoinableThread");
  183. EXPECT_TRUE(a.Start());
  184. EXPECT_TRUE(a.task_runner());
  185. // Test that all events are dispatched before the Thread object is
  186. // destroyed. We do this by dispatching a sleep event before the
  187. // event that will toggle our sentinel value.
  188. a.task_runner()->PostTask(
  189. FROM_HERE, base::BindOnce(static_cast<void (*)(base::TimeDelta)>(
  190. &base::PlatformThread::Sleep),
  191. base::Milliseconds(20)));
  192. a.task_runner()->PostTask(FROM_HERE,
  193. base::BindOnce(&ToggleValue, &was_invoked));
  194. }
  195. EXPECT_TRUE(was_invoked);
  196. }
  197. TEST_F(ThreadTest, DestroyWhileRunningIsSafe) {
  198. Thread a("DestroyWhileRunningIsSafe");
  199. EXPECT_TRUE(a.Start());
  200. EXPECT_TRUE(a.WaitUntilThreadStarted());
  201. }
  202. // TODO(gab): Enable this test when destroying a non-joinable Thread instance
  203. // is supported (proposal @ https://crbug.com/629139#c14).
  204. TEST_F(ThreadTest, DISABLED_DestroyWhileRunningNonJoinableIsSafe) {
  205. {
  206. Thread a("DestroyWhileRunningNonJoinableIsSafe");
  207. Thread::Options options;
  208. options.joinable = false;
  209. EXPECT_TRUE(a.StartWithOptions(std::move(options)));
  210. EXPECT_TRUE(a.WaitUntilThreadStarted());
  211. }
  212. // Attempt to catch use-after-frees from the non-joinable thread in the
  213. // scope of this test if any.
  214. base::PlatformThread::Sleep(base::Milliseconds(20));
  215. }
  216. TEST_F(ThreadTest, StopSoon) {
  217. Thread a("StopSoon");
  218. EXPECT_TRUE(a.Start());
  219. EXPECT_TRUE(a.task_runner());
  220. EXPECT_TRUE(a.IsRunning());
  221. a.StopSoon();
  222. a.Stop();
  223. EXPECT_FALSE(a.task_runner());
  224. EXPECT_FALSE(a.IsRunning());
  225. }
  226. TEST_F(ThreadTest, StopTwiceNop) {
  227. Thread a("StopTwiceNop");
  228. EXPECT_TRUE(a.Start());
  229. EXPECT_TRUE(a.task_runner());
  230. EXPECT_TRUE(a.IsRunning());
  231. a.StopSoon();
  232. // Calling StopSoon() a second time should be a nop.
  233. a.StopSoon();
  234. a.Stop();
  235. // Same with Stop().
  236. a.Stop();
  237. EXPECT_FALSE(a.task_runner());
  238. EXPECT_FALSE(a.IsRunning());
  239. // Calling them when not running should also nop.
  240. a.StopSoon();
  241. a.Stop();
  242. }
  243. // TODO(gab): Enable this test in conjunction with re-enabling the sequence
  244. // check in Thread::Stop() as part of http://crbug.com/629139.
  245. TEST_F(ThreadTest, DISABLED_StopOnNonOwningThreadIsDeath) {
  246. Thread a("StopOnNonOwningThreadDeath");
  247. EXPECT_TRUE(a.StartAndWaitForTesting());
  248. Thread b("NonOwningThread");
  249. b.Start();
  250. EXPECT_DCHECK_DEATH({
  251. // Stopping |a| on |b| isn't allowed.
  252. b.task_runner()->PostTask(
  253. FROM_HERE, base::BindOnce(&Thread::Stop, base::Unretained(&a)));
  254. // Block here so the DCHECK on |b| always happens in this scope.
  255. base::PlatformThread::Sleep(base::TimeDelta::Max());
  256. });
  257. }
  258. TEST_F(ThreadTest, TransferOwnershipAndStop) {
  259. std::unique_ptr<Thread> a =
  260. std::make_unique<Thread>("TransferOwnershipAndStop");
  261. EXPECT_TRUE(a->StartAndWaitForTesting());
  262. EXPECT_TRUE(a->IsRunning());
  263. Thread b("TakingOwnershipThread");
  264. b.Start();
  265. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
  266. base::WaitableEvent::InitialState::NOT_SIGNALED);
  267. // a->DetachFromSequence() should allow |b| to use |a|'s Thread API.
  268. a->DetachFromSequence();
  269. b.task_runner()->PostTask(
  270. FROM_HERE, base::BindOnce(
  271. [](std::unique_ptr<Thread> thread_to_stop,
  272. base::WaitableEvent* event_to_signal) -> void {
  273. thread_to_stop->Stop();
  274. event_to_signal->Signal();
  275. },
  276. std::move(a), base::Unretained(&event)));
  277. event.Wait();
  278. }
  279. TEST_F(ThreadTest, StartTwice) {
  280. Thread a("StartTwice");
  281. EXPECT_FALSE(a.task_runner());
  282. EXPECT_FALSE(a.IsRunning());
  283. EXPECT_TRUE(a.Start());
  284. EXPECT_TRUE(a.task_runner());
  285. EXPECT_TRUE(a.IsRunning());
  286. a.Stop();
  287. EXPECT_FALSE(a.task_runner());
  288. EXPECT_FALSE(a.IsRunning());
  289. EXPECT_TRUE(a.Start());
  290. EXPECT_TRUE(a.task_runner());
  291. EXPECT_TRUE(a.IsRunning());
  292. a.Stop();
  293. EXPECT_FALSE(a.task_runner());
  294. EXPECT_FALSE(a.IsRunning());
  295. }
  296. // Intentional test-only race for otherwise untestable code, won't fix.
  297. // https://crbug.com/634383
  298. #if !defined(THREAD_SANITIZER)
  299. TEST_F(ThreadTest, StartTwiceNonJoinableNotAllowed) {
  300. LOG(ERROR) << __FUNCTION__;
  301. Thread* a = new Thread("StartTwiceNonJoinable");
  302. // Non-joinable threads have to be leaked for now (see
  303. // Thread::Options::joinable for details).
  304. ANNOTATE_LEAKING_OBJECT_PTR(a);
  305. Thread::Options options;
  306. options.joinable = false;
  307. EXPECT_TRUE(a->StartWithOptions(std::move(options)));
  308. EXPECT_TRUE(a->task_runner());
  309. EXPECT_TRUE(a->IsRunning());
  310. // Signaled when last task on |a| is processed.
  311. base::WaitableEvent last_task_event(
  312. base::WaitableEvent::ResetPolicy::AUTOMATIC,
  313. base::WaitableEvent::InitialState::NOT_SIGNALED);
  314. a->task_runner()->PostTask(
  315. FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
  316. base::Unretained(&last_task_event)));
  317. // StopSoon() is non-blocking, Yield() to |a|, wait for last task to be
  318. // processed and a little more for QuitWhenIdle() to unwind before considering
  319. // the thread "stopped".
  320. a->StopSoon();
  321. base::PlatformThread::YieldCurrentThread();
  322. last_task_event.Wait();
  323. base::PlatformThread::Sleep(base::Milliseconds(20));
  324. // This test assumes that the above was sufficient to let the thread fully
  325. // stop.
  326. ASSERT_FALSE(a->IsRunning());
  327. // Restarting it should not be allowed.
  328. EXPECT_DCHECK_DEATH(a->Start());
  329. }
  330. #endif
  331. TEST_F(ThreadTest, ThreadName) {
  332. Thread a("ThreadName");
  333. EXPECT_TRUE(a.Start());
  334. EXPECT_EQ("ThreadName", a.thread_name());
  335. }
  336. TEST_F(ThreadTest, ThreadId) {
  337. Thread a("ThreadId0");
  338. Thread b("ThreadId1");
  339. a.Start();
  340. b.Start();
  341. // Post a task that calls GetThreadId() on the created thread.
  342. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
  343. base::WaitableEvent::InitialState::NOT_SIGNALED);
  344. base::PlatformThreadId id_from_new_thread;
  345. a.task_runner()->PostTask(
  346. FROM_HERE,
  347. base::BindOnce(ReturnThreadId, &a, &id_from_new_thread, &event));
  348. // Call GetThreadId() on the current thread before calling event.Wait() so
  349. // that this test can find a race issue with TSAN.
  350. base::PlatformThreadId id_from_current_thread = a.GetThreadId();
  351. // Check if GetThreadId() returns consistent value in both threads.
  352. event.Wait();
  353. EXPECT_EQ(id_from_current_thread, id_from_new_thread);
  354. // A started thread should have a valid ID.
  355. EXPECT_NE(base::kInvalidThreadId, a.GetThreadId());
  356. EXPECT_NE(base::kInvalidThreadId, b.GetThreadId());
  357. // Each thread should have a different thread ID.
  358. EXPECT_NE(a.GetThreadId(), b.GetThreadId());
  359. }
  360. TEST_F(ThreadTest, ThreadIdWithRestart) {
  361. Thread a("ThreadIdWithRestart");
  362. base::PlatformThreadId previous_id = base::kInvalidThreadId;
  363. for (size_t i = 0; i < 16; ++i) {
  364. EXPECT_TRUE(a.Start());
  365. base::PlatformThreadId current_id = a.GetThreadId();
  366. EXPECT_NE(previous_id, current_id);
  367. previous_id = current_id;
  368. a.Stop();
  369. }
  370. }
  371. // Make sure Init() is called after Start() and before
  372. // WaitUntilThreadInitialized() returns.
  373. TEST_F(ThreadTest, SleepInsideInit) {
  374. SleepInsideInitThread t;
  375. EXPECT_FALSE(t.InitCalled());
  376. t.StartAndWaitForTesting();
  377. EXPECT_TRUE(t.InitCalled());
  378. }
  379. // Make sure that the destruction sequence is:
  380. //
  381. // (1) Thread::CleanUp()
  382. // (2) MessageLoop::~MessageLoop()
  383. // CurrentThread::DestructionObservers called.
  384. TEST_F(ThreadTest, CleanUp) {
  385. EventList captured_events;
  386. CapturingDestructionObserver loop_destruction_observer(&captured_events);
  387. {
  388. // Start a thread which writes its event into |captured_events|.
  389. CaptureToEventList t(&captured_events);
  390. EXPECT_TRUE(t.Start());
  391. EXPECT_TRUE(t.task_runner());
  392. EXPECT_TRUE(t.IsRunning());
  393. // Register an observer that writes into |captured_events| once the
  394. // thread's message loop is destroyed.
  395. t.task_runner()->PostTask(
  396. FROM_HERE,
  397. base::BindOnce(&RegisterDestructionObserver,
  398. base::Unretained(&loop_destruction_observer)));
  399. // Upon leaving this scope, the thread is deleted.
  400. }
  401. // Check the order of events during shutdown.
  402. ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size());
  403. EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]);
  404. EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]);
  405. EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]);
  406. }
  407. TEST_F(ThreadTest, ThreadNotStarted) {
  408. Thread a("Inert");
  409. EXPECT_FALSE(a.task_runner());
  410. }
  411. TEST_F(ThreadTest, MultipleWaitUntilThreadStarted) {
  412. Thread a("MultipleWaitUntilThreadStarted");
  413. EXPECT_TRUE(a.Start());
  414. // It's OK to call WaitUntilThreadStarted() multiple times.
  415. EXPECT_TRUE(a.WaitUntilThreadStarted());
  416. EXPECT_TRUE(a.WaitUntilThreadStarted());
  417. }
  418. TEST_F(ThreadTest, FlushForTesting) {
  419. Thread a("FlushForTesting");
  420. // Flushing a non-running thread should be a no-op.
  421. a.FlushForTesting();
  422. ASSERT_TRUE(a.Start());
  423. // Flushing a thread with no tasks shouldn't block.
  424. a.FlushForTesting();
  425. constexpr base::TimeDelta kSleepPerTestTask = base::Milliseconds(50);
  426. constexpr size_t kNumSleepTasks = 5;
  427. const base::TimeTicks ticks_before_post = base::TimeTicks::Now();
  428. for (size_t i = 0; i < kNumSleepTasks; ++i) {
  429. a.task_runner()->PostTask(
  430. FROM_HERE,
  431. base::BindOnce(&base::PlatformThread::Sleep, kSleepPerTestTask));
  432. }
  433. // All tasks should have executed, as reflected by the elapsed time.
  434. a.FlushForTesting();
  435. EXPECT_GE(base::TimeTicks::Now() - ticks_before_post,
  436. kNumSleepTasks * kSleepPerTestTask);
  437. a.Stop();
  438. // Flushing a stopped thread should be a no-op.
  439. a.FlushForTesting();
  440. }
  441. TEST_F(ThreadTest, GetTaskExecutorForCurrentThread) {
  442. Thread a("GetTaskExecutorForCurrentThread");
  443. ASSERT_TRUE(a.Start());
  444. base::WaitableEvent event;
  445. a.task_runner()->PostTask(
  446. FROM_HERE, base::BindLambdaForTesting([&]() {
  447. EXPECT_THAT(base::GetTaskExecutorForCurrentThread(), NotNull());
  448. event.Signal();
  449. }));
  450. event.Wait();
  451. a.Stop();
  452. }
  453. namespace {
  454. class SequenceManagerThreadDelegate : public Thread::Delegate {
  455. public:
  456. SequenceManagerThreadDelegate()
  457. : sequence_manager_(
  458. base::sequence_manager::CreateUnboundSequenceManager()),
  459. task_queue_(
  460. sequence_manager_
  461. ->CreateTaskQueueWithType<base::sequence_manager::TaskQueue>(
  462. base::sequence_manager::TaskQueue::Spec("default_tq"))) {
  463. sequence_manager_->SetDefaultTaskRunner(GetDefaultTaskRunner());
  464. }
  465. SequenceManagerThreadDelegate(const SequenceManagerThreadDelegate&) = delete;
  466. SequenceManagerThreadDelegate& operator=(
  467. const SequenceManagerThreadDelegate&) = delete;
  468. ~SequenceManagerThreadDelegate() override {}
  469. // Thread::Delegate:
  470. scoped_refptr<base::SingleThreadTaskRunner> GetDefaultTaskRunner() override {
  471. return task_queue_->task_runner();
  472. }
  473. void BindToCurrentThread(base::TimerSlack timer_slack) override {
  474. sequence_manager_->BindToMessagePump(
  475. base::MessagePump::Create(base::MessagePumpType::DEFAULT));
  476. sequence_manager_->SetTimerSlack(timer_slack);
  477. }
  478. private:
  479. std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager_;
  480. scoped_refptr<base::sequence_manager::TaskQueue> task_queue_;
  481. };
  482. } // namespace
  483. TEST_F(ThreadTest, ProvidedThreadDelegate) {
  484. Thread thread("ThreadDelegate");
  485. base::Thread::Options options;
  486. options.delegate = std::make_unique<SequenceManagerThreadDelegate>();
  487. scoped_refptr<base::SingleThreadTaskRunner> task_runner =
  488. options.delegate->GetDefaultTaskRunner();
  489. thread.StartWithOptions(std::move(options));
  490. base::WaitableEvent event;
  491. task_runner->PostTask(FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
  492. base::Unretained(&event)));
  493. event.Wait();
  494. thread.Stop();
  495. }