diff options
author | haibinlu <haibinlu@chromium.org> | 2015-12-17 17:55:34 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-18 01:56:24 +0000 |
commit | 87329b210c0369bca136d02b603d4e5df0010419 (patch) | |
tree | f43f511381a9d2533aef2d3946db5b1e3d3ee4ae /blimp | |
parent | 50cbe2069fcf41ec3adef3a2ee68c91585ab90f8 (diff) | |
download | chromium_src-87329b210c0369bca136d02b603d4e5df0010419.zip chromium_src-87329b210c0369bca136d02b603d4e5df0010419.tar.gz chromium_src-87329b210c0369bca136d02b603d4e5df0010419.tar.bz2 |
[Blimp Net] Adds unit test for BrowserConnectionHandler
Review URL: https://codereview.chromium.org/1512763008
Cr-Commit-Position: refs/heads/master@{#365979}
Diffstat (limited to 'blimp')
-rw-r--r-- | blimp/net/BUILD.gn | 1 | ||||
-rw-r--r-- | blimp/net/blimp_connection.cc | 2 | ||||
-rw-r--r-- | blimp/net/blimp_connection.h | 2 | ||||
-rw-r--r-- | blimp/net/blimp_message_checkpoint_observer.h | 2 | ||||
-rw-r--r-- | blimp/net/blimp_message_output_buffer.h | 4 | ||||
-rw-r--r-- | blimp/net/browser_connection_handler.cc | 6 | ||||
-rw-r--r-- | blimp/net/browser_connection_handler_unittest.cc | 223 | ||||
-rw-r--r-- | blimp/net/test_common.h | 2 |
8 files changed, 235 insertions, 7 deletions
diff --git a/blimp/net/BUILD.gn b/blimp/net/BUILD.gn index 94b8a01..5a37dc7 100644 --- a/blimp/net/BUILD.gn +++ b/blimp/net/BUILD.gn @@ -88,6 +88,7 @@ source_set("unit_tests") { "blimp_message_multiplexer_unittest.cc", "blimp_message_output_buffer_unittest.cc", "blimp_message_pump_unittest.cc", + "browser_connection_handler_unittest.cc", "client_connection_manager_unittest.cc", "engine_authentication_handler_unittest.cc", "engine_connection_manager_unittest.cc", diff --git a/blimp/net/blimp_connection.cc b/blimp/net/blimp_connection.cc index db2f63d..dd40021 100644 --- a/blimp/net/blimp_connection.cc +++ b/blimp/net/blimp_connection.cc @@ -113,7 +113,7 @@ void BlimpConnection::SetIncomingMessageProcessor( message_pump_->SetMessageProcessor(processor); } -BlimpMessageProcessor* BlimpConnection::GetOutgoingMessageProcessor() const { +BlimpMessageProcessor* BlimpConnection::GetOutgoingMessageProcessor() { return outgoing_msg_processor_.get(); } diff --git a/blimp/net/blimp_connection.h b/blimp/net/blimp_connection.h index f95a91c..36128af 100644 --- a/blimp/net/blimp_connection.h +++ b/blimp/net/blimp_connection.h @@ -35,7 +35,7 @@ class BLIMP_NET_EXPORT BlimpConnection { virtual void SetIncomingMessageProcessor(BlimpMessageProcessor* processor); // Gets a processor for BrowserSession->BlimpConnection message routing. - virtual BlimpMessageProcessor* GetOutgoingMessageProcessor() const; + virtual BlimpMessageProcessor* GetOutgoingMessageProcessor(); protected: BlimpConnection(); diff --git a/blimp/net/blimp_message_checkpoint_observer.h b/blimp/net/blimp_message_checkpoint_observer.h index 127ce33..890819c 100644 --- a/blimp/net/blimp_message_checkpoint_observer.h +++ b/blimp/net/blimp_message_checkpoint_observer.h @@ -9,7 +9,7 @@ namespace blimp { -// Allows objects to subscribe to message acknowledgement checkpoints. +// Allows objects to subscribe to message acknowledgment checkpoints. class BlimpMessageCheckpointObserver { public: virtual ~BlimpMessageCheckpointObserver() {} diff --git a/blimp/net/blimp_message_output_buffer.h b/blimp/net/blimp_message_output_buffer.h index 0a7bddf..d8168ba 100644 --- a/blimp/net/blimp_message_output_buffer.h +++ b/blimp/net/blimp_message_output_buffer.h @@ -23,7 +23,7 @@ class BlimpConnection; // Messages are retained for redelivery until they are acknowledged by the // receiving end (via BlimpMessageCheckpointObserver). // Messages can be paired with callbacks that are invoked on successful -// message acknowledgement. +// message acknowledgment. // (Redelivery will be used in a future CL to implement Fast Recovery // of dropped connections.) class BLIMP_NET_EXPORT BlimpMessageOutputBuffer @@ -86,7 +86,7 @@ class BLIMP_NET_EXPORT BlimpMessageOutputBuffer // List of unsent messages. MessageBuffer write_buffer_; - // List of messages that are sent and awaiting acknoweldgement. + // List of messages that are sent and awaiting acknowledgment. // The messages in |ack_buffer_| are contiguous with the messages in // |write_buffer_|. MessageBuffer ack_buffer_; diff --git a/blimp/net/browser_connection_handler.cc b/blimp/net/browser_connection_handler.cc index 9d3931c..baa63c3 100644 --- a/blimp/net/browser_connection_handler.cc +++ b/blimp/net/browser_connection_handler.cc @@ -11,6 +11,7 @@ #include "blimp/net/blimp_message_multiplexer.h" #include "blimp/net/blimp_message_output_buffer.h" #include "blimp/net/blimp_message_processor.h" +#include "net/base/net_errors.h" namespace blimp { namespace { @@ -41,6 +42,7 @@ void BrowserConnectionHandler::HandleConnection( // replace an existing one. DropCurrentConnection(); connection_ = std::move(connection); + connection_->SetConnectionErrorObserver(this); // Connect the incoming & outgoing message streams. connection_->SetIncomingMessageProcessor(demultiplexer_.get()); @@ -51,13 +53,15 @@ void BrowserConnectionHandler::HandleConnection( void BrowserConnectionHandler::DropCurrentConnection() { if (!connection_) return; + + connection_->SetConnectionErrorObserver(nullptr); connection_->SetIncomingMessageProcessor(nullptr); output_buffer_->SetOutputProcessor(nullptr); connection_.reset(); } void BrowserConnectionHandler::OnConnectionError(int error) { - LOG(WARNING) << "Connection error " << error; + LOG(WARNING) << "Connection error " << net::ErrorToString(error); DropCurrentConnection(); } diff --git a/blimp/net/browser_connection_handler_unittest.cc b/blimp/net/browser_connection_handler_unittest.cc new file mode 100644 index 0000000..c838ba6e --- /dev/null +++ b/blimp/net/browser_connection_handler_unittest.cc @@ -0,0 +1,223 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <string> + +#include "base/callback_helpers.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "blimp/common/proto/blimp_message.pb.h" +#include "blimp/net/blimp_message_processor.h" +#include "blimp/net/browser_connection_handler.h" +#include "blimp/net/common.h" +#include "blimp/net/connection_error_observer.h" +#include "blimp/net/test_common.h" +#include "net/base/completion_callback.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::InSequence; +using testing::Return; +using testing::SaveArg; + +namespace blimp { +namespace { + +// Compares two blimp messages and ignores message_id field. +MATCHER_P(EqualsMessageIgnoringId, message, "") { + BlimpMessage expected_message = message; + expected_message.clear_message_id(); + BlimpMessage actual_message = arg; + actual_message.clear_message_id(); + + std::string expected_serialized; + std::string actual_serialized; + expected_message.SerializeToString(&expected_serialized); + actual_message.SerializeToString(&actual_serialized); + return expected_serialized == actual_serialized; +} + +class FakeFeature { + public: + FakeFeature(BlimpMessage::Type type, + BrowserConnectionHandler* connection_handler) { + outgoing_message_processor_ = + connection_handler->RegisterFeature(type, &incoming_message_processor_); + } + + ~FakeFeature() {} + + BlimpMessageProcessor* outgoing_message_processor() { + return outgoing_message_processor_.get(); + } + + MockBlimpMessageProcessor* incoming_message_processor() { + return &incoming_message_processor_; + } + + private: + testing::StrictMock<MockBlimpMessageProcessor> incoming_message_processor_; + scoped_ptr<BlimpMessageProcessor> outgoing_message_processor_; +}; + +class FakeBlimpConnection : public BlimpConnection, + public BlimpMessageProcessor { + public: + FakeBlimpConnection() {} + ~FakeBlimpConnection() override {} + + void set_other_end(FakeBlimpConnection* other_end) { other_end_ = other_end; } + + ConnectionErrorObserver* error_observer() { return error_observer_; } + + // BlimpConnection implementation. + void SetConnectionErrorObserver(ConnectionErrorObserver* observer) override { + error_observer_ = observer; + } + + void SetIncomingMessageProcessor(BlimpMessageProcessor* processor) override { + incoming_message_processor_ = processor; + } + + BlimpMessageProcessor* GetOutgoingMessageProcessor() override { return this; } + + private: + void ForwardMessage(scoped_ptr<BlimpMessage> message) { + other_end_->incoming_message_processor_->ProcessMessage( + std::move(message), net::CompletionCallback()); + } + + // BlimpMessageProcessor implementation. + void ProcessMessage(scoped_ptr<BlimpMessage> message, + const net::CompletionCallback& callback) override { + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&FakeBlimpConnection::ForwardMessage, + base::Unretained(this), base::Passed(&message))); + + callback.Run(net::OK); + } + + FakeBlimpConnection* other_end_ = nullptr; + ConnectionErrorObserver* error_observer_ = nullptr; + BlimpMessageProcessor* incoming_message_processor_ = nullptr; +}; + +scoped_ptr<BlimpMessage> CreateInputMessage(int tab_id) { + scoped_ptr<BlimpMessage> output(new BlimpMessage); + output->set_type(BlimpMessage::INPUT); + output->set_target_tab_id(tab_id); + return output; +} + +scoped_ptr<BlimpMessage> CreateControlMessage(int tab_id) { + scoped_ptr<BlimpMessage> output(new BlimpMessage); + output->set_type(BlimpMessage::TAB_CONTROL); + output->set_target_tab_id(tab_id); + return output; +} + +class BrowserConnectionHandlerTest : public testing::Test { + public: + BrowserConnectionHandlerTest() + : client_connection_handler_(new BrowserConnectionHandler), + engine_connection_handler_(new BrowserConnectionHandler) { + SetupConnections(); + + client_input_feature_.reset( + new FakeFeature(BlimpMessage::INPUT, client_connection_handler_.get())); + engine_input_feature_.reset( + new FakeFeature(BlimpMessage::INPUT, engine_connection_handler_.get())); + client_control_feature_.reset(new FakeFeature( + BlimpMessage::TAB_CONTROL, client_connection_handler_.get())); + engine_control_feature_.reset(new FakeFeature( + BlimpMessage::TAB_CONTROL, engine_connection_handler_.get())); + } + + ~BrowserConnectionHandlerTest() override {} + void TearDown() override { base::RunLoop().RunUntilIdle(); } + + protected: + void SetupConnections() { + client_connection_ = new FakeBlimpConnection(); + engine_connection_ = new FakeBlimpConnection(); + client_connection_->set_other_end(engine_connection_); + engine_connection_->set_other_end(client_connection_); + client_connection_handler_->HandleConnection( + make_scoped_ptr(client_connection_)); + engine_connection_handler_->HandleConnection( + make_scoped_ptr(engine_connection_)); + } + + base::MessageLoop message_loop_; + + FakeBlimpConnection* client_connection_; + FakeBlimpConnection* engine_connection_; + + scoped_ptr<BrowserConnectionHandler> client_connection_handler_; + scoped_ptr<BrowserConnectionHandler> engine_connection_handler_; + + scoped_ptr<FakeFeature> client_input_feature_; + scoped_ptr<FakeFeature> engine_input_feature_; + scoped_ptr<FakeFeature> client_control_feature_; + scoped_ptr<FakeFeature> engine_control_feature_; +}; + +TEST_F(BrowserConnectionHandlerTest, ExchangeMessages) { + scoped_ptr<BlimpMessage> client_input_message = CreateInputMessage(1); + scoped_ptr<BlimpMessage> client_control_message = CreateControlMessage(1); + scoped_ptr<BlimpMessage> engine_control_message = CreateControlMessage(2); + + EXPECT_CALL( + *(engine_input_feature_->incoming_message_processor()), + MockableProcessMessage(EqualsMessageIgnoringId(*client_input_message), _)) + .RetiresOnSaturation(); + EXPECT_CALL(*(engine_control_feature_->incoming_message_processor()), + MockableProcessMessage( + EqualsMessageIgnoringId(*client_control_message), _)) + .RetiresOnSaturation(); + EXPECT_CALL(*(client_control_feature_->incoming_message_processor()), + MockableProcessMessage( + EqualsMessageIgnoringId(*engine_control_message), _)) + .RetiresOnSaturation(); + + client_input_feature_->outgoing_message_processor()->ProcessMessage( + std::move(client_input_message), net::CompletionCallback()); + client_control_feature_->outgoing_message_processor()->ProcessMessage( + std::move(client_control_message), net::CompletionCallback()); + engine_control_feature_->outgoing_message_processor()->ProcessMessage( + std::move(engine_control_message), net::CompletionCallback()); +} + +TEST_F(BrowserConnectionHandlerTest, ConnectionError) { + // Engine will not get message after connection error. + client_connection_->error_observer()->OnConnectionError(net::ERR_FAILED); + scoped_ptr<BlimpMessage> client_input_message = CreateInputMessage(1); + client_input_feature_->outgoing_message_processor()->ProcessMessage( + std::move(client_input_message), net::CompletionCallback()); +} + +TEST_F(BrowserConnectionHandlerTest, ReconnectionAfterError) { + scoped_ptr<BlimpMessage> client_input_message = CreateInputMessage(1); + EXPECT_CALL( + *(engine_input_feature_->incoming_message_processor()), + MockableProcessMessage(EqualsMessageIgnoringId(*client_input_message), _)) + .RetiresOnSaturation(); + + client_connection_->error_observer()->OnConnectionError(net::ERR_FAILED); + // Message will be queued to be transmitted when the connection is + // re-established. + client_input_feature_->outgoing_message_processor()->ProcessMessage( + std::move(client_input_message), net::CompletionCallback()); + + // Simulates reconnection. + SetupConnections(); +} + +} // namespace +} // namespace blimp diff --git a/blimp/net/test_common.h b/blimp/net/test_common.h index b42c3d8..b743c4a 100644 --- a/blimp/net/test_common.h +++ b/blimp/net/test_common.h @@ -177,7 +177,7 @@ class MockBlimpConnection : public BlimpConnection { MOCK_METHOD1(SetIncomingMessageProcessor, void(BlimpMessageProcessor* processor)); - MOCK_CONST_METHOD0(GetOutgoingMessageProcessor, BlimpMessageProcessor*()); + MOCK_METHOD0(GetOutgoingMessageProcessor, BlimpMessageProcessor*()); }; class MockConnectionErrorObserver : public ConnectionErrorObserver { |