1 // Copyright 2020 Google LLC
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 //     https://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 #include "core/internal/offline_frames.h"
16 
17 #include <array>
18 #include <memory>
19 #include <utility>
20 #include <vector>
21 
22 #include "proto/connections/offline_wire_formats.pb.h"
23 #include "platform/base/byte_array.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 
27 namespace location {
28 namespace nearby {
29 namespace connections {
30 namespace parser {
31 namespace {
32 
33 using Medium = proto::connections::Medium;
34 using ::testing::EqualsProto;
35 
36 constexpr absl::string_view kEndpointId{"ABC"};
37 constexpr absl::string_view kEndpointName{"XYZ"};
38 constexpr int kNonce = 1234;
39 constexpr bool kSupports5ghz = true;
40 constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"};
41 constexpr std::array<Medium, 9> kMediums = {
42     Medium::MDNS, Medium::BLUETOOTH,   Medium::WIFI_HOTSPOT,
43     Medium::BLE,  Medium::WIFI_LAN,    Medium::WIFI_AWARE,
44     Medium::NFC,  Medium::WIFI_DIRECT, Medium::WEB_RTC,
45 };
46 
TEST(OfflineFramesTest,CanParseMessageFromBytes)47 TEST(OfflineFramesTest, CanParseMessageFromBytes) {
48   OfflineFrame tx_message;
49 
50   {
51     tx_message.set_version(OfflineFrame::V1);
52     auto* v1_frame = tx_message.mutable_v1();
53     auto* sub_frame = v1_frame->mutable_connection_request();
54 
55     v1_frame->set_type(V1Frame::CONNECTION_REQUEST);
56     sub_frame->set_endpoint_id(kEndpointId);
57     sub_frame->set_endpoint_name(kEndpointName);
58     sub_frame->set_endpoint_info(kEndpointName);
59     sub_frame->set_nonce(kNonce);
60     auto* medium_metadata = sub_frame->mutable_medium_metadata();
61 
62     medium_metadata->set_supports_5_ghz(kSupports5ghz);
63     medium_metadata->set_bssid(kBssid);
64 
65     for (auto& medium : kMediums) {
66       sub_frame->add_mediums(MediumToConnectionRequestMedium(medium));
67     }
68   }
69   auto serialized_bytes = ByteArray(tx_message.SerializeAsString());
70   auto ret_value = FromBytes(serialized_bytes);
71   ASSERT_TRUE(ret_value.ok());
72   const auto& rx_message = ret_value.result();
73   EXPECT_THAT(rx_message, EqualsProto(tx_message));
74   EXPECT_EQ(GetFrameType(rx_message), V1Frame::CONNECTION_REQUEST);
75   EXPECT_EQ(
76       ConnectionRequestMediumsToMediums(rx_message.v1().connection_request()),
77       std::vector(kMediums.begin(), kMediums.end()));
78 }
79 
TEST(OfflineFramesTest,CanGenerateConnectionRequest)80 TEST(OfflineFramesTest, CanGenerateConnectionRequest) {
81   constexpr char kExpected[] =
82       R"pb(
83     version: V1
84     v1: <
85       type: CONNECTION_REQUEST
86       connection_request: <
87         endpoint_id: "ABC"
88         endpoint_name: "XYZ"
89         endpoint_info: "XYZ"
90         nonce: 1234
91         medium_metadata: <
92           supports_5_ghz: true
93           bssid: "FF:FF:FF:FF:FF:FF"
94         >
95         mediums: MDNS
96         mediums: BLUETOOTH
97         mediums: WIFI_HOTSPOT
98         mediums: BLE
99         mediums: WIFI_LAN
100         mediums: WIFI_AWARE
101         mediums: NFC
102         mediums: WIFI_DIRECT
103         mediums: WEB_RTC
104       >
105     >)pb";
106   ByteArray bytes = ForConnectionRequest(
107       std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
108       kSupports5ghz, std::string(kBssid),
109       std::vector(kMediums.begin(), kMediums.end()));
110   auto response = FromBytes(bytes);
111   ASSERT_TRUE(response.ok());
112   OfflineFrame message = FromBytes(bytes).result();
113   EXPECT_THAT(message, EqualsProto(kExpected));
114 }
115 
TEST(OfflineFramesTest,CanGenerateConnectionResponse)116 TEST(OfflineFramesTest, CanGenerateConnectionResponse) {
117   constexpr char kExpected[] =
118       R"pb(
119     version: V1
120     v1: <
121       type: CONNECTION_RESPONSE
122       connection_response: <
123         status: 1
124         response: REJECT
125       >
126     >)pb";
127   ByteArray bytes = ForConnectionResponse(1);
128   auto response = FromBytes(bytes);
129   ASSERT_TRUE(response.ok());
130   OfflineFrame message = FromBytes(bytes).result();
131   EXPECT_THAT(message, EqualsProto(kExpected));
132 }
133 
TEST(OfflineFramesTest,CanGenerateControlPayloadTransfer)134 TEST(OfflineFramesTest, CanGenerateControlPayloadTransfer) {
135   PayloadTransferFrame::PayloadHeader header;
136   PayloadTransferFrame::ControlMessage control;
137   header.set_id(12345);
138   header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
139   header.set_total_size(1024);
140   control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED);
141   control.set_offset(150);
142 
143   constexpr char kExpected[] =
144       R"pb(
145     version: V1
146     v1: <
147       type: PAYLOAD_TRANSFER
148       payload_transfer: <
149         packet_type: CONTROL,
150         payload_header: < type: BYTES id: 12345 total_size: 1024 >
151         control_message: < event: PAYLOAD_CANCELED offset: 150 >
152       >
153     >)pb";
154   ByteArray bytes = ForControlPayloadTransfer(header, control);
155   auto response = FromBytes(bytes);
156   ASSERT_TRUE(response.ok());
157   OfflineFrame message = FromBytes(bytes).result();
158   EXPECT_THAT(message, EqualsProto(kExpected));
159 }
160 
TEST(OfflineFramesTest,CanGenerateDataPayloadTransfer)161 TEST(OfflineFramesTest, CanGenerateDataPayloadTransfer) {
162   PayloadTransferFrame::PayloadHeader header;
163   PayloadTransferFrame::PayloadChunk chunk;
164   header.set_id(12345);
165   header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
166   header.set_total_size(1024);
167   chunk.set_body("payload data");
168   chunk.set_offset(150);
169   chunk.set_flags(1);
170 
171   constexpr char kExpected[] =
172       R"pb(
173     version: V1
174     v1: <
175       type: PAYLOAD_TRANSFER
176       payload_transfer: <
177         packet_type: DATA,
178         payload_header: < type: BYTES id: 12345 total_size: 1024 >
179         payload_chunk: < flags: 1 offset: 150 body: "payload data" >
180       >
181     >)pb";
182   ByteArray bytes = ForDataPayloadTransfer(header, chunk);
183   auto response = FromBytes(bytes);
184   ASSERT_TRUE(response.ok());
185   OfflineFrame message = FromBytes(bytes).result();
186   EXPECT_THAT(message, EqualsProto(kExpected));
187 }
188 
TEST(OfflineFramesTest,CanGenerateBwuWifiHotspotPathAvailable)189 TEST(OfflineFramesTest, CanGenerateBwuWifiHotspotPathAvailable) {
190   constexpr char kExpected[] =
191       R"pb(
192     version: V1
193     v1: <
194       type: BANDWIDTH_UPGRADE_NEGOTIATION
195       bandwidth_upgrade_negotiation: <
196         event_type: UPGRADE_PATH_AVAILABLE
197         upgrade_path_info: <
198           medium: WIFI_HOTSPOT
199           wifi_hotspot_credentials: <
200             ssid: "ssid"
201             password: "password"
202             port: 1234
203             gateway: "0.0.0.0"
204           >
205           supports_disabling_encryption: false
206         >
207       >
208     >)pb";
209   ByteArray bytes = ForBwuWifiHotspotPathAvailable("ssid", "password", 1234,
210                                                    "0.0.0.0", false);
211   auto response = FromBytes(bytes);
212   ASSERT_TRUE(response.ok());
213   OfflineFrame message = FromBytes(bytes).result();
214   EXPECT_THAT(message, EqualsProto(kExpected));
215 }
216 
TEST(OfflineFramesTest,CanGenerateBwuWifiLanPathAvailable)217 TEST(OfflineFramesTest, CanGenerateBwuWifiLanPathAvailable) {
218   constexpr char kExpected[] =
219       R"pb(
220     version: V1
221     v1: <
222       type: BANDWIDTH_UPGRADE_NEGOTIATION
223       bandwidth_upgrade_negotiation: <
224         event_type: UPGRADE_PATH_AVAILABLE
225         upgrade_path_info: <
226           medium: WIFI_LAN
227           wifi_lan_socket: < ip_address: "\x01\x02\x03\x04" wifi_port: 1234 >
228         >
229       >
230     >)pb";
231   ByteArray bytes = ForBwuWifiLanPathAvailable("\x01\x02\x03\x04", 1234);
232   auto response = FromBytes(bytes);
233   ASSERT_TRUE(response.ok());
234   OfflineFrame message = FromBytes(bytes).result();
235   EXPECT_THAT(message, EqualsProto(kExpected));
236 }
237 
TEST(OfflineFramesTest,CanGenerateBwuWifiAwarePathAvailable)238 TEST(OfflineFramesTest, CanGenerateBwuWifiAwarePathAvailable) {
239   constexpr char kExpected[] =
240       R"pb(
241     version: V1
242     v1: <
243       type: BANDWIDTH_UPGRADE_NEGOTIATION
244       bandwidth_upgrade_negotiation: <
245         event_type: UPGRADE_PATH_AVAILABLE
246         upgrade_path_info: <
247           medium: WIFI_AWARE
248           wifi_aware_credentials: <
249             service_id: "service_id"
250             service_info: "service_info"
251             password: "password"
252           >
253           supports_disabling_encryption: false
254         >
255       >
256     >)pb";
257   ByteArray bytes = ForBwuWifiAwarePathAvailable("service_id", "service_info",
258                                                  "password", false);
259   auto response = FromBytes(bytes);
260   ASSERT_TRUE(response.ok());
261   OfflineFrame message = FromBytes(bytes).result();
262   EXPECT_THAT(message, EqualsProto(kExpected));
263 }
264 
TEST(OfflineFramesTest,CanGenerateBwuWifiDirectPathAvailable)265 TEST(OfflineFramesTest, CanGenerateBwuWifiDirectPathAvailable) {
266   constexpr char kExpected[] =
267       R"pb(
268     version: V1
269     v1: <
270       type: BANDWIDTH_UPGRADE_NEGOTIATION
271       bandwidth_upgrade_negotiation: <
272         event_type: UPGRADE_PATH_AVAILABLE
273         upgrade_path_info: <
274           medium: WIFI_DIRECT
275           wifi_direct_credentials: <
276             ssid: "DIRECT-A0-0123456789AB"
277             password: "password"
278             port: 1000
279             frequency: 1000
280           >
281           supports_disabling_encryption: false
282         >
283       >
284     >)pb";
285   ByteArray bytes = ForBwuWifiDirectPathAvailable(
286       "DIRECT-A0-0123456789AB", "password", 1000, 1000, false);
287   auto response = FromBytes(bytes);
288   ASSERT_TRUE(response.ok());
289   OfflineFrame message = FromBytes(bytes).result();
290   EXPECT_THAT(message, EqualsProto(kExpected));
291 }
292 
TEST(OfflineFramesTest,CanGenerateBwuBluetoothPathAvailable)293 TEST(OfflineFramesTest, CanGenerateBwuBluetoothPathAvailable) {
294   constexpr char kExpected[] =
295       R"pb(
296     version: V1
297     v1: <
298       type: BANDWIDTH_UPGRADE_NEGOTIATION
299       bandwidth_upgrade_negotiation: <
300         event_type: UPGRADE_PATH_AVAILABLE
301         upgrade_path_info: <
302           medium: BLUETOOTH
303           bluetooth_credentials: <
304             service_name: "service"
305             mac_address: "\x11\x22\x33\x44\x55\x66"
306           >
307         >
308       >
309     >)pb";
310   ByteArray bytes =
311       ForBwuBluetoothPathAvailable("service", "\x11\x22\x33\x44\x55\x66");
312   auto response = FromBytes(bytes);
313   ASSERT_TRUE(response.ok());
314   OfflineFrame message = FromBytes(bytes).result();
315   EXPECT_THAT(message, EqualsProto(kExpected));
316 }
317 
TEST(OfflineFramesTest,CanGenerateBwuLastWrite)318 TEST(OfflineFramesTest, CanGenerateBwuLastWrite) {
319   constexpr char kExpected[] =
320       R"pb(
321     version: V1
322     v1: <
323       type: BANDWIDTH_UPGRADE_NEGOTIATION
324       bandwidth_upgrade_negotiation: < event_type: LAST_WRITE_TO_PRIOR_CHANNEL >
325     >)pb";
326   ByteArray bytes = ForBwuLastWrite();
327   auto response = FromBytes(bytes);
328   ASSERT_TRUE(response.ok());
329   OfflineFrame message = FromBytes(bytes).result();
330   EXPECT_THAT(message, EqualsProto(kExpected));
331 }
332 
TEST(OfflineFramesTest,CanGenerateBwuSafeToClose)333 TEST(OfflineFramesTest, CanGenerateBwuSafeToClose) {
334   constexpr char kExpected[] =
335       R"pb(
336     version: V1
337     v1: <
338       type: BANDWIDTH_UPGRADE_NEGOTIATION
339       bandwidth_upgrade_negotiation: < event_type: SAFE_TO_CLOSE_PRIOR_CHANNEL >
340     >)pb";
341   ByteArray bytes = ForBwuSafeToClose();
342   auto response = FromBytes(bytes);
343   ASSERT_TRUE(response.ok());
344   OfflineFrame message = FromBytes(bytes).result();
345   EXPECT_THAT(message, EqualsProto(kExpected));
346 }
347 
TEST(OfflineFramesTest,CanGenerateBwuIntroduction)348 TEST(OfflineFramesTest, CanGenerateBwuIntroduction) {
349   constexpr char kExpected[] =
350       R"pb(
351     version: V1
352     v1: <
353       type: BANDWIDTH_UPGRADE_NEGOTIATION
354       bandwidth_upgrade_negotiation: <
355         event_type: CLIENT_INTRODUCTION
356         client_introduction: < endpoint_id: "ABC" >
357       >
358     >)pb";
359   ByteArray bytes = ForBwuIntroduction(std::string(kEndpointId));
360   auto response = FromBytes(bytes);
361   ASSERT_TRUE(response.ok());
362   OfflineFrame message = FromBytes(bytes).result();
363   EXPECT_THAT(message, EqualsProto(kExpected));
364 }
365 
TEST(OfflineFramesTest,CanGenerateKeepAlive)366 TEST(OfflineFramesTest, CanGenerateKeepAlive) {
367   constexpr char kExpected[] =
368       R"pb(
369     version: V1
370     v1: <
371       type: KEEP_ALIVE
372       keep_alive: <>
373     >)pb";
374   ByteArray bytes = ForKeepAlive();
375   auto response = FromBytes(bytes);
376   ASSERT_TRUE(response.ok());
377   OfflineFrame message = FromBytes(bytes).result();
378   EXPECT_THAT(message, EqualsProto(kExpected));
379 }
380 
381 }  // namespace
382 }  // namespace parser
383 }  // namespace connections
384 }  // namespace nearby
385 }  // namespace location
386