From b56d18d57748d478a1913cae21676a48832b1f7b Mon Sep 17 00:00:00 2001 From: hai007 Date: Fri, 12 Sep 2025 11:00:34 -0700 Subject: [PATCH] Refactor WifiLanBwuHandler test to improve test coverage. PiperOrigin-RevId: 806350972 --- Package.swift | 1 + connections/implementation/BUILD | 1 + .../implementation/wifi_lan_bwu_handler.cc | 20 +-- .../implementation/wifi_lan_bwu_test.cc | 169 ++++++++++++++++++ internal/platform/implementation/g3/BUILD | 1 + .../platform/implementation/g3/wifi_lan.cc | 43 ++++- .../platform/implementation/g3/wifi_lan.h | 9 +- 7 files changed, 226 insertions(+), 18 deletions(-) create mode 100644 connections/implementation/wifi_lan_bwu_test.cc diff --git a/Package.swift b/Package.swift index 968db7b1..f34b09ee 100644 --- a/Package.swift +++ b/Package.swift @@ -463,6 +463,7 @@ let package = Package( "connections/implementation/bluetooth_bwu_test.cc", "connections/implementation/wifi_direct_bwu_test.cc", "connections/implementation/wifi_hotspot_bwu_test.cc", + "connections/implementation/wifi_lan_bwu_test.cc", "connections/implementation/analytics/analytics_recorder_test.cc", "connections/implementation/analytics/throughput_recorder_test.cc", "connections/implementation/mediums/advertisements/data_element_test.cc", diff --git a/connections/implementation/BUILD b/connections/implementation/BUILD index 5f194bec..c1832da3 100644 --- a/connections/implementation/BUILD +++ b/connections/implementation/BUILD @@ -249,6 +249,7 @@ cc_test( "bwu_manager_test.cc", "wifi_direct_bwu_test.cc", "wifi_hotspot_bwu_test.cc", + "wifi_lan_bwu_test.cc", ], deps = [ ":internal", diff --git a/connections/implementation/wifi_lan_bwu_handler.cc b/connections/implementation/wifi_lan_bwu_handler.cc index 93e89a6b..80c64bff 100644 --- a/connections/implementation/wifi_lan_bwu_handler.cc +++ b/connections/implementation/wifi_lan_bwu_handler.cc @@ -65,9 +65,8 @@ WifiLanBwuHandler::CreateUpgradedEndpointChannel( const std::string& ip_address = upgrade_path_info_socket.ip_address(); std::int32_t port = upgrade_path_info_socket.wifi_port(); - VLOG(1) << "WifiLanBwuHandler is attempting to connect to " - << "available WifiLan service (" << ip_address << ":" << port - << ") for endpoint " << endpoint_id; + VLOG(1) << "WifiLanBwuHandler is attempting to connect to WifiLan service (" + << ip_address << ":" << port << ") for endpoint " << endpoint_id; ErrorOr socket_result = wifi_lan_medium_.Connect( service_id, ip_address, port, client->GetCancellationFlag(endpoint_id)); @@ -78,7 +77,7 @@ WifiLanBwuHandler::CreateUpgradedEndpointChannel( return {Error(socket_result.error().operation_result_code().value())}; } - VLOG(1) << "WifiLanBwuHandler successfully connected to WifiLan service (" + LOG(INFO) << "WifiLanBwuHandler successfully connected to WifiLan service (" << ip_address << ":" << port << ") while upgrading endpoint " << endpoint_id; @@ -86,9 +85,8 @@ WifiLanBwuHandler::CreateUpgradedEndpointChannel( auto channel = std::make_unique( service_id, /*channel_name=*/service_id, socket_result.value()); if (channel == nullptr) { - LOG(ERROR) << "WifiLanBwuHandler failed to create WifiLan endpoint " - << "channel to the WifiLan service (" << ip_address << ":" - << port << ") for endpoint " << endpoint_id; + LOG(ERROR) << "WifiLanBwuHandler failed to create endpoint channel for (" + << ip_address << ":" << port << ") for endpoint " << endpoint_id; socket_result.value().Close(); return {Error( OperationResultCode::NEARBY_LAN_ENDPOINT_CHANNEL_CREATION_FAILURE)}; @@ -109,10 +107,9 @@ ByteArray WifiLanBwuHandler::HandleInitializeUpgradedMediumForEndpoint( absl::bind_front(&WifiLanBwuHandler::OnIncomingWifiLanConnection, this, client))) { LOG(ERROR) - << "WifiLanBwuHandler couldn't initiate the WifiLan upgrade for " + << "WifiLanBwuHandler couldn't init the WifiLan upgrade for " << "service " << upgrade_service_id << " and endpoint " << endpoint_id - << " because it failed to start listening for incoming WifiLan " - "connections."; + << " because it failed to start listening for incoming connections."; return {}; } LOG(INFO) @@ -130,8 +127,7 @@ ByteArray WifiLanBwuHandler::HandleInitializeUpgradedMediumForEndpoint( if (ip_address.empty()) { LOG(INFO) << "WifiLanBwuHandler couldn't initiate the wifi_lan upgrade for " << "service " << upgrade_service_id << " and endpoint " - << endpoint_id - << " because the wifi_lan ip address were unable to be obtained."; + << endpoint_id << " because wifi_lan ip address is empty."; return {}; } diff --git a/connections/implementation/wifi_lan_bwu_test.cc b/connections/implementation/wifi_lan_bwu_test.cc new file mode 100644 index 00000000..04a42c2d --- /dev/null +++ b/connections/implementation/wifi_lan_bwu_test.cc @@ -0,0 +1,169 @@ +// 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 +#include +#include + +#include "gtest/gtest.h" +#include "absl/strings/string_view.h" +#include "absl/time/clock.h" +#include "absl/time/time.h" +#include "connections/implementation/bwu_handler.h" +#include "connections/implementation/client_proxy.h" +#include "connections/implementation/endpoint_channel.h" +#include "connections/implementation/mediums/mediums.h" +#include "connections/implementation/offline_frames.h" +#include "connections/implementation/wifi_lan_bwu_handler.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/count_down_latch.h" +#include "internal/platform/exception.h" +#include "internal/platform/expected.h" +#include "internal/platform/logging.h" +#include "internal/platform/medium_environment.h" +#include "internal/platform/single_thread_executor.h" + +namespace nearby { +namespace connections { + +namespace { +using ::location::nearby::connections::OfflineFrame; +using UpgradePathInfo = ::location::nearby::connections:: + BandwidthUpgradeNegotiationFrame::UpgradePathInfo; +constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000); +constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"}; +constexpr absl::string_view kEndpointID{"WifiLan_Server"}; +} // namespace + +class WifiLanBwuTest : public testing::Test { + protected: + WifiLanBwuTest() { env_.Start(); } + ~WifiLanBwuTest() override { env_.Stop(); } + + MediumEnvironment& env_{MediumEnvironment::Instance()}; +}; + +TEST_F(WifiLanBwuTest, CanCreateBwuHandler) { + ClientProxy client; + Mediums mediums; + + auto handler = std::make_unique(mediums, nullptr); + + handler->InitializeUpgradedMediumForEndpoint(&client, std::string(kServiceID), + std::string(kEndpointID)); + handler->RevertInitiatorState(); + SUCCEED(); + handler.reset(); +} + +TEST_F(WifiLanBwuTest, WifiLanBWUInit_ClientCreateEndpointChannel) { + CountDownLatch start_latch(1); + CountDownLatch accept_latch(1); + CountDownLatch end_latch(1); + + ClientProxy client_wlan_server, client_wlan_client; + Mediums mediums_lan_ap, mediums_lan_sta; + ExceptionOr upgrade_frame; + + auto handler_server = std::make_unique( + mediums_lan_ap, [&](ClientProxy* client, + std::unique_ptr + mutable_connection) { + LOG(INFO) << "Server socket connection accept call back, Socket name: " + << mutable_connection->socket->ToString(); + accept_latch.CountDown(); + EXPECT_TRUE(end_latch.Await(kWaitDuration).result()); + }); + + SingleThreadExecutor server_executor; + server_executor.Execute([&]() { + ByteArray upgrade_path_available_frame = + handler_server->InitializeUpgradedMediumForEndpoint( + &client_wlan_server, std::string(kServiceID), + std::string(kEndpointID)); + EXPECT_FALSE(upgrade_path_available_frame.Empty()); + + upgrade_frame = parser::FromBytes(upgrade_path_available_frame); + start_latch.CountDown(); + }); + + client_wlan_client.AddCancellationFlag(std::string(kEndpointID)); + SingleThreadExecutor client_executor; + // Wait till client_wlan_server started as hotspot and then connect to it + EXPECT_TRUE(start_latch.Await(kWaitDuration).result()); + std::unique_ptr handler_client = + std::make_unique(mediums_lan_sta, nullptr); + + client_executor.Execute([&]() { + // Fail case 1: + UpgradePathInfo upgrade_path_info; + ErrorOr> result_error = + handler_client->CreateUpgradedEndpointChannel( + &client_wlan_client, std::string(kServiceID), + std::string(kEndpointID), upgrade_path_info); + EXPECT_TRUE(result_error.has_error()); + + // Fail case 2: + upgrade_path_info.set_medium(UpgradePathInfo::WIFI_LAN); + upgrade_path_info.mutable_wifi_lan_socket()->set_ip_address("192.168.1.1"); + result_error = handler_client->CreateUpgradedEndpointChannel( + &client_wlan_client, std::string(kServiceID), std::string(kEndpointID), + upgrade_path_info); + EXPECT_TRUE(result_error.has_error()); + + // Fail case 3: + upgrade_path_info.mutable_wifi_lan_socket()->set_wifi_port(12345); + result_error = handler_client->CreateUpgradedEndpointChannel( + &client_wlan_client, std::string(kServiceID), std::string(kEndpointID), + upgrade_path_info); + EXPECT_TRUE(result_error.has_error()); + + // Success case: + auto bwu_frame = + upgrade_frame.result().v1().bandwidth_upgrade_negotiation(); + + ErrorOr> result = + handler_client->CreateUpgradedEndpointChannel( + &client_wlan_client, std::string(kServiceID), + std::string(kEndpointID), bwu_frame.upgrade_path_info()); + EXPECT_EQ(handler_client->GetUpgradeMedium(), + location::nearby::proto::connections::Medium::WIFI_LAN); + + if (!client_wlan_client.GetCancellationFlag(std::string(kEndpointID)) + ->Cancelled()) { + ASSERT_TRUE(result.has_value()); + std::unique_ptr new_channel = std::move(result.value()); + EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); + EXPECT_EQ(new_channel->GetMedium(), + location::nearby::proto::connections::Medium::WIFI_LAN); + new_channel->EnableMultiplexSocket(); + absl::SleepFor(absl::Milliseconds(100)); + new_channel->Close(); + } else { + EXPECT_FALSE(result.has_value()); + EXPECT_TRUE(result.has_error()); + accept_latch.CountDown(); + } + handler_client->RevertResponderState(std::string(kServiceID)); + end_latch.CountDown(); + }); + handler_client->OnEndpointDisconnect(&client_wlan_client, + std::string(kEndpointID)); + + EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); + EXPECT_TRUE(end_latch.Await(kWaitDuration).result()); +} + +} // namespace connections +} // namespace nearby diff --git a/internal/platform/implementation/g3/BUILD b/internal/platform/implementation/g3/BUILD index db53a1bc..35e20659 100644 --- a/internal/platform/implementation/g3/BUILD +++ b/internal/platform/implementation/g3/BUILD @@ -126,6 +126,7 @@ cc_library( "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/synchronization", "@com_google_absl//absl/time", + "@com_google_absl//absl/types:optional", ], ) diff --git a/internal/platform/implementation/g3/wifi_lan.cc b/internal/platform/implementation/g3/wifi_lan.cc index 56c19ed6..c9cadddd 100644 --- a/internal/platform/implementation/g3/wifi_lan.cc +++ b/internal/platform/implementation/g3/wifi_lan.cc @@ -14,14 +14,15 @@ #include "internal/platform/implementation/g3/wifi_lan.h" -#include #include #include #include +#include "absl/functional/any_invocable.h" #include "absl/log/check.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/cancellation_flag_listener.h" @@ -34,6 +35,13 @@ namespace nearby { namespace g3 { +namespace { +constexpr absl::string_view kServiceInfoName{"DEFAULT_SERVICE_INFO_NAME"}; +constexpr absl::string_view kServiceType{"_default._tcp.local"}; +constexpr absl::string_view kEndpointName{"DEFAULT_ENDPOINT_NAME"}; +constexpr absl::string_view kEndpointInfoKey{"n"}; +} // namespace + std::string WifiLanServerSocket::GetName(const std::string& ip_address, int port) { std::string dot_delimited_string; @@ -120,6 +128,10 @@ Exception WifiLanServerSocket::DoClose() { WifiLanMedium::WifiLanMedium() { auto& env = MediumEnvironment::Instance(); env.RegisterWifiLanMedium(*this); + default_nsd_service_info_.SetServiceName(std::string(kServiceInfoName)); + default_nsd_service_info_.SetServiceType(std::string(kServiceType)); + default_nsd_service_info_.SetTxtRecord(std::string(kEndpointInfoKey), + std::string(kEndpointName)); } WifiLanMedium::~WifiLanMedium() { @@ -144,6 +156,11 @@ bool WifiLanMedium::StartAdvertising(const NsdServiceInfo& nsd_service_info) { } } auto& env = MediumEnvironment::Instance(); + // Delete the default_nsd_service_info_ that added in ListenForService stage + // as we will have a real service info to advertise. + env.UpdateWifiLanMediumForAdvertising(*this, default_nsd_service_info_, + /*enabled=*/false); + env.UpdateWifiLanMediumForAdvertising(*this, nsd_service_info, /*enabled=*/true); { @@ -230,12 +247,21 @@ std::unique_ptr WifiLanMedium::ConnectToService( std::string socket_name = WifiLanServerSocket::GetName(ip_address, port); LOG(INFO) << "G3 WifiLan ConnectToService [self]: medium=" << this << ", ip address + port=" << socket_name; + // First, find an instance of remote medium, that exposed this service. auto& env = MediumEnvironment::Instance(); auto* remote_medium = static_cast(env.GetWifiLanMedium(ip_address, port)); if (!remote_medium) { - return {}; + // In case of WLAN BWU, here's no discovery phase, so we need to + // update the discovery state with default_nsd_service_info_. + env.UpdateWifiLanMediumForDiscovery( + *this, {}, default_nsd_service_info_.GetServiceType(), true); + remote_medium = + static_cast(env.GetWifiLanMedium(ip_address, port)); + if (!remote_medium) { + return {}; + } } WifiLanServerSocket* server_socket = nullptr; @@ -285,8 +311,10 @@ std::unique_ptr WifiLanMedium::ListenForService( int port) { auto& env = MediumEnvironment::Instance(); auto server_socket = std::make_unique(); - server_socket->SetIPAddress(env.GetFakeIPAddress()); - server_socket->SetPort(port == 0 ? env.GetFakePort() : port); + std::string ip_address = env.GetFakeIPAddress(); + int fake_port = port == 0 ? env.GetFakePort() : port; + server_socket->SetIPAddress(ip_address); + server_socket->SetPort(fake_port); std::string socket_name = WifiLanServerSocket::GetName( server_socket->GetIPAddress(), server_socket->GetPort()); server_socket->SetCloseNotifier([this, socket_name]() { @@ -295,6 +323,13 @@ std::unique_ptr WifiLanMedium::ListenForService( }); LOG(INFO) << "G3 WifiLan Adding server socket: medium=" << this << ", socket_name=" << socket_name; + default_nsd_service_info_.SetIPAddress(ip_address); + default_nsd_service_info_.SetPort(fake_port); + + // In case of WLAN BWU, here's no advertisement phase, so we need to update + // the advertising state with default_nsd_service_info_ in advance. + env.UpdateWifiLanMediumForAdvertising(*this, default_nsd_service_info_, + /*enabled=*/true); absl::MutexLock lock(mutex_); server_sockets_.insert({socket_name, server_socket.get()}); return server_socket; diff --git a/internal/platform/implementation/g3/wifi_lan.h b/internal/platform/implementation/g3/wifi_lan.h index b51f05fd..7b9fe54b 100644 --- a/internal/platform/implementation/g3/wifi_lan.h +++ b/internal/platform/implementation/g3/wifi_lan.h @@ -15,15 +15,19 @@ #ifndef PLATFORM_IMPL_G3_WIFI_LAN_H_ #define PLATFORM_IMPL_G3_WIFI_LAN_H_ +#include #include #include #include +#include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" +#include "absl/functional/any_invocable.h" #include "absl/synchronization/mutex.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/implementation/g3/multi_thread_executor.h" +#include "absl/types/optional.h" +#include "internal/platform/cancellation_flag.h" +#include "internal/platform/exception.h" #include "internal/platform/implementation/g3/socket_base.h" #include "internal/platform/implementation/wifi_lan.h" #include "internal/platform/input_stream.h" @@ -241,6 +245,7 @@ class WifiLanMedium : public api::WifiLanMedium { absl::flat_hash_set service_types; }; + NsdServiceInfo default_nsd_service_info_; absl::Mutex mutex_; AdvertisingInfo advertising_info_ ABSL_GUARDED_BY(mutex_); DiscoveringInfo discovering_info_ ABSL_GUARDED_BY(mutex_);