| Index: chrome/browser/policy/cloud_policy_provider_unittest.cc
|
| diff --git a/chrome/browser/policy/cloud_policy_provider_unittest.cc b/chrome/browser/policy/cloud_policy_provider_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0481571ba5edf41e203132e703d461eeaa5a36a9
|
| --- /dev/null
|
| +++ b/chrome/browser/policy/cloud_policy_provider_unittest.cc
|
| @@ -0,0 +1,396 @@
|
| +// Copyright (c) 2011 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_provider.h"
|
| +
|
| +#include "base/values.h"
|
| +#include "base/string_util.h"
|
| +#include "chrome/browser/policy/cloud_policy_cache_base.h"
|
| +#include "chrome/browser/policy/cloud_policy_provider.h"
|
| +#include "chrome/browser/policy/configuration_policy_pref_store.h"
|
| +#include "chrome/browser/policy/mock_configuration_policy_store.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +
|
| +using testing::AnyNumber;
|
| +using testing::_;
|
| +
|
| +namespace policy {
|
| +
|
| +class MockCloudPolicyCacheBase : public CloudPolicyCacheBase {
|
| + public:
|
| + MockCloudPolicyCacheBase() {}
|
| + virtual ~MockCloudPolicyCacheBase() {}
|
| +
|
| + // CloudPolicyCacheBase Implementation.
|
| + void Load(){}
|
| + void SetPolicy(const em::PolicyFetchResponse& policy) {}
|
| + bool DecodePolicyData(const em::PolicyData& policy_data,
|
| + PolicyMap* mandatory,
|
| + PolicyMap* recommended) {
|
| + return true;
|
| + }
|
| +
|
| + // Non-const accessors for underlying PolicyMaps.
|
| + PolicyMap* raw_mandatory_policy() {
|
| + return &mandatory_policy_;
|
| + }
|
| +
|
| + PolicyMap* raw_recommended_policy() {
|
| + return &recommended_policy_;
|
| + }
|
| +
|
| + void SetUnmanaged() {
|
| + is_unmanaged_ = true;
|
| + }
|
| +
|
| + void set_initialized(bool initialized) {
|
| + initialization_complete_ = initialized;
|
| + }
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyCacheBase);
|
| +};
|
| +
|
| +class CloudPolicyProviderTest : public testing::Test {
|
| + public:
|
| + void CreateCloudPolicyProvider(
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list,
|
| + CloudPolicyCacheBase::PolicyLevel level) {
|
| + cloud_policy_provider_.reset(new CloudPolicyProvider(policy_list, level));
|
| + }
|
| +
|
| + void CreateCloudPolicyProvider(
|
| + CloudPolicyCacheBase::PolicyLevel level) {
|
| + CreateCloudPolicyProvider(
|
| + policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
|
| + level);
|
| + }
|
| +
|
| + void Provide(ConfigurationPolicyStoreInterface* store) {
|
| + DCHECK(cloud_policy_provider_.get());
|
| + cloud_policy_provider_->Provide(store);
|
| + }
|
| +
|
| + void AppendCache(CloudPolicyCacheBase* cache) {
|
| + DCHECK(cloud_policy_provider_.get());
|
| + cloud_policy_provider_->AppendCache(cache);
|
| + }
|
| +
|
| + void PrependCache(CloudPolicyCacheBase* cache) {
|
| + DCHECK(cloud_policy_provider_.get());
|
| + cloud_policy_provider_->PrependCache(cache);
|
| + }
|
| +
|
| + void CombineTwoPolicyMaps(const PolicyMap& base,
|
| + const PolicyMap& overlay,
|
| + PolicyMap* out_map) {
|
| + DCHECK(cloud_policy_provider_.get());
|
| + cloud_policy_provider_->CombineTwoPolicyMaps(base, overlay, out_map);
|
| + }
|
| +
|
| + ConfigurationPolicyProvider::PolicyDefinitionList* simple_list() {
|
| + return &simple_list_;
|
| + }
|
| +
|
| + unsigned int simple_list_length() {
|
| + return simple_list_length_;
|
| + }
|
| +
|
| + unsigned int proxy_policy_count() {
|
| + return CloudPolicyProvider::proxy_policy_count();
|
| + }
|
| +
|
| + bool is_proxy_policy(ConfigurationPolicyType policy) {
|
| + return CloudPolicyProvider::is_proxy_policy(policy);
|
| + }
|
| +
|
| + ConfigurationPolicyType get_proxy_policy(unsigned int i) {
|
| + DCHECK(i<proxy_policy_count());
|
| + return CloudPolicyProvider::proxy_policies[i];
|
| + }
|
| + protected:
|
| + virtual void SetUp() {
|
| + // Extract all non-proxy policies from the default chrome policy definition
|
| + // list but set all the types to integer and set the names to the zero-based
|
| + // index.
|
| + // For example the 8-th elements will be of the form:
|
| + // {ConfigurationPolicyType, Value::TYPE_INTEGER, "007"}
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList* real_list =
|
| + ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
|
| +
|
| + // Counting the number of non-proxy policies.
|
| + unsigned int n = 0;
|
| + for (current = real_list->begin; current != real_list->end; ++current) {
|
| + if (!CloudPolicyProvider::is_proxy_policy(current->policy_type)) {
|
| + ++n;
|
| + }
|
| + }
|
| +
|
| + // Numbers bigger than 1000 will mess with the key names.
|
| + DCHECK(n < 1000);
|
| +
|
| + unsigned int counter = 0;
|
| + entries.reset(
|
| + new ConfigurationPolicyProvider::PolicyDefinitionList::Entry[n]);
|
| + for (current = real_list->begin; current != real_list->end; ++current) {
|
| + if (CloudPolicyProvider::is_proxy_policy(current->policy_type))
|
| + continue;
|
| +
|
| + // The size of the keys depends on their format. Currently they are of the
|
| + // form "007" needing 4 characters including the terminal \0.
|
| + char* key = new char[4];
|
| + base::snprintf(key, 4, "%03u", counter);
|
| +
|
| + entries[counter].policy_type = current->policy_type;
|
| + entries[counter].value_type = Value::TYPE_INTEGER;
|
| + entries[counter].name = key;
|
| + ++counter;
|
| + }
|
| +
|
| + simple_list_.begin = entries.get();
|
| + simple_list_.end = entries.get() + n;
|
| + }
|
| +
|
| + private:
|
| + scoped_ptr<CloudPolicyProvider> cloud_policy_provider_;
|
| + ConfigurationPolicyProvider::PolicyDefinitionList simple_list_;
|
| + scoped_array<ConfigurationPolicyProvider::PolicyDefinitionList::Entry>
|
| + entries;
|
| + unsigned int simple_list_length_;
|
| +};
|
| +
|
| +// Proxy setting distributed over multiple caches.
|
| +TEST_F(CloudPolicyProviderTest,
|
| + ProxySettingDistributedOverMultipleCaches) {
|
| + const unsigned int proxy_related_policies = proxy_policy_count();
|
| +
|
| + // There are |proxy_related_policies|+1 caches and they are mixed together by
|
| + // one instance of CloudPolicyProvider. The first cache has some policies but
|
| + // no proxy-related ones. The following caches have each one proxy-policy set.
|
| + const unsigned int n = proxy_related_policies + 1;
|
| +
|
| + // Make sure that our assumptions about the existing proxy-related policies
|
| + // are still correct.
|
| + DCHECK(proxy_related_policies == 5);
|
| +
|
| + MockCloudPolicyCacheBase caches[n];
|
| +
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList* list =
|
| + policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
|
| +
|
| + // Prepare |cache[0]| to serve some non-proxy policies.
|
| + caches[0].set_initialized(true);
|
| + caches[0].raw_mandatory_policy()->Set(kPolicyShowHomeButton,
|
| + Value::CreateBooleanValue(true));
|
| + caches[0].raw_mandatory_policy()->Set(kPolicyIncognitoEnabled,
|
| + Value::CreateBooleanValue(true));
|
| + caches[0].raw_mandatory_policy()->Set(kPolicyTranslateEnabled,
|
| + Value::CreateBooleanValue(true));
|
| +
|
| + // Prepare the other caches to serve one proxy-policy each.
|
| + caches[1].set_initialized(true);
|
| + caches[1].raw_mandatory_policy()->Set(kPolicyProxyMode,
|
| + Value::CreateStringValue("cache 1"));
|
| + caches[2].set_initialized(true);
|
| + caches[2].raw_mandatory_policy()->Set(kPolicyProxyServerMode,
|
| + Value::CreateIntegerValue(2));
|
| + caches[3].set_initialized(true);
|
| + caches[3].raw_mandatory_policy()->Set(kPolicyProxyServer,
|
| + Value::CreateStringValue("cache 3"));
|
| + caches[4].set_initialized(true);
|
| + caches[4].raw_mandatory_policy()->Set(kPolicyProxyPacUrl,
|
| + Value::CreateStringValue("cache 4"));
|
| + caches[5].set_initialized(true);
|
| + caches[5].raw_mandatory_policy()->Set(kPolicyProxyMode,
|
| + Value::CreateStringValue("cache 5"));
|
| +
|
| + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY);
|
| +
|
| + // Prepend from the end.
|
| + for (unsigned int i = 0; i < n; ++i)
|
| + PrependCache(&caches[n-i-1]);
|
| +
|
| + MockConfigurationPolicyStore store;
|
| + EXPECT_CALL(store, Apply(_, _)).Times(AnyNumber());
|
| + Provide(&store);
|
| +
|
| + // The final compilation should have some policies set to true. From the proxy
|
| + // related policies only |kPolicyProxyMode| should be set.
|
| + for (current = list->begin; current != list->end; ++current) {
|
| + const Value* value = store.Get(current->policy_type);
|
| + if (current->policy_type == kPolicyProxyMode) {
|
| + EXPECT_TRUE(value);
|
| + std::string string_value;
|
| + bool result = value->GetAsString(&string_value);
|
| + EXPECT_TRUE(result);
|
| + EXPECT_EQ(string_value, "cache 1");
|
| + } else if (is_proxy_policy(current->policy_type)) {
|
| + EXPECT_FALSE(value);
|
| + } else if (current->policy_type == kPolicyShowHomeButton ||
|
| + current->policy_type == kPolicyIncognitoEnabled ||
|
| + current->policy_type == kPolicyTranslateEnabled) {
|
| + EXPECT_TRUE(value);
|
| + bool boolean_value = false;
|
| + bool result = value->GetAsBoolean(&boolean_value);
|
| + EXPECT_TRUE(result);
|
| + EXPECT_TRUE(boolean_value);
|
| + } else {
|
| + EXPECT_FALSE(value);
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Having many different caches adding them to the end incrementally.
|
| +TEST_F(CloudPolicyProviderTest, MultipleCaches) {
|
| + // We have as many caches as non-proxy policies. Every other cache is set to
|
| + // be initialized (starting with a non-initialized one). The i-th cache will
|
| + // serve i policies and be at position i in the list of CloudPolicyProvider.
|
| + // Thus in the end there should be exactly two policies applied per
|
| + // initialized cache.
|
| +
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList* list = simple_list();
|
| +
|
| + const unsigned int n = simple_list_length();
|
| +
|
| + // Prepare |cache[i]| to serve the first i policies from |list|.
|
| + MockCloudPolicyCacheBase caches[n];
|
| + for (unsigned int i = 0; i < n; ++i) {
|
| + current = list->begin;
|
| + for (unsigned int j = 0; j <= i; ++j) {
|
| + // Set a unique value.
|
| + caches[i].raw_recommended_policy()->Set(
|
| + current->policy_type,
|
| + Value::CreateIntegerValue(i * n + j));
|
| + caches[i].raw_mandatory_policy()->Set(
|
| + current->policy_type,
|
| + Value::CreateIntegerValue(i * n + j));
|
| +
|
| + // Odd numbers are initialized and even are not.
|
| + caches[i].set_initialized(i & 1);
|
| + }
|
| + }
|
| +
|
| + // Executed twice. Once for recommended and once for mandatory policy level.
|
| + for (int l = 0; l < 2; ++l) {
|
| + CloudPolicyCacheBase::PolicyLevel level = l ?
|
| + CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED :
|
| + CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY;
|
| + CreateCloudPolicyProvider(list,level);
|
| + MockConfigurationPolicyStore store;
|
| + current = list->begin;
|
| + for (unsigned int i = 0; i < n; ++i)
|
| + AppendCache(&caches[i]);
|
| +
|
| + EXPECT_CALL(store, Apply(_, _)).Times(AnyNumber());
|
| + Provide(&store);
|
| +
|
| + // The final compilation should have exactly two policies per active cache
|
| + // set.
|
| + current = list->begin;
|
| + for (unsigned int i = 0; i < n; ++i, ++current) {
|
| + // Initialized caches will have their corresponding policy set.
|
| + if (caches[i].initialization_complete()) {
|
| + const Value* value = store.Get(current->policy_type);
|
| + EXPECT_TRUE(value);
|
| + int expected = i * n + i;
|
| + int integer_value;
|
| + bool result = value->GetAsInteger(&integer_value);
|
| + EXPECT_TRUE(result);
|
| + EXPECT_EQ(integer_value, expected);
|
| + } else {
|
| + // For non-initialized providers the corresponding value will be set by
|
| + // the next provider, except if it is the last one.
|
| + if (i == n-1) {
|
| + EXPECT_FALSE(store.Get(current->policy_type));
|
| + break;
|
| + }
|
| +
|
| + const Value* value = store.Get(current->policy_type);
|
| + EXPECT_TRUE(value);
|
| + int expected = (i + 1) * n + (int) i;
|
| + int integer_value;
|
| + bool result = value->GetAsInteger(&integer_value);
|
| + EXPECT_TRUE(result);
|
| + EXPECT_EQ(integer_value, expected);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Combining two PolicyMaps.
|
| +TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsSame) {
|
| + PolicyMap A, B, C;
|
| + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED);
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList* list =
|
| + simple_list();
|
| + const int n = (int) simple_list_length();
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
|
| + current = list->begin;
|
| + for (int i=0; i < n; ++i, ++current)
|
| + A.Set(current->policy_type, Value::CreateIntegerValue(i));
|
| +
|
| + current = list->begin;
|
| + for (int i=0; i < n; ++i, ++current)
|
| + B.Set(current->policy_type, Value::CreateIntegerValue(-1 * i));
|
| +
|
| + CombineTwoPolicyMaps(A, B, &C);
|
| + EXPECT_TRUE(A.Equals(C));
|
| +}
|
| +
|
| +TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsEmpty) {
|
| + PolicyMap A, B, C;
|
| + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED);
|
| + CombineTwoPolicyMaps(A, B, &C);
|
| + EXPECT_TRUE(C.empty());
|
| +}
|
| +
|
| +TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsPartial) {
|
| + PolicyMap A, B, C;
|
| + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED);
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList* list = simple_list();
|
| + const int n = (int) simple_list_length();
|
| + const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
|
| +
|
| + current = list->begin;
|
| + for (int i=0; i < n; ++i, ++current) {
|
| + B.Set(current->policy_type, Value::CreateIntegerValue(-i));
|
| + if (!(i & 1))
|
| + A.Set(current->policy_type, Value::CreateIntegerValue(i));
|
| + }
|
| +
|
| + CombineTwoPolicyMaps(A, B, &C);
|
| +
|
| + current = list->begin;
|
| + for (int i=0; i < n; ++i, ++current) {
|
| + if (const Value* value = C.Get(current->policy_type)) {
|
| + int int_value;
|
| + EXPECT_TRUE(value->GetAsInteger(&int_value));
|
| + if (i & 1)
|
| + EXPECT_EQ(int_value, -1 * i);
|
| + else
|
| + EXPECT_EQ(int_value, i);
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsProxies) {
|
| + const int n = proxy_policy_count();
|
| + const int a_value = 1;
|
| + const int b_value = -1;
|
| + PolicyMap A, B, C;
|
| + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED);
|
| +
|
| + A.Set(get_proxy_policy(0), Value::CreateIntegerValue(a_value));
|
| + for (int i=1; i < n; ++i)
|
| + B.Set(get_proxy_policy(i), Value::CreateIntegerValue(b_value));
|
| +
|
| + CombineTwoPolicyMaps(A, B, &C);
|
| +
|
| + EXPECT_TRUE(A.Equals(C));
|
| + EXPECT_FALSE(B.Equals(C));
|
| +}
|
| +
|
| +} // namespace policy
|
|
|