| // |
| // Copyright (C) 2014 The Android Open Source Project |
| // |
| // 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 |
| // |
| // http://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 "shill/cellular/cellular_bearer.h" |
| |
| #include <ModemManager/ModemManager.h> |
| |
| #include <base/memory/ptr_util.h> |
| |
| #include "shill/mock_control.h" |
| #include "shill/mock_dbus_properties_proxy.h" |
| #include "shill/testing.h" |
| |
| using std::string; |
| using std::vector; |
| using testing::Return; |
| using testing::ReturnNull; |
| using testing::_; |
| |
| namespace shill { |
| |
| namespace { |
| |
| const char kBearerDBusPath[] = "/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 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 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.SetUint("method", ipconfig_method); |
| if (ipconfig_method == MM_BEARER_IP_METHOD_STATIC) { |
| ipconfig_properties.SetString("address", kIPv4Address); |
| ipconfig_properties.SetString("gateway", kIPv4Gateway); |
| ipconfig_properties.SetUint("prefix", kIPv4SubnetPrefix); |
| ipconfig_properties.SetString("dns1", kIPv4DNS[0]); |
| ipconfig_properties.SetString("dns2", kIPv4DNS[1]); |
| ipconfig_properties.SetString("dns3", kIPv4DNS[2]); |
| } |
| return ipconfig_properties; |
| } |
| |
| static KeyValueStore ConstructIPv6ConfigProperties( |
| MMBearerIpMethod ipconfig_method) { |
| KeyValueStore ipconfig_properties; |
| ipconfig_properties.SetUint("method", ipconfig_method); |
| if (ipconfig_method == MM_BEARER_IP_METHOD_STATIC) { |
| ipconfig_properties.SetString("address", kIPv6Address); |
| ipconfig_properties.SetString("gateway", kIPv6Gateway); |
| ipconfig_properties.SetUint("prefix", kIPv6SubnetPrefix); |
| ipconfig_properties.SetString("dns1", kIPv6DNS[0]); |
| ipconfig_properties.SetString("dns2", kIPv6DNS[1]); |
| ipconfig_properties.SetString("dns3", kIPv6DNS[2]); |
| } |
| return ipconfig_properties; |
| } |
| |
| static KeyValueStore ConstructBearerProperties( |
| bool connected, const string& data_interface, |
| MMBearerIpMethod ipv4_config_method, |
| MMBearerIpMethod ipv6_config_method) { |
| KeyValueStore properties; |
| properties.SetBool(MM_BEARER_PROPERTY_CONNECTED, connected); |
| properties.SetString(MM_BEARER_PROPERTY_INTERFACE, data_interface); |
| |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP4CONFIG, |
| ConstructIPv4ConfigProperties(ipv4_config_method)); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP6CONFIG, |
| ConstructIPv6ConfigProperties(ipv6_config_method)); |
| return properties; |
| } |
| |
| 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]); |
| } |
| |
| 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]); |
| } |
| |
| std::unique_ptr<MockControl> control_; |
| CellularBearer bearer_; |
| }; |
| |
| TEST_F(CellularBearerTest, Constructor) { |
| VerifyDefaultProperties(); |
| } |
| |
| TEST_F(CellularBearerTest, Init) { |
| // Ownership of |properties_proxy| is transferred to |bearer_| via |
| // |control_|. |
| auto properties_proxy = base::MakeUnique<MockDBusPropertiesProxy>(); |
| EXPECT_CALL(*control_.get(), |
| CreateDBusPropertiesProxy(kBearerDBusPath, kBearerDBusService)) |
| .WillOnce(ReturnAndReleasePointee(&properties_proxy)); |
| EXPECT_CALL(*properties_proxy.get(), set_properties_changed_callback(_)) |
| .Times(1); |
| EXPECT_CALL(*properties_proxy.get(), GetAll(MM_DBUS_INTERFACE_BEARER)) |
| .WillOnce(Return(ConstructBearerProperties(true, kDataInterface, |
| MM_BEARER_IP_METHOD_STATIC, |
| MM_BEARER_IP_METHOD_STATIC))); |
| bearer_.Init(); |
| EXPECT_TRUE(bearer_.connected()); |
| EXPECT_EQ(kDataInterface, bearer_.data_interface()); |
| VerifyStaticIPv4ConfigMethodAndProperties(); |
| VerifyStaticIPv6ConfigMethodAndProperties(); |
| } |
| |
| TEST_F(CellularBearerTest, InitAndCreateDBusPropertiesProxyFails) { |
| EXPECT_CALL(*control_.get(), |
| 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, vector<string>()); |
| VerifyDefaultProperties(); |
| |
| properties.SetBool(MM_BEARER_PROPERTY_CONNECTED, true); |
| bearer_.OnPropertiesChanged("", properties, vector<string>()); |
| VerifyDefaultProperties(); |
| |
| // Update 'interface' property. |
| properties.Clear(); |
| properties.SetString(MM_BEARER_PROPERTY_INTERFACE, kDataInterface); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(kDataInterface, bearer_.data_interface()); |
| |
| // Update 'connected' property. |
| properties.Clear(); |
| properties.SetBool(MM_BEARER_PROPERTY_CONNECTED, true); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_TRUE(bearer_.connected()); |
| // 'interface' property remains unchanged. |
| EXPECT_EQ(kDataInterface, bearer_.data_interface()); |
| |
| // Update 'ip4config' property. |
| properties.Clear(); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP4CONFIG, |
| ConstructIPv4ConfigProperties(MM_BEARER_IP_METHOD_UNKNOWN)); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(IPConfig::kMethodUnknown, bearer_.ipv4_config_method()); |
| |
| properties.Clear(); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP4CONFIG, |
| ConstructIPv4ConfigProperties(MM_BEARER_IP_METHOD_PPP)); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(IPConfig::kMethodPPP, bearer_.ipv4_config_method()); |
| |
| properties.Clear(); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP4CONFIG, |
| ConstructIPv4ConfigProperties(MM_BEARER_IP_METHOD_STATIC)); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(IPConfig::kMethodStatic, bearer_.ipv4_config_method()); |
| VerifyStaticIPv4ConfigMethodAndProperties(); |
| |
| properties.Clear(); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP4CONFIG, |
| ConstructIPv4ConfigProperties(MM_BEARER_IP_METHOD_DHCP)); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(IPConfig::kMethodDHCP, bearer_.ipv4_config_method()); |
| |
| // Update 'ip6config' property. |
| properties.Clear(); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP6CONFIG, |
| ConstructIPv6ConfigProperties(MM_BEARER_IP_METHOD_UNKNOWN)); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(IPConfig::kMethodUnknown, bearer_.ipv6_config_method()); |
| |
| properties.Clear(); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP6CONFIG, |
| ConstructIPv6ConfigProperties(MM_BEARER_IP_METHOD_PPP)); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(IPConfig::kMethodPPP, bearer_.ipv6_config_method()); |
| |
| properties.Clear(); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP6CONFIG, |
| ConstructIPv6ConfigProperties(MM_BEARER_IP_METHOD_STATIC)); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(IPConfig::kMethodStatic, bearer_.ipv6_config_method()); |
| VerifyStaticIPv6ConfigMethodAndProperties(); |
| |
| properties.Clear(); |
| properties.SetKeyValueStore( |
| MM_BEARER_PROPERTY_IP6CONFIG, |
| ConstructIPv6ConfigProperties(MM_BEARER_IP_METHOD_DHCP)); |
| bearer_.OnPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties, |
| vector<string>()); |
| EXPECT_EQ(IPConfig::kMethodDHCP, bearer_.ipv6_config_method()); |
| } |
| |
| } // namespace shill |