summaryrefslogtreecommitdiff
path: root/cros/connection_manager_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cros/connection_manager_unittest.cc')
-rw-r--r--cros/connection_manager_unittest.cc360
1 files changed, 360 insertions, 0 deletions
diff --git a/cros/connection_manager_unittest.cc b/cros/connection_manager_unittest.cc
new file mode 100644
index 00000000..46da8cc9
--- /dev/null
+++ b/cros/connection_manager_unittest.cc
@@ -0,0 +1,360 @@
+//
+// Copyright (C) 2012 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 "update_engine/cros/connection_manager.h"
+
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+
+#include <base/logging.h>
+#include <brillo/any.h>
+#include <brillo/message_loops/fake_message_loop.h>
+#include <brillo/variant_dictionary.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <shill/dbus-constants.h>
+#include <shill/dbus-proxies.h>
+#include <shill/dbus-proxy-mocks.h>
+
+#include "update_engine/common/test_utils.h"
+#include "update_engine/cros/fake_shill_proxy.h"
+#include "update_engine/cros/fake_system_state.h"
+
+using chromeos_update_engine::connection_utils::StringForConnectionType;
+using org::chromium::flimflam::ManagerProxyMock;
+using org::chromium::flimflam::ServiceProxyMock;
+using std::set;
+using std::string;
+using testing::_;
+using testing::Return;
+using testing::SetArgPointee;
+
+namespace chromeos_update_engine {
+
+class ConnectionManagerTest : public ::testing::Test {
+ public:
+ ConnectionManagerTest() : fake_shill_proxy_(new FakeShillProxy()) {}
+
+ void SetUp() override {
+ loop_.SetAsCurrent();
+ FakeSystemState::CreateInstance();
+ FakeSystemState::Get()->set_connection_manager(&cmut_);
+ }
+
+ void TearDown() override { EXPECT_FALSE(loop_.PendingTasks()); }
+
+ protected:
+ // Sets the default_service object path in the response from the
+ // ManagerProxyMock instance.
+ void SetManagerReply(const char* default_service, bool reply_succeeds);
+
+ // Sets the |service_type|, |physical_technology| and |service_tethering|
+ // properties in the mocked service |service_path|. If any of the three
+ // const char* is a nullptr, the corresponding property will not be included
+ // in the response.
+ void SetServiceReply(const string& service_path,
+ const char* service_type,
+ const char* physical_technology,
+ const char* service_tethering);
+
+ void TestWithServiceType(const char* service_type,
+ const char* physical_technology,
+ ConnectionType expected_type);
+
+ void TestWithServiceDisconnected(ConnectionType expected_type);
+
+ void TestWithServiceTethering(const char* service_tethering,
+ ConnectionTethering expected_tethering);
+
+ brillo::FakeMessageLoop loop_{nullptr};
+ FakeShillProxy* fake_shill_proxy_;
+
+ // ConnectionManager under test.
+ ConnectionManager cmut_{fake_shill_proxy_};
+};
+
+void ConnectionManagerTest::SetManagerReply(const char* default_service,
+ bool reply_succeeds) {
+ ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_->GetManagerProxy();
+ if (!reply_succeeds) {
+ EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _))
+ .WillOnce(Return(false));
+ return;
+ }
+
+ // Create a dictionary of properties and optionally include the default
+ // service.
+ brillo::VariantDictionary reply_dict;
+ reply_dict["SomeOtherProperty"] = 0xC0FFEE;
+
+ if (default_service) {
+ reply_dict[shill::kDefaultServiceProperty] =
+ dbus::ObjectPath(default_service);
+ }
+ EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _))
+ .WillOnce(DoAll(SetArgPointee<0>(reply_dict), Return(true)));
+}
+
+void ConnectionManagerTest::SetServiceReply(const string& service_path,
+ const char* service_type,
+ const char* physical_technology,
+ const char* service_tethering) {
+ brillo::VariantDictionary reply_dict;
+ reply_dict["SomeOtherProperty"] = 0xC0FFEE;
+
+ if (service_type)
+ reply_dict[shill::kTypeProperty] = string(service_type);
+
+ if (physical_technology) {
+ reply_dict[shill::kPhysicalTechnologyProperty] =
+ string(physical_technology);
+ }
+
+ if (service_tethering)
+ reply_dict[shill::kTetheringProperty] = string(service_tethering);
+
+ std::unique_ptr<ServiceProxyMock> service_proxy_mock(new ServiceProxyMock());
+
+ // Plumb return value into mock object.
+ EXPECT_CALL(*service_proxy_mock.get(), GetProperties(_, _, _))
+ .WillOnce(DoAll(SetArgPointee<0>(reply_dict), Return(true)));
+
+ fake_shill_proxy_->SetServiceForPath(dbus::ObjectPath(service_path),
+ std::move(service_proxy_mock));
+}
+
+void ConnectionManagerTest::TestWithServiceType(const char* service_type,
+ const char* physical_technology,
+ ConnectionType expected_type) {
+ SetManagerReply("/service/guest/network", true);
+ SetServiceReply("/service/guest/network",
+ service_type,
+ physical_technology,
+ shill::kTetheringNotDetectedState);
+
+ ConnectionType type;
+ ConnectionTethering tethering;
+ EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering));
+ EXPECT_EQ(expected_type, type);
+ testing::Mock::VerifyAndClearExpectations(
+ fake_shill_proxy_->GetManagerProxy());
+}
+
+void ConnectionManagerTest::TestWithServiceTethering(
+ const char* service_tethering, ConnectionTethering expected_tethering) {
+ SetManagerReply("/service/guest/network", true);
+ SetServiceReply(
+ "/service/guest/network", shill::kTypeWifi, nullptr, service_tethering);
+
+ ConnectionType type;
+ ConnectionTethering tethering;
+ EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering));
+ EXPECT_EQ(expected_tethering, tethering);
+ testing::Mock::VerifyAndClearExpectations(
+ fake_shill_proxy_->GetManagerProxy());
+}
+
+void ConnectionManagerTest::TestWithServiceDisconnected(
+ ConnectionType expected_type) {
+ SetManagerReply("/", true);
+
+ ConnectionType type;
+ ConnectionTethering tethering;
+ EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering));
+ EXPECT_EQ(expected_type, type);
+ testing::Mock::VerifyAndClearExpectations(
+ fake_shill_proxy_->GetManagerProxy());
+}
+
+TEST_F(ConnectionManagerTest, SimpleTest) {
+ TestWithServiceType(shill::kTypeEthernet, nullptr, ConnectionType::kEthernet);
+ TestWithServiceType(shill::kTypeWifi, nullptr, ConnectionType::kWifi);
+ TestWithServiceType(shill::kTypeCellular, nullptr, ConnectionType::kCellular);
+}
+
+TEST_F(ConnectionManagerTest, PhysicalTechnologyTest) {
+ TestWithServiceType(shill::kTypeVPN, nullptr, ConnectionType::kUnknown);
+ TestWithServiceType(
+ shill::kTypeVPN, shill::kTypeVPN, ConnectionType::kUnknown);
+ TestWithServiceType(shill::kTypeVPN, shill::kTypeWifi, ConnectionType::kWifi);
+}
+
+TEST_F(ConnectionManagerTest, TetheringTest) {
+ TestWithServiceTethering(shill::kTetheringConfirmedState,
+ ConnectionTethering::kConfirmed);
+ TestWithServiceTethering(shill::kTetheringNotDetectedState,
+ ConnectionTethering::kNotDetected);
+ TestWithServiceTethering(shill::kTetheringSuspectedState,
+ ConnectionTethering::kSuspected);
+ TestWithServiceTethering("I'm not a valid property value =)",
+ ConnectionTethering::kUnknown);
+}
+
+TEST_F(ConnectionManagerTest, UnknownTest) {
+ TestWithServiceType("foo", nullptr, ConnectionType::kUnknown);
+}
+
+TEST_F(ConnectionManagerTest, DisconnectTest) {
+ TestWithServiceDisconnected(ConnectionType::kDisconnected);
+}
+
+TEST_F(ConnectionManagerTest, AllowUpdatesOverEthernetTest) {
+ // Updates over Ethernet are allowed even if there's no policy.
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+ ConnectionTethering::kUnknown));
+}
+
+TEST_F(ConnectionManagerTest, AllowUpdatesOverWifiTest) {
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+ ConnectionTethering::kUnknown));
+}
+
+TEST_F(ConnectionManagerTest, AllowUpdatesOnlyOver3GPerPolicyTest) {
+ policy::MockDevicePolicy allow_3g_policy;
+
+ FakeSystemState::Get()->set_device_policy(&allow_3g_policy);
+
+ // This test tests cellular (3G) being the only connection type being allowed.
+ set<string> allowed_set;
+ allowed_set.insert(StringForConnectionType(ConnectionType::kCellular));
+
+ EXPECT_CALL(allow_3g_policy, GetAllowedConnectionTypesForUpdate(_))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<0>(allowed_set), Return(true)));
+
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+ ConnectionTethering::kUnknown));
+}
+
+TEST_F(ConnectionManagerTest, AllowUpdatesOver3GAndOtherTypesPerPolicyTest) {
+ policy::MockDevicePolicy allow_3g_policy;
+
+ FakeSystemState::Get()->set_device_policy(&allow_3g_policy);
+
+ // This test tests multiple connection types being allowed, with
+ // 3G one among them. Only Cellular is currently enforced by the policy
+ // setting.
+ set<string> allowed_set;
+ allowed_set.insert(StringForConnectionType(ConnectionType::kCellular));
+
+ EXPECT_CALL(allow_3g_policy, GetAllowedConnectionTypesForUpdate(_))
+ .Times(3)
+ .WillRepeatedly(DoAll(SetArgPointee<0>(allowed_set), Return(true)));
+
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+ ConnectionTethering::kUnknown));
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+ ConnectionTethering::kNotDetected));
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+ ConnectionTethering::kUnknown));
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+ ConnectionTethering::kUnknown));
+
+ // Tethered networks are treated in the same way as Cellular networks and
+ // thus allowed.
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+ ConnectionTethering::kConfirmed));
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+ ConnectionTethering::kConfirmed));
+}
+
+TEST_F(ConnectionManagerTest, AllowUpdatesOverCellularByDefaultTest) {
+ policy::MockDevicePolicy device_policy;
+ // Set an empty device policy.
+ FakeSystemState::Get()->set_device_policy(&device_policy);
+
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+ ConnectionTethering::kUnknown));
+}
+
+TEST_F(ConnectionManagerTest, AllowUpdatesOverTetheredNetworkByDefaultTest) {
+ policy::MockDevicePolicy device_policy;
+ // Set an empty device policy.
+ FakeSystemState::Get()->set_device_policy(&device_policy);
+
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+ ConnectionTethering::kConfirmed));
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+ ConnectionTethering::kConfirmed));
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+ ConnectionTethering::kSuspected));
+}
+
+TEST_F(ConnectionManagerTest, BlockUpdatesOver3GPerPolicyTest) {
+ policy::MockDevicePolicy block_3g_policy;
+
+ FakeSystemState::Get()->set_device_policy(&block_3g_policy);
+
+ // Test that updates for 3G are blocked while updates are allowed
+ // over several other types.
+ set<string> allowed_set;
+ allowed_set.insert(StringForConnectionType(ConnectionType::kEthernet));
+ allowed_set.insert(StringForConnectionType(ConnectionType::kWifi));
+
+ EXPECT_CALL(block_3g_policy, GetAllowedConnectionTypesForUpdate(_))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<0>(allowed_set), Return(true)));
+
+ EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+ ConnectionTethering::kUnknown));
+}
+
+TEST_F(ConnectionManagerTest, AllowUpdatesOver3GIfPolicyIsNotSet) {
+ policy::MockDevicePolicy device_policy;
+
+ FakeSystemState::Get()->set_device_policy(&device_policy);
+
+ // Return false for GetAllowedConnectionTypesForUpdate and see
+ // that updates are allowed as device policy is not set. Further
+ // check is left to |OmahaRequestAction|.
+ EXPECT_CALL(device_policy, GetAllowedConnectionTypesForUpdate(_))
+ .Times(1)
+ .WillOnce(Return(false));
+
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+ ConnectionTethering::kUnknown));
+}
+
+TEST_F(ConnectionManagerTest, AllowUpdatesOverCellularIfPolicyFailsToBeLoaded) {
+ FakeSystemState::Get()->set_device_policy(nullptr);
+
+ EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+ ConnectionTethering::kUnknown));
+}
+
+TEST_F(ConnectionManagerTest, StringForConnectionTypeTest) {
+ EXPECT_STREQ(shill::kTypeEthernet,
+ StringForConnectionType(ConnectionType::kEthernet));
+ EXPECT_STREQ(shill::kTypeWifi,
+ StringForConnectionType(ConnectionType::kWifi));
+ EXPECT_STREQ(shill::kTypeCellular,
+ StringForConnectionType(ConnectionType::kCellular));
+ EXPECT_STREQ("Unknown", StringForConnectionType(ConnectionType::kUnknown));
+ EXPECT_STREQ("Unknown",
+ StringForConnectionType(static_cast<ConnectionType>(999999)));
+}
+
+TEST_F(ConnectionManagerTest, MalformedServiceList) {
+ SetManagerReply("/service/guest/network", false);
+
+ ConnectionType type;
+ ConnectionTethering tethering;
+ EXPECT_FALSE(cmut_.GetConnectionProperties(&type, &tethering));
+}
+
+} // namespace chromeos_update_engine