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