blob: 2c2980a0e565dc9f2b20350cb6ca12cfb945a4a4 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shill/cellular/cellular_bearer.h"
#include <ModemManager/ModemManager.h>
#include <memory>
#include "shill/dbus/dbus_properties_proxy.h"
#include "shill/dbus/fake_properties_proxy.h"
#include "shill/mock_control.h"
#include "shill/testing.h"
using std::string;
using std::vector;
using testing::_;
using testing::ByMove;
using testing::Return;
using testing::ReturnNull;
namespace shill {
namespace {
const RpcIdentifier kBearerDBusPath =
RpcIdentifier("/org/freedesktop/ModemManager/Bearer/0");
const char kBearerDBusService[] = "org.freedesktop.ModemManager";
const char kDataInterface[] = "/dev/ppp0";
const char kIPv4Address[] = "10.0.0.1";
const char kIPv4Gateway[] = "10.0.0.254";
const int kIPv4SubnetPrefix = 8;
const uint32_t kIPv4Mtu = 1300;
const char* const kIPv4DNS[] = {"10.0.0.2", "8.8.4.4", "8.8.8.8"};
const char kIPv6Address[] = "0:0:0:0:0:ffff:a00:1";
const char kIPv6Gateway[] = "0:0:0:0:0:ffff:a00:fe";
const int kIPv6SubnetPrefix = 16;
const uint32_t kIPv6Mtu = 1400;
const char* const kIPv6DNS[] = {"0:0:0:0:0:ffff:a00:fe",
"0:0:0:0:0:ffff:808:404",
"0:0:0:0:0:ffff:808:808"};
} // namespace
class CellularBearerTest : public testing::Test {
public:
CellularBearerTest()
: control_(new MockControl()),
bearer_(control_.get(), kBearerDBusPath, kBearerDBusService) {}
protected:
void VerifyDefaultProperties() {
EXPECT_EQ(kBearerDBusPath, bearer_.dbus_path());
EXPECT_EQ(kBearerDBusService, bearer_.dbus_service());
EXPECT_FALSE(bearer_.connected());
EXPECT_EQ("", bearer_.data_interface());
EXPECT_EQ(IPConfig::kMethodUnknown, bearer_.ipv4_config_method());
EXPECT_EQ(nullptr, bearer_.ipv4_config_properties());
EXPECT_EQ(IPConfig::kMethodUnknown, bearer_.ipv6_config_method());
EXPECT_EQ(nullptr, bearer_.ipv6_config_properties());
}
static KeyValueStore ConstructIPv4ConfigProperties(
MMBearerIpMethod ipconfig_method) {
KeyValueStore ipconfig_properties;
ipconfig_properties.Set<uint32_t>("method", ipconfig_method);
if (ipconfig_method == MM_BEARER_IP_METHOD_STATIC) {
ipconfig_properties.Set<string>("address", kIPv4Address);
ipconfig_properties.Set<string>("gateway", kIPv4Gateway);
ipconfig_properties.Set<uint32_t>("prefix", kIPv4SubnetPrefix);
ipconfig_properties.Set<string>("dns1", kIPv4DNS[0]);
ipconfig_properties.Set<string>("dns2", kIPv4DNS[1]);
ipconfig_properties.Set<string>("dns3", kIPv4DNS[2]);
ipconfig_properties.Set<uint32_t>("mtu", kIPv4Mtu);
}
return ipconfig_properties;
}
static KeyValueStore ConstructIPv6ConfigProperties(
MMBearerIpMethod ipconfig_method) {
KeyValueStore ipconfig_properties;
ipconfig_properties.Set<uint32_t>("method", ipconfig_method);
if (ipconfig_method == MM_BEARER_IP_METHOD_STATIC) {
ipconfig_properties.Set<string>("address", kIPv6Address);
ipconfig_properties.Set<string>("gateway", kIPv6Gateway);
ipconfig_properties.Set<uint32_t>("prefix", kIPv6SubnetPrefix);
ipconfig_properties.Set<string>("dns1", kIPv6DNS[0]);
ipconfig_properties.Set<string>("dns2", kIPv6DNS[1]);
ipconfig_properties.Set<string>("dns3", kIPv6DNS[2]);
ipconfig_properties.Set<uint32_t>("mtu", kIPv6Mtu);
}
return ipconfig_properties;
}
static void SetBearerProperties(FakePropertiesProxy* fake_properties_proxy) {
bool connected = true;
const std::string interface_name = MM_DBUS_INTERFACE_BEARER;
const std::string data_interface = kDataInterface;
MMBearerIpMethod ipv4_config_method = MM_BEARER_IP_METHOD_STATIC;
MMBearerIpMethod ipv6_config_method = MM_BEARER_IP_METHOD_STATIC;
fake_properties_proxy->SetForTesting(
interface_name, MM_BEARER_PROPERTY_CONNECTED, brillo::Any(connected));
fake_properties_proxy->SetForTesting(interface_name,
MM_BEARER_PROPERTY_INTERFACE,
brillo::Any(data_interface));
fake_properties_proxy->SetForTesting(
interface_name, MM_BEARER_PROPERTY_IP4CONFIG,
brillo::Any(ConstructIPv4ConfigProperties(ipv4_config_method)));
fake_properties_proxy->SetForTesting(
interface_name, MM_BEARER_PROPERTY_IP6CONFIG,
brillo::Any(ConstructIPv6ConfigProperties(ipv6_config_method)));
}
void VerifyStaticIPv4ConfigMethodAndProperties() {
EXPECT_EQ(IPConfig::kMethodStatic, bearer_.ipv4_config_method());
const IPConfig::Properties* ipv4_config_properties =
bearer_.ipv4_config_properties();
ASSERT_NE(nullptr, ipv4_config_properties);
EXPECT_EQ(IPAddress::kFamilyIPv4, ipv4_config_properties->address_family);
EXPECT_EQ(kIPv4Address, ipv4_config_properties->address);
EXPECT_EQ(kIPv4Gateway, ipv4_config_properties->gateway);
EXPECT_EQ(kIPv4SubnetPrefix, ipv4_config_properties->subnet_prefix);
ASSERT_EQ(3, ipv4_config_properties->dns_servers.size());
EXPECT_EQ(kIPv4DNS[0], ipv4_config_properties->dns_servers[0]);
EXPECT_EQ(kIPv4DNS[1], ipv4_config_properties->dns_servers[1]);
EXPECT_EQ(kIPv4DNS[2], ipv4_config_properties->dns_servers[2]);
EXPECT_EQ(kIPv4Mtu, ipv4_config_properties->mtu);
}
void VerifyStaticIPv6ConfigMethodAndProperties() {
EXPECT_EQ(IPConfig::kMethodStatic, bearer_.ipv6_config_method());
const IPConfig::Properties* ipv6_config_properties =
bearer_.ipv6_config_properties();
ASSERT_NE(nullptr, ipv6_config_properties);
EXPECT_EQ(IPAddress::kFamilyIPv6, ipv6_config_properties->address_family);
EXPECT_EQ(kIPv6Address, ipv6_config_properties->address);
EXPECT_EQ(kIPv6Gateway, ipv6_config_properties->gateway);
EXPECT_EQ(kIPv6SubnetPrefix, ipv6_config_properties->subnet_prefix);
ASSERT_EQ(3, ipv6_config_properties->dns_servers.size());
EXPECT_EQ(kIPv6DNS[0], ipv6_config_properties->dns_servers[0]);
EXPECT_EQ(kIPv6DNS[1], ipv6_config_properties->dns_servers[1]);
EXPECT_EQ(kIPv6DNS[2], ipv6_config_properties->dns_servers[2]);
EXPECT_EQ(kIPv6Mtu, ipv6_config_properties->mtu);
}
std::unique_ptr<MockControl> control_;
CellularBearer bearer_;
};
TEST_F(CellularBearerTest, Constructor) {
VerifyDefaultProperties();
}
TEST_F(CellularBearerTest, Init) {
std::unique_ptr<DBusPropertiesProxy> dbus_properties_proxy =
DBusPropertiesProxy::CreateDBusPropertiesProxyForTesting();
SetBearerProperties(
dbus_properties_proxy->GetFakePropertiesProxyForTesting());
EXPECT_CALL(*control_,
CreateDBusPropertiesProxy(kBearerDBusPath, kBearerDBusService))
.WillOnce(Return(ByMove(std::move(dbus_properties_proxy))));
bearer_.Init();
EXPECT_TRUE(bearer_.connected());
EXPECT_EQ(kDataInterface, bearer_.data_interface());
VerifyStaticIPv4ConfigMethodAndProperties();
VerifyStaticIPv6ConfigMethodAndProperties();
}
TEST_F(CellularBearerTest, InitAndCreateDBusPropertiesProxyFails) {
EXPECT_CALL(*control_,
CreateDBusPropertiesProxy(kBearerDBusPath, kBearerDBusService))
.WillOnce(ReturnNull());
bearer_.Init();
VerifyDefaultProperties();
}
TEST_F(CellularBearerTest, OnPropertiesChanged) {
KeyValueStore properties;
// If interface is not MM_DBUS_INTERFACE_BEARER, no updates should be done.
bearer_.OnPropertiesChanged("", properties);
VerifyDefaultProperties();
properties.Set<bool>(MM_BEARER_PROPERTY_CONNECTED, true);
bearer_.OnPropertiesChanged("", properties);
VerifyDefaultProperties();
// Update 'interface' property.
properties.Clear();
properties.Set<string>(MM_BEARER_PROPERTY_INTERFACE, kDataInterface);
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(kDataInterface, bearer_.data_interface());
// Update 'connected' property.
properties.Clear();
properties.Set<bool>(MM_BEARER_PROPERTY_CONNECTED, true);
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_TRUE(bearer_.connected());
// 'interface' property remains unchanged.
EXPECT_EQ(kDataInterface, bearer_.data_interface());
// Update 'ip4config' property.
properties.Clear();
properties.Set<KeyValueStore>(
MM_BEARER_PROPERTY_IP4CONFIG,
ConstructIPv4ConfigProperties(MM_BEARER_IP_METHOD_UNKNOWN));
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(IPConfig::kMethodUnknown, bearer_.ipv4_config_method());
properties.Clear();
properties.Set<KeyValueStore>(
MM_BEARER_PROPERTY_IP4CONFIG,
ConstructIPv4ConfigProperties(MM_BEARER_IP_METHOD_PPP));
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(IPConfig::kMethodPPP, bearer_.ipv4_config_method());
properties.Clear();
properties.Set<KeyValueStore>(
MM_BEARER_PROPERTY_IP4CONFIG,
ConstructIPv4ConfigProperties(MM_BEARER_IP_METHOD_STATIC));
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(IPConfig::kMethodStatic, bearer_.ipv4_config_method());
VerifyStaticIPv4ConfigMethodAndProperties();
properties.Clear();
properties.Set<KeyValueStore>(
MM_BEARER_PROPERTY_IP4CONFIG,
ConstructIPv4ConfigProperties(MM_BEARER_IP_METHOD_DHCP));
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(IPConfig::kMethodDHCP, bearer_.ipv4_config_method());
// Update 'ip6config' property.
properties.Clear();
properties.Set<KeyValueStore>(
MM_BEARER_PROPERTY_IP6CONFIG,
ConstructIPv6ConfigProperties(MM_BEARER_IP_METHOD_UNKNOWN));
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(IPConfig::kMethodUnknown, bearer_.ipv6_config_method());
properties.Clear();
properties.Set<KeyValueStore>(
MM_BEARER_PROPERTY_IP6CONFIG,
ConstructIPv6ConfigProperties(MM_BEARER_IP_METHOD_PPP));
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(IPConfig::kMethodPPP, bearer_.ipv6_config_method());
properties.Clear();
properties.Set<KeyValueStore>(
MM_BEARER_PROPERTY_IP6CONFIG,
ConstructIPv6ConfigProperties(MM_BEARER_IP_METHOD_STATIC));
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(IPConfig::kMethodStatic, bearer_.ipv6_config_method());
VerifyStaticIPv6ConfigMethodAndProperties();
properties.Clear();
properties.Set<KeyValueStore>(
MM_BEARER_PROPERTY_IP6CONFIG,
ConstructIPv6ConfigProperties(MM_BEARER_IP_METHOD_DHCP));
bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties);
EXPECT_EQ(IPConfig::kMethodDHCP, bearer_.ipv6_config_method());
}
} // namespace shill