blob: 4c385f80219251954d5a9470e5707b046369fda9 [file] [log] [blame]
// Copyright (c) 2014 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 "update_engine/update_manager/real_device_policy_provider.h"
#include <memory>
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>
#include <policy/mock_device_policy.h>
#include <policy/mock_libpolicy.h>
#include "update_engine/mock_dbus_wrapper.h"
#include "update_engine/test_utils.h"
#include "update_engine/update_manager/umtest_utils.h"
using base::TimeDelta;
using chromeos_update_engine::test_utils::RunGMainLoopMaxIterations;
using std::set;
using std::string;
using std::unique_ptr;
using testing::DoAll;
using testing::Mock;
using testing::Return;
using testing::ReturnRef;
using testing::SaveArg;
using testing::SetArgumentPointee;
using testing::StrEq;
using testing::_;
namespace {
// Fake dbus-glib objects. These should be different values, to ease diagnosis
// of errors.
DBusGConnection* const kFakeConnection = reinterpret_cast<DBusGConnection*>(1);
DBusGProxy* const kFakeManagerProxy = reinterpret_cast<DBusGProxy*>(2);
} // namespace
namespace chromeos_update_manager {
class UmRealDevicePolicyProviderTest : public ::testing::Test {
protected:
void SetUp() override {
provider_.reset(new RealDevicePolicyProvider(&mock_dbus_,
&mock_policy_provider_));
// By default, we have a device policy loaded. Tests can call
// SetUpNonExistentDevicePolicy() to override this.
SetUpExistentDevicePolicy();
SetUpDBusSignalExpectations();
}
void TearDown() override {
// Check for leaked callbacks on the main loop.
EXPECT_EQ(0, RunGMainLoopMaxIterations(100));
// We need to set these expectation before the object is destroyed but
// after it finished running the test so the values of signal_callback_ and
// signal_callback_data_ are correct.
EXPECT_CALL(mock_dbus_, ProxyDisconnectSignal(
kFakeManagerProxy,
StrEq(login_manager::kPropertyChangeCompleteSignal),
signal_callback_,
signal_callback_data_));
EXPECT_CALL(mock_dbus_, ProxyUnref(kFakeManagerProxy));
provider_.reset();
}
void SetUpNonExistentDevicePolicy() {
ON_CALL(mock_policy_provider_, Reload())
.WillByDefault(Return(false));
ON_CALL(mock_policy_provider_, device_policy_is_loaded())
.WillByDefault(Return(false));
EXPECT_CALL(mock_policy_provider_, GetDevicePolicy()).Times(0);
}
void SetUpExistentDevicePolicy() {
// Setup the default behavior of the mocked PolicyProvider.
ON_CALL(mock_policy_provider_, Reload())
.WillByDefault(Return(true));
ON_CALL(mock_policy_provider_, device_policy_is_loaded())
.WillByDefault(Return(true));
ON_CALL(mock_policy_provider_, GetDevicePolicy())
.WillByDefault(ReturnRef(mock_device_policy_));
}
void SetUpDBusSignalExpectations() {
// Setup the DBus connection with default actions that should be performed
// once.
EXPECT_CALL(mock_dbus_, BusGet(_, _)).WillOnce(
Return(kFakeConnection));
EXPECT_CALL(mock_dbus_, ProxyNewForName(
kFakeConnection, StrEq(login_manager::kSessionManagerServiceName),
StrEq(login_manager::kSessionManagerServicePath),
StrEq(login_manager::kSessionManagerInterface)))
.WillOnce(Return(kFakeManagerProxy));
// Expect the signal to be added, registered and released.
EXPECT_CALL(mock_dbus_, ProxyAddSignal_1(
kFakeManagerProxy,
StrEq(login_manager::kPropertyChangeCompleteSignal),
G_TYPE_STRING));
EXPECT_CALL(mock_dbus_, ProxyConnectSignal(
kFakeManagerProxy,
StrEq(login_manager::kPropertyChangeCompleteSignal),
_ /* callback */, _ /* data */, _ /* free function */))
.WillOnce(DoAll(SaveArg<2>(&signal_callback_),
SaveArg<3>(&signal_callback_data_)));
}
chromeos_update_engine::MockDBusWrapper mock_dbus_;
testing::NiceMock<policy::MockDevicePolicy> mock_device_policy_;
testing::NiceMock<policy::MockPolicyProvider> mock_policy_provider_;
unique_ptr<RealDevicePolicyProvider> provider_;
// The registered signal handler for the signal.
GCallback signal_callback_ = nullptr;
void* signal_callback_data_ = nullptr;
};
TEST_F(UmRealDevicePolicyProviderTest, RefreshScheduledTest) {
// Check that the RefreshPolicy gets scheduled by checking the EventId.
EXPECT_TRUE(provider_->Init());
EXPECT_NE(kEventIdNull, provider_->scheduled_refresh_);
}
TEST_F(UmRealDevicePolicyProviderTest, FirstReload) {
// Checks that the policy is reloaded and the DevicePolicy is consulted.
EXPECT_CALL(mock_policy_provider_, Reload());
EXPECT_TRUE(provider_->Init());
}
TEST_F(UmRealDevicePolicyProviderTest, NonExistentDevicePolicyReloaded) {
// Checks that the policy is reloaded by RefreshDevicePolicy().
SetUpNonExistentDevicePolicy();
EXPECT_CALL(mock_policy_provider_, Reload()).Times(2);
EXPECT_TRUE(provider_->Init());
// Force the policy refresh.
provider_->RefreshDevicePolicy();
}
TEST_F(UmRealDevicePolicyProviderTest, SessionManagerSignalForcesReload) {
// Checks that a signal from the SessionManager forces a reload.
SetUpNonExistentDevicePolicy();
EXPECT_CALL(mock_policy_provider_, Reload()).Times(2);
EXPECT_TRUE(provider_->Init());
ASSERT_NE(nullptr, signal_callback_);
// Convert the GCallback to a function pointer and call it. GCallback is just
// a void function pointer to ensure that the type of the passed callback is a
// pointer. We need to cast it back to the right function type before calling
// it.
typedef void (*StaticSignalHandler)(DBusGProxy*, const char*, void*);
StaticSignalHandler signal_handler = reinterpret_cast<StaticSignalHandler>(
signal_callback_);
(*signal_handler)(kFakeManagerProxy, "success", signal_callback_data_);
}
TEST_F(UmRealDevicePolicyProviderTest, NonExistentDevicePolicyEmptyVariables) {
SetUpNonExistentDevicePolicy();
EXPECT_CALL(mock_policy_provider_, GetDevicePolicy()).Times(0);
EXPECT_TRUE(provider_->Init());
UmTestUtils::ExpectVariableHasValue(false,
provider_->var_device_policy_is_loaded());
UmTestUtils::ExpectVariableNotSet(provider_->var_release_channel());
UmTestUtils::ExpectVariableNotSet(provider_->var_release_channel_delegated());
UmTestUtils::ExpectVariableNotSet(provider_->var_update_disabled());
UmTestUtils::ExpectVariableNotSet(provider_->var_target_version_prefix());
UmTestUtils::ExpectVariableNotSet(provider_->var_scatter_factor());
UmTestUtils::ExpectVariableNotSet(
provider_->var_allowed_connection_types_for_update());
UmTestUtils::ExpectVariableNotSet(provider_->var_owner());
UmTestUtils::ExpectVariableNotSet(provider_->var_http_downloads_enabled());
UmTestUtils::ExpectVariableNotSet(provider_->var_au_p2p_enabled());
}
TEST_F(UmRealDevicePolicyProviderTest, ValuesUpdated) {
SetUpNonExistentDevicePolicy();
EXPECT_TRUE(provider_->Init());
Mock::VerifyAndClearExpectations(&mock_policy_provider_);
// Reload the policy with a good one and set some values as present. The
// remaining values are false.
SetUpExistentDevicePolicy();
EXPECT_CALL(mock_device_policy_, GetReleaseChannel(_))
.WillOnce(DoAll(SetArgumentPointee<0>(string("mychannel")),
Return(true)));
EXPECT_CALL(mock_device_policy_, GetAllowedConnectionTypesForUpdate(_))
.WillOnce(Return(false));
provider_->RefreshDevicePolicy();
UmTestUtils::ExpectVariableHasValue(true,
provider_->var_device_policy_is_loaded());
// Test that at least one variable is set, to ensure the refresh occurred.
UmTestUtils::ExpectVariableHasValue(string("mychannel"),
provider_->var_release_channel());
UmTestUtils::ExpectVariableNotSet(
provider_->var_allowed_connection_types_for_update());
}
TEST_F(UmRealDevicePolicyProviderTest, ScatterFactorConverted) {
SetUpExistentDevicePolicy();
EXPECT_CALL(mock_device_policy_, GetScatterFactorInSeconds(_))
.WillOnce(DoAll(SetArgumentPointee<0>(1234), Return(true)));
EXPECT_TRUE(provider_->Init());
UmTestUtils::ExpectVariableHasValue(TimeDelta::FromSeconds(1234),
provider_->var_scatter_factor());
}
TEST_F(UmRealDevicePolicyProviderTest, NegativeScatterFactorIgnored) {
SetUpExistentDevicePolicy();
EXPECT_CALL(mock_device_policy_, GetScatterFactorInSeconds(_))
.WillOnce(DoAll(SetArgumentPointee<0>(-1), Return(true)));
EXPECT_TRUE(provider_->Init());
UmTestUtils::ExpectVariableNotSet(provider_->var_scatter_factor());
}
TEST_F(UmRealDevicePolicyProviderTest, AllowedTypesConverted) {
SetUpExistentDevicePolicy();
EXPECT_CALL(mock_device_policy_, GetAllowedConnectionTypesForUpdate(_))
.WillOnce(DoAll(SetArgumentPointee<0>(
set<string>{"bluetooth", "wifi", "not-a-type"}),
Return(true)));
EXPECT_TRUE(provider_->Init());
UmTestUtils::ExpectVariableHasValue(
set<ConnectionType>{ConnectionType::kWifi, ConnectionType::kBluetooth},
provider_->var_allowed_connection_types_for_update());
}
} // namespace chromeos_update_manager