• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 #ifndef BASE_TASK_THREAD_POOL_CAN_RUN_POLICY_TEST_H_
6 #define BASE_TASK_THREAD_POOL_CAN_RUN_POLICY_TEST_H_
7 
8 #include "base/synchronization/atomic_flag.h"
9 #include "base/task/task_runner.h"
10 #include "base/task/thread_pool/task_tracker.h"
11 #include "base/task/thread_pool/test_utils.h"
12 #include "base/test/bind.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/test/test_waitable_event.h"
15 #include "base/threading/platform_thread.h"
16 #include "build/build_config.h"
17 
18 namespace base {
19 namespace internal {
20 namespace test {
21 
22 // Verify that tasks only run when allowed by the CanRunPolicy. |target| is the
23 // object on which DidUpdateCanRunPolicy() must be called after updating the
24 // CanRunPolicy in |task_tracker|. |create_task_runner| is a function that
25 // receives a TaskPriority and returns a TaskRunner. |task_tracker| is the
26 // TaskTracker.
27 template <typename Target, typename CreateTaskRunner>
TestCanRunPolicyBasic(Target * target,CreateTaskRunner create_task_runner,TaskTracker * task_tracker)28 void TestCanRunPolicyBasic(Target* target,
29                            CreateTaskRunner create_task_runner,
30                            TaskTracker* task_tracker) {
31   AtomicFlag foreground_can_run;
32   TestWaitableEvent foreground_did_run;
33   AtomicFlag best_effort_can_run;
34   TestWaitableEvent best_effort_did_run;
35 
36   task_tracker->SetCanRunPolicy(CanRunPolicy::kNone);
37   target->DidUpdateCanRunPolicy();
38 
39   const auto user_visible_task_runner =
40       create_task_runner(TaskPriority::USER_VISIBLE);
41   user_visible_task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&] {
42                                        EXPECT_TRUE(foreground_can_run.IsSet());
43                                        foreground_did_run.Signal();
44                                      }));
45   const auto best_effort_task_runner =
46       create_task_runner(TaskPriority::BEST_EFFORT);
47   best_effort_task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&] {
48                                       EXPECT_TRUE(best_effort_can_run.IsSet());
49                                       best_effort_did_run.Signal();
50                                     }));
51 
52   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
53 
54   foreground_can_run.Set();
55   task_tracker->SetCanRunPolicy(CanRunPolicy::kForegroundOnly);
56   target->DidUpdateCanRunPolicy();
57   foreground_did_run.Wait();
58 
59   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
60 
61   best_effort_can_run.Set();
62   task_tracker->SetCanRunPolicy(CanRunPolicy::kAll);
63   target->DidUpdateCanRunPolicy();
64   best_effort_did_run.Wait();
65 }
66 
67 // Verify that if a task was allowed to run by the CanRunPolicy when it was
68 // posted, but the CanRunPolicy is updated to disallow it from running before it
69 // starts running, it doesn't run. |target| is the object on which
70 // DidUpdateCanRunPolicy() must be called after updating the CanRunPolicy in
71 // |task_tracker|. |create_task_runner| is a function that receives a
72 // TaskPriority and returns a *Sequenced*TaskRunner. |task_tracker| is the
73 // TaskTracker.
74 template <typename Target, typename CreateTaskRunner>
TestCanRunPolicyChangedBeforeRun(Target * target,CreateTaskRunner create_task_runner,TaskTracker * task_tracker)75 void TestCanRunPolicyChangedBeforeRun(Target* target,
76                                       CreateTaskRunner create_task_runner,
77                                       TaskTracker* task_tracker) {
78   constexpr struct {
79     // Descriptor for the test case.
80     const char* descriptor;
81     // Task priority being tested.
82     TaskPriority priority;
83     // Policy that disallows running tasks with |priority|.
84     CanRunPolicy disallow_policy;
85     // Policy that allows running tasks with |priority|.
86     CanRunPolicy allow_policy;
87   } kTestCases[] = {
88       {"BestEffort/kNone/kAll", TaskPriority::BEST_EFFORT, CanRunPolicy::kNone,
89        CanRunPolicy::kAll},
90       {"BestEffort/kForegroundOnly/kAll", TaskPriority::BEST_EFFORT,
91        CanRunPolicy::kForegroundOnly, CanRunPolicy::kAll},
92       {"UserVisible/kNone/kForegroundOnly", TaskPriority::USER_VISIBLE,
93        CanRunPolicy::kNone, CanRunPolicy::kForegroundOnly},
94       {"UserVisible/kNone/kAll", TaskPriority::USER_VISIBLE,
95        CanRunPolicy::kNone, CanRunPolicy::kAll}};
96 
97   for (auto& test_case : kTestCases) {
98     SCOPED_TRACE(test_case.descriptor);
99 
100     TestWaitableEvent first_task_started;
101     TestWaitableEvent first_task_blocked;
102     AtomicFlag second_task_can_run;
103 
104     task_tracker->SetCanRunPolicy(test_case.allow_policy);
105     target->DidUpdateCanRunPolicy();
106 
107     const auto task_runner = create_task_runner(test_case.priority);
108     task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&] {
109                             first_task_started.Signal();
110                             first_task_blocked.Wait();
111                           }));
112     task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&] {
113                             EXPECT_TRUE(second_task_can_run.IsSet());
114                           }));
115 
116     first_task_started.Wait();
117     task_tracker->SetCanRunPolicy(test_case.disallow_policy);
118     target->DidUpdateCanRunPolicy();
119     first_task_blocked.Signal();
120 
121     PlatformThread::Sleep(TestTimeouts::tiny_timeout());
122 
123     second_task_can_run.Set();
124     task_tracker->SetCanRunPolicy(test_case.allow_policy);
125     target->DidUpdateCanRunPolicy();
126     task_tracker->FlushForTesting();
127   }
128 }
129 
130 // Regression test for https://crbug.com/950383
131 template <typename Target, typename CreateTaskRunner>
TestCanRunPolicyLoad(Target * target,CreateTaskRunner create_task_runner,TaskTracker * task_tracker)132 void TestCanRunPolicyLoad(Target* target,
133                           CreateTaskRunner create_task_runner,
134                           TaskTracker* task_tracker) {
135   constexpr struct {
136     // Descriptor for the test case.
137     const char* descriptor;
138     // Task priority being tested.
139     TaskPriority priority;
140     // Policy that allows running tasks with |priority|.
141     CanRunPolicy allow_policy;
142     // Policy that disallows running tasks with |priority|.
143     CanRunPolicy disallow_policy;
144   } kTestCases[] = {
145       {"BestEffort/kAll/kNone", TaskPriority::BEST_EFFORT, CanRunPolicy::kAll,
146        CanRunPolicy::kNone},
147       {"BestEffort/kAll/kForegroundOnly", TaskPriority::BEST_EFFORT,
148        CanRunPolicy::kAll, CanRunPolicy::kForegroundOnly},
149       {"UserVisible/kForegroundOnly/kNone", TaskPriority::USER_VISIBLE,
150        CanRunPolicy::kForegroundOnly, CanRunPolicy::kNone},
151       {"UserVisible/kAll/kNone", TaskPriority::USER_VISIBLE, CanRunPolicy::kAll,
152        CanRunPolicy::kNone}};
153 
154   for (auto& test_case : kTestCases) {
155     SCOPED_TRACE(test_case.descriptor);
156 
157     task_tracker->SetCanRunPolicy(test_case.allow_policy);
158     target->DidUpdateCanRunPolicy();
159 
160     const auto task_runner = create_task_runner(test_case.priority);
161 
162     // Post less tasks on iOS to avoid timeouts.
163     const size_t kLargeNumber =
164 #if BUILDFLAG(IS_IOS)
165         16;
166 #else
167         256;
168 #endif
169     for (size_t i = 0; i < kLargeNumber; ++i)
170       task_runner->PostTask(FROM_HERE, DoNothing());
171 
172     // Change the CanRunPolicy concurrently with running tasks.
173     // This should not cause crashes.
174     for (size_t i = 0; i < kLargeNumber; ++i) {
175       task_tracker->SetCanRunPolicy(test_case.disallow_policy);
176       target->DidUpdateCanRunPolicy();
177 
178       task_tracker->SetCanRunPolicy(test_case.allow_policy);
179       target->DidUpdateCanRunPolicy();
180     }
181 
182     task_tracker->FlushForTesting();
183   }
184 }
185 
186 }  // namespace test
187 }  // namespace internal
188 }  // namespace base
189 
190 #endif  // BASE_TASK_THREAD_POOL_CAN_RUN_POLICY_TEST_H_
191