diff options
author | Alex Deymo <deymo@chromium.org> | 2015-08-04 19:32:31 -0700 |
---|---|---|
committer | Bertrand SIMONNET <bsimonnet@google.com> | 2015-08-12 10:55:24 -0700 |
commit | 3dbcfa4ec55edbf275d47b1fbc74c7587de0ff8b (patch) | |
tree | b6ffbaaaf948e8f46d207151032bf6f2ddc84058 | |
parent | 000726053bddc605a6c78b5dece37bcb2c67f291 (diff) | |
download | libbrillo-3dbcfa4ec55edbf275d47b1fbc74c7587de0ff8b.tar.gz |
libchromeos: Use MockMessageLoop on FakeStream.
The added MockMessageLoop is a mockable FakeMessageLoop. By default the
mock object will behave like a fake one, but it is also possible to set
expectations on the MessageLoop methods.
The MockMessageLoop now replaces the base::TaskRunner used in
FakeStream and runs the posted callbacks from the message loop instead
of running them when they are posted.
libweave is updated to create the FakeStream using a
chromeos::MessageLoop.
BUG=chromium:499886
TEST=FEATURES=test emerge-link libchromeos libweave buffet
Reviewed-on: https://chromium-review.googlesource.com/290632
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
(cherry-picked from
https://chromium.googlesource.com/chromiumos/platform2 at
78c174362c0ce8f75c53ab37da1874533eb1a56a)
Change-Id: I5b6952fc75e7300e9734e6f8f8103fe684584712
-rw-r--r-- | chromeos/message_loops/mock_message_loop.h | 89 | ||||
-rw-r--r-- | chromeos/streams/fake_stream.cc | 8 | ||||
-rw-r--r-- | chromeos/streams/fake_stream.h | 4 | ||||
-rw-r--r-- | chromeos/streams/fake_stream_unittest.cc | 68 |
4 files changed, 124 insertions, 45 deletions
diff --git a/chromeos/message_loops/mock_message_loop.h b/chromeos/message_loops/mock_message_loop.h new file mode 100644 index 0000000..a4fcd77 --- /dev/null +++ b/chromeos/message_loops/mock_message_loop.h @@ -0,0 +1,89 @@ +// Copyright 2015 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LIBCHROMEOS_CHROMEOS_MESSAGE_LOOPS_MOCK_MESSAGE_LOOP_H_ +#define LIBCHROMEOS_CHROMEOS_MESSAGE_LOOPS_MOCK_MESSAGE_LOOP_H_ + +#include <gmock/gmock.h> + +#include <base/location.h> +#include <base/test/simple_test_clock.h> +#include <base/time/time.h> + +#include <chromeos/chromeos_export.h> +#include <chromeos/message_loops/fake_message_loop.h> +#include <chromeos/message_loops/message_loop.h> + +namespace chromeos { + +// The MockMessageLoop is a mockable MessageLoop that will by default act as a +// FakeMessageLoop. It is possible to set expectations with EXPECT_CALL without +// any action associated and they will call the same methods in the underlying +// FakeMessageLoop implementation. +// This message loop implementation is useful to check interaction with the +// message loop when running unittests. +class CHROMEOS_EXPORT MockMessageLoop : public MessageLoop { + public: + // Create a FakeMessageLoop optionally using a SimpleTestClock to update the + // time when Run() or RunOnce(true) are called and should block. + explicit MockMessageLoop(base::SimpleTestClock* clock) + : fake_loop_(clock) { + // Redirect all actions to calling the underlying FakeMessageLoop by + // default. For the overloaded methods, we need to disambiguate between the + // different options by specifying the type of the method pointer. + ON_CALL(*this, PostDelayedTask(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + &fake_loop_, + static_cast<TaskId(FakeMessageLoop::*)( + const tracked_objects::Location&, + const base::Closure&, + base::TimeDelta)>( + &FakeMessageLoop::PostDelayedTask))); + ON_CALL(*this, WatchFileDescriptor( + ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + &fake_loop_, + static_cast<TaskId(FakeMessageLoop::*)( + const tracked_objects::Location&, int, WatchMode, bool, + const base::Closure&)>( + &FakeMessageLoop::WatchFileDescriptor))); + ON_CALL(*this, CancelTask(::testing::_)) + .WillByDefault(::testing::Invoke(&fake_loop_, + &FakeMessageLoop::CancelTask)); + ON_CALL(*this, RunOnce(::testing::_)) + .WillByDefault(::testing::Invoke(&fake_loop_, + &FakeMessageLoop::RunOnce)); + } + ~MockMessageLoop() override = default; + + MOCK_METHOD3(PostDelayedTask, + TaskId(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay)); + using MessageLoop::PostDelayedTask; + MOCK_METHOD5(WatchFileDescriptor, + TaskId(const tracked_objects::Location& from_here, + int fd, + WatchMode mode, + bool persistent, + const base::Closure& task)); + using MessageLoop::WatchFileDescriptor; + MOCK_METHOD1(CancelTask, bool(TaskId task_id)); + MOCK_METHOD1(RunOnce, bool(bool may_block)); + + // Returns the actual FakeMessageLoop instance so default actions can be + // override with other actions or call + FakeMessageLoop* fake_loop() { + return &fake_loop_; + } + + private: + FakeMessageLoop fake_loop_; + + DISALLOW_COPY_AND_ASSIGN(MockMessageLoop); +}; + +} // namespace chromeos + +#endif // LIBCHROMEOS_CHROMEOS_MESSAGE_LOOPS_MOCK_MESSAGE_LOOP_H_ diff --git a/chromeos/streams/fake_stream.cc b/chromeos/streams/fake_stream.cc index c786bca..c1ccacd 100644 --- a/chromeos/streams/fake_stream.cc +++ b/chromeos/streams/fake_stream.cc @@ -7,7 +7,7 @@ #include <algorithm> #include <base/bind.h> -#include <base/message_loop/message_loop.h> +#include <chromeos/message_loops/message_loop.h> #include <chromeos/streams/stream_utils.h> namespace chromeos { @@ -55,9 +55,8 @@ void GetMinDelayAndMode(const base::Time& now, } // anonymous namespace FakeStream::FakeStream(Stream::AccessMode mode, - const scoped_refptr<base::TaskRunner>& task_runner, base::Clock* clock) - : mode_{mode}, task_runner_{task_runner}, clock_{clock} {} + : mode_{mode}, clock_{clock} {} void FakeStream::AddReadPacketData(base::TimeDelta delay, const void* data, @@ -373,7 +372,8 @@ bool FakeStream::WaitForData(AccessMode mode, base::TimeDelta delay; GetMinDelayAndMode(clock_->Now(), read_requested, delay_input_until_, write_requested, delay_output_until_, &mode, &delay); - task_runner_->PostDelayedTask(FROM_HERE, base::Bind(callback, mode), delay); + MessageLoop::current()->PostDelayedTask( + FROM_HERE, base::Bind(callback, mode), delay); return true; } diff --git a/chromeos/streams/fake_stream.h b/chromeos/streams/fake_stream.h index 690366e..2f8567d 100644 --- a/chromeos/streams/fake_stream.h +++ b/chromeos/streams/fake_stream.h @@ -10,7 +10,6 @@ #include <base/callback_forward.h> #include <base/macros.h> -#include <base/task_runner.h> #include <base/time/clock.h> #include <base/time/time.h> #include <chromeos/secure_blob.h> @@ -37,10 +36,8 @@ class FakeStream : public Stream { public: // Construct a new instance of the fake stream. // mode - expected read/write mode supported by the stream. - // task_runner - the task runner to use to post async tasks to. // clock - the clock to use to get the current time. FakeStream(Stream::AccessMode mode, - const scoped_refptr<base::TaskRunner>& task_runner, base::Clock* clock); // Add data packets to the read queue of the stream. @@ -148,7 +145,6 @@ class FakeStream : public Stream { bool is_open_{true}; Stream::AccessMode mode_; - scoped_refptr<base::TaskRunner> task_runner_; base::Clock* clock_; // Internal data for read operations. diff --git a/chromeos/streams/fake_stream_unittest.cc b/chromeos/streams/fake_stream_unittest.cc index f9856d7..89bada0 100644 --- a/chromeos/streams/fake_stream_unittest.cc +++ b/chromeos/streams/fake_stream_unittest.cc @@ -9,44 +9,26 @@ #include <base/callback.h> #include <base/test/simple_test_clock.h> #include <chromeos/bind_lambda.h> +#include <chromeos/message_loops/mock_message_loop.h> #include <gmock/gmock.h> #include <gtest/gtest.h> +using testing::AnyNumber; using testing::InSequence; -using testing::Invoke; using testing::_; namespace chromeos { -// Mock-like task runner that allow the tests to inspect the calls to -// TaskRunner::PostDelayedTask and verify the delays. -class TestTaskRunner : public base::TaskRunner { - public: - MOCK_METHOD3(PostDelayedTask, bool(const tracked_objects::Location&, - const base::Closure&, - base::TimeDelta)); - bool RunsTasksOnCurrentThread() const { return true; } -}; - class FakeStreamTest : public testing::Test { public: void SetUp() override { - task_runner_ = new TestTaskRunner; - - auto callback = [this](const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) -> bool { - clock_.Advance(delay); - task.Run(); - return true; - }; - - ON_CALL(*task_runner_, PostDelayedTask(_, _, _)) - .WillByDefault(Invoke(callback)); + mock_loop_.SetAsCurrent(); + // Ignore calls to RunOnce(). + EXPECT_CALL(mock_loop_, RunOnce(true)).Times(AnyNumber()); } void CreateStream(Stream::AccessMode mode) { - stream_.reset(new FakeStream{mode, task_runner_, &clock_}); + stream_.reset(new FakeStream{mode, &clock_}); } // Performs non-blocking read on the stream and returns the read data @@ -78,8 +60,8 @@ class FakeStreamTest : public testing::Test { protected: base::SimpleTestClock clock_; + MockMessageLoop mock_loop_{&clock_}; std::unique_ptr<FakeStream> stream_; - scoped_refptr<TestTaskRunner> task_runner_; const base::TimeDelta zero_delay; }; @@ -251,7 +233,7 @@ TEST_F(FakeStreamTest, ReadPacketsWithError) { TEST_F(FakeStreamTest, WaitForDataRead) { CreateStream(Stream::AccessMode::READ); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, zero_delay)).Times(2); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(2); int call_count = 0; auto callback = [&call_count](Stream::AccessMode mode) { @@ -261,20 +243,23 @@ TEST_F(FakeStreamTest, WaitForDataRead) { EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ, base::Bind(callback), nullptr)); + mock_loop_.Run(); EXPECT_EQ(1, call_count); stream_->AddReadPacketString({}, "foobar"); EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ, base::Bind(callback), nullptr)); + mock_loop_.Run(); EXPECT_EQ(2, call_count); stream_->ClearReadQueue(); auto one_sec_delay = base::TimeDelta::FromSeconds(1); stream_->AddReadPacketString(one_sec_delay, "baz"); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, one_sec_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1); EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ, base::Bind(callback), nullptr)); + mock_loop_.Run(); EXPECT_EQ(3, call_count); } @@ -289,8 +274,8 @@ TEST_F(FakeStreamTest, ReadAsync) { { InSequence seq; - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, zero_delay)).Times(1); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, one_sec_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1); } std::vector<char> buffer; @@ -305,6 +290,7 @@ TEST_F(FakeStreamTest, ReadAsync) { base::Bind(on_success), base::Bind(on_failure), nullptr)); + mock_loop_.Run(); EXPECT_EQ(1, success_count); EXPECT_EQ(0, error_count); EXPECT_EQ(input_data, (std::string{buffer.begin(), buffer.end()})); @@ -402,7 +388,7 @@ TEST_F(FakeStreamTest, WriteWithError) { TEST_F(FakeStreamTest, WaitForDataWrite) { CreateStream(Stream::AccessMode::WRITE); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, zero_delay)).Times(2); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(2); int call_count = 0; auto callback = [&call_count](Stream::AccessMode mode) { @@ -412,20 +398,23 @@ TEST_F(FakeStreamTest, WaitForDataWrite) { EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::WRITE, base::Bind(callback), nullptr)); + mock_loop_.Run(); EXPECT_EQ(1, call_count); stream_->ExpectWritePacketString({}, "foobar"); EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::WRITE, base::Bind(callback), nullptr)); + mock_loop_.Run(); EXPECT_EQ(2, call_count); stream_->ClearWriteQueue(); auto one_sec_delay = base::TimeDelta::FromSeconds(1); stream_->ExpectWritePacketString(one_sec_delay, "baz"); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, one_sec_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1); EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::WRITE, base::Bind(callback), nullptr)); + mock_loop_.Run(); EXPECT_EQ(3, call_count); } @@ -441,8 +430,8 @@ TEST_F(FakeStreamTest, WriteAsync) { { InSequence seq; - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, zero_delay)).Times(1); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, one_sec_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1); } int success_count = 0; @@ -454,6 +443,7 @@ TEST_F(FakeStreamTest, WriteAsync) { base::Bind(on_success), base::Bind(on_failure), nullptr)); + mock_loop_.Run(); EXPECT_EQ(1, success_count); EXPECT_EQ(0, error_count); EXPECT_EQ(output_data, stream_->GetFlushedOutputDataAsString()); @@ -474,30 +464,33 @@ TEST_F(FakeStreamTest, WaitForDataReadWrite) { stream_->AddReadPacketString(one_sec_delay, "foo"); stream_->ExpectWritePacketString(two_sec_delay, "bar"); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, one_sec_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1); EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE, base::Bind(callback, Stream::AccessMode::READ), nullptr)); + mock_loop_.Run(); EXPECT_EQ(1, call_count); // The above step has adjusted the clock by 1 second already. stream_->ClearReadQueue(); stream_->AddReadPacketString(two_sec_delay, "foo"); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, one_sec_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1); EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE, base::Bind(callback, Stream::AccessMode::WRITE), nullptr)); + mock_loop_.Run(); EXPECT_EQ(2, call_count); clock_.Advance(one_sec_delay); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, zero_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1); EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE, base::Bind(callback, Stream::AccessMode::READ_WRITE), nullptr)); + mock_loop_.Run(); EXPECT_EQ(3, call_count); stream_->ClearReadQueue(); @@ -505,11 +498,12 @@ TEST_F(FakeStreamTest, WaitForDataReadWrite) { stream_->AddReadPacketString(one_sec_delay, "foo"); stream_->ExpectWritePacketString(one_sec_delay, "bar"); - EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, one_sec_delay)).Times(1); + EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1); EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE, base::Bind(callback, Stream::AccessMode::READ_WRITE), nullptr)); + mock_loop_.Run(); EXPECT_EQ(4, call_count); } |