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/message_loop.h>
6
7 // These are the common tests for all the brillo::MessageLoop implementations
8 // that should conform to this interface's contracts. For extra
9 // implementation-specific tests see the particular implementation unittests in
10 // the *_test.cc files.
11
12 #include <memory>
13 #include <vector>
14
15 #include <base/bind.h>
16 #include <base/bind_helpers.h>
17 #include <base/location.h>
18 #include <base/posix/eintr_wrapper.h>
19 #include <gtest/gtest.h>
20
21 #include <brillo/message_loops/base_message_loop.h>
22 #include <brillo/message_loops/message_loop_utils.h>
23 #include <brillo/unittest_utils.h>
24
25 using base::BindOnce;
26 using base::BindRepeating;
27 using base::TimeDelta;
28
29 namespace {
30
31 // Convenience functions for passing to base::Bind{Once,Repeating}.
SetToTrue(bool * b)32 void SetToTrue(bool* b) {
33 *b = true;
34 }
35
ReturnBool(bool * b)36 bool ReturnBool(bool *b) {
37 return *b;
38 }
39
40 } // namespace
41
42 namespace brillo {
43
44 using TaskId = MessageLoop::TaskId;
45
46 template <typename T>
47 class MessageLoopTest : public ::testing::Test {
48 protected:
SetUp()49 void SetUp() override {
50 MessageLoopSetUp();
51 EXPECT_TRUE(this->loop_.get());
52 }
53
54 std::unique_ptr<base::MessageLoopForIO> base_loop_;
55
56 std::unique_ptr<MessageLoop> loop_;
57
58 private:
59 // These MessageLoopSetUp() methods are used to setup each MessageLoop
60 // according to its constructor requirements.
61 void MessageLoopSetUp();
62 };
63
64 template <>
MessageLoopSetUp()65 void MessageLoopTest<BaseMessageLoop>::MessageLoopSetUp() {
66 base_loop_.reset(new base::MessageLoopForIO());
67 loop_.reset(new BaseMessageLoop(base_loop_.get()));
68 loop_->SetAsCurrent();
69 }
70
71 // This setups gtest to run each one of the following TYPED_TEST test cases on
72 // on each implementation.
73 typedef ::testing::Types<BaseMessageLoop> MessageLoopTypes;
74 TYPED_TEST_CASE(MessageLoopTest, MessageLoopTypes);
75
76
TYPED_TEST(MessageLoopTest,CancelTaskInvalidValuesTest)77 TYPED_TEST(MessageLoopTest, CancelTaskInvalidValuesTest) {
78 EXPECT_FALSE(this->loop_->CancelTask(MessageLoop::kTaskIdNull));
79 EXPECT_FALSE(this->loop_->CancelTask(1234));
80 }
81
TYPED_TEST(MessageLoopTest,PostTaskTest)82 TYPED_TEST(MessageLoopTest, PostTaskTest) {
83 bool called = false;
84 TaskId task_id =
85 this->loop_->PostTask(FROM_HERE, BindOnce(&SetToTrue, &called));
86 EXPECT_NE(MessageLoop::kTaskIdNull, task_id);
87 MessageLoopRunMaxIterations(this->loop_.get(), 100);
88 EXPECT_TRUE(called);
89 }
90
91 // Tests that we can cancel tasks right after we schedule them.
TYPED_TEST(MessageLoopTest,PostTaskCancelledTest)92 TYPED_TEST(MessageLoopTest, PostTaskCancelledTest) {
93 bool called = false;
94 TaskId task_id =
95 this->loop_->PostTask(FROM_HERE, BindOnce(&SetToTrue, &called));
96 EXPECT_TRUE(this->loop_->CancelTask(task_id));
97 MessageLoopRunMaxIterations(this->loop_.get(), 100);
98 EXPECT_FALSE(called);
99 // Can't remove a task you already removed.
100 EXPECT_FALSE(this->loop_->CancelTask(task_id));
101 }
102
TYPED_TEST(MessageLoopTest,PostDelayedTaskRunsEventuallyTest)103 TYPED_TEST(MessageLoopTest, PostDelayedTaskRunsEventuallyTest) {
104 bool called = false;
105 TaskId task_id =
106 this->loop_->PostDelayedTask(FROM_HERE, BindOnce(&SetToTrue, &called),
107 TimeDelta::FromMilliseconds(50));
108 EXPECT_NE(MessageLoop::kTaskIdNull, task_id);
109 MessageLoopRunUntil(this->loop_.get(), TimeDelta::FromSeconds(10),
110 BindRepeating(&ReturnBool, &called));
111 // Check that the main loop finished before the 10 seconds timeout, so it
112 // finished due to the callback being called and not due to the timeout.
113 EXPECT_TRUE(called);
114 }
115
116 // Test that you can call the overloaded version of PostDelayedTask from
117 // MessageLoop. This is important because only one of the two methods is
118 // virtual, so you need to unhide the other when overriding the virtual one.
TYPED_TEST(MessageLoopTest,PostDelayedTaskWithoutLocation)119 TYPED_TEST(MessageLoopTest, PostDelayedTaskWithoutLocation) {
120 this->loop_->PostDelayedTask(base::DoNothing(), TimeDelta());
121 EXPECT_EQ(1, MessageLoopRunMaxIterations(this->loop_.get(), 100));
122 }
123
124 // Test that we can cancel the task we are running, and should just fail.
TYPED_TEST(MessageLoopTest,DeleteTaskFromSelf)125 TYPED_TEST(MessageLoopTest, DeleteTaskFromSelf) {
126 bool cancel_result = true; // We would expect this to be false.
127 TaskId task_id;
128 task_id = this->loop_->PostTask(
129 FROM_HERE,
130 BindOnce(
131 [](bool* cancel_result, MessageLoop* loop, TaskId* task_id) {
132 *cancel_result = loop->CancelTask(*task_id);
133 },
134 &cancel_result, this->loop_.get(), &task_id));
135 EXPECT_EQ(1, MessageLoopRunMaxIterations(this->loop_.get(), 100));
136 EXPECT_FALSE(cancel_result);
137 }
138
139 } // namespace brillo
140