1// Copyright 2012 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Tests for PairingSession.
16
17#include <gtest/gtest.h>
18#include <polo/pairing/clientpairingsession.h>
19#include "polo/pairing/mocks.h"
20#include "polo/wire/mocks.h"
21
22using ::testing::Const;
23using ::testing::InSequence;
24using ::testing::Mock;
25using ::testing::Return;
26using ::testing::ReturnRef;
27using ::testing::StrictMock;
28using ::testing::_;
29
30namespace polo {
31namespace pairing {
32
33class TestPairingSession : public PairingSession {
34 public:
35  TestPairingSession(wire::PoloWireAdapter* wire,
36                     PairingContext* context,
37                     PoloChallengeResponse* challenge)
38      : PairingSession(wire, context, challenge) {
39  }
40
41  void TestDoPairingPhase() {
42    DoPairingPhase();
43  }
44
45  bool TestSetConfiguration(const message::ConfigurationMessage& message) {
46    return SetConfiguration(message);
47  }
48
49  const message::ConfigurationMessage* GetConfiguration() {
50    return configuration();
51  }
52
53  const message::OptionsMessage& GetLocalOptions() {
54    return local_options();
55  }
56
57  void TestOnSecretMessage(const message::SecretMessage& message) {
58    OnSecretMessage(message);
59  }
60
61  void TestOnSecretAckmessage(const message::SecretAckMessage& message) {
62    OnSecretAckMessage(message);
63  }
64
65  MOCK_METHOD0(DoInitializationPhase, void());
66  MOCK_METHOD0(DoConfigurationPhase, void());
67  MOCK_METHOD1(OnConfigurationMessage,
68               void(const pairing::message::ConfigurationMessage& message));
69  MOCK_METHOD1(OnConfigurationAckMessage,
70               void(const pairing::message::ConfigurationAckMessage& message));
71  MOCK_METHOD1(OnOptionsMessage,
72               void(const pairing::message::OptionsMessage& message));
73  MOCK_METHOD1(OnPairingRequestMessage,
74               void(const pairing::message::PairingRequestMessage& message));
75  MOCK_METHOD1(OnPairingRequestAckMessage,
76               void(const pairing::message::PairingRequestAckMessage& message));
77};
78
79class PairingSessionTest : public ::testing::Test {
80 protected:
81  PairingSessionTest()
82      : interface_(),
83        wire_(&interface_),
84        challenge_(),
85        context_(NULL, NULL, false),
86        session_(&wire_, &context_, &challenge_) {
87  }
88
89  virtual void SetUp() {
90  }
91
92  virtual void TearDown() {
93  }
94
95  void InitSession() {
96    InSequence sequence;
97
98    EXPECT_CALL(listener_, OnSessionCreated());
99    EXPECT_CALL(session_, DoInitializationPhase());
100
101    session_.DoPair(&listener_);
102  }
103
104  StrictMock<wire::MockWireInterface> interface_;
105  StrictMock<wire::MockWireAdapter> wire_;
106  StrictMock<MockChallengeResponse> challenge_;
107  PairingContext context_;
108  StrictMock<MockPairingListener> listener_;
109  StrictMock<TestPairingSession> session_;
110};
111
112TEST_F(PairingSessionTest, DoPair) {
113  // Test the base SetUp case which initializes the pairing session.
114  InitSession();
115}
116
117TEST_F(PairingSessionTest, SetConfiguration) {
118  encoding::EncodingOption encoding(encoding::EncodingOption::kHexadecimal, 8);
119  message::ConfigurationMessage configuration(encoding,
120      message::OptionsMessage::kInputDevice);
121  session_.TestSetConfiguration(configuration);
122
123  ASSERT_TRUE(session_.GetConfiguration());
124  ASSERT_EQ(encoding::EncodingOption::kHexadecimal,
125            session_.GetConfiguration()->encoding().encoding_type());
126  ASSERT_EQ(8, session_.GetConfiguration()->encoding().symbol_length());
127  ASSERT_EQ(message::OptionsMessage::kInputDevice,
128            session_.GetConfiguration()->client_role());
129
130  ASSERT_TRUE(session_.encoder());
131  ASSERT_EQ(2, session_.encoder()->symbols_per_byte());
132}
133
134TEST_F(PairingSessionTest, DoPairingPhaseInputDevice) {
135  InitSession();
136  InSequence sequence;
137
138  encoding::EncodingOption encoding(encoding::EncodingOption::kHexadecimal, 8);
139  message::ConfigurationMessage configuration(encoding,
140      message::OptionsMessage::kInputDevice);
141  session_.TestSetConfiguration(configuration);
142
143  EXPECT_CALL(listener_, OnPerformInputDeviceRole());
144
145  session_.TestDoPairingPhase();
146}
147
148TEST_F(PairingSessionTest, DoPairingPhaseDisplayDevice) {
149  InitSession();
150  InSequence sequence;
151
152  encoding::EncodingOption encoding(encoding::EncodingOption::kHexadecimal, 8);
153  message::ConfigurationMessage configuration(encoding,
154      message::OptionsMessage::kDisplayDevice);
155  session_.TestSetConfiguration(configuration);
156
157  EXPECT_CALL(challenge_, GetGamma(_)).WillOnce(Return(new Gamma(10, 0x5)));
158  EXPECT_CALL(listener_, OnPerformOutputDeviceRole(Gamma(10, 0x5)));
159  EXPECT_CALL(wire_, GetNextMessage());
160
161  session_.TestDoPairingPhase();
162}
163
164TEST_F(PairingSessionTest, AddInputEncoding) {
165  encoding::EncodingOption encoding(encoding::EncodingOption::kHexadecimal, 8);
166  session_.AddInputEncoding(encoding);
167  ASSERT_TRUE(session_.GetLocalOptions().SupportsInputEncoding(encoding));
168}
169
170TEST_F(PairingSessionTest, AddInputEncodingInvalidEncoding) {
171  encoding::EncodingOption encoding(encoding::EncodingOption::kHexadecimal, 1);
172    session_.AddInputEncoding(encoding);
173  ASSERT_FALSE(session_.GetLocalOptions().SupportsInputEncoding(encoding));
174}
175
176TEST_F(PairingSessionTest, AddOutputEncoding) {
177  encoding::EncodingOption encoding(encoding::EncodingOption::kHexadecimal, 8);
178  session_.AddOutputEncoding(encoding);
179  ASSERT_TRUE(session_.GetLocalOptions().SupportsOutputEncoding(encoding));
180}
181
182TEST_F(PairingSessionTest, AddOutputEncodingInvalidEncoding) {
183  encoding::EncodingOption encoding(encoding::EncodingOption::kUnknown, 8);
184  session_.AddOutputEncoding(encoding);
185  ASSERT_FALSE(session_.GetLocalOptions().SupportsOutputEncoding(encoding));
186}
187
188TEST_F(PairingSessionTest, SetSecret) {
189  InitSession();
190  InSequence sequence;
191
192  // Do the setup so the session is expecting the secret.
193  encoding::EncodingOption encoding(encoding::EncodingOption::kHexadecimal, 8);
194  message::ConfigurationMessage configuration(encoding,
195      message::OptionsMessage::kInputDevice);
196  session_.TestSetConfiguration(configuration);
197
198  EXPECT_CALL(listener_, OnPerformInputDeviceRole());
199
200  session_.TestDoPairingPhase();
201
202  Gamma gamma(5, 0x1);
203  Nonce nonce(5, 0x2);
204  Alpha alpha(5, 0x3);
205
206  EXPECT_CALL(challenge_, CheckGamma(gamma)).WillOnce(Return(true));
207  EXPECT_CALL(challenge_, ExtractNonce(gamma))
208      .WillOnce(Return(new Nonce(nonce)));
209  EXPECT_CALL(challenge_, GetAlpha(nonce))
210      .WillOnce(Return(new Alpha(alpha)));
211
212  EXPECT_CALL(wire_, SendSecretMessage(_));
213  EXPECT_CALL(wire_, GetNextMessage());
214
215  session_.SetSecret(gamma);
216}
217
218TEST_F(PairingSessionTest, OnSecretMessage) {
219  InitSession();
220  InSequence sequence;
221
222  // Do the setup to set the secret.
223  encoding::EncodingOption encoding(encoding::EncodingOption::kHexadecimal, 8);
224  message::ConfigurationMessage configuration(encoding,
225      message::OptionsMessage::kInputDevice);
226  session_.TestSetConfiguration(configuration);
227
228  EXPECT_CALL(listener_, OnPerformInputDeviceRole());
229
230  session_.TestDoPairingPhase();
231
232  Gamma gamma(5, 0x1);
233  Nonce nonce(5, 0x2);
234  Alpha alpha(5, 0x3);
235
236  EXPECT_CALL(challenge_, CheckGamma(gamma)).WillOnce(Return(true));
237  EXPECT_CALL(challenge_, ExtractNonce(gamma))
238      .WillOnce(Return(new Nonce(nonce)));
239  EXPECT_CALL(challenge_, GetAlpha(nonce))
240      .WillOnce(Return(new Alpha(alpha)));
241
242  EXPECT_CALL(wire_, SendSecretMessage(_));
243  EXPECT_CALL(wire_, GetNextMessage());
244
245  session_.SetSecret(gamma);
246
247  EXPECT_CALL(challenge_, GetAlpha(nonce))
248      .WillOnce(Return(new Alpha(alpha)));
249
250  EXPECT_CALL(challenge_, GetAlpha(nonce))
251        .WillOnce(Return(new Alpha(alpha)));
252
253  EXPECT_CALL(wire_, SendSecretAckMessage(_));
254  EXPECT_CALL(listener_, OnPairingSuccess());
255
256  message::SecretMessage message(alpha);
257  session_.TestOnSecretMessage(message);
258}
259
260TEST_F(PairingSessionTest, OnSecretAckMessage) {
261  EXPECT_CALL(listener_, OnPairingSuccess());
262
263  Alpha alpha(5, 0x3);
264  message::SecretAckMessage message(alpha);
265  session_.TestOnSecretAckmessage(message);
266}
267
268}  // namespace pairing
269}  // namespace polo
270