| // Copyright 2014 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 "components/cryptauth/connection.h" |
| |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "components/cryptauth/connection_observer.h" |
| #include "components/cryptauth/remote_device.h" |
| #include "components/cryptauth/wire_message.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::_; |
| using testing::DoAll; |
| using testing::NiceMock; |
| using testing::Return; |
| using testing::SetArgPointee; |
| using testing::StrictMock; |
| |
| namespace cryptauth { |
| namespace { |
| |
| class MockConnection : public Connection { |
| public: |
| MockConnection() : Connection(RemoteDevice()) {} |
| ~MockConnection() {} |
| |
| MOCK_METHOD1(SetPaused, void(bool paused)); |
| MOCK_METHOD0(Connect, void()); |
| MOCK_METHOD0(Disconnect, void()); |
| MOCK_METHOD0(CancelConnectionAttempt, void()); |
| MOCK_METHOD1(SendMessageImplProxy, void(WireMessage* message)); |
| MOCK_METHOD1(DeserializeWireMessageProxy, |
| WireMessage*(bool* is_incomplete_message)); |
| |
| // Gmock only supports copyable types, so create simple wrapper methods for |
| // ease of mocking. |
| void SendMessageImpl(std::unique_ptr<WireMessage> message) override { |
| SendMessageImplProxy(message.get()); |
| } |
| |
| std::unique_ptr<WireMessage> DeserializeWireMessage( |
| bool* is_incomplete_message) override { |
| return base::WrapUnique(DeserializeWireMessageProxy(is_incomplete_message)); |
| } |
| |
| using Connection::status; |
| using Connection::SetStatus; |
| using Connection::OnDidSendMessage; |
| using Connection::OnBytesReceived; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MockConnection); |
| }; |
| |
| class MockConnectionObserver : public ConnectionObserver { |
| public: |
| MockConnectionObserver() {} |
| virtual ~MockConnectionObserver() {} |
| |
| MOCK_METHOD3(OnConnectionStatusChanged, |
| void(Connection* connection, |
| Connection::Status old_status, |
| Connection::Status new_status)); |
| MOCK_METHOD2(OnMessageReceived, |
| void(const Connection& connection, const WireMessage& message)); |
| MOCK_METHOD3(OnSendCompleted, |
| void(const Connection& connection, |
| const WireMessage& message, |
| bool success)); |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MockConnectionObserver); |
| }; |
| |
| // Unlike WireMessage, offers a public constructor. |
| class TestWireMessage : public WireMessage { |
| public: |
| TestWireMessage() : WireMessage("payload", "feature") {} |
| ~TestWireMessage() override {} |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TestWireMessage); |
| }; |
| |
| } // namespace |
| |
| class CryptAuthConnectionTest : public testing::Test { |
| protected: |
| CryptAuthConnectionTest() {} |
| ~CryptAuthConnectionTest() override {} |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(CryptAuthConnectionTest); |
| }; |
| |
| TEST(CryptAuthConnectionTest, IsConnected) { |
| StrictMock<MockConnection> connection; |
| EXPECT_FALSE(connection.IsConnected()); |
| |
| connection.SetStatus(Connection::CONNECTED); |
| EXPECT_TRUE(connection.IsConnected()); |
| |
| connection.SetStatus(Connection::DISCONNECTED); |
| EXPECT_FALSE(connection.IsConnected()); |
| |
| connection.SetStatus(Connection::IN_PROGRESS); |
| EXPECT_FALSE(connection.IsConnected()); |
| } |
| |
| TEST(CryptAuthConnectionTest, SendMessage_FailsWhenNotConnected) { |
| StrictMock<MockConnection> connection; |
| connection.SetStatus(Connection::IN_PROGRESS); |
| |
| EXPECT_CALL(connection, SendMessageImplProxy(_)).Times(0); |
| connection.SendMessage(std::unique_ptr<WireMessage>()); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| SendMessage_FailsWhenAnotherMessageSendIsInProgress) { |
| NiceMock<MockConnection> connection; |
| connection.SetStatus(Connection::CONNECTED); |
| connection.SendMessage(std::unique_ptr<WireMessage>()); |
| |
| EXPECT_CALL(connection, SendMessageImplProxy(_)).Times(0); |
| connection.SendMessage(std::unique_ptr<WireMessage>()); |
| } |
| |
| TEST(CryptAuthConnectionTest, SendMessage_SucceedsWhenConnected) { |
| StrictMock<MockConnection> connection; |
| connection.SetStatus(Connection::CONNECTED); |
| |
| EXPECT_CALL(connection, SendMessageImplProxy(_)); |
| connection.SendMessage(std::unique_ptr<WireMessage>()); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| SendMessage_SucceedsAfterPreviousMessageSendCompletes) { |
| NiceMock<MockConnection> connection; |
| connection.SetStatus(Connection::CONNECTED); |
| connection.SendMessage(std::unique_ptr<WireMessage>()); |
| connection.OnDidSendMessage(TestWireMessage(), true /* success */); |
| |
| EXPECT_CALL(connection, SendMessageImplProxy(_)); |
| connection.SendMessage(std::unique_ptr<WireMessage>()); |
| } |
| |
| TEST(CryptAuthConnectionTest, SetStatus_NotifiesObserversOfStatusChange) { |
| StrictMock<MockConnection> connection; |
| EXPECT_EQ(Connection::DISCONNECTED, connection.status()); |
| |
| StrictMock<MockConnectionObserver> observer; |
| connection.AddObserver(&observer); |
| |
| EXPECT_CALL(observer, |
| OnConnectionStatusChanged(&connection, Connection::DISCONNECTED, |
| Connection::CONNECTED)); |
| connection.SetStatus(Connection::CONNECTED); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| SetStatus_DoesntNotifyObserversIfStatusUnchanged) { |
| StrictMock<MockConnection> connection; |
| EXPECT_EQ(Connection::DISCONNECTED, connection.status()); |
| |
| StrictMock<MockConnectionObserver> observer; |
| connection.AddObserver(&observer); |
| |
| EXPECT_CALL(observer, OnConnectionStatusChanged(_, _, _)).Times(0); |
| connection.SetStatus(Connection::DISCONNECTED); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| OnDidSendMessage_NotifiesObserversIfMessageSendInProgress) { |
| NiceMock<MockConnection> connection; |
| connection.SetStatus(Connection::CONNECTED); |
| connection.SendMessage(std::unique_ptr<WireMessage>()); |
| |
| StrictMock<MockConnectionObserver> observer; |
| connection.AddObserver(&observer); |
| |
| EXPECT_CALL(observer, OnSendCompleted(Ref(connection), _, true)); |
| connection.OnDidSendMessage(TestWireMessage(), true /* success */); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| OnDidSendMessage_DoesntNotifyObserversIfNoMessageSendInProgress) { |
| NiceMock<MockConnection> connection; |
| connection.SetStatus(Connection::CONNECTED); |
| |
| StrictMock<MockConnectionObserver> observer; |
| connection.AddObserver(&observer); |
| |
| EXPECT_CALL(observer, OnSendCompleted(_, _, _)).Times(0); |
| connection.OnDidSendMessage(TestWireMessage(), true /* success */); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| OnBytesReceived_NotifiesObserversOnValidMessage) { |
| NiceMock<MockConnection> connection; |
| connection.SetStatus(Connection::CONNECTED); |
| |
| StrictMock<MockConnectionObserver> observer; |
| connection.AddObserver(&observer); |
| |
| ON_CALL(connection, DeserializeWireMessageProxy(_)) |
| .WillByDefault( |
| DoAll(SetArgPointee<0>(false), Return(new TestWireMessage))); |
| EXPECT_CALL(observer, OnMessageReceived(Ref(connection), _)); |
| connection.OnBytesReceived(std::string()); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| OnBytesReceived_DoesntNotifyObserversIfNotConnected) { |
| StrictMock<MockConnection> connection; |
| connection.SetStatus(Connection::IN_PROGRESS); |
| |
| StrictMock<MockConnectionObserver> observer; |
| connection.AddObserver(&observer); |
| |
| EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0); |
| connection.OnBytesReceived(std::string()); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| OnBytesReceived_DoesntNotifyObserversIfMessageIsIncomplete) { |
| NiceMock<MockConnection> connection; |
| connection.SetStatus(Connection::CONNECTED); |
| |
| StrictMock<MockConnectionObserver> observer; |
| connection.AddObserver(&observer); |
| |
| ON_CALL(connection, DeserializeWireMessageProxy(_)) |
| .WillByDefault(DoAll(SetArgPointee<0>(true), Return(nullptr))); |
| EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0); |
| connection.OnBytesReceived(std::string()); |
| } |
| |
| TEST(CryptAuthConnectionTest, |
| OnBytesReceived_DoesntNotifyObserversIfMessageIsInvalid) { |
| NiceMock<MockConnection> connection; |
| connection.SetStatus(Connection::CONNECTED); |
| |
| StrictMock<MockConnectionObserver> observer; |
| connection.AddObserver(&observer); |
| |
| ON_CALL(connection, DeserializeWireMessageProxy(_)) |
| .WillByDefault(DoAll(SetArgPointee<0>(false), Return(nullptr))); |
| EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0); |
| connection.OnBytesReceived(std::string()); |
| } |
| |
| } // namespace cryptauth |