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