1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/proximity_auth/connection.h"
6
7#include "components/proximity_auth/connection_observer.h"
8#include "components/proximity_auth/remote_device.h"
9#include "components/proximity_auth/wire_message.h"
10#include "testing/gmock/include/gmock/gmock.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13using testing::_;
14using testing::DoAll;
15using testing::NiceMock;
16using testing::Return;
17using testing::SetArgPointee;
18using testing::StrictMock;
19
20namespace proximity_auth {
21namespace {
22
23class MockConnection : public Connection {
24 public:
25  MockConnection() : Connection(RemoteDevice()) {}
26  ~MockConnection() {}
27
28  MOCK_METHOD1(SetPaused, void(bool paused));
29  MOCK_METHOD0(Connect, void());
30  MOCK_METHOD0(Disconnect, void());
31  MOCK_METHOD0(CancelConnectionAttempt, void());
32  MOCK_METHOD1(SendMessageImplProxy, void(WireMessage* message));
33  MOCK_METHOD1(DeserializeWireMessageProxy,
34               WireMessage*(bool* is_incomplete_message));
35
36  // Gmock only supports copyable types, so create simple wrapper methods for
37  // ease of mocking.
38  virtual void SendMessageImpl(scoped_ptr<WireMessage> message) OVERRIDE {
39    SendMessageImplProxy(message.get());
40  }
41
42  virtual scoped_ptr<WireMessage> DeserializeWireMessage(
43      bool* is_incomplete_message) OVERRIDE {
44    return make_scoped_ptr(DeserializeWireMessageProxy(is_incomplete_message));
45  }
46
47  using Connection::status;
48  using Connection::SetStatus;
49  using Connection::OnDidSendMessage;
50  using Connection::OnBytesReceived;
51
52 private:
53  DISALLOW_COPY_AND_ASSIGN(MockConnection);
54};
55
56class MockConnectionObserver : public ConnectionObserver {
57 public:
58  MockConnectionObserver() {}
59  virtual ~MockConnectionObserver() {}
60
61  MOCK_METHOD3(OnConnectionStatusChanged,
62               void(const Connection& connection,
63                    Connection::Status old_status,
64                    Connection::Status new_status));
65  MOCK_METHOD2(OnMessageReceived,
66               void(const Connection& connection, const WireMessage& message));
67  MOCK_METHOD3(OnSendCompleted,
68               void(const Connection& connection,
69                    const WireMessage& message,
70                    bool success));
71
72 private:
73  DISALLOW_COPY_AND_ASSIGN(MockConnectionObserver);
74};
75
76// Unlike WireMessage, offers a public constructor.
77class TestWireMessage : public WireMessage {
78 public:
79  TestWireMessage() : WireMessage(std::string(), std::string()) {}
80  virtual ~TestWireMessage() {}
81
82 private:
83  DISALLOW_COPY_AND_ASSIGN(TestWireMessage);
84};
85
86}  // namespace
87
88TEST(ProximityAuthConnectionTest, IsConnected) {
89  StrictMock<MockConnection> connection;
90  EXPECT_FALSE(connection.IsConnected());
91
92  connection.SetStatus(Connection::CONNECTED);
93  EXPECT_TRUE(connection.IsConnected());
94
95  connection.SetStatus(Connection::DISCONNECTED);
96  EXPECT_FALSE(connection.IsConnected());
97
98  connection.SetStatus(Connection::IN_PROGRESS);
99  EXPECT_FALSE(connection.IsConnected());
100}
101
102TEST(ProximityAuthConnectionTest, SendMessage_FailsWhenNotConnected) {
103  StrictMock<MockConnection> connection;
104  connection.SetStatus(Connection::IN_PROGRESS);
105
106  EXPECT_CALL(connection, SendMessageImplProxy(_)).Times(0);
107  connection.SendMessage(scoped_ptr<WireMessage>());
108}
109
110TEST(ProximityAuthConnectionTest,
111     SendMessage_FailsWhenAnotherMessageSendIsInProgress) {
112  NiceMock<MockConnection> connection;
113  connection.SetStatus(Connection::CONNECTED);
114  connection.SendMessage(scoped_ptr<WireMessage>());
115
116  EXPECT_CALL(connection, SendMessageImplProxy(_)).Times(0);
117  connection.SendMessage(scoped_ptr<WireMessage>());
118}
119
120TEST(ProximityAuthConnectionTest, SendMessage_SucceedsWhenConnected) {
121  StrictMock<MockConnection> connection;
122  connection.SetStatus(Connection::CONNECTED);
123
124  EXPECT_CALL(connection, SendMessageImplProxy(_));
125  connection.SendMessage(scoped_ptr<WireMessage>());
126}
127
128TEST(ProximityAuthConnectionTest,
129     SendMessage_SucceedsAfterPreviousMessageSendCompletes) {
130  NiceMock<MockConnection> connection;
131  connection.SetStatus(Connection::CONNECTED);
132  connection.SendMessage(scoped_ptr<WireMessage>());
133  connection.OnDidSendMessage(TestWireMessage(), true /* success */);
134
135  EXPECT_CALL(connection, SendMessageImplProxy(_));
136  connection.SendMessage(scoped_ptr<WireMessage>());
137}
138
139TEST(ProximityAuthConnectionTest, SetStatus_NotifiesObserversOfStatusChange) {
140  StrictMock<MockConnection> connection;
141  EXPECT_EQ(Connection::DISCONNECTED, connection.status());
142
143  StrictMock<MockConnectionObserver> observer;
144  connection.AddObserver(&observer);
145
146  EXPECT_CALL(
147      observer,
148      OnConnectionStatusChanged(
149          Ref(connection), Connection::DISCONNECTED, Connection::CONNECTED));
150  connection.SetStatus(Connection::CONNECTED);
151}
152
153TEST(ProximityAuthConnectionTest,
154     SetStatus_DoesntNotifyObserversIfStatusUnchanged) {
155  StrictMock<MockConnection> connection;
156  EXPECT_EQ(Connection::DISCONNECTED, connection.status());
157
158  StrictMock<MockConnectionObserver> observer;
159  connection.AddObserver(&observer);
160
161  EXPECT_CALL(observer, OnConnectionStatusChanged(_, _, _)).Times(0);
162  connection.SetStatus(Connection::DISCONNECTED);
163}
164
165TEST(ProximityAuthConnectionTest,
166     OnDidSendMessage_NotifiesObserversIfMessageSendInProgress) {
167  NiceMock<MockConnection> connection;
168  connection.SetStatus(Connection::CONNECTED);
169  connection.SendMessage(scoped_ptr<WireMessage>());
170
171  StrictMock<MockConnectionObserver> observer;
172  connection.AddObserver(&observer);
173
174  EXPECT_CALL(observer, OnSendCompleted(Ref(connection), _, true));
175  connection.OnDidSendMessage(TestWireMessage(), true /* success */);
176}
177
178TEST(ProximityAuthConnectionTest,
179     OnDidSendMessage_DoesntNotifyObserversIfNoMessageSendInProgress) {
180  NiceMock<MockConnection> connection;
181  connection.SetStatus(Connection::CONNECTED);
182
183  StrictMock<MockConnectionObserver> observer;
184  connection.AddObserver(&observer);
185
186  EXPECT_CALL(observer, OnSendCompleted(_, _, _)).Times(0);
187  connection.OnDidSendMessage(TestWireMessage(), true /* success */);
188}
189
190TEST(ProximityAuthConnectionTest,
191     OnBytesReceived_NotifiesObserversOnValidMessage) {
192  NiceMock<MockConnection> connection;
193  connection.SetStatus(Connection::CONNECTED);
194
195  StrictMock<MockConnectionObserver> observer;
196  connection.AddObserver(&observer);
197
198  ON_CALL(connection, DeserializeWireMessageProxy(_))
199      .WillByDefault(
200          DoAll(SetArgPointee<0>(false), Return(new TestWireMessage)));
201  EXPECT_CALL(observer, OnMessageReceived(Ref(connection), _));
202  connection.OnBytesReceived(std::string());
203}
204
205TEST(ProximityAuthConnectionTest,
206     OnBytesReceived_DoesntNotifyObserversIfNotConnected) {
207  StrictMock<MockConnection> connection;
208  connection.SetStatus(Connection::IN_PROGRESS);
209
210  StrictMock<MockConnectionObserver> observer;
211  connection.AddObserver(&observer);
212
213  EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0);
214  connection.OnBytesReceived(std::string());
215}
216
217TEST(ProximityAuthConnectionTest,
218     OnBytesReceived_DoesntNotifyObserversIfMessageIsIncomplete) {
219  NiceMock<MockConnection> connection;
220  connection.SetStatus(Connection::CONNECTED);
221
222  StrictMock<MockConnectionObserver> observer;
223  connection.AddObserver(&observer);
224
225  ON_CALL(connection, DeserializeWireMessageProxy(_))
226      .WillByDefault(DoAll(SetArgPointee<0>(true),
227                           Return(static_cast<WireMessage*>(NULL))));
228  EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0);
229  connection.OnBytesReceived(std::string());
230}
231
232TEST(ProximityAuthConnectionTest,
233     OnBytesReceived_DoesntNotifyObserversIfMessageIsInvalid) {
234  NiceMock<MockConnection> connection;
235  connection.SetStatus(Connection::CONNECTED);
236
237  StrictMock<MockConnectionObserver> observer;
238  connection.AddObserver(&observer);
239
240  ON_CALL(connection, DeserializeWireMessageProxy(_))
241      .WillByDefault(DoAll(SetArgPointee<0>(false),
242                           Return(static_cast<WireMessage*>(NULL))));
243  EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0);
244  connection.OnBytesReceived(std::string());
245}
246
247}  // namespace proximity_auth
248