blob: 5d60816fc32bf8d5901c4846817b39ddd618c1fe [file] [log] [blame]
Sami Kyostila2c6c2f52017-11-21 16:08:16 +00001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "base/unix_task_runner.h"
18
Sami Kyostila73d41c82017-11-24 18:38:46 +000019#include "base/build_config.h"
Sami Kyostila2c6c2f52017-11-21 16:08:16 +000020#include "base/scoped_file.h"
21#include "gtest/gtest.h"
22
Sami Kyostila73d41c82017-11-24 18:38:46 +000023#if BUILDFLAG(OS_ANDROID)
24#include "base/android_task_runner.h"
25#endif
26
Sami Kyostila2c6c2f52017-11-21 16:08:16 +000027#include <thread>
28
29namespace perfetto {
30namespace base {
31namespace {
32
Sami Kyostila73d41c82017-11-24 18:38:46 +000033template <typename T>
34class TaskRunnerTest : public ::testing::Test {
35 public:
36 T task_runner;
37};
38
39#if BUILDFLAG(OS_ANDROID)
40using TaskRunnerTypes = ::testing::Types<AndroidTaskRunner, UnixTaskRunner>;
41#else
42using TaskRunnerTypes = ::testing::Types<UnixTaskRunner>;
43#endif
44TYPED_TEST_CASE(TaskRunnerTest, TaskRunnerTypes);
45
Sami Kyostila2c6c2f52017-11-21 16:08:16 +000046struct Pipe {
47 Pipe() {
48 int pipe_fds[2];
49 PERFETTO_DCHECK(pipe(pipe_fds) == 0);
50 read_fd.reset(pipe_fds[0]);
51 write_fd.reset(pipe_fds[1]);
52 // Make the pipe initially readable.
53 Write();
54 }
55
56 void Read() {
57 char b;
58 PERFETTO_DCHECK(read(read_fd.get(), &b, 1) == 1);
59 }
60
61 void Write() {
62 const char b = '?';
63 PERFETTO_DCHECK(write(write_fd.get(), &b, 1) == 1);
64 }
65
66 ScopedFile read_fd;
67 ScopedFile write_fd;
68};
69
Sami Kyostila73d41c82017-11-24 18:38:46 +000070TYPED_TEST(TaskRunnerTest, PostImmediateTask) {
71 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +000072 int counter = 0;
73 task_runner.PostTask([&counter] { counter = (counter << 4) | 1; });
74 task_runner.PostTask([&counter] { counter = (counter << 4) | 2; });
75 task_runner.PostTask([&counter] { counter = (counter << 4) | 3; });
76 task_runner.PostTask([&counter] { counter = (counter << 4) | 4; });
77 task_runner.PostTask([&task_runner] { task_runner.Quit(); });
78 task_runner.Run();
79 EXPECT_EQ(0x1234, counter);
80}
81
Sami Kyostila73d41c82017-11-24 18:38:46 +000082TYPED_TEST(TaskRunnerTest, PostDelayedTask) {
83 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +000084 int counter = 0;
85 task_runner.PostDelayedTask([&counter] { counter = (counter << 4) | 1; }, 5);
86 task_runner.PostDelayedTask([&counter] { counter = (counter << 4) | 2; }, 10);
87 task_runner.PostDelayedTask([&counter] { counter = (counter << 4) | 3; }, 15);
88 task_runner.PostDelayedTask([&counter] { counter = (counter << 4) | 4; }, 15);
89 task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 20);
90 task_runner.Run();
91 EXPECT_EQ(0x1234, counter);
92}
93
Sami Kyostila73d41c82017-11-24 18:38:46 +000094TYPED_TEST(TaskRunnerTest, PostImmediateTaskFromTask) {
95 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +000096 task_runner.PostTask([&task_runner] {
97 task_runner.PostTask([&task_runner] { task_runner.Quit(); });
98 });
99 task_runner.Run();
100}
101
Sami Kyostila73d41c82017-11-24 18:38:46 +0000102TYPED_TEST(TaskRunnerTest, PostDelayedTaskFromTask) {
103 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000104 task_runner.PostTask([&task_runner] {
105 task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
106 });
107 task_runner.Run();
108}
109
Sami Kyostila73d41c82017-11-24 18:38:46 +0000110TYPED_TEST(TaskRunnerTest, PostImmediateTaskFromOtherThread) {
111 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000112 ThreadChecker thread_checker;
113 int counter = 0;
114 std::thread thread([&task_runner, &counter, &thread_checker] {
115 task_runner.PostTask([&thread_checker] {
116 EXPECT_TRUE(thread_checker.CalledOnValidThread());
117 });
118 task_runner.PostTask([&counter] { counter = (counter << 4) | 1; });
119 task_runner.PostTask([&counter] { counter = (counter << 4) | 2; });
120 task_runner.PostTask([&counter] { counter = (counter << 4) | 3; });
121 task_runner.PostTask([&counter] { counter = (counter << 4) | 4; });
122 task_runner.PostTask([&task_runner] { task_runner.Quit(); });
123 });
124 task_runner.Run();
125 thread.join();
126 EXPECT_EQ(0x1234, counter);
127}
128
Sami Kyostila73d41c82017-11-24 18:38:46 +0000129TYPED_TEST(TaskRunnerTest, PostDelayedTaskFromOtherThread) {
130 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000131 std::thread thread([&task_runner] {
132 task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
133 });
134 task_runner.Run();
135 thread.join();
136}
137
Sami Kyostila73d41c82017-11-24 18:38:46 +0000138TYPED_TEST(TaskRunnerTest, AddFileDescriptorWatch) {
139 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000140 Pipe pipe;
141 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
142 [&task_runner] { task_runner.Quit(); });
143 task_runner.Run();
144}
145
Sami Kyostila73d41c82017-11-24 18:38:46 +0000146TYPED_TEST(TaskRunnerTest, RemoveFileDescriptorWatch) {
147 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000148 Pipe pipe;
149
150 bool watch_ran = false;
151 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
152 [&watch_ran] { watch_ran = true; });
153 task_runner.RemoveFileDescriptorWatch(pipe.read_fd.get());
154 task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
155 task_runner.Run();
156
157 EXPECT_FALSE(watch_ran);
158}
159
Sami Kyostila73d41c82017-11-24 18:38:46 +0000160TYPED_TEST(TaskRunnerTest, RemoveFileDescriptorWatchFromTask) {
161 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000162 Pipe pipe;
163
164 bool watch_ran = false;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000165 task_runner.PostTask([&task_runner, &pipe] {
166 task_runner.RemoveFileDescriptorWatch(pipe.read_fd.get());
167 });
Sami Kyostila73d41c82017-11-24 18:38:46 +0000168 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
169 [&watch_ran] { watch_ran = true; });
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000170 task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
171 task_runner.Run();
172
173 EXPECT_FALSE(watch_ran);
174}
175
Sami Kyostila73d41c82017-11-24 18:38:46 +0000176TYPED_TEST(TaskRunnerTest, AddFileDescriptorWatchFromAnotherWatch) {
177 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000178 Pipe pipe;
179 Pipe pipe2;
180
181 task_runner.AddFileDescriptorWatch(
182 pipe.read_fd.get(), [&task_runner, &pipe, &pipe2] {
183 pipe.Read();
184 task_runner.AddFileDescriptorWatch(
185 pipe2.read_fd.get(), [&task_runner] { task_runner.Quit(); });
186 });
187 task_runner.Run();
188}
189
Sami Kyostila73d41c82017-11-24 18:38:46 +0000190TYPED_TEST(TaskRunnerTest, RemoveFileDescriptorWatchFromAnotherWatch) {
191 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000192 Pipe pipe;
193 Pipe pipe2;
194
195 bool watch_ran = false;
196 task_runner.AddFileDescriptorWatch(
197 pipe.read_fd.get(), [&task_runner, &pipe, &pipe2] {
198 pipe.Read();
199 task_runner.RemoveFileDescriptorWatch(pipe2.read_fd.get());
200 });
201 task_runner.AddFileDescriptorWatch(pipe2.read_fd.get(),
202 [&watch_ran] { watch_ran = true; });
203 task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
204 task_runner.Run();
205
206 EXPECT_FALSE(watch_ran);
207}
208
Sami Kyostila73d41c82017-11-24 18:38:46 +0000209TYPED_TEST(TaskRunnerTest, ReplaceFileDescriptorWatchFromAnotherWatch) {
210 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000211 Pipe pipe;
212 Pipe pipe2;
213
214 bool watch_ran = false;
215 task_runner.AddFileDescriptorWatch(
216 pipe.read_fd.get(), [&task_runner, &pipe2] {
217 task_runner.RemoveFileDescriptorWatch(pipe2.read_fd.get());
218 task_runner.AddFileDescriptorWatch(
219 pipe2.read_fd.get(), [&task_runner] { task_runner.Quit(); });
220 });
221 task_runner.AddFileDescriptorWatch(pipe2.read_fd.get(),
222 [&watch_ran] { watch_ran = true; });
223 task_runner.Run();
224
225 EXPECT_FALSE(watch_ran);
226}
227
Sami Kyostila73d41c82017-11-24 18:38:46 +0000228TYPED_TEST(TaskRunnerTest, AddFileDescriptorWatchFromAnotherThread) {
229 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000230 Pipe pipe;
231
232 std::thread thread([&task_runner, &pipe] {
233 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
234 [&task_runner] { task_runner.Quit(); });
235 });
236 task_runner.Run();
237 thread.join();
238}
239
Sami Kyostila73d41c82017-11-24 18:38:46 +0000240TYPED_TEST(TaskRunnerTest, FileDescriptorWatchWithMultipleEvents) {
241 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000242 Pipe pipe;
243
244 int event_count = 0;
245 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
246 [&task_runner, &pipe, &event_count] {
247 if (++event_count == 3) {
248 task_runner.Quit();
249 return;
250 }
251 pipe.Read();
252 });
253 task_runner.PostTask([&pipe] { pipe.Write(); });
254 task_runner.PostTask([&pipe] { pipe.Write(); });
255 task_runner.Run();
256}
257
Sami Kyostila73d41c82017-11-24 18:38:46 +0000258TYPED_TEST(TaskRunnerTest, FileDescriptorClosedEvent) {
259 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000260 int pipe_fds[2];
261 PERFETTO_DCHECK(pipe(pipe_fds) == 0);
262 ScopedFile read_fd(pipe_fds[0]);
263 ScopedFile write_fd(pipe_fds[1]);
264
265 write_fd.reset();
266 task_runner.AddFileDescriptorWatch(read_fd.get(),
267 [&task_runner] { task_runner.Quit(); });
268 task_runner.Run();
269}
270
Sami Kyostila73d41c82017-11-24 18:38:46 +0000271TYPED_TEST(TaskRunnerTest, PostManyDelayedTasks) {
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000272 // Check that PostTask doesn't start failing if there are too many scheduled
273 // wake-ups.
Sami Kyostila73d41c82017-11-24 18:38:46 +0000274 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000275 for (int i = 0; i < 0x1000; i++)
276 task_runner.PostDelayedTask([] {}, 0);
277 task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
278 task_runner.Run();
279}
280
Sami Kyostila73d41c82017-11-24 18:38:46 +0000281TYPED_TEST(TaskRunnerTest, RunAgain) {
282 auto& task_runner = this->task_runner;
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000283 int counter = 0;
284 task_runner.PostTask([&task_runner, &counter] {
285 counter++;
286 task_runner.Quit();
287 });
288 task_runner.Run();
289 task_runner.PostTask([&task_runner, &counter] {
290 counter++;
291 task_runner.Quit();
292 });
293 task_runner.Run();
294 EXPECT_EQ(2, counter);
295}
296
Sami Kyostila73d41c82017-11-24 18:38:46 +0000297template <typename TaskRunner>
298void RepeatingTask(TaskRunner* task_runner) {
299 task_runner->PostTask(std::bind(&RepeatingTask<TaskRunner>, task_runner));
Sami Kyostilac25f8372017-11-22 11:15:41 +0000300}
301
Sami Kyostila73d41c82017-11-24 18:38:46 +0000302TYPED_TEST(TaskRunnerTest, FileDescriptorWatchesNotStarved) {
303 auto& task_runner = this->task_runner;
Sami Kyostilac25f8372017-11-22 11:15:41 +0000304 Pipe pipe;
Sami Kyostila73d41c82017-11-24 18:38:46 +0000305 task_runner.PostTask(std::bind(&RepeatingTask<TypeParam>, &task_runner));
Sami Kyostilac25f8372017-11-22 11:15:41 +0000306 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
307 [&task_runner] { task_runner.Quit(); });
308 task_runner.Run();
309}
310
Sami Kyostila73d41c82017-11-24 18:38:46 +0000311template <typename TaskRunner>
312void CountdownTask(TaskRunner* task_runner, int* counter) {
Sami Kyostila78b72d32017-11-23 18:08:57 +0000313 if (!--(*counter)) {
314 task_runner->Quit();
315 return;
316 }
Sami Kyostila73d41c82017-11-24 18:38:46 +0000317 task_runner->PostTask(
318 std::bind(&CountdownTask<TaskRunner>, task_runner, counter));
Sami Kyostila78b72d32017-11-23 18:08:57 +0000319}
320
Sami Kyostila73d41c82017-11-24 18:38:46 +0000321TYPED_TEST(TaskRunnerTest, NoDuplicateFileDescriptorWatchCallbacks) {
322 auto& task_runner = this->task_runner;
Sami Kyostila78b72d32017-11-23 18:08:57 +0000323 Pipe pipe;
324 bool watch_called = 0;
325 int counter = 10;
326 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
327 [&pipe, &watch_called] {
328 ASSERT_FALSE(watch_called);
329 pipe.Read();
330 watch_called = true;
331 });
Sami Kyostila73d41c82017-11-24 18:38:46 +0000332 task_runner.PostTask(
333 std::bind(&CountdownTask<TypeParam>, &task_runner, &counter));
Sami Kyostila78b72d32017-11-23 18:08:57 +0000334 task_runner.Run();
335}
336
Sami Kyostila73d41c82017-11-24 18:38:46 +0000337TYPED_TEST(TaskRunnerTest, ReplaceFileDescriptorWatchFromOtherThread) {
338 auto& task_runner = this->task_runner;
Sami Kyostila78b72d32017-11-23 18:08:57 +0000339 Pipe pipe;
340
341 // The two watch tasks here race each other. We don't particularly care which
342 // wins as long as one of them runs.
343 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
344 [&task_runner] { task_runner.Quit(); });
345
346 std::thread thread([&task_runner, &pipe] {
347 task_runner.RemoveFileDescriptorWatch(pipe.read_fd.get());
348 task_runner.AddFileDescriptorWatch(pipe.read_fd.get(),
349 [&task_runner] { task_runner.Quit(); });
350 });
351
352 task_runner.Run();
353 thread.join();
354}
355
Sami Kyostila73d41c82017-11-24 18:38:46 +0000356TYPED_TEST(TaskRunnerTest, IsIdleForTesting) {
357 auto& task_runner = this->task_runner;
Sami Kyostilaeaed9562017-11-22 12:48:10 +0000358 task_runner.PostTask(
359 [&task_runner] { EXPECT_FALSE(task_runner.IsIdleForTesting()); });
360 task_runner.PostTask([&task_runner] {
361 EXPECT_TRUE(task_runner.IsIdleForTesting());
362 task_runner.Quit();
363 });
364 task_runner.Run();
365}
366
Sami Kyostila2c6c2f52017-11-21 16:08:16 +0000367} // namespace
368} // namespace base
369} // namespace perfetto