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 ProtobufWireAdapter.
16 
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <polo/util/poloutil.h>
20 #include <polo/wire/protobuf/protobufwireadapter.h>
21 #include "polo/wire/mocks.h"
22 
23 using ::testing::InSequence;
24 using ::testing::Mock;
25 using ::testing::Return;
26 using ::testing::StrictMock;
27 
28 namespace polo {
29 namespace wire {
30 namespace protobuf {
31 
32 // A mock MessageListener.
33 class MockMessageListener : public pairing::message::MessageListener {
34   MOCK_METHOD1(OnConfigurationMessage,
35                void(const pairing::message::ConfigurationMessage& message));
36 
37   MOCK_METHOD1(OnConfigurationAckMessage,
38                void(const pairing::message::ConfigurationAckMessage& message));
39 
40   MOCK_METHOD1(OnOptionsMessage,
41                void(const pairing::message::OptionsMessage& message));
42 
43   MOCK_METHOD1(OnPairingRequestMessage,
44                void(const pairing::message::PairingRequestMessage& message));
45 
46   MOCK_METHOD1(OnPairingRequestAckMessage,
47                void(const pairing::message::PairingRequestAckMessage& message));
48 
49   MOCK_METHOD1(OnSecretMessage,
50                void(const pairing::message::SecretMessage& message));
51 
52   MOCK_METHOD1(OnSecretAckMessage,
53                void(const pairing::message::SecretAckMessage& message));
54 
55   MOCK_METHOD1(OnError, void(pairing::PoloError error));
56 };
57 
58 // Test fixture for ProtobufWireAdapter tests.
59 class ProtobufWireAdapterTest : public ::testing::Test {
60  public:
ProtobufWireAdapterTest()61   ProtobufWireAdapterTest() : interface_(), adapter_(&interface_) {}
62 
63  protected:
SetUp()64   virtual void SetUp() {
65     adapter_.set_listener(&listener_);
66   }
67 
68   // Expects that a call to GetNextMessage will be made which triggers a read
69   // for the 4 byte preamble.
ExpectGetPreamble()70   void ExpectGetPreamble() {
71     EXPECT_CALL(interface_, Receive(4));
72     adapter_.GetNextMessage();
73   }
74 
75   // Expects that a call to GetNextMessage will be made, and the preamble will
76   // be read containing the given message size. This will trigger another read
77   // for the full message.
ExpectReadPreamble(uint32_t message_size)78   void ExpectReadPreamble(uint32_t message_size) {
79     ExpectGetPreamble();
80 
81     unsigned char* size_bytes;
82     util::PoloUtil::IntToBigEndianBytes(message_size, size_bytes);
83     EXPECT_CALL(interface_, Receive(message_size));
84 
85     adapter_.OnBytesReceived(
86         std::vector<uint8_t>(size_bytes, size_bytes + 4));
87   }
88 
89   // Expects that the given OuterMessage will be sent over the interface.
ExpectSend(const OuterMessage & message)90   void ExpectSend(const OuterMessage& message) {
91     std::string outer_string = message.SerializeAsString();
92 
93     unsigned char* size_bytes;
94     util::PoloUtil::IntToBigEndianBytes(outer_string.length(), size_bytes);
95 
96     std::vector<unsigned char> data(outer_string.length() + 4);
97     unsigned char* buffer = &data[0];
98     memcpy(buffer, size_bytes, 4);
99     memcpy((buffer + 4), &outer_string[0], outer_string.length());
100 
101     EXPECT_CALL(interface_, Send(data));
102   }
103 
104   StrictMock<MockWireInterface> interface_;
105   StrictMock<MockMessageListener> listener_;
106   ProtobufWireAdapter adapter_;
107 };
108 
109 // Verifies that a call to GetNextMessage will trigger a read for the 4 byte
110 // preamble.
TEST_F(ProtobufWireAdapterTest,GetNextMessage)111 TEST_F(ProtobufWireAdapterTest, GetNextMessage) {
112   ExpectGetPreamble();
113 }
114 
115 // Verifies that once the preamble is received, a read will be triggered for
116 // the full message.
TEST_F(ProtobufWireAdapterTest,OnBytesReceivedPreamble)117 TEST_F(ProtobufWireAdapterTest, OnBytesReceivedPreamble) {
118   InSequence sequence;
119 
120   ExpectReadPreamble(0xAABBCCDD);
121 }
122 
123 // Verifies that a ConfigurationMessage is successfully sent over the interface.
TEST_F(ProtobufWireAdapterTest,SendConfigurationMessage)124 TEST_F(ProtobufWireAdapterTest, SendConfigurationMessage) {
125   InSequence sequence;
126 
127   Configuration proto;
128   proto.set_client_role(Options_RoleType_ROLE_TYPE_OUTPUT);
129   proto.mutable_encoding()->set_type(
130       Options_Encoding_EncodingType_ENCODING_TYPE_QRCODE);
131   proto.mutable_encoding()->set_symbol_length(64);
132 
133   OuterMessage outer;
134   outer.set_type(OuterMessage_MessageType_MESSAGE_TYPE_CONFIGURATION);
135   outer.set_payload(proto.SerializeAsString());
136   outer.set_protocol_version(1);
137   outer.set_status(OuterMessage_Status_STATUS_OK);
138 
139   ExpectSend(outer);
140 
141   pairing::message::ConfigurationMessage message(
142       encoding::EncodingOption(encoding::EncodingOption::kQRCode, 64),
143       pairing::message::OptionsMessage::kDisplayDevice);
144   adapter_.SendConfigurationMessage(message);
145 }
146 
147 // Verifies that a ConfigurationAckMessage is successfully sent over the
148 // interface.
TEST_F(ProtobufWireAdapterTest,SendConfigurationAckMessage)149 TEST_F(ProtobufWireAdapterTest, SendConfigurationAckMessage) {
150   InSequence sequence;
151 
152   ConfigurationAck proto;
153 
154   OuterMessage outer;
155   outer.set_type(OuterMessage_MessageType_MESSAGE_TYPE_CONFIGURATION_ACK);
156   outer.set_payload(proto.SerializeAsString());
157   outer.set_protocol_version(1);
158   outer.set_status(OuterMessage_Status_STATUS_OK);
159 
160   ExpectSend(outer);
161 
162   pairing::message::ConfigurationAckMessage message;
163   adapter_.SendConfigurationAckMessage(message);
164 }
165 
166 // Verifies that an OptionsMessage is successfully sent over the interface.
TEST_F(ProtobufWireAdapterTest,SendOptionsMessage)167 TEST_F(ProtobufWireAdapterTest, SendOptionsMessage) {
168   InSequence sequence;
169 
170   Options proto;
171   proto.set_preferred_role(Options_RoleType_ROLE_TYPE_INPUT);
172   Options_Encoding* encoding = proto.add_input_encodings();
173   encoding->set_type(Options_Encoding_EncodingType_ENCODING_TYPE_NUMERIC);
174   encoding->set_symbol_length(16);
175 
176   encoding = proto.add_input_encodings();
177   encoding->set_type(Options_Encoding_EncodingType_ENCODING_TYPE_ALPHANUMERIC);
178   encoding->set_symbol_length(32);
179 
180   encoding = proto.add_output_encodings();
181   encoding->set_type(Options_Encoding_EncodingType_ENCODING_TYPE_HEXADECIMAL);
182   encoding->set_symbol_length(128);
183 
184   encoding = proto.add_output_encodings();
185   encoding->set_type(Options_Encoding_EncodingType_ENCODING_TYPE_QRCODE);
186   encoding->set_symbol_length(512);
187 
188   OuterMessage outer;
189   outer.set_type(OuterMessage_MessageType_MESSAGE_TYPE_OPTIONS);
190   outer.set_payload(proto.SerializeAsString());
191   outer.set_protocol_version(1);
192   outer.set_status(OuterMessage_Status_STATUS_OK);
193 
194   ExpectSend(outer);
195 
196   pairing::message::OptionsMessage message;
197   message.set_protocol_role_preference(
198       pairing::message::OptionsMessage::kInputDevice);
199 
200   // Note, the input and output encoding sets are sorted by complexity, so these
201   // should be in the same order as the encodings added to the proto above to
202   // ensure the assert matches.
203   message.AddInputEncoding(
204       encoding::EncodingOption(encoding::EncodingOption::kNumeric, 16));
205   message.AddInputEncoding(
206       encoding::EncodingOption(encoding::EncodingOption::kAlphaNumeric, 32));
207   message.AddOutputEncoding(
208       encoding::EncodingOption(encoding::EncodingOption::kHexadecimal, 128));
209   message.AddOutputEncoding(
210       encoding::EncodingOption(encoding::EncodingOption::kQRCode, 512));
211 
212   adapter_.SendOptionsMessage(message);
213 }
214 
215 // Verifies that a PairingRequestMessage is successfully sent over the
216 // interface.
TEST_F(ProtobufWireAdapterTest,SendPairingRequestMessage)217 TEST_F(ProtobufWireAdapterTest, SendPairingRequestMessage) {
218   InSequence sequence;
219 
220   PairingRequest proto;
221   proto.set_client_name("foo-client");
222   proto.set_service_name("foo-service");
223 
224   OuterMessage outer;
225   outer.set_type(OuterMessage_MessageType_MESSAGE_TYPE_PAIRING_REQUEST);
226   outer.set_payload(proto.SerializeAsString());
227   outer.set_protocol_version(1);
228   outer.set_status(OuterMessage_Status_STATUS_OK);
229 
230   ExpectSend(outer);
231 
232   pairing::message::PairingRequestMessage message("foo-service", "foo-client");
233   adapter_.SendPairingRequestMessage(message);
234 }
235 
236 // Verifies that a SendPairingRequestAckMesssage is successfully sent over the
237 // interface.
TEST_F(ProtobufWireAdapterTest,SendPairingRequestAckMessage)238 TEST_F(ProtobufWireAdapterTest, SendPairingRequestAckMessage) {
239   InSequence sequence;
240 
241   PairingRequestAck proto;
242   proto.set_server_name("foo-server");
243 
244   OuterMessage outer;
245   outer.set_type(OuterMessage_MessageType_MESSAGE_TYPE_PAIRING_REQUEST_ACK);
246   outer.set_payload(proto.SerializeAsString());
247   outer.set_protocol_version(1);
248   outer.set_status(OuterMessage_Status_STATUS_OK);
249 
250   ExpectSend(outer);
251 
252   pairing::message::PairingRequestAckMessage message("foo-server");
253   adapter_.SendPairingRequestAckMessage(message);
254 }
255 
256 // Verifies that a SecretMessage is successfully sent over the interface.
TEST_F(ProtobufWireAdapterTest,SendSecretMessage)257 TEST_F(ProtobufWireAdapterTest, SendSecretMessage) {
258   InSequence sequence;
259 
260   std::vector<unsigned char> secret(4);
261   secret[0] = 0xAA;
262   secret[1] = 0xBB;
263   secret[2] = 0xCC;
264   secret[3] = 0xDD;
265 
266   Secret proto;
267   proto.set_secret(&secret[0], secret.size());
268 
269   OuterMessage outer;
270   outer.set_type(OuterMessage_MessageType_MESSAGE_TYPE_SECRET);
271   outer.set_payload(proto.SerializeAsString());
272   outer.set_protocol_version(1);
273   outer.set_status(OuterMessage_Status_STATUS_OK);
274 
275   ExpectSend(outer);
276 
277   pairing::message::SecretMessage message(secret);
278   adapter_.SendSecretMessage(message);
279 }
280 
281 // Verifies that a SecretAckMessage is successfully sent over the interface.
TEST_F(ProtobufWireAdapterTest,SendSecretAckMessage)282 TEST_F(ProtobufWireAdapterTest, SendSecretAckMessage) {
283   InSequence sequence;
284 
285   std::vector<unsigned char> secret(4);
286   secret[0] = 0xAA;
287   secret[1] = 0xBB;
288   secret[2] = 0xCC;
289   secret[3] = 0xDD;
290 
291   SecretAck proto;
292   proto.set_secret(&secret[0], secret.size());
293 
294   OuterMessage outer;
295   outer.set_type(OuterMessage_MessageType_MESSAGE_TYPE_SECRET_ACK);
296   outer.set_payload(proto.SerializeAsString());
297   outer.set_protocol_version(1);
298   outer.set_status(OuterMessage_Status_STATUS_OK);
299 
300   ExpectSend(outer);
301 
302   pairing::message::SecretAckMessage message(secret);
303   adapter_.SendSecretAckMessage(message);
304 }
305 
306 // Verifies that an ErrorMessage is successfully sent over the interface.
TEST_F(ProtobufWireAdapterTest,SendErrorMessage)307 TEST_F(ProtobufWireAdapterTest, SendErrorMessage) {
308   InSequence sequence;
309 
310   OuterMessage outer;
311   outer.set_protocol_version(1);
312   outer.set_status(OuterMessage_Status_STATUS_BAD_SECRET);
313 
314   ExpectSend(outer);
315 
316   adapter_.SendErrorMessage(pairing::kErrorInvalidChallengeResponse);
317 }
318 
319 }  // namespace protobuf
320 }  // namespace wire
321 }  // namespace polo
322