aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deymo <deymo@chromium.org>2015-08-04 19:32:31 -0700
committerBertrand SIMONNET <bsimonnet@google.com>2015-08-12 10:55:24 -0700
commit3dbcfa4ec55edbf275d47b1fbc74c7587de0ff8b (patch)
treeb6ffbaaaf948e8f46d207151032bf6f2ddc84058
parent000726053bddc605a6c78b5dece37bcb2c67f291 (diff)
downloadlibbrillo-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.h89
-rw-r--r--chromeos/streams/fake_stream.cc8
-rw-r--r--chromeos/streams/fake_stream.h4
-rw-r--r--chromeos/streams/fake_stream_unittest.cc68
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);
}