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