blob: 2ac751d02ebf2e56509ef81bb110713cdb7615cd [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shill/tethering_manager.h"
#include <sys/socket.h>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include <base/cancelable_callback.h>
#include <base/containers/contains.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/string_number_conversions.h>
#include <base/test/mock_callback.h>
#include <chromeos/dbus/shill/dbus-constants.h>
#include <chromeos/patchpanel/dbus/fake_client.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <net-base/http_url.h>
#include "shill/cellular/cellular_service_provider.h"
#include "shill/cellular/mock_cellular.h"
#include "shill/cellular/mock_cellular_service.h"
#include "shill/cellular/mock_cellular_service_provider.h"
#include "shill/cellular/mock_modem_info.h"
#include "shill/error.h"
#include "shill/ethernet/mock_ethernet_provider.h"
#include "shill/http_request.h"
#include "shill/manager.h"
#include "shill/mock_control.h"
#include "shill/mock_device.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_profile.h"
#include "shill/mock_service.h"
#include "shill/network/mock_network.h"
#include "shill/portal_detector.h"
#include "shill/store/fake_store.h"
#include "shill/store/property_store.h"
#include "shill/technology.h"
#include "shill/test_event_dispatcher.h"
#include "shill/upstart/mock_upstart.h"
#include "shill/wifi/local_device.h"
#include "shill/wifi/local_service.h"
#include "shill/wifi/mock_hotspot_device.h"
#include "shill/wifi/mock_wifi.h"
#include "shill/wifi/mock_wifi_phy.h"
#include "shill/wifi/mock_wifi_provider.h"
using testing::_;
using testing::DoAll;
using testing::DoDefault;
using testing::Eq;
using testing::Invoke;
using testing::Mock;
using testing::NiceMock;
using testing::Not;
using testing::Return;
using testing::StrictMock;
using testing::Test;
using testing::WithArg;
namespace shill {
namespace {
// Fake profile identities
constexpr char kDefaultProfile[] = "default";
constexpr char kUserProfile[] = "~user/profile";
constexpr uint32_t kPhyIndex = 5678;
constexpr int kTestInterfaceIndex = 3;
constexpr char kTestInterfaceName[] = "wwan0";
constexpr char kTestDownstreamDeviceForTest[] = "wlan5";
constexpr uint32_t kTestDownstreamPhyIndexForTest = 5;
// The value below is "testAP-0000" in hex;
constexpr char kTestAPHexSSID[] = "7465737441502d30303030";
constexpr char kTestPassword[] = "user_password";
bool GetConfigMAR(const KeyValueStore& caps) {
return caps.Get<bool>(kTetheringConfMARProperty);
}
bool GetConfigAutoDisable(const KeyValueStore& caps) {
return caps.Get<bool>(kTetheringConfAutoDisableProperty);
}
std::string GetConfigSSID(const KeyValueStore& caps) {
return caps.Get<std::string>(kTetheringConfSSIDProperty);
}
std::string GetConfigPassphrase(const KeyValueStore& caps) {
return caps.Get<std::string>(kTetheringConfPassphraseProperty);
}
std::string GetConfigSecurity(const KeyValueStore& caps) {
return caps.Get<std::string>(kTetheringConfSecurityProperty);
}
std::string GetConfigBand(const KeyValueStore& caps) {
return caps.Get<std::string>(kTetheringConfBandProperty);
}
std::string GetConfigUpstream(const KeyValueStore& caps) {
return caps.Get<std::string>(kTetheringConfUpstreamTechProperty);
}
std::string GetConfigDownstreamDeviceForTest(const KeyValueStore& caps) {
return caps.Get<std::string>(kTetheringConfDownstreamDeviceForTestProperty);
}
uint32_t GetConfigDownstreamPhyIndexForTest(const KeyValueStore& caps) {
return caps.Get<uint32_t>(kTetheringConfDownstreamPhyIndexForTestProperty);
}
void SetConfigMAR(KeyValueStore& caps, bool value) {
caps.Set<bool>(kTetheringConfMARProperty, value);
}
void SetConfigAutoDisable(KeyValueStore& caps, bool value) {
caps.Set<bool>(kTetheringConfAutoDisableProperty, value);
}
void SetConfigSSID(KeyValueStore& caps, const std::string& value) {
caps.Set<std::string>(kTetheringConfSSIDProperty, value);
}
void SetConfigPassphrase(KeyValueStore& caps, const std::string& value) {
caps.Set<std::string>(kTetheringConfPassphraseProperty, value);
}
void SetConfigSecurity(KeyValueStore& caps, const std::string& value) {
caps.Set<std::string>(kTetheringConfSecurityProperty, value);
}
void SetConfigBand(KeyValueStore& caps, const std::string& value) {
caps.Set<std::string>(kTetheringConfBandProperty, value);
}
void SetConfigUpstream(KeyValueStore& caps, const std::string& value) {
caps.Set<std::string>(kTetheringConfUpstreamTechProperty, value);
}
void SetConfigDownstreamDeviceForTest(KeyValueStore& caps,
const std::string& value) {
caps.Set<std::string>(kTetheringConfDownstreamDeviceForTestProperty, value);
}
void SetConfigDownstreamPhyIndexForTest(KeyValueStore& caps, uint32_t value) {
caps.Set<uint32_t>(kTetheringConfDownstreamPhyIndexForTestProperty, value);
}
base::ScopedTempDir MakeTempDir() {
base::ScopedTempDir temp_dir;
EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
return temp_dir;
}
class MockPatchpanelClient : public patchpanel::FakeClient {
public:
MockPatchpanelClient() = default;
~MockPatchpanelClient() override = default;
MOCK_METHOD(bool,
CreateTetheredNetwork,
(const std::string&,
const std::string&,
const std::optional<DHCPOptions>&,
const std::optional<UplinkIPv6Configuration>&,
const std::optional<int>& mtu,
patchpanel::Client::CreateTetheredNetworkCallback),
(override));
};
base::ScopedFD MakeFd() {
return base::ScopedFD(socket(AF_INET, SOCK_DGRAM, 0));
}
} // namespace
class TetheringManagerTest : public testing::Test {
public:
TetheringManagerTest()
: temp_dir_(MakeTempDir()),
path_(temp_dir_.GetPath().value()),
manager_(
&control_interface_, &dispatcher_, &metrics_, path_, path_, path_),
modem_info_(&control_interface_, &manager_),
tethering_manager_(manager_.tethering_manager()),
wifi_provider_(new NiceMock<MockWiFiProvider>(&manager_)),
ethernet_provider_(new NiceMock<MockEthernetProvider>()),
cellular_service_provider_(
new NiceMock<MockCellularServiceProvider>(&manager_)),
upstart_(new NiceMock<MockUpstart>(&control_interface_)),
hotspot_device_(new NiceMock<MockHotspotDevice>(
&manager_, "wlan0", "ap0", "", 0, event_cb_.Get())),
network_(new MockNetwork(
kTestInterfaceIndex, kTestInterfaceName, Technology::kCellular)),
service_(new MockService(&manager_)),
wifi_phy_(hotspot_device_->phy_index()) {
// Replace the Manager's WiFi provider with a mock.
manager_.wifi_provider_.reset(wifi_provider_);
// Replace the Manager's Ethernet provider with a mock.
manager_.ethernet_provider_.reset(ethernet_provider_);
// Replace the Manager's Cellular provider with a mock.
manager_.cellular_service_provider_.reset(cellular_service_provider_);
// Update the Manager's map from technology to provider.
manager_.UpdateProviderMapping();
// Replace the Manager's upstart instance with a mock.
manager_.upstart_.reset(upstart_);
// Replace the Manager's patchpanel DBus client with a mock.
auto patchpanel = std::make_unique<MockPatchpanelClient>();
patchpanel_ = patchpanel.get();
manager_.set_patchpanel_client_for_testing(std::move(patchpanel));
ON_CALL(manager_, cellular_service_provider())
.WillByDefault(Return(cellular_service_provider_));
cellular_profile_ = new NiceMock<MockProfile>(&manager_);
cellular_service_provider_->set_profile_for_testing(cellular_profile_);
ON_CALL(manager_, modem_info()).WillByDefault(Return(&modem_info_));
ON_CALL(*wifi_provider_, CreateHotspotDevice)
.WillByDefault(Return(hotspot_device_));
ON_CALL(*hotspot_device_.get(), ConfigureService(_))
.WillByDefault(Return(true));
ON_CALL(*hotspot_device_.get(), DeconfigureService())
.WillByDefault(Return(true));
ON_CALL(*hotspot_device_.get(), IsServiceUp()).WillByDefault(Return(true));
ON_CALL(*cellular_service_provider_, AcquireTetheringNetwork(_, _, _, _))
.WillByDefault(Return());
ON_CALL(*cellular_service_provider_, ReleaseTetheringNetwork(_, _))
.WillByDefault(Return());
ON_CALL(*network_, IsConnected()).WillByDefault(Return(true));
ON_CALL(*wifi_provider_, GetPhyAtIndex(hotspot_device_->phy_index()))
.WillByDefault(Return(&wifi_phy_));
wifi_phy_.SetFrequencies(
{{0, {{.value = 2412}, {.value = 2432}, {.value = 2437}}},
{1, {{.value = 5220}, {.value = 5240}}}});
}
~TetheringManagerTest() override = default;
scoped_refptr<MockCellular> MakeCellular(const std::string& link_name,
const std::string& address,
int interface_index) {
return new NiceMock<MockCellular>(&manager_, link_name, address,
interface_index, "", RpcIdentifier(""));
}
Error::Type TestCreateProfile(Manager* manager, const std::string& name) {
Error error;
std::string path;
manager->CreateProfile(name, &path, &error);
return error.type();
}
Error::Type TestPushProfile(Manager* manager, const std::string& name) {
Error error;
std::string path;
manager->PushProfile(name, &path, &error);
return error.type();
}
Error::Type TestPopProfile(Manager* manager, const std::string& name) {
Error error;
manager->PopProfile(name, &error);
return error.type();
}
void SetAllowed(TetheringManager* tethering_manager, bool allowed) {
Error error;
PropertyStore store;
tethering_manager->InitPropertyStore(&store);
store.SetBoolProperty(kTetheringAllowedProperty, allowed, &error);
EXPECT_TRUE(error.IsSuccess());
}
KeyValueStore GetCapabilities(TetheringManager* tethering_manager) {
Error error;
KeyValueStore caps = tethering_manager->GetCapabilities(&error);
EXPECT_TRUE(error.IsSuccess());
return caps;
}
bool SetAndPersistConfig(TetheringManager* tethering_manager,
const KeyValueStore& config) {
Error error;
bool is_success = tethering_manager->SetAndPersistConfig(config, &error);
EXPECT_EQ(is_success, error.IsSuccess());
return is_success;
}
void SetEnabled(TetheringManager* tethering_manager, bool enabled) {
tethering_manager->SetEnabled(enabled, result_cb_.Get());
}
void VerifyResult(TetheringManager::SetEnabledResult expected_result) {
EXPECT_CALL(result_cb_, Run(expected_result));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&result_cb_);
EXPECT_TRUE(GetStartTimer(tethering_manager_).IsCancelled());
}
void SetEnabledVerifyResult(
TetheringManager* tethering_manager,
bool enabled,
TetheringManager::SetEnabledResult expected_result) {
SetEnabled(tethering_manager, enabled);
if (enabled) {
ON_CALL(*patchpanel_, CreateTetheredNetwork("ap0", "wwan0", _, _, _, _))
.WillByDefault(Return(true));
// Send upstream downstream ready events.
DownStreamDeviceEvent(tethering_manager,
LocalDevice::DeviceEvent::kInterfaceEnabled,
hotspot_device_.get());
DownStreamDeviceEvent(tethering_manager,
LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
OnDownstreamNetworkReady(tethering_manager_, MakeFd());
} else {
// Send upstream tear down event
OnUpstreamNetworkReleased(tethering_manager_, true);
}
VerifyResult(expected_result);
}
KeyValueStore GetConfig(TetheringManager* tethering_manager) {
Error error;
KeyValueStore caps = tethering_manager->GetConfig(&error);
EXPECT_TRUE(error.IsSuccess());
return caps;
}
bool SaveConfig(TetheringManager* tethering_manager,
StoreInterface* storage) {
return tethering_manager->Save(storage);
}
bool FromProperties(TetheringManager* tethering_manager,
const KeyValueStore& config) {
return tethering_manager->FromProperties(config).has_value();
}
KeyValueStore VerifyDefaultTetheringConfig(
TetheringManager* tethering_manager) {
KeyValueStore caps = GetConfig(tethering_manager);
EXPECT_TRUE(GetConfigMAR(caps));
EXPECT_TRUE(tethering_manager->stable_mac_addr_.is_set());
EXPECT_TRUE(GetConfigAutoDisable(caps));
EXPECT_FALSE(tethering_manager_->experimental_tethering_functionality_);
std::string ssid = GetConfigSSID(caps);
EXPECT_FALSE(ssid.empty());
EXPECT_TRUE(std::all_of(ssid.begin(), ssid.end(), ::isxdigit));
std::string passphrase = GetConfigPassphrase(caps);
EXPECT_FALSE(passphrase.empty());
EXPECT_TRUE(std::all_of(passphrase.begin(), passphrase.end(), ::isxdigit));
EXPECT_EQ(kSecurityWpa2, GetConfigSecurity(caps));
EXPECT_EQ(GetConfigBand(caps), kBandAll);
EXPECT_TRUE(caps.Contains<std::string>(kTetheringConfUpstreamTechProperty));
EXPECT_FALSE(caps.Contains<std::string>(
kTetheringConfDownstreamDeviceForTestProperty));
EXPECT_FALSE(caps.Contains<uint32_t>(
kTetheringConfDownstreamPhyIndexForTestProperty));
return caps;
}
KeyValueStore GenerateFakeConfig(
const std::string& ssid,
const std::string passphrase,
const std::optional<std::string> downstream_device_for_test =
std::nullopt,
const std::optional<uint32_t> downstream_phy_index_for_test =
std::nullopt) {
KeyValueStore config;
SetConfigMAR(config, false);
SetConfigAutoDisable(config, false);
SetConfigSSID(config, ssid);
SetConfigPassphrase(config, passphrase);
SetConfigSecurity(config, kSecurityWpa3);
SetConfigBand(config, kBand2GHz);
SetConfigUpstream(config, kTypeCellular);
if (downstream_device_for_test) {
SetConfigDownstreamDeviceForTest(config, *downstream_device_for_test);
EXPECT_NE(downstream_phy_index_for_test, std::nullopt);
SetConfigDownstreamPhyIndexForTest(config,
*downstream_phy_index_for_test);
}
return config;
}
void DispatchPendingEvents() { dispatcher_.DispatchPendingEvents(); }
void TetheringPrerequisite(TetheringManager* tethering_manager) {
SetAllowed(tethering_manager, true);
ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager_, kDefaultProfile));
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kDefaultProfile));
ASSERT_TRUE(base::CreateDirectory(temp_dir_.GetPath().Append("user")));
ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager_, kUserProfile));
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kUserProfile));
}
void DownStreamDeviceEvent(TetheringManager* tethering_manager,
LocalDevice::DeviceEvent event,
LocalDevice* device) {
tethering_manager->OnDownstreamDeviceEvent(event, device);
}
void OnCellularUpstreamEvent(TetheringManager* tethering_manager,
TetheringManager::CellularUpstreamEvent event) {
tethering_manager->OnCellularUpstreamEvent(event);
}
TetheringManager::TetheringState TetheringState(
TetheringManager* tethering_manager) {
return tethering_manager->state_;
}
std::string StopReason(TetheringManager* tethering_manager) {
return TetheringManager::StopReasonToString(
tethering_manager->stop_reason_);
}
void CheckTetheringStopping(TetheringManager* tethering_manager,
const char* reason) {
EXPECT_EQ(TetheringState(tethering_manager),
TetheringManager::TetheringState::kTetheringStopping);
EXPECT_EQ(StopReason(tethering_manager), reason);
}
void CheckTetheringIdle(TetheringManager* tethering_manager,
const char* reason) {
EXPECT_EQ(tethering_manager->hotspot_dev_, nullptr);
EXPECT_EQ(TetheringState(tethering_manager),
TetheringManager::TetheringState::kTetheringIdle);
auto status = GetStatus(tethering_manager);
EXPECT_EQ(status.Get<std::string>(kTetheringStatusIdleReasonProperty),
reason);
EXPECT_TRUE(GetStartTimer(tethering_manager_).IsCancelled());
EXPECT_TRUE(GetStopTimer(tethering_manager_).IsCancelled());
}
KeyValueStore GetStatus(TetheringManager* tethering_manager) {
return tethering_manager->GetStatus();
}
void OnStartingTetheringTimeout(TetheringManager* tethering_manager) {
tethering_manager->OnStartingTetheringTimeout();
}
void OnStartingTetheringUpdateTimeout(TetheringManager* tethering_manager,
base::TimeDelta timeout) {
tethering_manager->OnStartingTetheringUpdateTimeout(timeout);
}
void OnStoppingTetheringTimeout(TetheringManager* tethering_manager) {
tethering_manager->OnStoppingTetheringTimeout();
}
const base::CancelableOnceClosure& GetStartTimer(
TetheringManager* tethering_manager) {
return tethering_manager->start_timer_callback_;
}
const base::CancelableOnceClosure& GetStopTimer(
TetheringManager* tethering_manager) {
return tethering_manager->stop_timer_callback_;
}
const base::CancelableOnceClosure& GetInactiveTimer(
TetheringManager* tethering_manager) {
return tethering_manager->inactive_timer_callback_;
}
void AddServiceToCellularProvider(CellularServiceRefPtr service) {
cellular_service_provider_->AddService(service);
}
void OnDownstreamNetworkReady(TetheringManager* tethering_manager,
base::ScopedFD fd) {
tethering_manager->OnDownstreamNetworkReady(std::move(fd));
}
void OnUpstreamNetworkAcquired(TetheringManager* tethering_manager,
TetheringManager::SetEnabledResult result) {
tethering_manager->OnUpstreamNetworkAcquired(result, network_.get(),
service_.get());
}
void OnUpstreamNetworkReleased(TetheringManager* tethering_manager,
bool success) {
tethering_manager->OnUpstreamNetworkReleased(success);
}
void OnUpstreamNetworkStopped(TetheringManager* tethering_manager) {
tethering_manager->OnNetworkStopped(kTestInterfaceIndex, false);
}
void OnUpstreamNetworkDestroyed(TetheringManager* tethering_manager) {
tethering_manager->OnNetworkDestroyed(kTestInterfaceIndex);
}
void OnUpstreamNetworkValidationResult(TetheringManager* tethering_manager,
const PortalDetector::Result& result) {
tethering_manager->OnNetworkValidationResult(kTestInterfaceIndex, result);
}
protected:
StrictMock<base::MockRepeatingCallback<void(LocalDevice::DeviceEvent,
const LocalDevice*)>>
event_cb_;
StrictMock<base::MockOnceCallback<void(TetheringManager::SetEnabledResult)>>
result_cb_;
NiceMock<MockControl> control_interface_;
EventDispatcherForTest dispatcher_;
NiceMock<MockMetrics> metrics_;
base::ScopedTempDir temp_dir_;
std::string path_;
MockManager manager_;
MockModemInfo modem_info_;
MockPatchpanelClient* patchpanel_;
TetheringManager* tethering_manager_;
MockWiFiProvider* wifi_provider_;
MockEthernetProvider* ethernet_provider_;
scoped_refptr<NiceMock<MockProfile>> cellular_profile_;
MockCellularServiceProvider* cellular_service_provider_;
MockUpstart* upstart_;
scoped_refptr<MockHotspotDevice> hotspot_device_;
std::unique_ptr<MockNetwork> network_;
scoped_refptr<MockService> service_;
MockWiFiPhy wifi_phy_;
};
TEST_F(TetheringManagerTest, GetTetheringCapabilities) {
std::unique_ptr<NiceMock<MockWiFiPhy>> phy(
new NiceMock<MockWiFiPhy>(kPhyIndex));
const std::vector<const WiFiPhy*> phys = {phy.get()};
ON_CALL(*wifi_provider_, GetPhys()).WillByDefault(Return(phys));
ON_CALL(*phy, SupportAPMode()).WillByDefault(Return(true));
ON_CALL(*phy, SupportAPSTAConcurrency()).WillByDefault(Return(true));
EXPECT_CALL(*cellular_service_provider_, HardwareSupportsTethering(_))
.WillOnce(Return(true));
SetAllowed(tethering_manager_, true);
KeyValueStore caps = GetCapabilities(tethering_manager_);
auto upstream_technologies =
caps.Get<std::vector<std::string>>(kTetheringCapUpstreamProperty);
EXPECT_FALSE(upstream_technologies.empty());
EXPECT_TRUE(base::Contains(upstream_technologies, kTypeEthernet));
EXPECT_TRUE(base::Contains(upstream_technologies, kTypeCellular));
EXPECT_FALSE(base::Contains(upstream_technologies, kTypeWifi));
auto downstream_technologies =
caps.Get<std::vector<std::string>>(kTetheringCapDownstreamProperty);
EXPECT_FALSE(downstream_technologies.empty());
EXPECT_FALSE(base::Contains(downstream_technologies, kTypeEthernet));
EXPECT_FALSE(base::Contains(downstream_technologies, kTypeCellular));
EXPECT_TRUE(base::Contains(downstream_technologies, kTypeWifi));
std::vector<std::string> wifi_security =
caps.Get<std::vector<std::string>>(kTetheringCapSecurityProperty);
EXPECT_FALSE(wifi_security.empty());
}
TEST_F(TetheringManagerTest, GetTetheringCapabilitiesWithoutWiFi) {
const std::vector<DeviceRefPtr> devices;
ON_CALL(manager_, FilterByTechnology(Technology::kWiFi))
.WillByDefault(Return(devices));
EXPECT_CALL(*cellular_service_provider_, HardwareSupportsTethering(_))
.WillOnce(Return(true));
SetAllowed(tethering_manager_, true);
KeyValueStore caps = GetCapabilities(tethering_manager_);
auto upstream_technologies =
caps.Get<std::vector<std::string>>(kTetheringCapUpstreamProperty);
EXPECT_FALSE(upstream_technologies.empty());
EXPECT_TRUE(base::Contains(upstream_technologies, kTypeEthernet));
EXPECT_TRUE(base::Contains(upstream_technologies, kTypeCellular));
EXPECT_FALSE(base::Contains(upstream_technologies, kTypeWifi));
auto downstream_technologies =
caps.Get<std::vector<std::string>>(kTetheringCapDownstreamProperty);
EXPECT_TRUE(downstream_technologies.empty());
EXPECT_FALSE(
caps.Contains<std::vector<std::string>>(kTetheringCapSecurityProperty));
}
TEST_F(TetheringManagerTest, GetTetheringCapabilitiesWithoutCellular) {
std::unique_ptr<NiceMock<MockWiFiPhy>> phy(
new NiceMock<MockWiFiPhy>(kPhyIndex));
const std::vector<const WiFiPhy*> phys = {phy.get()};
ON_CALL(*wifi_provider_, GetPhys()).WillByDefault(Return(phys));
ON_CALL(*phy, SupportAPMode()).WillByDefault(Return(true));
ON_CALL(*phy, SupportAPSTAConcurrency()).WillByDefault(Return(true));
EXPECT_CALL(*cellular_service_provider_, HardwareSupportsTethering(_))
.WillOnce(Return(false));
SetAllowed(tethering_manager_, true);
KeyValueStore caps = GetCapabilities(tethering_manager_);
auto upstream_technologies =
caps.Get<std::vector<std::string>>(kTetheringCapUpstreamProperty);
EXPECT_FALSE(upstream_technologies.empty());
EXPECT_TRUE(base::Contains(upstream_technologies, kTypeEthernet));
EXPECT_FALSE(base::Contains(upstream_technologies, kTypeCellular));
EXPECT_FALSE(base::Contains(upstream_technologies, kTypeWifi));
auto downstream_technologies =
caps.Get<std::vector<std::string>>(kTetheringCapDownstreamProperty);
EXPECT_FALSE(downstream_technologies.empty());
EXPECT_FALSE(base::Contains(downstream_technologies, kTypeEthernet));
EXPECT_FALSE(base::Contains(downstream_technologies, kTypeCellular));
EXPECT_TRUE(base::Contains(downstream_technologies, kTypeWifi));
std::vector<std::string> wifi_security =
caps.Get<std::vector<std::string>>(kTetheringCapSecurityProperty);
EXPECT_FALSE(wifi_security.empty());
}
TEST_F(TetheringManagerTest, TetheringConfig) {
SetAllowed(tethering_manager_, true);
ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager_, kDefaultProfile));
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kDefaultProfile));
// Check default TetheringConfig.
VerifyDefaultTetheringConfig(tethering_manager_);
// Fake Tethering configuration.
KeyValueStore args = GenerateFakeConfig(kTestAPHexSSID, kTestPassword,
kTestDownstreamDeviceForTest,
kTestDownstreamPhyIndexForTest);
// Block SetAndPersistConfig when no user has logged in.
EXPECT_FALSE(SetAndPersistConfig(tethering_manager_, args));
// SetAndPersistConfig succeeds when a user is logged in.
ASSERT_TRUE(base::CreateDirectory(temp_dir_.GetPath().Append("user")));
ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager_, kUserProfile));
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kUserProfile));
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, args));
// Read the configuration and check if it matches.
KeyValueStore config = GetConfig(tethering_manager_);
EXPECT_FALSE(GetConfigMAR(config));
EXPECT_FALSE(GetConfigAutoDisable(config));
EXPECT_EQ(GetConfigSSID(config), kTestAPHexSSID);
EXPECT_EQ(GetConfigPassphrase(config), kTestPassword);
EXPECT_EQ(GetConfigSecurity(config), kSecurityWpa3);
EXPECT_EQ(GetConfigBand(config), kBand2GHz);
EXPECT_EQ(GetConfigUpstream(config), kTypeCellular);
EXPECT_EQ(GetConfigDownstreamDeviceForTest(config),
kTestDownstreamDeviceForTest);
EXPECT_EQ(GetConfigDownstreamPhyIndexForTest(config),
kTestDownstreamPhyIndexForTest);
// Log out user and check user's tethering config is not present.
EXPECT_EQ(Error::kSuccess, TestPopProfile(&manager_, kUserProfile));
KeyValueStore default_config = GetConfig(tethering_manager_);
EXPECT_NE(GetConfigSSID(default_config), kTestAPHexSSID);
EXPECT_NE(GetConfigPassphrase(default_config), kTestPassword);
// Log in user and check tethering config again.
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kUserProfile));
config = GetConfig(tethering_manager_);
EXPECT_FALSE(GetConfigMAR(config));
EXPECT_FALSE(GetConfigAutoDisable(config));
EXPECT_EQ(GetConfigSSID(config), kTestAPHexSSID);
EXPECT_EQ(GetConfigPassphrase(config), kTestPassword);
EXPECT_EQ(GetConfigSecurity(config), kSecurityWpa3);
EXPECT_EQ(GetConfigBand(config), kBand2GHz);
EXPECT_EQ(GetConfigUpstream(config), kTypeCellular);
// These properties are only used for testing, should not be persisted.
EXPECT_FALSE(
config.ContainsVariant(kTetheringConfDownstreamDeviceForTestProperty));
EXPECT_FALSE(
config.ContainsVariant(kTetheringConfDownstreamPhyIndexForTestProperty));
}
TEST_F(TetheringManagerTest, DefaultConfigCheck) {
SetAllowed(tethering_manager_, true);
// SetEnabled proceed to starting state and persist the default config.
ASSERT_TRUE(base::CreateDirectory(temp_dir_.GetPath().Append("user")));
ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager_, kUserProfile));
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kUserProfile));
KeyValueStore config = GetConfig(tethering_manager_);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Log out user and check a new SSID and passphrase is generated.
EXPECT_EQ(Error::kSuccess, TestPopProfile(&manager_, kUserProfile));
KeyValueStore default_config = GetConfig(tethering_manager_);
EXPECT_NE(GetConfigSSID(config), GetConfigSSID(default_config));
EXPECT_NE(GetConfigPassphrase(config), GetConfigPassphrase(default_config));
EXPECT_FALSE(default_config.ContainsVariant(
kTetheringConfDownstreamDeviceForTestProperty));
EXPECT_FALSE(default_config.ContainsVariant(
kTetheringConfDownstreamPhyIndexForTestProperty));
// Log in user and check the tethering config matches.
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kUserProfile));
KeyValueStore new_config = GetConfig(tethering_manager_);
EXPECT_EQ(GetConfigMAR(config), GetConfigMAR(new_config));
EXPECT_EQ(GetConfigAutoDisable(config), GetConfigAutoDisable(new_config));
EXPECT_EQ(GetConfigSSID(config), GetConfigSSID(new_config));
EXPECT_EQ(GetConfigPassphrase(config), GetConfigPassphrase(new_config));
EXPECT_EQ(GetConfigBand(config), kBandAll);
EXPECT_TRUE(
new_config.Contains<std::string>(kTetheringConfUpstreamTechProperty));
EXPECT_FALSE(new_config.ContainsVariant(
kTetheringConfDownstreamDeviceForTestProperty));
EXPECT_FALSE(new_config.ContainsVariant(
kTetheringConfDownstreamPhyIndexForTestProperty));
}
TEST_F(TetheringManagerTest, TetheringConfigLoadAndUnload) {
// Check properties of the default tethering configuration.
VerifyDefaultTetheringConfig(tethering_manager_);
// Prepare faked tethering configuration stored for a fake user profile.
FakeStore store;
store.SetBool(TetheringManager::kStorageId, kTetheringConfAutoDisableProperty,
true);
store.SetBool(TetheringManager::kStorageId, kTetheringConfMARProperty, true);
MACAddress mac;
mac.Randomize();
mac.Save(&store, TetheringManager::kStorageId);
store.SetString(TetheringManager::kStorageId, kTetheringConfSSIDProperty,
kTestAPHexSSID);
store.SetString(TetheringManager::kStorageId,
kTetheringConfPassphraseProperty, kTestPassword);
store.SetString(TetheringManager::kStorageId, kTetheringConfSecurityProperty,
kSecurityWpa3);
store.SetString(TetheringManager::kStorageId, kTetheringConfBandProperty,
kBand5GHz);
store.SetString(TetheringManager::kStorageId,
kTetheringConfUpstreamTechProperty, kTypeCellular);
store.SetString(TetheringManager::kStorageId,
kTetheringConfDownstreamDeviceForTestProperty, "wlan5");
store.SetUint64(TetheringManager::kStorageId,
kTetheringConfDownstreamPhyIndexForTestProperty, 5);
scoped_refptr<MockProfile> profile =
new MockProfile(&manager_, "~user/profile0");
EXPECT_CALL(*profile, GetConstStorage()).WillRepeatedly(Return(&store));
// Check faked properties are loaded.
tethering_manager_->LoadConfigFromProfile(profile);
KeyValueStore caps = GetConfig(tethering_manager_);
EXPECT_TRUE(GetConfigMAR(caps));
EXPECT_EQ(tethering_manager_->stable_mac_addr_, mac);
EXPECT_TRUE(GetConfigAutoDisable(caps));
EXPECT_EQ(kTestAPHexSSID, GetConfigSSID(caps));
EXPECT_EQ(kTestPassword, GetConfigPassphrase(caps));
EXPECT_EQ(kSecurityWpa3, GetConfigSecurity(caps));
EXPECT_EQ(kBand5GHz, GetConfigBand(caps));
EXPECT_EQ(kTypeCellular, GetConfigUpstream(caps));
// These properties should not be loaded from persisted storage, because they
// are only for testing.
EXPECT_FALSE(
caps.ContainsVariant(kTetheringConfDownstreamDeviceForTestProperty));
EXPECT_FALSE(
caps.ContainsVariant(kTetheringConfDownstreamPhyIndexForTestProperty));
// Check the tethering config is reset to default properties when unloading
// the profile.
tethering_manager_->UnloadConfigFromProfile();
caps = VerifyDefaultTetheringConfig(tethering_manager_);
EXPECT_NE(kTestAPHexSSID, caps.Get<std::string>(kTetheringConfSSIDProperty));
EXPECT_NE(kTestPassword,
caps.Get<std::string>(kTetheringConfPassphraseProperty));
}
TEST_F(TetheringManagerTest, TetheringConfigSaveAndLoad) {
// Load a fake tethering configuration.
KeyValueStore config1 = GenerateFakeConfig(kTestAPHexSSID, kTestPassword,
kTestDownstreamDeviceForTest,
kTestDownstreamPhyIndexForTest);
FromProperties(tethering_manager_, config1);
// Save the fake tethering configuration
FakeStore store;
SaveConfig(tethering_manager_, &store);
// These properties should not be saved to persisted storage, because they are
// only for testing.
EXPECT_FALSE(store.GetString(TetheringManager::kStorageId,
kTetheringConfDownstreamDeviceForTestProperty,
nullptr));
EXPECT_FALSE(store.GetUint64(TetheringManager::kStorageId,
kTetheringConfDownstreamPhyIndexForTestProperty,
nullptr));
// Force the default configuration to change by unloading the profile.
tethering_manager_->UnloadConfigFromProfile();
// Reload the configuration
scoped_refptr<MockProfile> profile =
new MockProfile(&manager_, "~user/profile0");
EXPECT_CALL(*profile, GetConstStorage()).WillRepeatedly(Return(&store));
tethering_manager_->LoadConfigFromProfile(profile);
// Check that the configurations are identical
KeyValueStore config2 = GetConfig(tethering_manager_);
EXPECT_EQ(GetConfigMAR(config1), GetConfigMAR(config2));
EXPECT_EQ(GetConfigAutoDisable(config1), GetConfigAutoDisable(config2));
EXPECT_EQ(GetConfigSSID(config1), GetConfigSSID(config2));
EXPECT_EQ(GetConfigPassphrase(config1), GetConfigPassphrase(config2));
EXPECT_EQ(GetConfigBand(config1), GetConfigBand(config2));
EXPECT_EQ(GetConfigUpstream(config1), GetConfigUpstream(config2));
}
TEST_F(TetheringManagerTest, TetheringIsNotAllowed) {
// Fake Tethering configuration.
KeyValueStore config = GenerateFakeConfig(kTestAPHexSSID, kTestPassword);
// Push a user profile
ASSERT_TRUE(base::CreateDirectory(temp_dir_.GetPath().Append("user")));
ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager_, kUserProfile));
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kUserProfile));
// Tethering is not allowed. SetAndPersistConfig and SetEnabled should fail
// with error code kNotAllowed.
SetAllowed(tethering_manager_, false);
EXPECT_FALSE(SetAndPersistConfig(tethering_manager_, config));
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kNotAllowed);
// Tethering is allowed. SetAndPersistConfig and SetEnabled should success
SetAllowed(tethering_manager_, true);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
}
TEST_F(TetheringManagerTest, TetheringInDefaultProfile) {
SetAllowed(tethering_manager_, true);
// SetEnabled fails for the default profile.
ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager_, kDefaultProfile));
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kDefaultProfile));
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kNotAllowed);
}
TEST_F(TetheringManagerTest, CheckReadinessNotAllowed) {
base::MockOnceCallback<void(TetheringManager::EntitlementStatus)> cb;
KeyValueStore config = GenerateFakeConfig(kTestAPHexSSID, kTestPassword);
// Not allowed.
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(cb, Run(TetheringManager::EntitlementStatus::kNotAllowed));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
}
TEST_F(TetheringManagerTest, CheckReadinessCellularUpstream) {
base::MockOnceCallback<void(TetheringManager::EntitlementStatus)> cb;
KeyValueStore config =
GenerateFakeConfig("757365725F73736964", "user_password");
SetConfigUpstream(config, TechnologyName(Technology::kCellular));
SetAllowed(tethering_manager_, true);
EXPECT_TRUE(FromProperties(tethering_manager_, config));
// No cellular Device.
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(
cb,
Run(TetheringManager::EntitlementStatus::kUpstreamNetworkNotAvailable));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
// Set one fake ethernet Device.
auto eth =
new NiceMock<MockDevice>(&manager_, "eth0", "0a:0b:0c:0d:0e:0f", 1);
ON_CALL(*eth, technology()).WillByDefault(Return(Technology::kEthernet));
const std::vector<DeviceRefPtr> eth_devices = {eth};
ON_CALL(manager_, FilterByTechnology(Technology::kEthernet))
.WillByDefault(Return(eth_devices));
auto eth_service(new MockService(&manager_));
eth->set_selected_service_for_testing(eth_service);
// Set one fake cellular Device.
auto cell = MakeCellular("wwan0", "000102030405", 2);
const std::vector<DeviceRefPtr> cell_devices = {cell};
ON_CALL(manager_, FilterByTechnology(Technology::kCellular))
.WillByDefault(Return(cell_devices));
scoped_refptr<MockCellularService> cell_service =
new MockCellularService(&manager_, cell);
AddServiceToCellularProvider(cell_service);
cell->set_selected_service_for_testing(cell_service);
// Both Ethernet Service and Cellular Service are disconnected.
EXPECT_CALL(*eth_service, IsConnected(_)).WillRepeatedly(Return(false));
EXPECT_CALL(*cell_service, state())
.WillRepeatedly(Return(Service::kStateIdle));
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(
cb,
Run(TetheringManager::EntitlementStatus::kUpstreamNetworkNotAvailable));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
// Ethernet Service is connected, Cellular Service is disconnected.
EXPECT_CALL(*eth_service, IsConnected(_)).WillRepeatedly(Return(true));
EXPECT_CALL(*cell_service, state())
.WillRepeatedly(Return(Service::kStateIdle));
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(
cb,
Run(TetheringManager::EntitlementStatus::kUpstreamNetworkNotAvailable));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
// Ethernet Service is disconnected, Cellular Service is connected.
EXPECT_CALL(*eth_service, IsConnected(_)).WillRepeatedly(Return(false));
EXPECT_CALL(*cell_service, state())
.WillRepeatedly(Return(Service::kStateConnected));
EXPECT_CALL(*cellular_service_provider_, TetheringEntitlementCheck(_, _));
tethering_manager_->CheckReadiness(cb.Get());
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
Mock::VerifyAndClearExpectations(cellular_service_provider_);
// Both Ethernet Service and Cellular Service are connected.
EXPECT_CALL(*eth_service, IsConnected(_)).WillRepeatedly(Return(true));
EXPECT_CALL(*cell_service, state())
.WillRepeatedly(Return(Service::kStateConnected));
EXPECT_CALL(*cellular_service_provider_, TetheringEntitlementCheck(_, _));
tethering_manager_->CheckReadiness(cb.Get());
DispatchPendingEvents();
}
TEST_F(TetheringManagerTest, CheckReadinessEthernetUpstream) {
base::MockOnceCallback<void(TetheringManager::EntitlementStatus)> cb;
KeyValueStore config =
GenerateFakeConfig("757365725F73736964", "user_password");
SetConfigUpstream(config, TechnologyName(Technology::kEthernet));
SetAllowed(tethering_manager_, true);
EXPECT_TRUE(FromProperties(tethering_manager_, config));
// No ethernet Device.
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(
cb,
Run(TetheringManager::EntitlementStatus::kUpstreamNetworkNotAvailable));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
// Set one fake ethernet Device.
auto eth =
new NiceMock<MockDevice>(&manager_, "eth0", "0a:0b:0c:0d:0e:0f", 1);
ON_CALL(*eth, technology()).WillByDefault(Return(Technology::kEthernet));
const std::vector<DeviceRefPtr> eth_devices = {eth};
ON_CALL(manager_, FilterByTechnology(Technology::kEthernet))
.WillByDefault(Return(eth_devices));
auto eth_service(new MockService(&manager_));
eth->set_selected_service_for_testing(eth_service);
// Set one fake cellular Device.
auto cell = MakeCellular("wwan0", "000102030405", 2);
const std::vector<DeviceRefPtr> cell_devices = {cell};
ON_CALL(manager_, FilterByTechnology(Technology::kCellular))
.WillByDefault(Return(cell_devices));
scoped_refptr<MockCellularService> cell_service =
new MockCellularService(&manager_, cell);
AddServiceToCellularProvider(cell_service);
cell->set_selected_service_for_testing(cell_service);
EXPECT_CALL(*cellular_service_provider_, TetheringEntitlementCheck(_, _))
.Times(0);
// Both Ethernet Service and Cellular Service are disconnected.
EXPECT_CALL(*eth_service, IsConnected(_)).WillRepeatedly(Return(false));
EXPECT_CALL(*cell_service, state())
.WillRepeatedly(Return(Service::kStateIdle));
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(
cb,
Run(TetheringManager::EntitlementStatus::kUpstreamNetworkNotAvailable));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
// Ethernet Service is connected, Cellular Service is disconnected.
EXPECT_CALL(*eth_service, IsConnected(_)).WillRepeatedly(Return(true));
EXPECT_CALL(*cell_service, state())
.WillRepeatedly(Return(Service::kStateIdle));
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(cb, Run(TetheringManager::EntitlementStatus::kReady));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
// Ethernet Service is disconnected, Cellular Service is connected.
EXPECT_CALL(*eth_service, IsConnected(_)).WillRepeatedly(Return(false));
EXPECT_CALL(*cell_service, state())
.WillRepeatedly(Return(Service::kStateConnected));
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(
cb,
Run(TetheringManager::EntitlementStatus::kUpstreamNetworkNotAvailable));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
// Both Ethernet Service and Cellular Service are connected.
EXPECT_CALL(*eth_service, IsConnected(_)).WillRepeatedly(Return(true));
EXPECT_CALL(*cell_service, state())
.WillRepeatedly(Return(Service::kStateConnected));
tethering_manager_->CheckReadiness(cb.Get());
EXPECT_CALL(cb, Run(TetheringManager::EntitlementStatus::kReady));
DispatchPendingEvents();
Mock::VerifyAndClearExpectations(&cb);
}
TEST_F(TetheringManagerTest, SetEnabledResultName) {
EXPECT_EQ("success", TetheringManager::SetEnabledResultName(
TetheringManager::SetEnabledResult::kSuccess));
EXPECT_EQ("failure", TetheringManager::SetEnabledResultName(
TetheringManager::SetEnabledResult::kFailure));
EXPECT_EQ("not_allowed",
TetheringManager::SetEnabledResultName(
TetheringManager::SetEnabledResult::kNotAllowed));
EXPECT_EQ("invalid_properties",
TetheringManager::SetEnabledResultName(
TetheringManager::SetEnabledResult::kInvalidProperties));
EXPECT_EQ(
"upstream_not_available",
TetheringManager::SetEnabledResultName(
TetheringManager::SetEnabledResult::kUpstreamNetworkNotAvailable));
}
TEST_F(TetheringManagerTest, StartTetheringSessionSuccessWithCellularUpstream) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
EXPECT_CALL(*patchpanel_, CreateTetheredNetwork("ap0", "wwan0", _, _, _, _))
.WillOnce(Return(true));
// Downstream device event service up.
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
// Upstream network fetched.
PortalDetector::Result portal_detector_result;
portal_detector_result.http_phase = PortalDetector::Phase::kContent,
portal_detector_result.http_status = PortalDetector::Status::kSuccess;
portal_detector_result.http_probe_completed = true;
portal_detector_result.https_probe_completed = true;
network_->set_portal_detector_result_for_testing(portal_detector_result);
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
// Tethering network created.
OnDownstreamNetworkReady(tethering_manager_, MakeFd());
VerifyResult(TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
Mock::VerifyAndClearExpectations(&manager_);
}
TEST_F(TetheringManagerTest, StartTetheringSessionSuccessWithEthernetUpstream) {
MockNetwork eth_network(kTestInterfaceIndex + 1, "eth0",
Technology::kEthernet);
ON_CALL(eth_network, IsConnected()).WillByDefault(Return(true));
scoped_refptr<MockService> eth_service = new MockService(&manager_);
EXPECT_CALL(manager_, GetFirstEthernetService())
.WillOnce(Return(eth_service));
EXPECT_CALL(manager_, FindActiveNetworkFromService(_))
.WillOnce(Return(&eth_network));
EXPECT_CALL(*patchpanel_, CreateTetheredNetwork("ap0", "eth0", _, _, _, _))
.WillOnce(Return(true));
// TetheringManager will evaluate the downstream service readiness as soon as
// it finds the ethernet upstream network.
ON_CALL(*hotspot_device_.get(), IsServiceUp()).WillByDefault(Return(false));
// Change the upstream technology to ethernet.
TetheringPrerequisite(tethering_manager_);
KeyValueStore config =
GenerateFakeConfig("757365725F73736964", "user_password");
SetConfigUpstream(config, TechnologyName(Technology::kEthernet));
EXPECT_TRUE(FromProperties(tethering_manager_, config));
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
Mock::VerifyAndClearExpectations(&manager_);
// Downstream device event service up.
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
ON_CALL(*hotspot_device_.get(), IsServiceUp()).WillByDefault(Return(true));
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
// Tethering network created.
PortalDetector::Result portal_detector_result;
portal_detector_result.http_phase = PortalDetector::Phase::kContent,
portal_detector_result.http_status = PortalDetector::Status::kSuccess;
portal_detector_result.http_probe_completed = true;
portal_detector_result.https_probe_completed = true;
eth_network.set_portal_detector_result_for_testing(portal_detector_result);
OnDownstreamNetworkReady(tethering_manager_, MakeFd());
Mock::VerifyAndClearExpectations(&manager_);
VerifyResult(TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
}
TEST_F(TetheringManagerTest,
StartTetheringSessionTetheredNetworkImmediateFailure) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Tethering network creation request fails.
EXPECT_CALL(*patchpanel_, CreateTetheredNetwork("ap0", "wwan0", _, _, _, _))
.WillOnce(Return(false));
// Downstream device event service up.
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
// Upstream network fetched.
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
VerifyResult(TetheringManager::SetEnabledResult::kFailure);
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest,
StartTetheringSessionTetheredNetworkDelayedFailure) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
EXPECT_CALL(*patchpanel_, CreateTetheredNetwork("ap0", "wwan0", _, _, _, _))
.WillOnce(Return(true));
// Downstream device event service up.
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
// Upstream network fetched.
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
// Tethering network creation request fails
OnDownstreamNetworkReady(tethering_manager_, base::ScopedFD(-1));
VerifyResult(TetheringManager::SetEnabledResult::kFailure);
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest,
StartTetheringSessionTetheredNetworkAlreadyStarted) {
TetheringPrerequisite(tethering_manager_);
// Tethering session is started.
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
Mock::VerifyAndClearExpectations(&manager_);
// Downstream device event service up.
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
// Upstream network fetched.
EXPECT_CALL(*patchpanel_, CreateTetheredNetwork("ap0", "wwan0", _, _, _, _))
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(0);
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
Mock::VerifyAndClearExpectations(&manager_);
// Force another LocalDevice::DeviceEvent::kLinkUp event for the
// downstream network.
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
VerifyResult(TetheringManager::SetEnabledResult::kFailure);
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, StartTetheringSessionUpstreamNetworkNotConnected) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
Mock::VerifyAndClearExpectations(&manager_);
// Upstream Network fetched but the the Network has disconnected.
EXPECT_CALL(*network_, IsConnected()).WillRepeatedly(Return(false));
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
VerifyResult(TetheringManager::SetEnabledResult::kFailure);
// Expect stopping state: the attempt will be aborted.
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, StartTetheringSessionUpstreamNetworkNotReady) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
EXPECT_CALL(*patchpanel_, CreateTetheredNetwork("ap0", "wwan0", _, _, _, _))
.WillOnce(Return(true));
// Downstream device event service up.
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
// Upstream network fetched. Network has no Internet connectivity
PortalDetector::Result portal_detector_result;
network_->set_portal_detector_result_for_testing(portal_detector_result);
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Tethering network created.
OnDownstreamNetworkReady(tethering_manager_, MakeFd());
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
// Feed network validation result event.
OnUpstreamNetworkValidationResult(tethering_manager_, portal_detector_result);
// TODO(b/291845893): Normally the session is expected to fail. Change the
// test expectations once a new tethering session properly fails if
// TetheringManager cannot observe the upstream network is ready after a few
// network validation retries.
VerifyResult(TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
Mock::VerifyAndClearExpectations(&manager_);
}
TEST_F(TetheringManagerTest, StartTetheringSessionUpstreamNetworkHasPortal) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
EXPECT_CALL(*patchpanel_, CreateTetheredNetwork("ap0", "wwan0", _, _, _, _))
.WillOnce(Return(true));
// Downstream device event service up.
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
// Upstream network fetched. Network is in a portal state.
PortalDetector::Result portal_detector_result;
portal_detector_result.http_phase = PortalDetector::Phase::kContent,
portal_detector_result.http_status = PortalDetector::Status::kRedirect;
portal_detector_result.http_probe_completed = true;
portal_detector_result.https_probe_completed = true;
portal_detector_result.redirect_url =
net_base::HttpUrl::CreateFromString("https://portal.com/login");
network_->set_portal_detector_result_for_testing(portal_detector_result);
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Tethering network created.
OnDownstreamNetworkReady(tethering_manager_, MakeFd());
VerifyResult(TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
Mock::VerifyAndClearExpectations(&manager_);
}
TEST_F(TetheringManagerTest, FailToCreateLocalInterface) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(*wifi_provider_, CreateHotspotDevice).WillOnce(Return(nullptr));
EXPECT_CALL(*hotspot_device_.get(), ConfigureService(_)).Times(0);
SetEnabledVerifyResult(
tethering_manager_, true,
TetheringManager::SetEnabledResult::kDownstreamWiFiFailure);
// Expect stopping state: the attempt will be aborted.
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, FailToConfigureService) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(*wifi_provider_, CreateHotspotDevice)
.WillOnce(Return(hotspot_device_));
EXPECT_CALL(*hotspot_device_.get(), ConfigureService(_))
.WillOnce(Return(false));
EXPECT_CALL(*hotspot_device_.get(), DeconfigureService())
.WillOnce(Return(true));
SetEnabledVerifyResult(
tethering_manager_, true,
TetheringManager::SetEnabledResult::kDownstreamWiFiFailure);
// Expect stopping state: the attempt will be aborted.
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, FailToFetchUpstreamNetwork) {
TetheringPrerequisite(tethering_manager_);
SetEnabled(tethering_manager_, true);
// Upstream network fetch failed.
OnUpstreamNetworkAcquired(
tethering_manager_,
TetheringManager::SetEnabledResult::kUpstreamNetworkNotAvailable);
VerifyResult(
TetheringManager::SetEnabledResult::kUpstreamNetworkNotAvailable);
// Expect stopping state: the attempt will be aborted.
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, UserStopTetheringSession) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
SetEnabledVerifyResult(tethering_manager_, false,
TetheringManager::SetEnabledResult::kSuccess);
CheckTetheringIdle(tethering_manager_, kTetheringIdleReasonClientStop);
}
TEST_F(TetheringManagerTest, TetheringStopWhenUserLogout) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
// Log out user should also stop active tethering session and put tethering
// state to idle.
EXPECT_EQ(Error::kSuccess, TestPopProfile(&manager_, kUserProfile));
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonUserExit);
}
TEST_F(TetheringManagerTest, DeviceEventInterfaceDisabled) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_,
LocalDevice::DeviceEvent::kInterfaceDisabled,
hotspot_device_.get());
DispatchPendingEvents();
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, DeviceEventServiceDown) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkDown,
hotspot_device_.get());
DispatchPendingEvents();
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, UpstreamNetworkStopped) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
OnUpstreamNetworkStopped(tethering_manager_);
CheckTetheringStopping(tethering_manager_,
kTetheringIdleReasonUpstreamDisconnect);
}
TEST_F(TetheringManagerTest, UpstreamNetworkDestroyed) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
// State change from active to stopping.
EXPECT_CALL(manager_, TetheringStatusChanged());
OnUpstreamNetworkDestroyed(tethering_manager_);
// Expect stopping state: the attempt will be aborted.
CheckTetheringStopping(tethering_manager_,
kTetheringIdleReasonUpstreamDisconnect);
}
TEST_F(TetheringManagerTest, InterfaceDisabledWhenTetheringIsStarting) {
TetheringPrerequisite(tethering_manager_);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
DownStreamDeviceEvent(tethering_manager_,
LocalDevice::DeviceEvent::kInterfaceDisabled,
hotspot_device_.get());
VerifyResult(TetheringManager::SetEnabledResult::kDownstreamWiFiFailure);
// Expect stopping state: the attempt will be aborted.
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
// TODO(b/273975270) Re-enable this test once Internet connectivity check on the
// upstream network has been re-enabled in TetheringManager.
TEST_F(TetheringManagerTest, DISABLED_UpstreamNetworkValidationFailed) {
TetheringPrerequisite(tethering_manager_);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
SetEnabled(tethering_manager_, true);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Downstream device event service up.
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_, LocalDevice::DeviceEvent::kLinkUp,
hotspot_device_.get());
// Upstream network fetched. Network not ready.
PortalDetector::Result portal_detector_result;
portal_detector_result.http_phase = PortalDetector::Phase::kConnection,
portal_detector_result.http_status = PortalDetector::Status::kFailure;
portal_detector_result.https_error = HttpRequest::Error::kConnectionFailure;
portal_detector_result.http_probe_completed = true;
portal_detector_result.https_probe_completed = true;
OnUpstreamNetworkAcquired(tethering_manager_,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Downstream network is fully configured. Upstream network is not yet ready.
OnDownstreamNetworkReady(tethering_manager_, MakeFd());
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Feed network validation result event.
OnUpstreamNetworkValidationResult(tethering_manager_, portal_detector_result);
VerifyResult(
TetheringManager::SetEnabledResult::kUpstreamNetworkWithoutInternet);
CheckTetheringStopping(tethering_manager_,
kTetheringIdleReasonUpstreamDisconnect);
}
TEST_F(TetheringManagerTest, DeviceEventPeerConnectedDisconnected) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_,
LocalDevice::DeviceEvent::kPeerConnected,
hotspot_device_.get());
EXPECT_CALL(manager_, TetheringStatusChanged()).Times(1);
DownStreamDeviceEvent(tethering_manager_,
LocalDevice::DeviceEvent::kPeerDisconnected,
hotspot_device_.get());
Mock::VerifyAndClearExpectations(&manager_);
}
TEST_F(TetheringManagerTest, GetStatus) {
// Check tethering status when idle.
auto status = GetStatus(tethering_manager_);
EXPECT_EQ(status.Get<std::string>(kTetheringStatusStateProperty),
kTetheringStateIdle);
EXPECT_EQ(status.Get<std::string>(kTetheringStatusIdleReasonProperty),
kTetheringIdleReasonInitialState);
EXPECT_FALSE(
status.Contains<std::string>(kTetheringStatusUpstreamTechProperty));
EXPECT_FALSE(
status.Contains<std::string>(kTetheringStatusDownstreamTechProperty));
EXPECT_FALSE(status.Contains<Stringmaps>(kTetheringStatusClientsProperty));
// Enabled tethering.
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
status = GetStatus(tethering_manager_);
EXPECT_EQ(status.Get<std::string>(kTetheringStatusStateProperty),
kTetheringStateActive);
EXPECT_EQ(status.Get<std::string>(kTetheringStatusUpstreamTechProperty),
kTypeCellular);
EXPECT_EQ(status.Get<std::string>(kTetheringStatusDownstreamTechProperty),
kTypeWifi);
EXPECT_EQ(status.Get<Stringmaps>(kTetheringStatusClientsProperty).size(), 0);
EXPECT_FALSE(
status.Contains<std::string>(kTetheringStatusIdleReasonProperty));
// Connect 2 clients.
std::vector<std::vector<uint8_t>> clients;
clients.push_back({00, 11, 22, 33, 44, 55});
clients.push_back({00, 11, 22, 33, 44, 66});
EXPECT_CALL(*hotspot_device_.get(), GetStations()).WillOnce(Return(clients));
status = GetStatus(tethering_manager_);
EXPECT_EQ(status.Get<Stringmaps>(kTetheringStatusClientsProperty).size(), 2);
// Stop tethering.
ON_CALL(*hotspot_device_.get(), DeconfigureService())
.WillByDefault(Return(true));
SetEnabledVerifyResult(tethering_manager_, false,
TetheringManager::SetEnabledResult::kSuccess);
status = GetStatus(tethering_manager_);
EXPECT_EQ(status.Get<std::string>(kTetheringStatusStateProperty),
kTetheringStateIdle);
EXPECT_EQ(status.Get<std::string>(kTetheringStatusIdleReasonProperty),
kTetheringIdleReasonClientStop);
EXPECT_FALSE(
status.Contains<std::string>(kTetheringStatusUpstreamTechProperty));
EXPECT_FALSE(
status.Contains<std::string>(kTetheringStatusDownstreamTechProperty));
EXPECT_FALSE(status.Contains<Stringmaps>(kTetheringStatusClientsProperty));
}
TEST_F(TetheringManagerTest, InactiveTimer) {
// Start tethering.
TetheringPrerequisite(tethering_manager_);
// Inactive timer is not triggered when tethering is not active.
EXPECT_TRUE(GetInactiveTimer(tethering_manager_).IsCancelled());
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
// Inactive timer should be armed when tethering is active and no client is
// connected.
EXPECT_FALSE(GetInactiveTimer(tethering_manager_).IsCancelled());
// Connect client to the hotspot.
std::vector<std::vector<uint8_t>> clients;
clients.push_back({00, 11, 22, 33, 44, 55});
EXPECT_CALL(*hotspot_device_.get(), GetStations()).WillOnce(Return(clients));
DownStreamDeviceEvent(tethering_manager_,
LocalDevice::DeviceEvent::kPeerConnected,
hotspot_device_.get());
DispatchPendingEvents();
// Inactive timer should be canceled if at least one client is connected.
EXPECT_TRUE(GetInactiveTimer(tethering_manager_).IsCancelled());
clients.clear();
EXPECT_CALL(*hotspot_device_.get(), GetStations()).WillOnce(Return(clients));
DownStreamDeviceEvent(tethering_manager_,
LocalDevice::DeviceEvent::kPeerDisconnected,
hotspot_device_.get());
DispatchPendingEvents();
// Inactive timer should be re-armed when tethering is active and the last
// client is gone.
EXPECT_FALSE(GetInactiveTimer(tethering_manager_).IsCancelled());
}
TEST_F(TetheringManagerTest, TetheringStartTimer) {
// Start tethering.
TetheringPrerequisite(tethering_manager_);
EXPECT_TRUE(GetStartTimer(tethering_manager_).IsCancelled());
SetEnabled(tethering_manager_, true);
EXPECT_FALSE(GetStartTimer(tethering_manager_).IsCancelled());
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Tethering start timeout
OnStartingTetheringTimeout(tethering_manager_);
// Expect stopping state: the attempt will be aborted.
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, TetheringStartTimerUpdated) {
// Start tethering.
TetheringPrerequisite(tethering_manager_);
EXPECT_TRUE(GetStartTimer(tethering_manager_).IsCancelled());
SetEnabled(tethering_manager_, true);
EXPECT_FALSE(GetStartTimer(tethering_manager_).IsCancelled());
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Timeout updated
OnStartingTetheringUpdateTimeout(tethering_manager_, base::Seconds(20));
EXPECT_FALSE(GetStartTimer(tethering_manager_).IsCancelled());
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringStarting);
// Tethering start timeout
OnStartingTetheringTimeout(tethering_manager_);
// Expect stopping state: the attempt will be aborted.
CheckTetheringStopping(tethering_manager_, kTetheringIdleReasonError);
}
TEST_F(TetheringManagerTest, TetheringStopTimer) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
// Stop tethering.
EXPECT_TRUE(GetStopTimer(tethering_manager_).IsCancelled());
SetEnabled(tethering_manager_, false);
EXPECT_FALSE(GetStopTimer(tethering_manager_).IsCancelled());
// Tethering stop timeout
OnStoppingTetheringTimeout(tethering_manager_);
VerifyResult(TetheringManager::SetEnabledResult::kUpstreamFailure);
CheckTetheringIdle(tethering_manager_, kTetheringIdleReasonClientStop);
}
TEST_F(TetheringManagerTest, MARWithSSIDChange) {
TetheringPrerequisite(tethering_manager_);
// Upon initialization TetheringManager generates some config. Let's take
// a snapshot of the SSID/MAC (to test if MAC changes upon SSID change).
std::string ini_ssid = tethering_manager_->hex_ssid_;
std::string ini_mac = tethering_manager_->stable_mac_addr_.ToString();
// Change SSID to cause regeneration of MAC address.
KeyValueStore args = GenerateFakeConfig(kTestAPHexSSID, kTestPassword);
// Turn off randomization.
SetConfigMAR(args, false);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, args));
std::string mac = tethering_manager_->stable_mac_addr_.ToString();
ASSERT_NE(ini_ssid, kTestAPHexSSID);
EXPECT_NE(ini_mac, mac);
// Test 1st argument for CreateHotspotDevice (MAC as a hex-string).
EXPECT_CALL(*wifi_provider_, CreateHotspotDevice(Eq(mac), _, _, _))
.WillOnce(Return(hotspot_device_));
SetEnabled(tethering_manager_, true);
}
MATCHER_P(IsContained, container, "") {
return base::Contains(container, arg);
}
TEST_F(TetheringManagerTest, MARWithTetheringRestart) {
TetheringPrerequisite(tethering_manager_);
std::set<std::string> known_macs;
known_macs.insert(tethering_manager_->stable_mac_addr_.ToString());
auto tether_onoff = [&]() {
EXPECT_CALL(*wifi_provider_,
CreateHotspotDevice(Not(IsContained(known_macs)), _, _, _))
.WillOnce(
DoAll(WithArg<0>(Invoke([&](auto mac) { known_macs.insert(mac); })),
Return(hotspot_device_)));
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
SetEnabledVerifyResult(tethering_manager_, false,
TetheringManager::SetEnabledResult::kSuccess);
CheckTetheringIdle(tethering_manager_, kTetheringIdleReasonClientStop);
};
for (int i = 0; i < 4; ++i) {
tether_onoff();
}
}
TEST_F(TetheringManagerTest, CheckMACStored) {
TetheringPrerequisite(tethering_manager_);
// Change SSID to cause regeneration of MAC address.
KeyValueStore args;
SetConfigSSID(args, kTestAPHexSSID);
// Turn off randomization to check the MAC is being used at the end.
SetConfigMAR(args, false);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, args));
std::string ini_mac = tethering_manager_->stable_mac_addr_.ToString();
// Now PopProfile and check that MAC is different.
EXPECT_EQ(Error::kSuccess, TestPopProfile(&manager_, kUserProfile));
EXPECT_NE(ini_mac, tethering_manager_->stable_mac_addr_.ToString());
// Repush the profile and check that MAC returns to its original value.
EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager_, kUserProfile));
EXPECT_EQ(ini_mac, tethering_manager_->stable_mac_addr_.ToString());
// And test that it is actually used.
EXPECT_CALL(*wifi_provider_, CreateHotspotDevice(Eq(ini_mac), _, _, _))
.WillOnce(Return(hotspot_device_));
SetEnabled(tethering_manager_, true);
}
TEST_F(TetheringManagerTest, OnCellularUpstreamEvent) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
OnCellularUpstreamEvent(
tethering_manager_,
TetheringManager::CellularUpstreamEvent::kUserNoLongerEntitled);
CheckTetheringStopping(tethering_manager_,
kTetheringIdleReasonUpstreamDisconnect);
}
TEST_F(TetheringManagerTest, ChangeSSIDWhileIdle) {
TetheringPrerequisite(tethering_manager_);
CheckTetheringIdle(tethering_manager_, kTetheringIdleReasonInitialState);
// Change SSID and set to TetheringConfig.
KeyValueStore config = GetConfig(tethering_manager_);
SetConfigSSID(config, kTestAPHexSSID);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
DispatchPendingEvents();
CheckTetheringIdle(tethering_manager_, kTetheringIdleReasonInitialState);
}
TEST_F(TetheringManagerTest, ChangeSSIDWhileActive) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
// Change SSID and set to TetheringConfig.
KeyValueStore config = GetConfig(tethering_manager_);
SetConfigSSID(config, kTestAPHexSSID);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
// Changing SSID should not touch the upstream network.
EXPECT_CALL(*cellular_service_provider_, ReleaseTetheringNetwork(_, _))
.Times(0);
DispatchPendingEvents();
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringRestarting);
}
TEST_F(TetheringManagerTest, ChangeUpstreamTechWhileActive) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
// Change upstream tech from cellular to eth and set to TetheringConfig.
KeyValueStore config = GetConfig(tethering_manager_);
SetConfigUpstream(config, TechnologyName(Technology::kEthernet));
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
// Changing upstream technology should release the upstream network.
EXPECT_CALL(*cellular_service_provider_, ReleaseTetheringNetwork(_, _))
.WillOnce(Return());
DispatchPendingEvents();
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringRestarting);
}
TEST_F(TetheringManagerTest, ChangeAutoDisableWhileIdle) {
TetheringPrerequisite(tethering_manager_);
KeyValueStore config = GetConfig(tethering_manager_);
SetConfigAutoDisable(config, false);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
EXPECT_TRUE(GetInactiveTimer(tethering_manager_).IsCancelled());
CheckTetheringIdle(tethering_manager_, kTetheringIdleReasonInitialState);
SetConfigAutoDisable(config, true);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
EXPECT_TRUE(GetInactiveTimer(tethering_manager_).IsCancelled());
CheckTetheringIdle(tethering_manager_, kTetheringIdleReasonInitialState);
}
TEST_F(TetheringManagerTest, ChangeAutoDisableWhileActive) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
// Change auto disable from true to false and set to TetheringConfig.
KeyValueStore config = GetConfig(tethering_manager_);
SetConfigAutoDisable(config, false);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
// Set auto disable to false will terminate the inactive timer.
EXPECT_TRUE(GetInactiveTimer(tethering_manager_).IsCancelled());
// No session restart is triggered.
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
// Change auto disable from false to true and set to TetheringConfig.
SetConfigAutoDisable(config, true);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
// Set auto disable to true will restart the inactive timer.
EXPECT_FALSE(GetInactiveTimer(tethering_manager_).IsCancelled());
// No session restart is triggered.
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
// Connect client to the hotspot.
std::vector<std::vector<uint8_t>> clients;
clients.push_back({00, 11, 22, 33, 44, 55});
ON_CALL(*hotspot_device_.get(), GetStations()).WillByDefault(Return(clients));
DownStreamDeviceEvent(tethering_manager_,
LocalDevice::DeviceEvent::kPeerConnected,
hotspot_device_.get());
DispatchPendingEvents();
// Change auto disable from true to false and set to TetheringConfig.
SetConfigAutoDisable(config, false);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
// Set auto disable to false will terminate the inactive timer.
EXPECT_TRUE(GetInactiveTimer(tethering_manager_).IsCancelled());
// No session restart is triggered.
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
// Change auto disable from false to true and set to TetheringConfig.
SetConfigAutoDisable(config, true);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
// Set auto disable to true will not restart the inactive timer if there is
// client connected to the hotspot.
EXPECT_TRUE(GetInactiveTimer(tethering_manager_).IsCancelled());
// No session restart is triggered.
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
}
TEST_F(TetheringManagerTest, SetConfigWithNoChangeWhileActive) {
TetheringPrerequisite(tethering_manager_);
SetEnabledVerifyResult(tethering_manager_, true,
TetheringManager::SetEnabledResult::kSuccess);
// Change nothing and set to TetheringConfig.
KeyValueStore config = GetConfig(tethering_manager_);
EXPECT_TRUE(SetAndPersistConfig(tethering_manager_, config));
// No session restart is triggered.
EXPECT_EQ(TetheringState(tethering_manager_),
TetheringManager::TetheringState::kTetheringActive);
}
} // namespace shill