blob: f95438a8b6c60b2acb7d3142805fe97470a9d40b [file] [log] [blame]
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "platform/public/wifi_lan.h"
#include <memory>
#include "platform/base/medium_environment.h"
#include "platform/public/count_down_latch.h"
#include "platform/public/logging.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "third_party/absl/strings/string_view.h"
namespace location {
namespace nearby {
namespace {
using FeatureFlags = FeatureFlags::Flags;
constexpr FeatureFlags kTestCases[] = {
FeatureFlags{
.enable_cancellation_flag = true,
},
FeatureFlags{
.enable_cancellation_flag = false,
},
};
constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"};
constexpr absl::string_view kServiceInfoName{"Simulated service info name"};
constexpr absl::string_view kEndpointName{"Simulated endpoint name"};
constexpr absl::string_view kEndpointInfoKey{"n"};
class WifiLanMediumTest : public ::testing::TestWithParam<FeatureFlags> {
protected:
using DiscoveredServiceCallback = WifiLanMedium::DiscoveredServiceCallback;
using AcceptedConnectionCallback = WifiLanMedium::AcceptedConnectionCallback;
WifiLanMediumTest() { env_.Stop(); }
MediumEnvironment& env_{MediumEnvironment::Instance()};
};
TEST_P(WifiLanMediumTest, CanStartAcceptingConnectionsAndConnect) {
FeatureFlags feature_flags = GetParam();
env_.SetFeatureFlags(feature_flags);
env_.Start();
WifiLanMedium wifi_a;
WifiLanMedium wifi_b;
std::string service_id(kServiceID);
std::string service_info_name{kServiceInfoName};
std::string endpoint_info_name{kEndpointName};
CountDownLatch found_latch(1);
CountDownLatch accepted_latch(1);
CancellationFlag flag;
WifiLanService* discovered_service = nullptr;
wifi_a.StartDiscovery(
service_id,
DiscoveredServiceCallback{
.service_discovered_cb =
[&found_latch, &discovered_service](
WifiLanService& service, const std::string& service_id) {
NEARBY_LOG(
INFO, "Service discovered: %s, %p",
service.GetServiceInfo().GetServiceInfoName().c_str(),
&service);
discovered_service = &service;
found_latch.CountDown();
},
});
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
wifi_b.StartAdvertising(service_id, nsd_service_info);
wifi_b.StartAcceptingConnections(
service_id,
AcceptedConnectionCallback{
.accepted_cb = [&accepted_latch](WifiLanSocket socket,
const std::string& service_id) {
NEARBY_LOG(INFO, "Connection accepted: socket=%p, service_id=%s",
&socket, service_id.c_str());
accepted_latch.CountDown();
}});
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
WifiLanSocket socket_a;
EXPECT_FALSE(socket_a.IsValid());
{
SingleThreadExecutor client_executor;
client_executor.Execute(
[&wifi_a, &socket_a, discovered_service, &service_id, &flag]() {
socket_a = wifi_a.Connect(*discovered_service, service_id, &flag);
});
}
EXPECT_TRUE(accepted_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_TRUE(socket_a.IsValid());
wifi_b.StopAcceptingConnections(service_id);
wifi_b.StopAdvertising(service_id);
wifi_a.StopDiscovery(service_id);
env_.Stop();
}
TEST_P(WifiLanMediumTest, CanCancelConnect) {
FeatureFlags feature_flags = GetParam();
env_.SetFeatureFlags(feature_flags);
env_.Start();
WifiLanMedium wifi_a;
WifiLanMedium wifi_b;
std::string service_id(kServiceID);
std::string service_info_name{kServiceInfoName};
std::string endpoint_info_name{kEndpointName};
CountDownLatch found_latch(1);
CountDownLatch accepted_latch(1);
CancellationFlag flag(true);
WifiLanService* discovered_service = nullptr;
wifi_a.StartDiscovery(
service_id,
DiscoveredServiceCallback{
.service_discovered_cb =
[&found_latch, &discovered_service](
WifiLanService& service, const std::string& service_id) {
NEARBY_LOG(
INFO, "Service discovered: %s, %p",
service.GetServiceInfo().GetServiceInfoName().c_str(),
&service);
discovered_service = &service;
found_latch.CountDown();
},
});
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
wifi_b.StartAdvertising(service_id, nsd_service_info);
wifi_b.StartAcceptingConnections(
service_id,
AcceptedConnectionCallback{
.accepted_cb = [&accepted_latch](WifiLanSocket socket,
const std::string& service_id) {
NEARBY_LOG(INFO, "Connection accepted: socket=%p, service_id=%s",
&socket, service_id.c_str());
accepted_latch.CountDown();
}});
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
WifiLanSocket socket_a;
EXPECT_FALSE(socket_a.IsValid());
{
SingleThreadExecutor client_executor;
client_executor.Execute(
[&wifi_a, &socket_a, discovered_service, &service_id, &flag]() {
socket_a = wifi_a.Connect(*discovered_service, service_id, &flag);
});
}
// If FeatureFlag is disabled, Cancelled is false as no-op.
if (!feature_flags.enable_cancellation_flag) {
EXPECT_TRUE(accepted_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_TRUE(socket_a.IsValid());
} else {
EXPECT_FALSE(accepted_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_FALSE(socket_a.IsValid());
}
wifi_b.StopAcceptingConnections(service_id);
wifi_b.StopAdvertising(service_id);
wifi_a.StopDiscovery(service_id);
env_.Stop();
}
INSTANTIATE_TEST_SUITE_P(ParametrisedWifiLanMediumTest, WifiLanMediumTest,
::testing::ValuesIn(kTestCases));
TEST_F(WifiLanMediumTest, ConstructorDestructorWorks) {
env_.Start();
WifiLanMedium wifi_a;
WifiLanMedium wifi_b;
// Make sure we can create functional mediums.
ASSERT_TRUE(wifi_a.IsValid());
ASSERT_TRUE(wifi_b.IsValid());
// Make sure we can create 2 distinct mediums.
EXPECT_NE(&wifi_a.GetImpl(), &wifi_b.GetImpl());
env_.Stop();
}
TEST_F(WifiLanMediumTest, CanStartAdvertising) {
env_.Start();
WifiLanMedium wifi_a;
WifiLanMedium wifi_b;
std::string service_id(kServiceID);
std::string service_info_name{kServiceInfoName};
std::string endpoint_info_name{kEndpointName};
CountDownLatch found_latch(1);
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
wifi_a.StartAdvertising(service_id, nsd_service_info);
EXPECT_TRUE(wifi_b.StartDiscovery(
service_id, DiscoveredServiceCallback{
.service_discovered_cb =
[&found_latch](WifiLanService& service,
const std::string& service_id) {
found_latch.CountDown();
},
}));
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_TRUE(wifi_a.StopAdvertising(service_id));
EXPECT_TRUE(wifi_b.StopDiscovery(service_id));
env_.Stop();
}
TEST_F(WifiLanMediumTest, CanStartDiscovery) {
env_.Start();
WifiLanMedium wifi_a;
WifiLanMedium wifi_b;
std::string service_id(kServiceID);
std::string service_info_name{kServiceInfoName};
std::string endpoint_info_name{kEndpointName};
CountDownLatch found_latch(1);
CountDownLatch lost_latch(1);
wifi_a.StartDiscovery(service_id,
DiscoveredServiceCallback{
.service_discovered_cb =
[&found_latch](WifiLanService& service,
absl::string_view service_id) {
found_latch.CountDown();
},
.service_lost_cb =
[&lost_latch](WifiLanService& service,
absl::string_view service_id) {
lost_latch.CountDown();
},
});
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
EXPECT_TRUE(wifi_b.StartAdvertising(service_id, nsd_service_info));
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_TRUE(wifi_b.StopAdvertising(service_id));
EXPECT_TRUE(lost_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_TRUE(wifi_a.StopDiscovery(service_id));
env_.Stop();
}
TEST_F(WifiLanMediumTest, CanStopDiscovery) {
env_.Start();
WifiLanMedium wifi_a;
WifiLanMedium wifi_b;
std::string service_id(kServiceID);
std::string service_info_name{kServiceInfoName};
std::string endpoint_info_name{kEndpointName};
CountDownLatch found_latch(1);
CountDownLatch lost_latch(1);
wifi_a.StartDiscovery(service_id,
DiscoveredServiceCallback{
.service_discovered_cb =
[&found_latch](WifiLanService& service,
absl::string_view service_id) {
found_latch.CountDown();
},
.service_lost_cb =
[&lost_latch](WifiLanService& service,
absl::string_view service_id) {
lost_latch.CountDown();
},
});
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
EXPECT_TRUE(wifi_b.StartAdvertising(service_id, nsd_service_info));
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_TRUE(wifi_a.StopDiscovery(service_id));
EXPECT_TRUE(wifi_b.StopAdvertising(service_id));
EXPECT_FALSE(lost_latch.Await(absl::Milliseconds(1000)).result());
env_.Stop();
}
} // namespace
} // namespace nearby
} // namespace location