1 // Copyright 2015 The Chromium OS 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 <brillo/message_loops/fake_message_loop.h>
6 
7 #include <memory>
8 #include <vector>
9 
10 #include <base/bind.h>
11 #include <base/bind_helpers.h>
12 #include <base/location.h>
13 #include <base/test/simple_test_clock.h>
14 #include <gtest/gtest.h>
15 
16 #include <brillo/bind_lambda.h>
17 #include <brillo/message_loops/message_loop.h>
18 
19 using base::Bind;
20 using base::Time;
21 using base::TimeDelta;
22 using std::vector;
23 
24 namespace brillo {
25 
26 using TaskId = MessageLoop::TaskId;
27 
28 class FakeMessageLoopTest : public ::testing::Test {
29  protected:
SetUp()30   void SetUp() override {
31     loop_.reset(new FakeMessageLoop(nullptr));
32     EXPECT_TRUE(loop_.get());
33   }
TearDown()34   void TearDown() override {
35     EXPECT_FALSE(loop_->PendingTasks());
36   }
37 
38   base::SimpleTestClock clock_;
39   std::unique_ptr<FakeMessageLoop> loop_;
40 };
41 
TEST_F(FakeMessageLoopTest,CancelTaskInvalidValuesTest)42 TEST_F(FakeMessageLoopTest, CancelTaskInvalidValuesTest) {
43   EXPECT_FALSE(loop_->CancelTask(MessageLoop::kTaskIdNull));
44   EXPECT_FALSE(loop_->CancelTask(1234));
45 }
46 
TEST_F(FakeMessageLoopTest,PostDelayedTaskRunsInOrder)47 TEST_F(FakeMessageLoopTest, PostDelayedTaskRunsInOrder) {
48   vector<int> order;
49   auto callback = [](std::vector<int>* order, int value) {
50     order->push_back(value);
51   };
52   loop_->PostDelayedTask(Bind(callback, base::Unretained(&order), 1),
53                          TimeDelta::FromSeconds(1));
54   loop_->PostDelayedTask(Bind(callback, base::Unretained(&order), 4),
55                          TimeDelta::FromSeconds(4));
56   loop_->PostDelayedTask(Bind(callback, base::Unretained(&order), 3),
57                          TimeDelta::FromSeconds(3));
58   loop_->PostDelayedTask(Bind(callback, base::Unretained(&order), 2),
59                          TimeDelta::FromSeconds(2));
60   // Run until all the tasks are run.
61   loop_->Run();
62   EXPECT_EQ((vector<int>{1, 2, 3, 4}), order);
63 }
64 
TEST_F(FakeMessageLoopTest,PostDelayedTaskAdvancesTheTime)65 TEST_F(FakeMessageLoopTest, PostDelayedTaskAdvancesTheTime) {
66   Time start = Time::FromInternalValue(1000000);
67   clock_.SetNow(start);
68   loop_.reset(new FakeMessageLoop(&clock_));
69   loop_->PostDelayedTask(base::DoNothing(), TimeDelta::FromSeconds(1));
70   loop_->PostDelayedTask(base::DoNothing(), TimeDelta::FromSeconds(2));
71   EXPECT_FALSE(loop_->RunOnce(false));
72   // If the callback didn't run, the time shouldn't change.
73   EXPECT_EQ(start, clock_.Now());
74 
75   // If we run only one callback, the time should be set to the time that
76   // callack ran.
77   EXPECT_TRUE(loop_->RunOnce(true));
78   EXPECT_EQ(start + TimeDelta::FromSeconds(1), clock_.Now());
79 
80   // If the clock is advanced manually, we should be able to run the
81   // callback without blocking, since the firing time is in the past.
82   clock_.SetNow(start + TimeDelta::FromSeconds(3));
83   EXPECT_TRUE(loop_->RunOnce(false));
84   // The time should not change even if the callback is due in the past.
85   EXPECT_EQ(start + TimeDelta::FromSeconds(3), clock_.Now());
86 }
87 
TEST_F(FakeMessageLoopTest,WatchFileDescriptorWaits)88 TEST_F(FakeMessageLoopTest, WatchFileDescriptorWaits) {
89   int fd = 1234;
90   // We will simulate this situation. At the beginning, we will watch for a
91   // file descriptor that won't trigger for 10s. Then we will pretend it is
92   // ready after 10s and expect its callback to run just once.
93   int called = 0;
94   TaskId task_id = loop_->WatchFileDescriptor(
95       FROM_HERE, fd, MessageLoop::kWatchRead, false,
96       Bind([](int* called) { (*called)++; }, base::Unretained(&called)));
97   EXPECT_NE(MessageLoop::kTaskIdNull, task_id);
98 
99   EXPECT_NE(MessageLoop::kTaskIdNull,
100             loop_->PostDelayedTask(Bind(&FakeMessageLoop::BreakLoop,
101                                         base::Unretained(loop_.get())),
102                                    TimeDelta::FromSeconds(10)));
103   EXPECT_NE(MessageLoop::kTaskIdNull,
104             loop_->PostDelayedTask(Bind(&FakeMessageLoop::BreakLoop,
105                                         base::Unretained(loop_.get())),
106                                    TimeDelta::FromSeconds(20)));
107   loop_->Run();
108   EXPECT_EQ(0, called);
109 
110   loop_->SetFileDescriptorReadiness(fd, MessageLoop::kWatchRead, true);
111   loop_->Run();
112   EXPECT_EQ(1, called);
113   EXPECT_FALSE(loop_->CancelTask(task_id));
114 }
115 
TEST_F(FakeMessageLoopTest,PendingTasksTest)116 TEST_F(FakeMessageLoopTest, PendingTasksTest) {
117   loop_->PostDelayedTask(base::DoNothing(), TimeDelta::FromSeconds(1));
118   EXPECT_TRUE(loop_->PendingTasks());
119   loop_->Run();
120 }
121 
122 }  // namespace brillo
123