// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "core/internal/offline_frames.h" #include #include #include #include #include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" #include "gmock/gmock.h" #include "gtest/gtest.h" namespace location { namespace nearby { namespace connections { namespace parser { namespace { using Medium = proto::connections::Medium; using ::testing::EqualsProto; constexpr absl::string_view kEndpointId{"ABC"}; constexpr absl::string_view kEndpointName{"XYZ"}; constexpr int kNonce = 1234; constexpr bool kSupports5ghz = true; constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"}; constexpr std::array kMediums = { Medium::MDNS, Medium::BLUETOOTH, Medium::WIFI_HOTSPOT, Medium::BLE, Medium::WIFI_LAN, Medium::WIFI_AWARE, Medium::NFC, Medium::WIFI_DIRECT, Medium::WEB_RTC, }; TEST(OfflineFramesTest, CanParseMessageFromBytes) { OfflineFrame tx_message; { tx_message.set_version(OfflineFrame::V1); auto* v1_frame = tx_message.mutable_v1(); auto* sub_frame = v1_frame->mutable_connection_request(); v1_frame->set_type(V1Frame::CONNECTION_REQUEST); sub_frame->set_endpoint_id(kEndpointId); sub_frame->set_endpoint_name(kEndpointName); sub_frame->set_endpoint_info(kEndpointName); sub_frame->set_nonce(kNonce); auto* medium_metadata = sub_frame->mutable_medium_metadata(); medium_metadata->set_supports_5_ghz(kSupports5ghz); medium_metadata->set_bssid(kBssid); for (auto& medium : kMediums) { sub_frame->add_mediums(MediumToConnectionRequestMedium(medium)); } } auto serialized_bytes = ByteArray(tx_message.SerializeAsString()); auto ret_value = FromBytes(serialized_bytes); ASSERT_TRUE(ret_value.ok()); const auto& rx_message = ret_value.result(); EXPECT_THAT(rx_message, EqualsProto(tx_message)); EXPECT_EQ(GetFrameType(rx_message), V1Frame::CONNECTION_REQUEST); EXPECT_EQ( ConnectionRequestMediumsToMediums(rx_message.v1().connection_request()), std::vector(kMediums.begin(), kMediums.end())); } TEST(OfflineFramesTest, CanGenerateConnectionRequest) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: CONNECTION_REQUEST connection_request: < endpoint_id: "ABC" endpoint_name: "XYZ" endpoint_info: "XYZ" nonce: 1234 medium_metadata: < supports_5_ghz: true bssid: "FF:FF:FF:FF:FF:FF" > mediums: MDNS mediums: BLUETOOTH mediums: WIFI_HOTSPOT mediums: BLE mediums: WIFI_LAN mediums: WIFI_AWARE mediums: NFC mediums: WIFI_DIRECT mediums: WEB_RTC > >)pb"; ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, kSupports5ghz, std::string(kBssid), std::vector(kMediums.begin(), kMediums.end())); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateConnectionResponse) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: CONNECTION_RESPONSE connection_response: < status: 1 response: REJECT > >)pb"; ByteArray bytes = ForConnectionResponse(1); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateControlPayloadTransfer) { PayloadTransferFrame::PayloadHeader header; PayloadTransferFrame::ControlMessage control; header.set_id(12345); header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); header.set_total_size(1024); control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); control.set_offset(150); constexpr char kExpected[] = R"pb( version: V1 v1: < type: PAYLOAD_TRANSFER payload_transfer: < packet_type: CONTROL, payload_header: < type: BYTES id: 12345 total_size: 1024 > control_message: < event: PAYLOAD_CANCELED offset: 150 > > >)pb"; ByteArray bytes = ForControlPayloadTransfer(header, control); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateDataPayloadTransfer) { PayloadTransferFrame::PayloadHeader header; PayloadTransferFrame::PayloadChunk chunk; header.set_id(12345); header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); header.set_total_size(1024); chunk.set_body("payload data"); chunk.set_offset(150); chunk.set_flags(1); constexpr char kExpected[] = R"pb( version: V1 v1: < type: PAYLOAD_TRANSFER payload_transfer: < packet_type: DATA, payload_header: < type: BYTES id: 12345 total_size: 1024 > payload_chunk: < flags: 1 offset: 150 body: "payload data" > > >)pb"; ByteArray bytes = ForDataPayloadTransfer(header, chunk); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateBwuWifiHotspotPathAvailable) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: BANDWIDTH_UPGRADE_NEGOTIATION bandwidth_upgrade_negotiation: < event_type: UPGRADE_PATH_AVAILABLE upgrade_path_info: < medium: WIFI_HOTSPOT wifi_hotspot_credentials: < ssid: "ssid" password: "password" port: 1234 gateway: "0.0.0.0" > supports_disabling_encryption: false supports_client_introduction_ack: true > > >)pb"; ByteArray bytes = ForBwuWifiHotspotPathAvailable("ssid", "password", 1234, "0.0.0.0", false); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateBwuWifiLanPathAvailable) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: BANDWIDTH_UPGRADE_NEGOTIATION bandwidth_upgrade_negotiation: < event_type: UPGRADE_PATH_AVAILABLE upgrade_path_info: < medium: WIFI_LAN wifi_lan_socket: < ip_address: "\x01\x02\x03\x04" wifi_port: 1234 > supports_client_introduction_ack: true > > >)pb"; ByteArray bytes = ForBwuWifiLanPathAvailable("\x01\x02\x03\x04", 1234); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateBwuWifiAwarePathAvailable) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: BANDWIDTH_UPGRADE_NEGOTIATION bandwidth_upgrade_negotiation: < event_type: UPGRADE_PATH_AVAILABLE upgrade_path_info: < medium: WIFI_AWARE wifi_aware_credentials: < service_id: "service_id" service_info: "service_info" password: "password" > supports_disabling_encryption: false supports_client_introduction_ack: true > > >)pb"; ByteArray bytes = ForBwuWifiAwarePathAvailable("service_id", "service_info", "password", false); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateBwuWifiDirectPathAvailable) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: BANDWIDTH_UPGRADE_NEGOTIATION bandwidth_upgrade_negotiation: < event_type: UPGRADE_PATH_AVAILABLE upgrade_path_info: < medium: WIFI_DIRECT wifi_direct_credentials: < ssid: "DIRECT-A0-0123456789AB" password: "password" port: 1000 frequency: 1000 > supports_disabling_encryption: false supports_client_introduction_ack: true > > >)pb"; ByteArray bytes = ForBwuWifiDirectPathAvailable( "DIRECT-A0-0123456789AB", "password", 1000, 1000, false); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateBwuBluetoothPathAvailable) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: BANDWIDTH_UPGRADE_NEGOTIATION bandwidth_upgrade_negotiation: < event_type: UPGRADE_PATH_AVAILABLE upgrade_path_info: < medium: BLUETOOTH bluetooth_credentials: < service_name: "service" mac_address: "\x11\x22\x33\x44\x55\x66" > supports_client_introduction_ack: true > > >)pb"; ByteArray bytes = ForBwuBluetoothPathAvailable("service", "\x11\x22\x33\x44\x55\x66"); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateBwuLastWrite) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: BANDWIDTH_UPGRADE_NEGOTIATION bandwidth_upgrade_negotiation: < event_type: LAST_WRITE_TO_PRIOR_CHANNEL > >)pb"; ByteArray bytes = ForBwuLastWrite(); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateBwuSafeToClose) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: BANDWIDTH_UPGRADE_NEGOTIATION bandwidth_upgrade_negotiation: < event_type: SAFE_TO_CLOSE_PRIOR_CHANNEL > >)pb"; ByteArray bytes = ForBwuSafeToClose(); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateBwuIntroduction) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: BANDWIDTH_UPGRADE_NEGOTIATION bandwidth_upgrade_negotiation: < event_type: CLIENT_INTRODUCTION client_introduction: < endpoint_id: "ABC" > > >)pb"; ByteArray bytes = ForBwuIntroduction(std::string(kEndpointId)); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } TEST(OfflineFramesTest, CanGenerateKeepAlive) { constexpr char kExpected[] = R"pb( version: V1 v1: < type: KEEP_ALIVE keep_alive: <> >)pb"; ByteArray bytes = ForKeepAlive(); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); EXPECT_THAT(message, EqualsProto(kExpected)); } } // namespace } // namespace parser } // namespace connections } // namespace nearby } // namespace location