Files
nearby/connections/implementation/client_proxy_test.cc
T
hai007 e0e428b00b Wi-Fi Direct security implementation
PiperOrigin-RevId: 939931482
2026-06-29 11:18:55 -07:00

1825 lines
69 KiB
C++

// Copyright 2021 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/client_proxy.h"
#include <atomic>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "connections/advertising_options.h"
#include "connections/connection_options.h"
#include "connections/discovery_options.h"
#include "connections/implementation/analytics/mock_analytics_recorder.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/payload.h"
#include "connections/status.h"
#include "connections/strategy.h"
#include "connections/v3/bandwidth_info.h"
#include "connections/v3/connection_listening_options.h"
#include "connections/v3/connection_result.h"
#include "connections/v3/connections_device_provider.h"
#include "connections/v3/listeners.h"
#include "internal/flags/nearby_flags.h"
#include "internal/interop/device.h"
#include "internal/interop/device_provider.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/single_thread_executor.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
namespace connections {
namespace {
using ::location::nearby::connections::OsInfo;
using ::testing::_;
using ::testing::IsEmpty;
using ::testing::MockFunction;
using ::testing::StrictMock;
constexpr FeatureFlags::Flags kTestCases[] = {
FeatureFlags::Flags{
.enable_cancellation_flag = true,
},
FeatureFlags::Flags{
.enable_cancellation_flag = false,
},
};
class MockDeviceProvider : public nearby::NearbyDeviceProvider {
public:
MOCK_METHOD((const NearbyDevice*), GetLocalDevice, (), (override));
};
class ClientProxyTest : public ::testing::TestWithParam<FeatureFlags::Flags> {
protected:
struct MockDiscoveryListener {
StrictMock<MockFunction<void(const std::string& endpoint_id,
const ByteArray& endpoint_info,
const std::string& service_id)>>
endpoint_found_cb;
StrictMock<MockFunction<void(const std::string& endpoint_id)>>
endpoint_lost_cb;
};
struct MockConnectionListener {
StrictMock<MockFunction<void(const std::string& endpoint_id,
const ConnectionResponseInfo& info)>>
initiated_cb;
StrictMock<MockFunction<void(const std::string& endpoint_id)>> accepted_cb;
StrictMock<MockFunction<void(const std::string& endpoint_id,
const Status& status)>>
rejected_cb;
StrictMock<MockFunction<void(const std::string& endpoint_id)>>
disconnected_cb;
StrictMock<MockFunction<void(const std::string& endpoint_id,
std::int32_t quality)>>
bandwidth_changed_cb;
};
struct MockPayloadListener {
StrictMock<
MockFunction<void(absl::string_view endpoint_id, Payload payload)>>
payload_cb;
StrictMock<MockFunction<void(absl::string_view endpoint_id,
const PayloadProgressInfo& info)>>
payload_progress_cb;
};
struct Endpoint {
ByteArray info;
std::string id;
};
void SetUp() override {
EnvironmentConfig config{/*webrtc_enabled=*/false,
/*use_simulated_clock=*/true,
/*use_temporary_directory_for_app_path=*/true};
env_.Start(config);
auto analytics_recorder1 =
std::make_unique<analytics::MockAnalyticsRecorder>();
mock_analytics_recorder1_ptr_ = analytics_recorder1.get();
client1_ = std::make_unique<ClientProxy>(std::move(analytics_recorder1));
auto analytics_recorder2 =
std::make_unique<analytics::MockAnalyticsRecorder>();
mock_analytics_recorder2_ptr_ = analytics_recorder2.get();
client2_ = std::make_unique<ClientProxy>(std::move(analytics_recorder2));
}
void TearDown() override {
client1_.reset();
client2_.reset();
env_.Stop();
NearbyFlags::GetInstance().ResetOverridedValues();
}
bool ShouldEnterStableEndpointIdMode(
const AdvertisingOptions& advertising_options) {
if (advertising_options.use_stable_endpoint_id) {
return true;
} else if (advertising_options.low_power) {
return false;
} else {
return true;
}
}
Endpoint StartAdvertising(
ClientProxy* client, ConnectionListener listener,
AdvertisingOptions advertising_options = AdvertisingOptions{}) {
if (ShouldEnterStableEndpointIdMode(advertising_options)) {
client->EnterStableEndpointIdMode();
}
Endpoint endpoint{
.info = ByteArray{"advertising endpoint name"},
.id = client->GetLocalEndpointId(),
};
client->StartedAdvertising(
service_id_, strategy_, listener, absl::MakeSpan(mediums_),
/*operation_result_with_medium=*/{}, advertising_options);
return endpoint;
}
void StopAdvertising(ClientProxy* client) {
client->StoppedAdvertising();
EXPECT_FALSE(client->IsAdvertising());
}
void OnAdvertisingConnectionInitiated(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_CALL(mock_advertising_connection_.initiated_cb, Call).Times(1);
const std::string auth_token{"auth_token"};
const ByteArray raw_auth_token{auth_token};
const std::string connection_token{"conntokn"};
discovery_connection_info_.remote_endpoint_info = endpoint.info;
client->OnConnectionInitiated(
endpoint.id, discovery_connection_info_, connection_options_,
advertising_connection_listener_, connection_token);
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id));
}
Endpoint StartListeningForIncomingConnections(
ClientProxy* client, v3::ConnectionListener listener,
v3::ConnectionListeningOptions options = {}) {
Endpoint endpoint{
.info = ByteArray{"advertising endpoint name"},
.id = client->GetLocalEndpointId(),
};
client->StartedListeningForIncomingConnections(
service_id_, strategy_, std::move(listener), options);
return endpoint;
}
void StopListeningForIncomingConnections(ClientProxy* client) {
client->StoppedListeningForIncomingConnections();
EXPECT_FALSE(client->IsListeningForIncomingConnections());
}
Endpoint StartDiscovery(ClientProxy* client, DiscoveryListener listener) {
Endpoint endpoint{
.info = ByteArray{"discovery endpoint name"},
.id = client->GetLocalEndpointId(),
};
client->StartedDiscovery(service_id_, strategy_, std::move(listener),
absl::MakeSpan(mediums_),
/*operation_result_with_medium=*/{});
return endpoint;
}
void StopDiscovery(ClientProxy* client) {
client->StoppedDiscovery();
EXPECT_FALSE(client->IsDiscovering());
}
void OnDiscoveryEndpointFound(ClientProxy* client, const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_.endpoint_found_cb, Call).Times(1);
client->OnEndpointFound(service_id_, endpoint.id, endpoint.info, medium_);
}
void OnDiscoveryEndpointLost(ClientProxy* client, const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_.endpoint_lost_cb, Call).Times(1);
client->OnEndpointLost(service_id_, endpoint.id);
}
void OnDiscoveryConnectionInitiated(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_connection_.initiated_cb, Call).Times(1);
const std::string auth_token{"auth_token"};
const ByteArray raw_auth_token{auth_token};
const std::string connection_token{"conntokn"};
advertising_connection_info_.remote_endpoint_info = endpoint.info;
client->OnConnectionInitiated(
endpoint.id, advertising_connection_info_, connection_options_,
discovery_connection_listener_, connection_token);
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id));
}
void OnDiscoveryConnectionLocalAccepted(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id));
EXPECT_FALSE(client->HasLocalEndpointResponded(endpoint.id));
client->LocalEndpointAcceptedConnection(
endpoint.id,
{
.payload_cb = mock_discovery_payload_.payload_cb.AsStdFunction(),
.payload_progress_cb =
mock_discovery_payload_.payload_progress_cb.AsStdFunction(),
});
EXPECT_TRUE(client->HasLocalEndpointResponded(endpoint.id));
EXPECT_TRUE(client->LocalConnectionIsAccepted(endpoint.id));
}
void OnDiscoveryConnectionRemoteAccepted(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id));
EXPECT_FALSE(client->HasRemoteEndpointResponded(endpoint.id));
client->RemoteEndpointAcceptedConnection(endpoint.id);
EXPECT_TRUE(client->HasRemoteEndpointResponded(endpoint.id));
EXPECT_TRUE(client->RemoteConnectionIsAccepted(endpoint.id));
}
void OnDiscoveryConnectionLocalRejected(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id));
EXPECT_FALSE(client->HasLocalEndpointResponded(endpoint.id));
client->LocalEndpointRejectedConnection(endpoint.id);
EXPECT_TRUE(client->HasLocalEndpointResponded(endpoint.id));
EXPECT_FALSE(client->LocalConnectionIsAccepted(endpoint.id));
}
void OnDiscoveryConnectionRemoteRejected(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id));
EXPECT_FALSE(client->HasRemoteEndpointResponded(endpoint.id));
client->RemoteEndpointRejectedConnection(endpoint.id);
EXPECT_TRUE(client->HasRemoteEndpointResponded(endpoint.id));
EXPECT_FALSE(client->RemoteConnectionIsAccepted(endpoint.id));
}
void OnDiscoveryConnectionAccepted(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_connection_.accepted_cb, Call).Times(1);
EXPECT_TRUE(client->IsConnectionAccepted(endpoint.id));
client->OnConnectionAccepted(endpoint.id);
}
void OnDiscoveryConnectionRejected(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_connection_.rejected_cb, Call).Times(1);
EXPECT_TRUE(client->IsConnectionRejected(endpoint.id));
client->OnConnectionRejected(endpoint.id, {Status::kConnectionRejected});
}
void OnDiscoveryBandwidthChanged(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_connection_.bandwidth_changed_cb, Call).Times(1);
client->OnBandwidthChanged(endpoint.id, Medium::WIFI_LAN);
}
void OnDiscoveryConnectionDisconnected(ClientProxy* client,
const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_connection_.disconnected_cb, Call).Times(1);
client->OnDisconnected(endpoint.id, true);
}
void OnPayload(ClientProxy* client, const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_payload_.payload_cb, Call).Times(1);
client->OnPayload(endpoint.id, Payload(payload_bytes_));
}
void OnPayloadProgress(ClientProxy* client, const Endpoint& endpoint) {
EXPECT_CALL(mock_discovery_payload_.payload_progress_cb, Call).Times(1);
client->OnPayloadProgress(endpoint.id, {});
}
ClientProxy* client1() { return client1_.get(); }
ClientProxy* client2() { return client2_.get(); }
void FastForward(absl::Duration duration) {
env_.FastForward(duration);
// make sure the timer based callback is executed.
absl::SleepFor(absl::Milliseconds(100));
}
MockConnectionListener mock_advertising_connection_;
MockDiscoveryListener mock_discovery_;
MockConnectionListener mock_discovery_connection_;
MockPayloadListener mock_discovery_payload_;
location::nearby::proto::connections::Medium medium_{
location::nearby::proto::connections::Medium::BLUETOOTH};
std::vector<location::nearby::proto::connections::Medium> mediums_{
location::nearby::proto::connections::Medium::BLUETOOTH,
};
MediumEnvironment& env_ = MediumEnvironment::Instance();
Strategy strategy_{Strategy::kP2pPointToPoint};
const std::string service_id_{"service"};
analytics::MockAnalyticsRecorder* mock_analytics_recorder1_ptr_;
analytics::MockAnalyticsRecorder* mock_analytics_recorder2_ptr_;
std::unique_ptr<ClientProxy> client1_;
std::unique_ptr<ClientProxy> client2_;
std::string auth_token_ = "auth_token";
ByteArray raw_auth_token_ = ByteArray(auth_token_);
ByteArray payload_bytes_{"bytes"};
ConnectionResponseInfo advertising_connection_info_{
.authentication_token = auth_token_,
.raw_authentication_token = raw_auth_token_,
.is_incoming_connection = true,
};
ConnectionListener advertising_connection_listener_{
.initiated_cb = mock_advertising_connection_.initiated_cb.AsStdFunction(),
};
ConnectionResponseInfo discovery_connection_info_{
.authentication_token = auth_token_,
.raw_authentication_token = raw_auth_token_,
.is_incoming_connection = false,
};
ConnectionListener discovery_connection_listener_{
.initiated_cb = mock_discovery_connection_.initiated_cb.AsStdFunction(),
.accepted_cb = mock_discovery_connection_.accepted_cb.AsStdFunction(),
.rejected_cb = mock_discovery_connection_.rejected_cb.AsStdFunction(),
.disconnected_cb =
mock_discovery_connection_.disconnected_cb.AsStdFunction(),
.bandwidth_changed_cb =
mock_discovery_connection_.bandwidth_changed_cb.AsStdFunction(),
};
DiscoveryListener GetDiscoveryListener() {
return DiscoveryListener{
.endpoint_found_cb = mock_discovery_.endpoint_found_cb.AsStdFunction(),
.endpoint_lost_cb = mock_discovery_.endpoint_lost_cb.AsStdFunction(),
};
}
ConnectionOptions connection_options_;
AdvertisingOptions advertising_options_;
DiscoveryOptions discovery_options_;
};
// Regression test for b/279962714.
TEST_P(ClientProxyTest, CanCancelEndpoint) {
FeatureFlags::Flags feature_flags = GetParam();
MediumEnvironment::Instance().SetFeatureFlags(feature_flags);
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
// `CancellationFlag` pointers are passed to other classes in Nearby
// Connections, and by using the pointers directly, we test their
// consumption of `CancellationFlag` pointers.
std::shared_ptr<CancellationFlag> cancellation_flag =
client2()->GetCancellationFlag(advertising_endpoint.id);
EXPECT_FALSE(
client2()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
EXPECT_FALSE(cancellation_flag->Cancelled());
client2()->CancelEndpoint(advertising_endpoint.id);
// If FeatureFlag is disabled, Cancelled is false as no-op.
if (!feature_flags.enable_cancellation_flag) {
EXPECT_FALSE(
client2()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
EXPECT_FALSE(cancellation_flag->Cancelled());
} else {
// The Cancelled is always true as the default flag being returned.
EXPECT_TRUE(
client2()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
EXPECT_TRUE(cancellation_flag->Cancelled());
}
}
// Regression test for b/279962714.
TEST_P(ClientProxyTest, CanCancelAllEndpoints) {
FeatureFlags::Flags feature_flags = GetParam();
MediumEnvironment::Instance().SetFeatureFlags(feature_flags);
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
// `CancellationFlag` pointers are passed to other classes in Nearby
// Connections, and by using the pointers directly, we test their
// consumption of `CancellationFlag` pointers.
std::shared_ptr<CancellationFlag> cancellation_flag =
client2()->GetCancellationFlag(advertising_endpoint.id);
EXPECT_FALSE(
client2()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
EXPECT_FALSE(cancellation_flag->Cancelled());
client2()->CancelAllEndpoints();
// If FeatureFlag is disabled, Cancelled is false as no-op.
if (!feature_flags.enable_cancellation_flag) {
EXPECT_FALSE(
client2()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
EXPECT_FALSE(cancellation_flag->Cancelled());
} else {
// The Cancelled is always true as the default flag being returned.
EXPECT_TRUE(
client2()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
EXPECT_TRUE(cancellation_flag->Cancelled());
}
}
TEST_P(ClientProxyTest, CanCancelAllEndpointsWithDifferentEndpoint) {
FeatureFlags::Flags feature_flags = GetParam();
MediumEnvironment::Instance().SetFeatureFlags(feature_flags);
ConnectionListener advertising_connection_listener_2;
ConnectionListener advertising_connection_listener_3;
ClientProxy client3;
StartDiscovery(client1(), GetDiscoveryListener());
Endpoint advertising_endpoint_2 =
StartAdvertising(client2(), advertising_connection_listener_2);
Endpoint advertising_endpoint_3 =
StartAdvertising(&client3, advertising_connection_listener_3);
OnDiscoveryEndpointFound(client1(), advertising_endpoint_2);
OnDiscoveryConnectionInitiated(client1(), advertising_endpoint_2);
OnDiscoveryEndpointFound(client1(), advertising_endpoint_3);
OnDiscoveryConnectionInitiated(client1(), advertising_endpoint_3);
// The CancellationFlag of endpoint_2 and endpoint_3 have been added. Default
// Cancelled is false.
EXPECT_FALSE(
client1()->GetCancellationFlag(advertising_endpoint_2.id)->Cancelled());
EXPECT_FALSE(
client1()->GetCancellationFlag(advertising_endpoint_3.id)->Cancelled());
client1()->CancelAllEndpoints();
if (!feature_flags.enable_cancellation_flag) {
// The CancellationFlag of endpoint_2 and endpoint_3 will not be removed
// since it is not added. The default flag returned as Cancelled being true,
// but Cancelled requested is false since the FeatureFlag is off.
EXPECT_FALSE(
client1()->GetCancellationFlag(advertising_endpoint_2.id)->Cancelled());
EXPECT_FALSE(
client1()->GetCancellationFlag(advertising_endpoint_3.id)->Cancelled());
} else {
// Expect the CancellationFlag of endpoint_2 and endpoint_3 has been
// removed. The Cancelled is always true as the default flag being returned.
EXPECT_TRUE(
client1()->GetCancellationFlag(advertising_endpoint_2.id)->Cancelled());
EXPECT_TRUE(
client1()->GetCancellationFlag(advertising_endpoint_3.id)->Cancelled());
}
}
TEST_P(ClientProxyTest, GetCancellationFlagRace) {
std::string endpoint_id = "test_endpoint";
client1()->AddCancellationFlag(endpoint_id);
std::atomic<bool> run{true};
SingleThreadExecutor executor;
executor.Execute([&]() {
while (run) {
client1()->GetCancellationFlag(endpoint_id);
}
});
for (int i = 0; i < 10000; ++i) {
client1()->Reset();
client1()->AddCancellationFlag(endpoint_id);
}
run = false;
}
INSTANTIATE_TEST_SUITE_P(ParametrisedClientProxyTest, ClientProxyTest,
::testing::ValuesIn(kTestCases));
TEST_F(ClientProxyTest, ConstructorDestructorWorks) { SUCCEED(); }
TEST_F(ClientProxyTest, ClientIdIsUnique) {
EXPECT_NE(client1()->GetClientId(), client2()->GetClientId());
}
TEST_F(ClientProxyTest, DumpString) {
std::string expect = absl::StrFormat(
"Nearby Connections State\n"
" Client ID: %d\n"
" Local Endpoint ID: %s\n"
" Is Advertising: false\n"
" Is Discovering: false\n"
" Advertising Service ID: \n"
" Discovery Service ID: \n"
" Connections: \n"
" Discovered endpoint IDs: \n",
client1()->GetClientId(), client1()->GetLocalEndpointId());
std::string dump = client1()->Dump();
EXPECT_EQ(dump, expect);
}
TEST_F(ClientProxyTest, GeneratedEndpointIdIsUnique) {
EXPECT_NE(client1()->GetLocalEndpointId(), client2()->GetLocalEndpointId());
}
TEST_F(ClientProxyTest, GeneratedEndpointIdIsUniqueWithDeviceProvider) {
client1()->RegisterConnectionsDeviceProvider(
std::make_unique<v3::ConnectionsDeviceProvider>(
v3::ConnectionsDeviceProvider("", {})));
client2()->RegisterConnectionsDeviceProvider(
std::make_unique<v3::ConnectionsDeviceProvider>(
v3::ConnectionsDeviceProvider("", {})));
EXPECT_NE(client1()->GetLocalEndpointId(), client2()->GetLocalEndpointId());
}
TEST_F(ClientProxyTest, ResetClearsState) {
client1()->Reset();
EXPECT_FALSE(client1()->IsAdvertising());
EXPECT_FALSE(client1()->IsDiscovering());
EXPECT_TRUE(client1()->GetAdvertisingServiceId().empty());
EXPECT_TRUE(client1()->GetDiscoveryServiceId().empty());
}
TEST_F(ClientProxyTest, StartedAdvertisingChangesStateFromIdle) {
client1()->StartedAdvertising(service_id_, strategy_, {}, {}, {});
EXPECT_TRUE(client1()->IsAdvertising());
EXPECT_FALSE(client1()->IsDiscovering());
EXPECT_EQ(client1()->GetAdvertisingServiceId(), service_id_);
EXPECT_TRUE(client1()->GetDiscoveryServiceId().empty());
}
TEST_F(ClientProxyTest, StartedDiscoveryChangesStateFromIdle) {
client1()->StartedDiscovery(service_id_, strategy_, {}, {}, {});
EXPECT_FALSE(client1()->IsAdvertising());
EXPECT_TRUE(client1()->IsDiscovering());
EXPECT_TRUE(client1()->GetAdvertisingServiceId().empty());
EXPECT_EQ(client1()->GetDiscoveryServiceId(), service_id_);
}
TEST_F(ClientProxyTest, OnEndpointFoundFiresNotificationInDiscovery) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, OnEndpointLostFiresNotificationInDiscovery) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryEndpointLost(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, OnConnectionInitiatedFiresNotificationInDiscovery) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, OnBandwidthChangedFiresNotificationInDiscovery) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
OnDiscoveryConnectionLocalAccepted(client2(), advertising_endpoint);
OnDiscoveryConnectionRemoteAccepted(client2(), advertising_endpoint);
OnDiscoveryConnectionAccepted(client2(), advertising_endpoint);
OnDiscoveryBandwidthChanged(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, OnDisconnectedFiresNotificationInDiscovery) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
OnDiscoveryConnectionDisconnected(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, LocalEndpointAcceptedConnectionChangesState) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
OnDiscoveryConnectionLocalAccepted(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, LocalEndpointRejectedConnectionChangesState) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
OnDiscoveryConnectionLocalRejected(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, RemoteEndpointAcceptedConnectionChangesState) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
OnDiscoveryConnectionRemoteAccepted(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, RemoteEndpointRejectedConnectionChangesState) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
OnDiscoveryConnectionRemoteRejected(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, OnPayloadChangesState) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
OnDiscoveryConnectionLocalAccepted(client2(), advertising_endpoint);
OnDiscoveryConnectionRemoteAccepted(client2(), advertising_endpoint);
OnDiscoveryConnectionAccepted(client2(), advertising_endpoint);
OnPayload(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, OnPayloadProgressChangesState) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
OnDiscoveryConnectionLocalAccepted(client2(), advertising_endpoint);
OnDiscoveryConnectionRemoteAccepted(client2(), advertising_endpoint);
OnDiscoveryConnectionAccepted(client2(), advertising_endpoint);
OnPayloadProgress(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest,
EndpointIdCacheWhenHighVizAdvertisementAgainImmediately) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
};
Endpoint advertising_endpoint_1 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
StopAdvertising(client1());
// Advertise immediately.
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
EXPECT_EQ(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(ClientProxyTest,
EndpointIdRotateWhenHighVizAdvertisementAgainForAWhile) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
};
Endpoint advertising_endpoint_1 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
StopAdvertising(client1());
// Wait to expire and then advertise.
FastForward(ClientProxy::kHighPowerAdvertisementEndpointIdCacheTimeout +
absl::Milliseconds(100));
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(ClientProxyTest,
EndpointIdRotateWhenLowVizAdvertisementAfterHighVizAdvertisement) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions high_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
};
Endpoint advertising_endpoint_1 =
StartAdvertising(client1(), advertising_connection_listener_,
high_viz_advertising_options);
StopAdvertising(client1());
AdvertisingOptions low_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
};
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, low_viz_advertising_options);
EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(ClientProxyTest,
RotateWhenLowVizAdvertisementAfterHighVizAndStableAdvertisement) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions high_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_1 =
StartAdvertising(client1(), advertising_connection_listener_,
high_viz_advertising_options);
StopAdvertising(client1());
AdvertisingOptions low_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
};
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, low_viz_advertising_options);
EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(
ClientProxyTest,
NoRotateWhenLowVizStableAdvertisementAfterHighVizAndStableAdvertisement) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions high_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_1 =
StartAdvertising(client1(), advertising_connection_listener_,
high_viz_advertising_options);
StopAdvertising(client1());
AdvertisingOptions low_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, low_viz_advertising_options);
EXPECT_EQ(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(
ClientProxyTest,
NoRotateWhenAdvertisementHasConnectionAfterStableAdvertisementForAWhile) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions high_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_1 =
StartAdvertising(client1(), advertising_connection_listener_,
high_viz_advertising_options);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint_1);
StopAdvertising(client1());
// Client should use cached endpoint id when having connection.
EXPECT_EQ(client1()->GetLocalEndpointId(), advertising_endpoint_1.id);
// Wait to expire and then advertise.
FastForward(ClientProxy::kHighPowerAdvertisementEndpointIdCacheTimeout +
absl::Milliseconds(100));
AdvertisingOptions low_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
};
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, low_viz_advertising_options);
EXPECT_EQ(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(ClientProxyTest, RotateWhenLowVizAdvertisementAfterDisconnection) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions high_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_1 =
StartAdvertising(client1(), advertising_connection_listener_,
high_viz_advertising_options);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint_1);
StopAdvertising(client1());
FastForward(absl::Seconds(2));
client1()->OnDisconnected(advertising_endpoint_1.id, true);
AdvertisingOptions low_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
};
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, low_viz_advertising_options);
EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(ClientProxyTest,
NoRotateWhenLowVizAndStableAdvertisementAfterDisconnection) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions high_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_1 =
StartAdvertising(client1(), advertising_connection_listener_,
high_viz_advertising_options);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint_1);
StopAdvertising(client1());
FastForward(absl::Seconds(2));
client1()->OnDisconnected(advertising_endpoint_1.id, true);
AdvertisingOptions low_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, low_viz_advertising_options);
EXPECT_EQ(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(ClientProxyTest, RotateWhenAdvertisementAfterDisconnectionForAWhile) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions high_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_1 =
StartAdvertising(client1(), advertising_connection_listener_,
high_viz_advertising_options);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint_1);
StopAdvertising(client1());
client1()->OnDisconnected(advertising_endpoint_1.id, true);
// Wait to expire and then advertise.
FastForward(ClientProxy::kHighPowerAdvertisementEndpointIdCacheTimeout +
absl::Milliseconds(100));
AdvertisingOptions low_viz_advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
};
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, low_viz_advertising_options);
EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
// Tests endpoint_id rotates when discover.
TEST_F(ClientProxyTest, EndpointIdRotateWhenStartDiscovery) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
};
Endpoint advertising_endpoint_1 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
StopAdvertising(client1());
StartDiscovery(client1(), GetDiscoveryListener());
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(ClientProxyTest,
EndpointIdRotateWhenStartDiscoveryAfterStableAdvertising) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = true;
AdvertisingOptions advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
false, // low_power
true, // enable_bluetooth_listening
false, // enable_webrtc_listening
true, // use_stable_endpoint_id
};
Endpoint advertising_endpoint_1 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
StopAdvertising(client1());
StartDiscovery(client1(), GetDiscoveryListener());
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
// Tests the low visibility mode with low power advertisment.
TEST_F(ClientProxyTest, EndpointIdRotateWhenLowVizAdvertisementWithLowPower) {
BooleanMediumSelector booleanMediumSelector;
booleanMediumSelector.bluetooth = false;
AdvertisingOptions advertising_options{
{
strategy_,
booleanMediumSelector,
},
false, // auto_upgrade_bandwidth
false, // enforce_topology_constraints
true, // low_power
};
Endpoint advertising_endpoint_1 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
StopAdvertising(client1());
Endpoint advertising_endpoint_2 = StartAdvertising(
client1(), advertising_connection_listener_, advertising_options);
EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id);
}
TEST_F(ClientProxyTest, NotLogSessionForStoppedAdvertisingWithConnection) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint);
StartDiscovery(client2(), GetDiscoveryListener());
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
// Before
EXPECT_TRUE(client1()->HasPendingConnectionToEndpoint(
advertising_endpoint.id)); // Connections are available
EXPECT_FALSE(client1()->IsDiscovering()); // No Discovery
EXPECT_TRUE(client1()->IsAdvertising()); // Advertising
// After
StopAdvertising(client1()); // No Advertising
EXPECT_CALL(*mock_analytics_recorder1_ptr_, LogSession()).Times(1);
}
TEST_F(ClientProxyTest,
LogSessionForStoppedAdvertisingWhenNoConnectionsAndNoDiscovering) {
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
// Before
EXPECT_FALSE(client1()->HasPendingConnectionToEndpoint(
advertising_endpoint.id)); // No Connections
EXPECT_FALSE(client1()->IsDiscovering()); // No Discovery
EXPECT_TRUE(client1()->IsAdvertising()); // Advertising
// After
EXPECT_CALL(*mock_analytics_recorder1_ptr_, OnStopAdvertising());
StopAdvertising(client1());
}
TEST_F(ClientProxyTest, NotLogSessionForStoppedDiscoveryWithConnection) {
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnStartDiscovery(strategy_, mediums_, _));
StartDiscovery(client2(), GetDiscoveryListener());
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnEndpointFound(Medium::BLUETOOTH));
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
// Before
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnConnectionRequestReceived(advertising_endpoint.id));
OnDiscoveryConnectionInitiated(
client2(), advertising_endpoint); // Connections are available
EXPECT_FALSE(client2()->IsAdvertising()); // No Advertising
EXPECT_TRUE(client2()->IsDiscovering()); // Discovering
// After
EXPECT_CALL(*mock_analytics_recorder2_ptr_, OnStopDiscovery());
StopDiscovery(client2());
}
TEST_F(ClientProxyTest,
NotLogSessionForStoppedDiscoveryWithoutConnectionsAndAdvertising) {
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnStartDiscovery(strategy_, mediums_, _));
StartDiscovery(client2(), GetDiscoveryListener());
// Before
EXPECT_FALSE(client2()->IsAdvertising()); // No Advertising
EXPECT_TRUE(client2()->IsDiscovering()); // Discovering
EXPECT_FALSE(client2()->HasPendingConnectionToEndpoint(
advertising_endpoint.id)); // No Connections
// After
EXPECT_CALL(*mock_analytics_recorder2_ptr_, OnStopDiscovery());
StopDiscovery(client2());
}
TEST_F(ClientProxyTest, LogSessionOnDisconnectedWithOneConnection) {
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnStartDiscovery(strategy_, mediums_, _));
StartDiscovery(client2(), GetDiscoveryListener());
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnEndpointFound(Medium::BLUETOOTH));
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnConnectionRequestReceived(advertising_endpoint.id));
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
// Before
EXPECT_FALSE(client2()->IsAdvertising()); // No Advertising
EXPECT_CALL(*mock_analytics_recorder2_ptr_, OnStopDiscovery());
StopDiscovery(client2()); // No Discovery
EXPECT_TRUE(client2()->HasPendingConnectionToEndpoint(
advertising_endpoint.id)); // One Connection
// After
OnDiscoveryConnectionDisconnected(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest,
NotLogSessionOnDisconnectedWithoutConnectionsDiscoveringAdvertising) {
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
// Before
EXPECT_FALSE(client2()->IsAdvertising()); // No Advertising
EXPECT_FALSE(client2()->IsDiscovering()); // No Discovery
EXPECT_FALSE(client2()->HasPendingConnectionToEndpoint(
advertising_endpoint.id)); // No Connections
// After
client2()->OnDisconnected(advertising_endpoint.id, /*notify=*/false);
}
TEST_F(ClientProxyTest, NotLogSessionOnDisconnectedWhenMoreThanOneConnection) {
ClientProxy client3;
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint_1 =
StartAdvertising(client1(), advertising_connection_listener_);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint_2 =
StartAdvertising(client2(), advertising_connection_listener_);
StartDiscovery(&client3, GetDiscoveryListener());
OnDiscoveryEndpointFound(&client3, advertising_endpoint_1);
OnDiscoveryConnectionInitiated(&client3, advertising_endpoint_1);
OnDiscoveryEndpointFound(&client3, advertising_endpoint_2);
OnDiscoveryConnectionInitiated(&client3, advertising_endpoint_2);
// Before
// - More than one Connection
EXPECT_TRUE(
client3.HasPendingConnectionToEndpoint(advertising_endpoint_1.id));
EXPECT_TRUE(
client3.HasPendingConnectionToEndpoint(advertising_endpoint_2.id));
EXPECT_FALSE(client3.IsAdvertising()); // No Advertising
StopDiscovery(&client3); // No Discovery
// After
client2()->OnDisconnected(advertising_endpoint_1.id, /*notify=*/false);
}
TEST_F(ClientProxyTest,
NotLogSessionOnDisconnectedForDiscoveringWithOnlyOneConnection) {
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnStartDiscovery(strategy_, mediums_, _));
StartDiscovery(client2(), GetDiscoveryListener());
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnEndpointFound(Medium::BLUETOOTH));
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnConnectionRequestReceived(advertising_endpoint.id));
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
// Before
EXPECT_FALSE(client2()->IsAdvertising()); // No Advertising
EXPECT_TRUE(client2()->IsDiscovering()); // Discovering
EXPECT_TRUE(client2()->HasPendingConnectionToEndpoint(
advertising_endpoint.id)); // One Connection
// After
OnDiscoveryConnectionDisconnected(client2(), advertising_endpoint);
}
TEST_F(ClientProxyTest, LogSessionForResetClientProxy) {
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
OnStartAdvertising(strategy_, mediums_, _));
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnStartDiscovery(strategy_, mediums_, _));
StartDiscovery(client2(), GetDiscoveryListener());
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnEndpointFound(Medium::BLUETOOTH));
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
OnConnectionRequestReceived(advertising_endpoint.id));
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
EXPECT_CALL(*mock_analytics_recorder1_ptr_, OnStopAdvertising());
client1()->Reset();
EXPECT_CALL(*mock_analytics_recorder2_ptr_, OnStopDiscovery());
client2()->Reset();
}
TEST_F(ClientProxyTest, GetLocalInfoCorrect) {
ClientProxy client;
// Default is g3 test Environment as LINUX.
EXPECT_EQ(client.GetLocalOsInfo().type(), OsInfo::LINUX);
}
TEST_F(ClientProxyTest, GetRemoteInfoNullWithoutConnections) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
EXPECT_FALSE(client1()->GetRemoteOsInfo(advertising_endpoint.id).has_value());
EXPECT_FALSE(client1()
->GetRemoteSafeToDisconnectVersion(advertising_endpoint.id)
.has_value());
EXPECT_EQ(client1()->GetRemoteDeviceName(advertising_endpoint.id), "");
}
TEST_F(ClientProxyTest, SetRemoteInfoCorrect) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint);
OsInfo os_info;
os_info.set_type(OsInfo::ANDROID);
std::int32_t nearby_connections_version = 2;
client1()->SetRemoteOsInfo(advertising_endpoint.id, os_info);
client1()->SetRemoteSafeToDisconnectVersion(advertising_endpoint.id,
nearby_connections_version);
ASSERT_TRUE(client1()->GetRemoteOsInfo(advertising_endpoint.id).has_value());
EXPECT_EQ(client1()->GetRemoteOsInfo(advertising_endpoint.id).value().type(),
OsInfo::ANDROID);
EXPECT_EQ(
client1()->GetRemoteSafeToDisconnectVersion(advertising_endpoint.id),
nearby_connections_version);
std::string device_name = "device_name";
client1()->SetRemoteDeviceName(advertising_endpoint.id, device_name);
EXPECT_EQ(client1()->GetRemoteDeviceName(advertising_endpoint.id),
device_name);
}
// Test ClientProxy::AddCancellationFlag, where if a flag is already in the map,
// uncancel it. This addresses the case when users use NS to share/receive a
// file, then cancel in the middle because the wrong file was selected, and then
// re-do right after. Without the ability to uncancel a flag in
// `AddCancelationFlag`, the second share/receive process will
// be seen as cancelled with cancellation flags enabled. However this tests that
// it will uncancel the flag which is added in RequestConnection and
// OnConnectionInitiated in the NS flow, and allow another attempt with the
// same endpoint.
TEST_F(ClientProxyTest, UncancelCancellationFlags) {
// Enable cancellation flags.
MediumEnvironment::Instance().SetFeatureFlags(kTestCases[0]);
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
// Add a cancellation flag to the client proxy.
client1()->AddCancellationFlag(advertising_endpoint.id);
auto flag = client1()->GetCancellationFlag(advertising_endpoint.id);
EXPECT_FALSE(flag->Cancelled());
EXPECT_FALSE(
client1()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
// Cancel the flag.
flag->Cancel();
EXPECT_TRUE(flag->Cancelled());
EXPECT_TRUE(
client1()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
// On subsequent calls to add a new cancellation flag, expect an the flag to
// be uncancelled.
client1()->AddCancellationFlag(advertising_endpoint.id);
flag = client1()->GetCancellationFlag(advertising_endpoint.id);
EXPECT_FALSE(flag->Cancelled());
EXPECT_FALSE(
client1()->GetCancellationFlag(advertising_endpoint.id)->Cancelled());
}
TEST_F(ClientProxyTest, GetLocalDeviceWorksWithoutDeviceProvider) {
auto device = client1()->GetLocalDevice();
EXPECT_NE(device, nullptr);
EXPECT_EQ(device->GetEndpointId().length(), 4);
EXPECT_NE(client1()->GetLocalDeviceProvider(), nullptr);
}
TEST_F(ClientProxyTest, GetLocalDeviceWorksWithDeviceProvider) {
MockDeviceProvider provider;
client1()->RegisterDeviceProvider(&provider);
ASSERT_NE(client1()->GetLocalDeviceProvider(), nullptr);
EXPECT_CALL(provider, GetLocalDevice);
client1()->GetLocalDevice();
}
TEST_F(ClientProxyTest, TestGetSetLocalEndpointInfo) {
client1()->UpdateLocalEndpointInfo("endpoint_info");
EXPECT_EQ(client1()->GetLocalEndpointInfo(), "endpoint_info");
}
TEST_F(ClientProxyTest, TestGetIncomingConnectionListener) {
CountDownLatch result_latch(2);
CountDownLatch bwu_latch(1);
CountDownLatch disconnect_latch(1);
CountDownLatch init_latch(1);
client1()->StartedListeningForIncomingConnections(
service_id_, Strategy::kP2pCluster,
{
.initiated_cb =
[&init_latch](const NearbyDevice&,
const v3::InitialConnectionInfo&) {
init_latch.CountDown();
},
.result_cb = [&result_latch](
const NearbyDevice&,
v3::ConnectionResult) { result_latch.CountDown(); },
.disconnected_cb =
[&disconnect_latch](const NearbyDevice&) {
disconnect_latch.CountDown();
},
.bandwidth_changed_cb =
[&bwu_latch](const NearbyDevice&, v3::BandwidthInfo) {
bwu_latch.CountDown();
},
},
{});
auto listener = client1()->GetAdvertisingOrIncomingConnectionListener();
listener.accepted_cb("endpoint-id");
listener.initiated_cb("endpoint-id", {.is_incoming_connection = false});
listener.disconnected_cb("endpoint-id");
listener.rejected_cb("endpoint-id", {Status::Value::kConnectionRejected});
listener.bandwidth_changed_cb("endpoint-id", Medium::WIFI_LAN);
EXPECT_TRUE(result_latch.Await().Ok());
EXPECT_TRUE(init_latch.Await().Ok());
EXPECT_TRUE(bwu_latch.Await().Ok());
EXPECT_TRUE(disconnect_latch.Await().Ok());
}
TEST_F(ClientProxyTest, EnforceTopologyWhenRequestedAdvertising) {
EXPECT_FALSE(client1()->ShouldEnforceTopologyConstraints());
StartAdvertising(client1(), advertising_connection_listener_,
{.enforce_topology_constraints = true});
EXPECT_TRUE(client1()->ShouldEnforceTopologyConstraints());
}
TEST_F(ClientProxyTest, EnforceTopologyWhenRequestedListeningWithStrategy) {
EXPECT_FALSE(client1()->ShouldEnforceTopologyConstraints());
StartListeningForIncomingConnections(client1(), {},
{.strategy = Strategy::kP2pCluster,
.enforce_topology_constraints = true});
EXPECT_TRUE(client1()->ShouldEnforceTopologyConstraints());
}
TEST_F(ClientProxyTest, DontEnforceTopologyWhenRequestedWithNoStrategy) {
EXPECT_FALSE(client1()->ShouldEnforceTopologyConstraints());
StartListeningForIncomingConnections(client1(), {},
{.strategy = Strategy::kNone});
EXPECT_TRUE(client1()->ShouldEnforceTopologyConstraints());
}
TEST_F(ClientProxyTest, TestAutoBwuWhenAdvertisingWithAutoBwu) {
EXPECT_FALSE(client1()->AutoUpgradeBandwidth());
StartAdvertising(client1(), advertising_connection_listener_,
{.auto_upgrade_bandwidth = true});
EXPECT_TRUE(client1()->AutoUpgradeBandwidth());
}
TEST_F(ClientProxyTest, TestAutoBwuWhenListeningWithAutoBwu) {
EXPECT_FALSE(client1()->AutoUpgradeBandwidth());
StartListeningForIncomingConnections(client1(), {},
{.auto_upgrade_bandwidth = true});
EXPECT_TRUE(client1()->AutoUpgradeBandwidth());
}
TEST_F(ClientProxyTest, SaveClientInfoFromPreferences) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableNearbyConnectionsPreferences,
true);
client1_ = std::make_unique<ClientProxy>();
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
std::string endpoint_id = advertising_endpoint.id;
client1_->SaveClientInfoToPreferences();
// Destroy the client and create a new one.
client1_.reset();
client1_ = std::make_unique<ClientProxy>();
// The new client should load the same endpoint ID.
EXPECT_EQ(client1()->GetLocalEndpointId(), endpoint_id);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableNearbyConnectionsPreferences,
false);
}
TEST_F(ClientProxyTest, NotLoadClientInfoFromPreferencesOnExpired) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableNearbyConnectionsPreferences,
true);
client1_ = std::make_unique<ClientProxy>();
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
std::string endpoint_id = advertising_endpoint.id;
client1_->SaveClientInfoToPreferences();
// Destroy the client and create a new one.
client1_.reset();
FastForward(absl::Hours(25));
client1_ = std::make_unique<ClientProxy>();
// The new client should load the same endpoint ID.
EXPECT_NE(client1()->GetLocalEndpointId(), endpoint_id);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableNearbyConnectionsPreferences,
false);
}
TEST_F(ClientProxyTest, OverrideSavePath) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint);
client1()->OverrideSavePath(advertising_endpoint.id, "/tmp/test_path");
EXPECT_EQ(client1()->GetSavePath(advertising_endpoint.id), "/tmp/test_path");
}
TEST_F(ClientProxyTest, GetSavePathDefaultsToEmpty) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint);
EXPECT_THAT(client1()->GetSavePath(advertising_endpoint.id), IsEmpty());
}
TEST_F(ClientProxyTest, GetLocalMediumRoleFlagDisabled) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableDynamicRoleSwitch,
false);
ClientProxy::MediumsAvailability availability;
availability.is_wifi_direct_go_available = true;
availability.is_wifi_direct_gc_available = true;
availability.is_wifi_hotspot_ap_available = true;
availability.is_wifi_hotspot_client_available = true;
location::nearby::connections::MediumRole role =
client1()->GetLocalMediumRole(availability);
EXPECT_FALSE(role.support_awdl_publisher());
EXPECT_FALSE(role.support_awdl_subscriber());
EXPECT_FALSE(role.support_wifi_direct_group_owner());
EXPECT_FALSE(role.support_wifi_direct_group_client());
EXPECT_FALSE(role.support_wifi_hotspot_host());
EXPECT_FALSE(role.support_wifi_hotspot_client());
}
TEST_F(ClientProxyTest, GetLocalMediumRoleAppleOs) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableDynamicRoleSwitch,
true);
client1()->SetLocalOsType(location::nearby::connections::OsInfo::APPLE);
ClientProxy::MediumsAvailability availability;
location::nearby::connections::MediumRole role =
client1()->GetLocalMediumRole(availability);
EXPECT_TRUE(role.support_awdl_publisher());
EXPECT_TRUE(role.support_awdl_subscriber());
EXPECT_TRUE(role.support_wifi_hotspot_client());
EXPECT_FALSE(role.support_wifi_direct_group_owner());
EXPECT_FALSE(role.support_wifi_direct_group_client());
EXPECT_FALSE(role.support_wifi_hotspot_host());
}
TEST_F(ClientProxyTest, GetLocalMediumRoleNonAppleOsNoP2pConnection) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableDynamicRoleSwitch,
true);
client1()->SetLocalOsType(location::nearby::connections::OsInfo::ANDROID);
ClientProxy::MediumsAvailability availability;
availability.is_wifi_direct_go_available = true;
availability.is_wifi_direct_gc_available = true;
availability.is_wifi_hotspot_ap_available = true;
availability.is_wifi_hotspot_client_available = true;
location::nearby::connections::MediumRole role =
client1()->GetLocalMediumRole(availability);
EXPECT_TRUE(role.support_wifi_direct_group_owner());
EXPECT_TRUE(role.support_wifi_direct_group_client());
EXPECT_TRUE(role.support_wifi_hotspot_host());
EXPECT_TRUE(role.support_wifi_hotspot_client());
}
TEST_F(ClientProxyTest, GetLocalMediumRoleNonAppleOsWithP2pConnection) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableDynamicRoleSwitch,
true);
client1()->SetLocalOsType(location::nearby::connections::OsInfo::ANDROID);
// Setup an active P2P connection to make IsUsingP2pMedium() true
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint);
client1()->OnBandwidthChanged(advertising_endpoint.id, Medium::WIFI_DIRECT);
EXPECT_TRUE(client1()->IsUsingP2pMedium());
ClientProxy::MediumsAvailability availability;
availability.is_wifi_direct_go_available = true;
availability.is_wifi_direct_gc_available = true;
availability.is_wifi_hotspot_ap_available = true;
availability.is_wifi_hotspot_client_available = true;
location::nearby::connections::MediumRole role =
client1()->GetLocalMediumRole(availability);
EXPECT_FALSE(role.support_wifi_direct_group_owner());
EXPECT_TRUE(role.support_wifi_direct_group_client());
EXPECT_FALSE(role.support_wifi_hotspot_host());
EXPECT_TRUE(role.support_wifi_hotspot_client());
}
TEST_F(ClientProxyTest, GetNumIncomingAndOutgoingConnections) {
// Initially no connections
EXPECT_EQ(client1()->GetNumIncomingConnections(), 0);
EXPECT_EQ(client1()->GetNumOutgoingConnections(), 0);
// Set expectation for acceptance callback on step 1
// (which is outgoing based on discovery_connection_info_)
EXPECT_CALL(mock_advertising_connection_.accepted_cb, Call).Times(1);
// Define a complete listener for advertising
ConnectionListener advertising_listener = {
.initiated_cb = mock_advertising_connection_.initiated_cb.AsStdFunction(),
.accepted_cb = mock_advertising_connection_.accepted_cb.AsStdFunction(),
};
// 1. Establish connection 1
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_listener);
EXPECT_CALL(mock_advertising_connection_.initiated_cb, Call).Times(1);
client1()->OnConnectionInitiated(
advertising_endpoint.id, discovery_connection_info_, connection_options_,
advertising_listener, "connection_token1");
// Accept local, accept remote, and then OnConnectionAccepted
client1()->LocalEndpointAcceptedConnection(
advertising_endpoint.id,
{
.payload_cb = mock_discovery_payload_.payload_cb.AsStdFunction(),
.payload_progress_cb =
mock_discovery_payload_.payload_progress_cb.AsStdFunction(),
});
client1()->RemoteEndpointAcceptedConnection(advertising_endpoint.id);
client1()->OnConnectionAccepted(advertising_endpoint.id);
// Verify client1 has 0 incoming connections and 1 outgoing connection
EXPECT_EQ(client1()->GetNumIncomingConnections(), 0);
EXPECT_EQ(client1()->GetNumOutgoingConnections(), 1);
// Set expectation for acceptance callback on step 2
// (which is incoming based on advertising_connection_info_)
EXPECT_CALL(mock_discovery_connection_.accepted_cb, Call).Times(1);
// 2. Establish connection 2
StartDiscovery(client1(), GetDiscoveryListener());
Endpoint remote_endpoint = {
.info = ByteArray{"remote endpoint name"},
.id = "rem_ep_id",
};
OnDiscoveryEndpointFound(client1(), remote_endpoint);
EXPECT_CALL(mock_discovery_connection_.initiated_cb, Call).Times(1);
client1()->OnConnectionInitiated(
remote_endpoint.id, advertising_connection_info_, connection_options_,
discovery_connection_listener_, "connection_token2");
// Accept local, accept remote, and then OnConnectionAccepted
client1()->LocalEndpointAcceptedConnection(
remote_endpoint.id,
{
.payload_cb = mock_discovery_payload_.payload_cb.AsStdFunction(),
.payload_progress_cb =
mock_discovery_payload_.payload_progress_cb.AsStdFunction(),
});
client1()->RemoteEndpointAcceptedConnection(remote_endpoint.id);
client1()->OnConnectionAccepted(remote_endpoint.id);
// Verify client1 has 1 incoming connection and 1 outgoing connection
EXPECT_EQ(client1()->GetNumIncomingConnections(), 1);
EXPECT_EQ(client1()->GetNumOutgoingConnections(), 1);
}
TEST_F(ClientProxyTest, IsUsingP2pMediumTests) {
// With no connections, IsUsingP2pMedium should be false
EXPECT_FALSE(client1()->IsUsingP2pMedium());
// 1. Connection with Non-P2P medium (e.g. WIFI_LAN)
Endpoint endpoint_lan =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), endpoint_lan);
client1()->OnBandwidthChanged(endpoint_lan.id, Medium::WIFI_LAN);
EXPECT_FALSE(client1()->IsUsingP2pMedium());
// Clean-up connection
client1()->OnDisconnected(endpoint_lan.id, /*notify=*/false);
EXPECT_FALSE(client1()->IsUsingP2pMedium());
// 2. Connection with WIFI_DIRECT
Endpoint endpoint_direct =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), endpoint_direct);
client1()->OnBandwidthChanged(endpoint_direct.id, Medium::WIFI_DIRECT);
EXPECT_TRUE(client1()->IsUsingP2pMedium());
client1()->OnDisconnected(endpoint_direct.id, /*notify=*/false);
// 3. Connection with WIFI_HOTSPOT
Endpoint endpoint_hotspot =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), endpoint_hotspot);
client1()->OnBandwidthChanged(endpoint_hotspot.id, Medium::WIFI_HOTSPOT);
EXPECT_TRUE(client1()->IsUsingP2pMedium());
client1()->OnDisconnected(endpoint_hotspot.id, /*notify=*/false);
// 4. Connection with WIFI_AWARE
Endpoint endpoint_aware =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), endpoint_aware);
client1()->OnBandwidthChanged(endpoint_aware.id, Medium::WIFI_AWARE);
EXPECT_TRUE(client1()->IsUsingP2pMedium());
client1()->OnDisconnected(endpoint_aware.id, /*notify=*/false);
EXPECT_FALSE(client1()->IsUsingP2pMedium());
}
TEST_F(ClientProxyTest, GetAndSetLastLocalEndpointId) {
EXPECT_TRUE(client1()->GetLastLocalEndpointId().empty());
client1()->SetLastLocalEndpointId("TestEndpointID");
EXPECT_EQ(client1()->GetLastLocalEndpointId(), "TestEndpointID");
}
TEST_F(ClientProxyTest, ResetLocalEndpointId_OngoingConnectionReturnsEarly) {
std::string old_id = client1()->GetLocalEndpointId();
ASSERT_FALSE(old_id.empty());
// Set up an ongoing connection
OnAdvertisingConnectionInitiated(client1(),
{ByteArray("EndpointInfo"), "EndA"});
EXPECT_TRUE(client1()->HasOngoingConnection());
// ResetLocalEndpointId should NOT clear local_endpoint_id
client1()->ResetLocalEndpointId();
EXPECT_EQ(client1()->GetLocalEndpointId(), old_id);
// Terminate connection
client1()->OnDisconnected("EndA", /*notify=*/false);
EXPECT_FALSE(client1()->HasOngoingConnection());
// ResetLocalEndpointId should now successfully clear local_endpoint_id
client1()->ResetLocalEndpointId();
EXPECT_NE(client1()->GetLocalEndpointId(), old_id);
}
TEST_F(ClientProxyTest, ResetLocalEndpointId_SavesToLastLocalEndpointId) {
std::string old_id = client1()->GetLocalEndpointId();
ASSERT_FALSE(old_id.empty());
client1()->ResetLocalEndpointId();
EXPECT_EQ(client1()->GetLastLocalEndpointId(), old_id);
}
TEST_F(ClientProxyTest, OnSessionComplete_SavesToLastLocalEndpointId) {
std::string old_id = client1()->GetLocalEndpointId();
ASSERT_FALSE(old_id.empty());
// Put client into advertising mode first
client1()->StartedAdvertising(service_id_, strategy_, {}, {}, {});
EXPECT_TRUE(client1()->IsAdvertising());
// Stopping advertising triggers OnSessionComplete.
// Since connections_ is empty, it completes the session and should save last
// endpoint ID.
client1()->StoppedAdvertising();
EXPECT_FALSE(client1()->IsAdvertising());
EXPECT_EQ(client1()->GetLastLocalEndpointId(), old_id);
}
} // namespace
} // namespace connections
} // namespace nearby