xref: /aosp_15_r20/external/libchrome/base/task_scheduler/task_tracker_posix_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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