// 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 #include #include "base/callback_helpers.h" #include "base/message_loop/message_loop.h" #include "blimp/common/create_blimp_message.h" #include "blimp/common/proto/blimp_message.pb.h" #include "blimp/common/protocol_version.h" #include "blimp/net/blimp_connection.h" #include "blimp/net/blimp_transport.h" #include "blimp/net/client_connection_manager.h" #include "blimp/net/test_common.h" #include "net/base/completion_callback.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::Eq; using testing::Return; using testing::SaveArg; namespace blimp { namespace { const char kDummyClientToken[] = "dummy-client-token"; } // namespace class ClientConnectionManagerTest : public testing::Test { public: ClientConnectionManagerTest() : manager_(new ClientConnectionManager(&connection_handler_)), transport1_(new testing::StrictMock), transport2_(new testing::StrictMock), reader_(new MockPacketReader), writer_(new MockPacketWriter), connection_(new BlimpConnection(make_scoped_ptr(reader_), make_scoped_ptr(writer_))), start_connection_message_( CreateStartConnectionMessage(kDummyClientToken, kProtocolVersion)) { manager_->set_client_token(kDummyClientToken); } ~ClientConnectionManagerTest() override {} protected: base::MessageLoop message_loop_; testing::StrictMock connection_handler_; scoped_ptr manager_; scoped_ptr> transport1_; scoped_ptr> transport2_; MockPacketReader* reader_; MockPacketWriter* writer_; scoped_ptr connection_; scoped_ptr start_connection_message_; }; // The 1st transport connects, and the 2nd transport is not used. TEST_F(ClientConnectionManagerTest, FirstTransportConnects) { net::CompletionCallback write_cb; net::CompletionCallback connect_cb_1; EXPECT_CALL(*transport1_, Connect(_)).WillOnce(SaveArg<0>(&connect_cb_1)); EXPECT_CALL(connection_handler_, HandleConnectionPtr(Eq(connection_.get()))); EXPECT_CALL(*writer_, WritePacket(BufferEqualsProto(*start_connection_message_), _)) .WillOnce(SaveArg<1>(&write_cb)); EXPECT_CALL(*transport1_, TakeConnectionPtr()) .WillOnce(Return(connection_.release())); ASSERT_TRUE(connect_cb_1.is_null()); manager_->AddTransport(std::move(transport1_)); manager_->AddTransport(std::move(transport2_)); manager_->Connect(); ASSERT_FALSE(connect_cb_1.is_null()); base::ResetAndReturn(&connect_cb_1).Run(net::OK); base::ResetAndReturn(&write_cb).Run(net::OK); } // The 1st transport fails to connect, and the 2nd transport connects. TEST_F(ClientConnectionManagerTest, SecondTransportConnects) { net::CompletionCallback write_cb; net::CompletionCallback connect_cb_1; EXPECT_CALL(*transport1_, Connect(_)).WillOnce(SaveArg<0>(&connect_cb_1)); net::CompletionCallback connect_cb_2; EXPECT_CALL(*transport2_, Connect(_)).WillOnce(SaveArg<0>(&connect_cb_2)); EXPECT_CALL(*writer_, WritePacket(BufferEqualsProto(*start_connection_message_), _)) .WillOnce(SaveArg<1>(&write_cb)); EXPECT_CALL(connection_handler_, HandleConnectionPtr(Eq(connection_.get()))); EXPECT_CALL(*transport2_, TakeConnectionPtr()) .WillOnce(Return(connection_.release())); ASSERT_TRUE(connect_cb_1.is_null()); ASSERT_TRUE(connect_cb_2.is_null()); manager_->AddTransport(std::move(transport1_)); manager_->AddTransport(std::move(transport2_)); manager_->Connect(); ASSERT_FALSE(connect_cb_1.is_null()); base::ResetAndReturn(&connect_cb_1).Run(net::ERR_FAILED); ASSERT_FALSE(connect_cb_2.is_null()); base::ResetAndReturn(&connect_cb_2).Run(net::OK); base::ResetAndReturn(&write_cb).Run(net::OK); } // Both transports fail to connect. TEST_F(ClientConnectionManagerTest, BothTransportsFailToConnect) { net::CompletionCallback connect_cb_1; EXPECT_CALL(*transport1_, Connect(_)).WillOnce(SaveArg<0>(&connect_cb_1)); net::CompletionCallback connect_cb_2; EXPECT_CALL(*transport2_, Connect(_)).WillOnce(SaveArg<0>(&connect_cb_2)); ASSERT_TRUE(connect_cb_1.is_null()); ASSERT_TRUE(connect_cb_2.is_null()); manager_->AddTransport(std::move(transport1_)); manager_->AddTransport(std::move(transport2_)); manager_->Connect(); ASSERT_FALSE(connect_cb_1.is_null()); ASSERT_TRUE(connect_cb_2.is_null()); base::ResetAndReturn(&connect_cb_1).Run(net::ERR_FAILED); ASSERT_FALSE(connect_cb_2.is_null()); base::ResetAndReturn(&connect_cb_2).Run(net::ERR_FAILED); } } // namespace blimp