blob: 2ac7c4719a9c9f29dd1de27c6a9a36dbc5814a66 [file] [log] [blame]
// Copyright (c) 2012 The Chromium 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 "chrome/browser/policy/cloud_policy_manager.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "chrome/browser/policy/configuration_policy_provider_test.h"
#include "chrome/browser/policy/mock_cloud_policy_client.h"
#include "chrome/browser/policy/mock_cloud_policy_store.h"
#include "chrome/browser/policy/mock_configuration_policy_provider.h"
#include "chrome/browser/policy/policy_builder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::Mock;
using testing::_;
namespace em = enterprise_management;
namespace policy {
namespace {
class TestHarness : public PolicyProviderTestHarness {
public:
explicit TestHarness(PolicyLevel level);
virtual ~TestHarness();
virtual void SetUp() OVERRIDE;
virtual ConfigurationPolicyProvider* CreateProvider(
const PolicyDefinitionList* policy_definition_list) OVERRIDE;
virtual void InstallEmptyPolicy() OVERRIDE;
virtual void InstallStringPolicy(const std::string& policy_name,
const std::string& policy_value) OVERRIDE;
virtual void InstallIntegerPolicy(const std::string& policy_name,
int policy_value) OVERRIDE;
virtual void InstallBooleanPolicy(const std::string& policy_name,
bool policy_value) OVERRIDE;
virtual void InstallStringListPolicy(
const std::string& policy_name,
const base::ListValue* policy_value) OVERRIDE;
virtual void InstallDictionaryPolicy(
const std::string& policy_name,
const base::DictionaryValue* policy_value) OVERRIDE;
// Creates harnesses for mandatory and recommended levels, respectively.
static PolicyProviderTestHarness* CreateMandatory();
static PolicyProviderTestHarness* CreateRecommended();
private:
MockCloudPolicyStore* store_;
DISALLOW_COPY_AND_ASSIGN(TestHarness);
};
TestHarness::TestHarness(PolicyLevel level)
: PolicyProviderTestHarness(level, POLICY_SCOPE_USER) {}
TestHarness::~TestHarness() {}
void TestHarness::SetUp() {}
ConfigurationPolicyProvider* TestHarness::CreateProvider(
const PolicyDefinitionList* policy_definition_list) {
// Create and initialize the store.
store_ = new MockCloudPolicyStore();
store_->NotifyStoreLoaded();
EXPECT_CALL(*store_, Load());
return new CloudPolicyManager(scoped_ptr<CloudPolicyStore>(store_));
Mock::VerifyAndClearExpectations(store_);
}
void TestHarness::InstallEmptyPolicy() {}
void TestHarness::InstallStringPolicy(const std::string& policy_name,
const std::string& policy_value) {
store_->policy_map_.Set(policy_name, policy_level(), policy_scope(),
base::Value::CreateStringValue(policy_value));
}
void TestHarness::InstallIntegerPolicy(const std::string& policy_name,
int policy_value) {
store_->policy_map_.Set(policy_name, policy_level(), policy_scope(),
base::Value::CreateIntegerValue(policy_value));
}
void TestHarness::InstallBooleanPolicy(const std::string& policy_name,
bool policy_value) {
store_->policy_map_.Set(policy_name, policy_level(), policy_scope(),
base::Value::CreateBooleanValue(policy_value));
}
void TestHarness::InstallStringListPolicy(const std::string& policy_name,
const base::ListValue* policy_value) {
store_->policy_map_.Set(policy_name, policy_level(), policy_scope(),
policy_value->DeepCopy());
}
void TestHarness::InstallDictionaryPolicy(
const std::string& policy_name,
const base::DictionaryValue* policy_value) {
store_->policy_map_.Set(policy_name, policy_level(), policy_scope(),
policy_value->DeepCopy());
}
// static
PolicyProviderTestHarness* TestHarness::CreateMandatory() {
return new TestHarness(POLICY_LEVEL_MANDATORY);
}
// static
PolicyProviderTestHarness* TestHarness::CreateRecommended() {
return new TestHarness(POLICY_LEVEL_RECOMMENDED);
}
// Instantiate abstract test case for basic policy reading tests.
INSTANTIATE_TEST_CASE_P(
UserCloudPolicyManagerProviderTest,
ConfigurationPolicyProviderTest,
testing::Values(TestHarness::CreateMandatory,
TestHarness::CreateRecommended));
class TestCloudPolicyManager : public CloudPolicyManager {
public:
explicit TestCloudPolicyManager(scoped_ptr<CloudPolicyStore> store)
: CloudPolicyManager(store.Pass()) {}
virtual ~TestCloudPolicyManager() {}
// Publish the protected members for testing.
using CloudPolicyManager::InitializeService;
using CloudPolicyManager::ShutdownService;
using CloudPolicyManager::StartRefreshScheduler;
using CloudPolicyManager::CheckAndPublishPolicy;
private:
DISALLOW_COPY_AND_ASSIGN(TestCloudPolicyManager);
};
MATCHER_P(ProtoMatches, proto, "") {
return arg.SerializePartialAsString() == proto.SerializePartialAsString();
}
class CloudPolicyManagerTest : public testing::Test {
protected:
CloudPolicyManagerTest() {}
virtual void SetUp() OVERRIDE {
// Set up a policy map for testing.
policy_map_.Set("key", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
base::Value::CreateStringValue("value"));
expected_bundle_.Get(POLICY_DOMAIN_CHROME, std::string()).CopyFrom(
policy_map_);
policy_.payload().mutable_homepagelocation()->set_homepagelocation(
"http://www.example.com");
policy_.Build();
store_ = new MockCloudPolicyStore();
EXPECT_CALL(*store_, Load());
manager_.reset(
new TestCloudPolicyManager(scoped_ptr<CloudPolicyStore>(store_)));
Mock::VerifyAndClearExpectations(store_);
registrar_.Init(manager_.get(), &observer_);
}
// Required by the refresh scheduler that's created by the manager.
MessageLoop loop_;
// Testing policy.
UserPolicyBuilder policy_;
PolicyMap policy_map_;
PolicyBundle expected_bundle_;
// Policy infrastructure.
MockConfigurationPolicyObserver observer_;
MockCloudPolicyStore* store_;
scoped_ptr<TestCloudPolicyManager> manager_;
ConfigurationPolicyObserverRegistrar registrar_;
private:
DISALLOW_COPY_AND_ASSIGN(CloudPolicyManagerTest);
};
TEST_F(CloudPolicyManagerTest, InitAndShutdown) {
PolicyBundle empty_bundle;
EXPECT_TRUE(empty_bundle.Equals(manager_->policies()));
EXPECT_FALSE(manager_->IsInitializationComplete());
EXPECT_CALL(observer_, OnUpdatePolicy(_)).Times(0);
manager_->CheckAndPublishPolicy();
Mock::VerifyAndClearExpectations(&observer_);
store_->policy_map_.CopyFrom(policy_map_);
store_->policy_.reset(new em::PolicyData(policy_.policy_data()));
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_TRUE(expected_bundle_.Equals(manager_->policies()));
EXPECT_TRUE(manager_->IsInitializationComplete());
MockCloudPolicyClient* client = new MockCloudPolicyClient();
EXPECT_CALL(*client, SetupRegistration(_, _));
manager_->InitializeService(scoped_ptr<CloudPolicyClient>(client));
Mock::VerifyAndClearExpectations(client);
EXPECT_TRUE(manager_->cloud_policy_client());
EXPECT_TRUE(manager_->cloud_policy_service());
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
manager_->CheckAndPublishPolicy();
Mock::VerifyAndClearExpectations(&observer_);
manager_->ShutdownService();
EXPECT_FALSE(manager_->cloud_policy_client());
EXPECT_FALSE(manager_->cloud_policy_service());
}
TEST_F(CloudPolicyManagerTest, RegistrationAndFetch) {
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_TRUE(manager_->IsInitializationComplete());
MockCloudPolicyClient* client = new MockCloudPolicyClient();
manager_->InitializeService(scoped_ptr<CloudPolicyClient>(client));
client->SetDMToken(policy_.policy_data().request_token());
client->NotifyRegistrationStateChanged();
client->SetPolicy(policy_.policy());
EXPECT_CALL(*store_, Store(ProtoMatches(policy_.policy())));
client->NotifyPolicyFetched();
Mock::VerifyAndClearExpectations(store_);
store_->policy_map_.CopyFrom(policy_map_);
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_TRUE(expected_bundle_.Equals(manager_->policies()));
}
TEST_F(CloudPolicyManagerTest, Update) {
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_TRUE(manager_->IsInitializationComplete());
PolicyBundle empty_bundle;
EXPECT_TRUE(empty_bundle.Equals(manager_->policies()));
store_->policy_map_.CopyFrom(policy_map_);
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_TRUE(expected_bundle_.Equals(manager_->policies()));
EXPECT_TRUE(manager_->IsInitializationComplete());
}
TEST_F(CloudPolicyManagerTest, RefreshNotRegistered) {
MockCloudPolicyClient* client = new MockCloudPolicyClient();
manager_->InitializeService(scoped_ptr<CloudPolicyClient>(client));
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(&observer_);
// A refresh on a non-registered store should not block.
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
manager_->RefreshPolicies();
Mock::VerifyAndClearExpectations(&observer_);
}
TEST_F(CloudPolicyManagerTest, RefreshSuccessful) {
MockCloudPolicyClient* client = new MockCloudPolicyClient();
manager_->InitializeService(scoped_ptr<CloudPolicyClient>(client));
// Simulate a store load.
store_->policy_.reset(new em::PolicyData(policy_.policy_data()));
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
EXPECT_CALL(*client, SetupRegistration(_, _));
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(client);
Mock::VerifyAndClearExpectations(&observer_);
// Acknowledge registration.
client->SetDMToken(policy_.policy_data().request_token());
// Start a refresh.
EXPECT_CALL(observer_, OnUpdatePolicy(_)).Times(0);
EXPECT_CALL(*client, FetchPolicy());
manager_->RefreshPolicies();
Mock::VerifyAndClearExpectations(client);
Mock::VerifyAndClearExpectations(&observer_);
store_->policy_map_.CopyFrom(policy_map_);
// A stray reload should be suppressed until the refresh completes.
EXPECT_CALL(observer_, OnUpdatePolicy(_)).Times(0);
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(&observer_);
// Respond to the policy fetch, which should trigger a write to |store_|.
EXPECT_CALL(observer_, OnUpdatePolicy(_)).Times(0);
EXPECT_CALL(*store_, Store(_));
client->SetPolicy(policy_.policy());
client->NotifyPolicyFetched();
Mock::VerifyAndClearExpectations(&observer_);
Mock::VerifyAndClearExpectations(store_);
// The load notification from |store_| should trigger the policy update.
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->NotifyStoreLoaded();
EXPECT_TRUE(expected_bundle_.Equals(manager_->policies()));
Mock::VerifyAndClearExpectations(&observer_);
}
} // namespace
} // namespace policy