xref: /aosp_15_r20/external/cronet/base/task/thread_pool_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/task/thread_pool.h"
6 
7 #include "base/functional/bind.h"
8 #include "base/location.h"
9 #include "base/run_loop.h"
10 #include "base/task/bind_post_task.h"
11 #include "base/task/single_thread_task_executor.h"
12 #include "base/task/thread_pool/thread_pool_instance.h"
13 #include "base/test/bind.h"
14 #include "base/test/task_environment.h"
15 #include "base/test/test_waitable_event.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace base {
19 
TEST(ThreadPool,PostTaskAndReplyWithResultThreeArgs)20 TEST(ThreadPool, PostTaskAndReplyWithResultThreeArgs) {
21   base::test::TaskEnvironment env;
22 
23   base::RunLoop run_loop;
24   base::ThreadPool::PostTaskAndReplyWithResult(
25       FROM_HERE, base::BindOnce([]() { return 3; }),
26       base::OnceCallback<void(int)>(
27           base::BindLambdaForTesting([&run_loop](int x) {
28             EXPECT_EQ(x, 3);
29             run_loop.Quit();
30           })));
31   run_loop.Run();
32 }
33 
TEST(ThreadPool,PostTaskAndReplyWithResultFourArgs)34 TEST(ThreadPool, PostTaskAndReplyWithResultFourArgs) {
35   base::test::TaskEnvironment env;
36 
37   base::RunLoop run_loop;
38   base::ThreadPool::PostTaskAndReplyWithResult(
39       FROM_HERE, /*traits=*/{}, base::BindOnce([]() { return 3; }),
40       base::OnceCallback<void(int)>(
41           base::BindLambdaForTesting([&run_loop](int x) {
42             EXPECT_EQ(x, 3);
43             run_loop.Quit();
44           })));
45   run_loop.Run();
46 }
47 
TEST(ThreadPool,BindPostTaskFizzlesOnShutdown)48 TEST(ThreadPool, BindPostTaskFizzlesOnShutdown) {
49   // Tests that a callback bound to a BLOCK_SHUTDOWN sequence doesn't trigger a
50   // DCHECK when it's deleted without running.
51   base::ThreadPoolInstance::CreateAndStartWithDefaultParams(
52       "BindPostTaskFizzlesOnShutdownTest");
53 
54   {
55     // Creating this callback and deleting it after the thread pool is shutdown
56     // used to trigger a DCHECK in task_tracker because the
57     // BindPostTaskTrampoline destructor has to delete its state on the sequence
58     // it's bound to. There is a DCHECK that ensures BLOCK_SHUTDOWN tasks aren't
59     // posted after shutdown, but BindPostTaskTrampoline uses
60     // base::ThreadPoolInstance::ScopedFizzleBlockShutdownTasks to avoid
61     // triggering it.
62     auto bound_callback =
63         base::BindPostTask(base::ThreadPool::CreateSequencedTaskRunner(
64                                {TaskShutdownBehavior::BLOCK_SHUTDOWN}),
65                            base::BindOnce([]() { ADD_FAILURE(); }));
66     base::ThreadPoolInstance::Get()->Shutdown();
67   }
68 
69   ThreadPoolInstance::Get()->JoinForTesting();
70   ThreadPoolInstance::Set(nullptr);
71 }
72 
TEST(ThreadPool,PostTaskAndReplyFizzlesOnShutdown)73 TEST(ThreadPool, PostTaskAndReplyFizzlesOnShutdown) {
74   // Tests that a PostTaskAndReply from a BLOCK_SHUTDOWN sequence doesn't
75   // trigger a DCHECK when it's not run at shutdown.
76   base::ThreadPoolInstance::CreateAndStartWithDefaultParams(
77       "PostTaskAndReplyFizzlesOnShutdown");
78 
79   {
80     base::SingleThreadTaskExecutor executor;
81     auto blocking_task_runner = base::ThreadPool::CreateSequencedTaskRunner(
82         {TaskShutdownBehavior::BLOCK_SHUTDOWN});
83 
84     base::RunLoop run_loop;
85 
86     // The setup that this test is exercising is as follows:
87     // - A task is posted using PostTaskAndReply from a BLOCK_SHUTDOWN sequence
88     // to the main thread
89     // - The task is not run on the main thread
90     // - Shutdown happens, the ThreadPool is shutdown
91     // - The main thread destroys its un-run tasks
92     // - ~PostTaskAndReplyRelay calls `DeleteSoon` to delete its reply's state
93     // on the sequence it's bound to
94     // - TaskTracker ensures that no BLOCK_SHUTDOWN tasks can be posted after
95     // shutdown. ~PostTaskAndReplyRelay avoids triggering this DCHECK by using a
96     // base::ThreadPoolInstance::ScopedFizzleBlockShutdownTasks
97 
98     // Post a task to the BLOCK_SHUTDOWN thread pool sequence to setup the test.
99     base::TestWaitableEvent event;
100     blocking_task_runner->PostTask(
101         FROM_HERE, base::BindLambdaForTesting([&]() {
102           // Enqueue a task whose only purpose is to exit the run loop, ensuring
103           // the following task is never run.
104           executor.task_runner()->PostTask(FROM_HERE,
105                                            base::BindLambdaForTesting([&]() {
106                                              event.Wait();
107                                              run_loop.Quit();
108                                            }));
109 
110           // Post the task for which the reply will trigger the `DeleteSoon`
111           // from `~PostTaskAndReplyRelay`.
112           executor.task_runner()->PostTaskAndReply(
113               FROM_HERE, base::BindOnce([]() { ADD_FAILURE(); }),
114               base::BindOnce([]() { ADD_FAILURE(); }));
115 
116           event.Signal();
117         }));
118 
119     // Run until the first task posted to the SingleThreadTaskExecutor quits the
120     // run loop, resulting in the `PostTaskAndReply` being queued but not run.
121     run_loop.Run();
122 
123     base::ThreadPoolInstance::Get()->Shutdown();
124   }
125 
126   ThreadPoolInstance::Get()->JoinForTesting();
127   ThreadPoolInstance::Set(nullptr);
128 }
129 
130 }  // namespace base
131