1 // Copyright 2016 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
5 #include "base/task_scheduler/task_tracker_posix.h"
6
7 #include <unistd.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/files/file_descriptor_watcher_posix.h"
14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/posix/eintr_wrapper.h"
19 #include "base/run_loop.h"
20 #include "base/sequence_token.h"
21 #include "base/task_scheduler/task.h"
22 #include "base/task_scheduler/task_traits.h"
23 #include "base/task_scheduler/test_utils.h"
24 #include "base/test/null_task_runner.h"
25 #include "base/threading/thread.h"
26 #include "base/time/time.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 namespace base {
30 namespace internal {
31
32 namespace {
33
34 class TaskSchedulerTaskTrackerPosixTest : public testing::Test {
35 public:
TaskSchedulerTaskTrackerPosixTest()36 TaskSchedulerTaskTrackerPosixTest() : service_thread_("ServiceThread") {
37 Thread::Options service_thread_options;
38 service_thread_options.message_loop_type = MessageLoop::TYPE_IO;
39 service_thread_.StartWithOptions(service_thread_options);
40 tracker_.set_watch_file_descriptor_message_loop(
41 static_cast<MessageLoopForIO*>(service_thread_.message_loop()));
42 }
43
44 protected:
45 Thread service_thread_;
46 TaskTrackerPosix tracker_ = {"Test"};
47
48 private:
49 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerPosixTest);
50 };
51
52 } // namespace
53
54 // Verify that TaskTrackerPosix runs a Task it receives.
TEST_F(TaskSchedulerTaskTrackerPosixTest,RunTask)55 TEST_F(TaskSchedulerTaskTrackerPosixTest, RunTask) {
56 bool did_run = false;
57 Task task(FROM_HERE,
58 Bind([](bool* did_run) { *did_run = true; }, Unretained(&did_run)),
59 TaskTraits(), TimeDelta());
60
61 EXPECT_TRUE(tracker_.WillPostTask(&task));
62
63 auto sequence = test::CreateSequenceWithTask(std::move(task));
64 EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr));
65 // Expect RunAndPopNextTask to return nullptr since |sequence| is empty after
66 // popping a task from it.
67 EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence, nullptr));
68
69 EXPECT_TRUE(did_run);
70 }
71
72 // Verify that FileDescriptorWatcher::WatchReadable() can be called from a task
73 // running in TaskTrackerPosix without a crash.
TEST_F(TaskSchedulerTaskTrackerPosixTest,FileDescriptorWatcher)74 TEST_F(TaskSchedulerTaskTrackerPosixTest, FileDescriptorWatcher) {
75 int fds[2];
76 ASSERT_EQ(0, pipe(fds));
77 Task task(FROM_HERE,
78 Bind(IgnoreResult(&FileDescriptorWatcher::WatchReadable), fds[0],
79 DoNothing()),
80 TaskTraits(), TimeDelta());
81 // FileDescriptorWatcher::WatchReadable needs a SequencedTaskRunnerHandle.
82 task.sequenced_task_runner_ref = MakeRefCounted<NullTaskRunner>();
83
84 EXPECT_TRUE(tracker_.WillPostTask(&task));
85
86 auto sequence = test::CreateSequenceWithTask(std::move(task));
87 EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr));
88 // Expect RunAndPopNextTask to return nullptr since |sequence| is empty after
89 // popping a task from it.
90 EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence, nullptr));
91
92 // Join the service thread to make sure that the read watch is registered and
93 // unregistered before file descriptors are closed.
94 service_thread_.Stop();
95
96 EXPECT_EQ(0, IGNORE_EINTR(close(fds[0])));
97 EXPECT_EQ(0, IGNORE_EINTR(close(fds[1])));
98 }
99
100 } // namespace internal
101 } // namespace base
102