• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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