mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-15 07:06:11 -04:00
358 lines
14 KiB
C++
358 lines
14 KiB
C++
// Copyright 2025 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 "connections/implementation/wifi_lan_bwu_handler.h"
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
|
#include "gtest/gtest.h"
|
|
#include "absl/strings/string_view.h"
|
|
#include "connections/implementation/bwu_handler.h"
|
|
#include "connections/implementation/client_proxy.h"
|
|
#include "connections/implementation/mediums/mediums.h"
|
|
#include "connections/strategy.h"
|
|
#include "internal/analytics/mock_event_logger.h"
|
|
#include "internal/analytics/sharing_log_matchers.h"
|
|
#include "internal/platform/implementation/platform.h"
|
|
#include "internal/platform/implementation/upgrade_address_info.h"
|
|
#include "internal/platform/implementation/wifi_lan.h"
|
|
#include "internal/platform/medium_environment.h"
|
|
#include "internal/platform/mock_input_stream.h"
|
|
#include "internal/platform/mock_output_stream.h"
|
|
#include "internal/platform/mock_wifi_lan_medium.h"
|
|
#include "internal/platform/mock_wifi_lan_server_socket.h"
|
|
#include "internal/platform/mock_wifi_lan_socket.h"
|
|
#include "internal/platform/service_address.h"
|
|
#include "internal/proto/analytics/connections_log.pb.h"
|
|
|
|
namespace nearby {
|
|
|
|
MockWifiLanMedium* wifi_lan_medium = nullptr;
|
|
|
|
namespace connections {
|
|
namespace {
|
|
using ::location::nearby::analytics::proto::ConnectionsLog;
|
|
using ::location::nearby::connections::BandwidthUpgradeNegotiationFrame;
|
|
using ::location::nearby::connections::OfflineFrame;
|
|
using ::location::nearby::connections::V1Frame;
|
|
using ::location::nearby::proto::connections::EventType;
|
|
using ::location::nearby::proto::connections::OperationResultCode;
|
|
using ::nearby::analytics::HasEventType;
|
|
using ::testing::_;
|
|
using ::testing::ByMove;
|
|
using ::protobuf_matchers::EqualsProto;
|
|
using ::testing::InSequence;
|
|
using ::testing::Matcher;
|
|
using ::testing::MockFunction;
|
|
using ::testing::Return;
|
|
using ::testing::ReturnRef;
|
|
|
|
constexpr absl::string_view kIpv4Address{"\xc0\xa8\x00\x01", 4};
|
|
constexpr absl::string_view kIpv6Address{
|
|
"\x2a\x00\x79\xe0\x2e\x87\x00\x06\xb7\x28\x67\x45\x7a\xdd\x01\x53", 16};
|
|
constexpr absl::string_view kServiceId{"service_id"};
|
|
constexpr absl::string_view kEndpointId{"endpoint_id"};
|
|
|
|
class WifiLanBwuHandlerTest : public ::testing::Test {
|
|
protected:
|
|
WifiLanBwuHandlerTest()
|
|
: handler_(mediums_, incoming_connection_callback_.AsStdFunction()) {}
|
|
|
|
Mediums mediums_;
|
|
MockFunction<void(ClientProxy*,
|
|
std::unique_ptr<BwuHandler::IncomingSocketConnection>)>
|
|
incoming_connection_callback_;
|
|
WifiLanBwuHandler handler_;
|
|
nearby::analytics::MockEventLogger mock_event_logger_;
|
|
};
|
|
|
|
TEST_F(WifiLanBwuHandlerTest,
|
|
CreateUpgradedEndpointChannel_EmptyPathInfo_Fails) {
|
|
ClientProxy client(&mock_event_logger_);
|
|
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
|
// Create an empty wifi_lan_socket.
|
|
path_info.mutable_wifi_lan_socket();
|
|
|
|
auto result = handler_.CreateUpgradedEndpointChannel(
|
|
&client, "service_id", "endpoint_id", std::move(path_info));
|
|
|
|
ASSERT_TRUE(result.has_error());
|
|
EXPECT_EQ(result.error().operation_result_code().value(),
|
|
OperationResultCode::CONNECTIVITY_WIFI_LAN_IP_ADDRESS_ERROR);
|
|
};
|
|
|
|
TEST_F(WifiLanBwuHandlerTest, CreateUpgradedEndpointChannel_IpAddress_Success) {
|
|
ClientProxy client(&mock_event_logger_);
|
|
client.AddCancellationFlag(std::string(kEndpointId));
|
|
MockInputStream input_stream;
|
|
MockOutputStream output_stream;
|
|
auto wifi_lan_socket = std::make_unique<MockWifiLanSocket>();
|
|
EXPECT_CALL(*wifi_lan_socket, GetInputStream())
|
|
.WillRepeatedly(ReturnRef(input_stream));
|
|
EXPECT_CALL(*wifi_lan_socket, GetOutputStream())
|
|
.WillRepeatedly(ReturnRef(output_stream));
|
|
EXPECT_CALL(*wifi_lan_medium, IsNetworkConnected())
|
|
.WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*wifi_lan_medium,
|
|
ConnectToService(
|
|
ServiceAddress{
|
|
.address = {kIpv4Address.begin(), kIpv4Address.end()},
|
|
.port = 8080,
|
|
},
|
|
_))
|
|
.WillOnce(Return(ByMove(std::move(wifi_lan_socket))));
|
|
|
|
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
|
path_info.mutable_wifi_lan_socket()->set_ip_address(kIpv4Address);
|
|
path_info.mutable_wifi_lan_socket()->set_wifi_port(8080);
|
|
|
|
auto result = handler_.CreateUpgradedEndpointChannel(
|
|
&client, std::string(kServiceId), std::string(kEndpointId),
|
|
std::move(path_info));
|
|
|
|
EXPECT_TRUE(result.has_value());
|
|
};
|
|
|
|
TEST_F(WifiLanBwuHandlerTest,
|
|
CreateUpgradedEndpointChannel_AddressCandidates_FirstCandidate_Success) {
|
|
ClientProxy client(&mock_event_logger_);
|
|
client.AddCancellationFlag(std::string(kEndpointId));
|
|
MockInputStream input_stream;
|
|
MockOutputStream output_stream;
|
|
auto wifi_lan_socket = std::make_unique<MockWifiLanSocket>();
|
|
EXPECT_CALL(*wifi_lan_socket, GetInputStream())
|
|
.WillRepeatedly(ReturnRef(input_stream));
|
|
EXPECT_CALL(*wifi_lan_socket, GetOutputStream())
|
|
.WillRepeatedly(ReturnRef(output_stream));
|
|
EXPECT_CALL(*wifi_lan_medium, IsNetworkConnected())
|
|
.WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*wifi_lan_medium,
|
|
ConnectToService(
|
|
ServiceAddress{
|
|
.address = {kIpv6Address.begin(), kIpv6Address.end()},
|
|
.port = 8080,
|
|
},
|
|
_))
|
|
.WillOnce(Return(ByMove(std::move(wifi_lan_socket))));
|
|
|
|
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
|
auto* address_candidate =
|
|
path_info.mutable_wifi_lan_socket()->add_address_candidates();
|
|
address_candidate->set_ip_address(kIpv6Address);
|
|
address_candidate->set_port(8080);
|
|
address_candidate =
|
|
path_info.mutable_wifi_lan_socket()->add_address_candidates();
|
|
address_candidate->set_ip_address(kIpv4Address);
|
|
address_candidate->set_port(8080);
|
|
|
|
auto result = handler_.CreateUpgradedEndpointChannel(
|
|
&client, std::string(kServiceId), std::string(kEndpointId),
|
|
std::move(path_info));
|
|
|
|
EXPECT_TRUE(result.has_value());
|
|
};
|
|
|
|
TEST_F(WifiLanBwuHandlerTest,
|
|
CreateUpgradedEndpointChannel_AddressCandidates_FirstCandidate_Fails) {
|
|
ClientProxy client(&mock_event_logger_);
|
|
client.AddCancellationFlag(std::string(kEndpointId));
|
|
MockInputStream input_stream;
|
|
MockOutputStream output_stream;
|
|
auto wifi_lan_socket = std::make_unique<MockWifiLanSocket>();
|
|
EXPECT_CALL(*wifi_lan_socket, GetInputStream())
|
|
.WillRepeatedly(ReturnRef(input_stream));
|
|
EXPECT_CALL(*wifi_lan_socket, GetOutputStream())
|
|
.WillRepeatedly(ReturnRef(output_stream));
|
|
EXPECT_CALL(*wifi_lan_medium, IsNetworkConnected())
|
|
.WillRepeatedly(Return(true));
|
|
InSequence seq;
|
|
EXPECT_CALL(*wifi_lan_medium,
|
|
ConnectToService(
|
|
ServiceAddress{
|
|
.address = {kIpv6Address.begin(), kIpv6Address.end()},
|
|
.port = 8080,
|
|
},
|
|
_))
|
|
.WillOnce(Return(ByMove(nullptr)));
|
|
EXPECT_CALL(*wifi_lan_medium,
|
|
ConnectToService(
|
|
ServiceAddress{
|
|
.address = {kIpv4Address.begin(), kIpv4Address.end()},
|
|
.port = 8080,
|
|
},
|
|
_))
|
|
.WillOnce(Return(ByMove(std::move(wifi_lan_socket))));
|
|
|
|
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
|
auto* address_candidate =
|
|
path_info.mutable_wifi_lan_socket()->add_address_candidates();
|
|
address_candidate->set_ip_address(kIpv6Address);
|
|
address_candidate->set_port(8080);
|
|
address_candidate =
|
|
path_info.mutable_wifi_lan_socket()->add_address_candidates();
|
|
address_candidate->set_ip_address(kIpv4Address);
|
|
address_candidate->set_port(8080);
|
|
|
|
auto result = handler_.CreateUpgradedEndpointChannel(
|
|
&client, std::string(kServiceId), std::string(kEndpointId),
|
|
std::move(path_info));
|
|
|
|
EXPECT_TRUE(result.has_value());
|
|
};
|
|
|
|
TEST_F(WifiLanBwuHandlerTest, InitializeUpgradedMediumForEndpoint_Success) {
|
|
MediumEnvironment::Instance().Start({.use_simulated_clock = true});
|
|
ClientProxy client(&mock_event_logger_);
|
|
client.GetAnalyticsRecorder().OnStartAdvertising(
|
|
Strategy::kP2pPointToPoint,
|
|
{location::nearby::proto::connections::Medium::BLUETOOTH},
|
|
/*advertising_metadata_params=*/nullptr);
|
|
client.GetAnalyticsRecorder().OnBandwidthUpgradeStarted(
|
|
std::string(kEndpointId),
|
|
location::nearby::proto::connections::Medium::BLUETOOTH,
|
|
location::nearby::proto::connections::Medium::WIFI_LAN,
|
|
location::nearby::proto::connections::ConnectionAttemptDirection::
|
|
OUTGOING,
|
|
/*connection_token=*/"");
|
|
client.AddCancellationFlag(std::string(kEndpointId));
|
|
auto wifi_lan_server_socket = std::make_unique<MockWifiLanServerSocket>();
|
|
EXPECT_CALL(*wifi_lan_server_socket, GetPort()).WillRepeatedly(Return(8080));
|
|
EXPECT_CALL(*wifi_lan_medium, IsNetworkConnected())
|
|
.WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*wifi_lan_medium, ListenForService(_))
|
|
.WillOnce(Return(ByMove(std::move(wifi_lan_server_socket))));
|
|
EXPECT_CALL(*wifi_lan_medium, GetUpgradeAddressCandidates(_))
|
|
.WillOnce(Return(api::UpgradeAddressInfo{
|
|
.num_interfaces = 1,
|
|
.num_ipv6_only_interfaces = 1,
|
|
.address_candidates = {
|
|
{std::vector<char>{kIpv6Address.begin(), kIpv6Address.end()},
|
|
8080},
|
|
{std::vector<char>{kIpv4Address.begin(), kIpv4Address.end()},
|
|
8888}}}));
|
|
OfflineFrame expected_frame;
|
|
expected_frame.set_version(OfflineFrame::V1);
|
|
expected_frame.mutable_v1()->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION);
|
|
auto* bwu_frame =
|
|
expected_frame.mutable_v1()->mutable_bandwidth_upgrade_negotiation();
|
|
bwu_frame->set_event_type(
|
|
BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE);
|
|
auto* upgrade_path_info = bwu_frame->mutable_upgrade_path_info();
|
|
upgrade_path_info->set_medium(
|
|
BandwidthUpgradeNegotiationFrame::UpgradePathInfo::WIFI_LAN);
|
|
auto* wifi_lan_socket = expected_frame.mutable_v1()
|
|
->mutable_bandwidth_upgrade_negotiation()
|
|
->mutable_upgrade_path_info()
|
|
->mutable_wifi_lan_socket();
|
|
wifi_lan_socket->set_ip_address(kIpv4Address);
|
|
wifi_lan_socket->set_wifi_port(8888);
|
|
auto* address_candidate = wifi_lan_socket->add_address_candidates();
|
|
address_candidate->set_ip_address(kIpv6Address);
|
|
address_candidate->set_port(8080);
|
|
address_candidate = wifi_lan_socket->add_address_candidates();
|
|
address_candidate->set_ip_address(kIpv4Address);
|
|
address_candidate->set_port(8888);
|
|
upgrade_path_info->set_supports_client_introduction_ack(true);
|
|
|
|
std::string result = handler_.InitializeUpgradedMediumForEndpoint(
|
|
&client, std::string(kServiceId), std::string(kEndpointId));
|
|
|
|
EXPECT_FALSE(result.empty());
|
|
OfflineFrame result_frame;
|
|
EXPECT_TRUE(result_frame.ParseFromString(result));
|
|
EXPECT_THAT(result_frame, EqualsProto(expected_frame));
|
|
|
|
constexpr absl::string_view kClientSessionLog = R"pb(
|
|
event_type: CLIENT_SESSION
|
|
client_session { duration_millis: 0 }
|
|
version: "v1.5.0"
|
|
)pb";
|
|
constexpr absl::string_view kExpectedUpgradeLog = R"pb(
|
|
event_type: CLIENT_SESSION
|
|
client_session {
|
|
duration_millis: 0
|
|
strategy_session {
|
|
duration_millis: 0
|
|
strategy: P2P_POINT_TO_POINT
|
|
role: ADVERTISER
|
|
advertising_phase {
|
|
duration_millis: 0
|
|
medium: BLUETOOTH
|
|
advertising_metadata {
|
|
supports_extended_ble_advertisements: false
|
|
connected_ap_frequency: 0
|
|
supports_nfc_technology: false
|
|
}
|
|
stop_reason: FINISH_SESSION_STOP_ADVERTISING
|
|
}
|
|
upgrade_attempt {
|
|
direction: OUTGOING
|
|
duration_millis: 0
|
|
from_medium: BLUETOOTH
|
|
to_medium: WIFI_LAN
|
|
upgrade_result: UNFINISHED_ERROR
|
|
error_stage: UPGRADE_UNFINISHED
|
|
connection_token: ""
|
|
operation_result {
|
|
result_category: CATEGORY_DEVICE_STATE_ERROR
|
|
result_code: DEVICE_STATE_ERROR_UNFINISHED_UPGRADE_ATTEMPTS
|
|
}
|
|
num_interfaces: 1
|
|
num_ipv6_only_interfaces: 1
|
|
}
|
|
}
|
|
}
|
|
version: "v1.5.0"
|
|
)pb";
|
|
EXPECT_CALL(mock_event_logger_,
|
|
Log(Matcher<const ConnectionsLog&>(
|
|
HasEventType(EventType::STOP_STRATEGY_SESSION))))
|
|
.Times(1);
|
|
EXPECT_CALL(mock_event_logger_,
|
|
Log(Matcher<const ConnectionsLog&>(
|
|
HasEventType(EventType::STOP_CLIENT_SESSION))))
|
|
.Times(3);
|
|
EXPECT_CALL(mock_event_logger_,
|
|
Log(Matcher<const ConnectionsLog&>(
|
|
HasEventType(EventType::START_CLIENT_SESSION))))
|
|
.Times(3);
|
|
EXPECT_CALL(
|
|
mock_event_logger_,
|
|
Log(Matcher<const ConnectionsLog&>(EqualsProto(kClientSessionLog))))
|
|
.Times(2);
|
|
EXPECT_CALL(
|
|
mock_event_logger_,
|
|
Log(Matcher<const ConnectionsLog&>(EqualsProto(kExpectedUpgradeLog))));
|
|
// Flush pending logs.
|
|
client.GetAnalyticsRecorder().LogSession();
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace connections
|
|
namespace api {
|
|
|
|
std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
|
|
auto medium = std::make_unique<MockWifiLanMedium>();
|
|
wifi_lan_medium = medium.get();
|
|
return medium;
|
|
}
|
|
|
|
} // namespace api
|
|
} // namespace nearby
|