Chromium Code Reviews| 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..a7120a2648f835c45bac2aab10ba4ea05f97b186 |
| --- /dev/null |
| +++ b/chrome/browser/policy/cloud_policy_provider_unittest.cc |
| @@ -0,0 +1,383 @@ |
| +// 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 <set> |
| + |
| +#include "base/values.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" |
| + |
| + |
| +namespace policy { |
| + |
| +namespace { |
| + |
| +ConfigurationPolicyType proxy_policies[]= { kPolicyProxyMode, |
| + kPolicyProxyServerMode, |
| + kPolicyProxyServer, |
| + kPolicyProxyPacUrl, |
| + kPolicyProxyBypassList }; |
| + |
| +} // namespace |
| + |
| +MATCHER_P(IntegerValueMatcher, expect, "Matcher for IntegerValue-types") { |
| + DCHECK(arg); |
| + int value; |
| + DCHECK(reinterpret_cast<const Value*>(arg)->GetAsInteger(&value)); |
|
Joao da Silva
2011/05/31 14:50:23
DCHECK will be removed on non-debug builds, and th
sfeuz
2011/06/03 08:30:35
Done. Nice catch.
|
| + return value == expect; |
| +} |
| + |
| +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; |
| + } |
| + void SetUnmanaged() { |
| + is_unmanaged_ = true; |
| + } |
| + |
| + void set_initialized() { |
| + initialization_complete_ = true; |
| + } |
| + |
| + void set_uninitialized() { |
| + initialization_complete_ = false; |
| + } |
| + |
| +}; |
| +class CombiningCloudPolicyProviderTest : public testing::Test { |
| + public: |
| + void CreateCombiningCloudPolicyProvider( |
| + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list) { |
| + combining_cloud_policy_provider_.reset( |
| + new CombiningCloudPolicyProvider(policy_list)); |
| + } |
| + |
| + void CreateCombiningCloudPolicyProvider() { |
| + CreateCombiningCloudPolicyProvider( |
| + policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList()); |
| + } |
| + |
| + void Provide(ConfigurationPolicyStoreInterface* store) { |
| + DCHECK(combining_cloud_policy_provider_.get()); |
| + combining_cloud_policy_provider_.get()->Provide(store); |
| + } |
| + |
| + void AddCloudPolicyProvider(CloudPolicyProvider* cloud_policy_provider) { |
| + DCHECK(combining_cloud_policy_provider_.get()); |
| + combining_cloud_policy_provider_.get()->AddCloudPolicyProvider( |
| + cloud_policy_provider); |
| + } |
| + |
| + private: |
| + scoped_ptr<CombiningCloudPolicyProvider> combining_cloud_policy_provider_; |
| + |
|
Joao da Silva
2011/05/31 14:50:23
Nit: remove extra line?
sfeuz
2011/06/03 08:30:35
Done.
|
| +}; |
| + |
| +// Proxy setting distributed over multiple caches. |
| +TEST_F(CombiningCloudPolicyProviderTest, |
| + ProxySettingDistributedOverMultipleCaches) { |
| + |
| + const unsigned int proxy_related_policies = arraysize(proxy_policies); |
| + |
| + // There are |proxy_related_policies|+1 instances of CloudPolicyProvider, |
| + // which are mixed together by one instance of CombiningCloudPolicyProvider. |
| + // The first CloudPolicyProvider has some policies but no proxy-related ones. |
| + // The following ones have each one proxy-policy set. |
| + const unsigned int n = proxy_related_policies + 1; |
| + |
| + scoped_ptr<CloudPolicyProvider> providers[n]; |
| + 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(); |
| + caches[0].mandatory_policy()->Set(kPolicyShowHomeButton, |
| + Value::CreateBooleanValue(true)); |
| + caches[0].recommended_policy()->Set(kPolicyShowHomeButton, |
| + Value::CreateBooleanValue(true)); |
| + |
| + caches[0].mandatory_policy()->Set(kPolicyIncognitoEnabled, |
| + Value::CreateBooleanValue(true)); |
| + caches[0].recommended_policy()->Set(kPolicyIncognitoEnabled, |
| + Value::CreateBooleanValue(true)); |
| + |
| + caches[0].mandatory_policy()->Set(kPolicyTranslateEnabled, |
| + Value::CreateBooleanValue(true)); |
| + caches[0].recommended_policy()->Set(kPolicyTranslateEnabled, |
| + Value::CreateBooleanValue(true)); |
| + |
| + // Prepare the other caches to serve one proxy-policy each. |
| + caches[1].set_initialized(); |
| + caches[1].mandatory_policy()->Set(kPolicyProxyMode, |
| + Value::CreateStringValue("cache 1")); |
| + caches[1].mandatory_policy()->Set(kPolicyProxyMode, |
| + Value::CreateStringValue("cache 1")); |
| + |
| + caches[2].set_initialized(); |
| + caches[2].mandatory_policy()->Set(kPolicyProxyServerMode, |
| + Value::CreateIntegerValue(2)); |
| + caches[2].mandatory_policy()->Set(kPolicyProxyServerMode, |
| + Value::CreateIntegerValue(2)); |
| + |
| + caches[3].set_initialized(); |
| + caches[3].mandatory_policy()->Set(kPolicyProxyServer, |
| + Value::CreateStringValue("cache 3")); |
| + caches[3].mandatory_policy()->Set(kPolicyProxyServer, |
| + Value::CreateStringValue("cache 3")); |
| + |
| + caches[4].set_initialized(); |
| + caches[4].mandatory_policy()->Set(kPolicyProxyPacUrl, |
| + Value::CreateStringValue("cache 4")); |
| + caches[4].mandatory_policy()->Set(kPolicyProxyPacUrl, |
| + Value::CreateStringValue("cache 4")); |
| + |
| + caches[5].set_initialized(); |
| + caches[5].mandatory_policy()->Set(kPolicyProxyMode, |
| + Value::CreateStringValue("cache 5")); |
| + caches[5].mandatory_policy()->Set(kPolicyProxyMode, |
| + Value::CreateStringValue("cache 5")); |
| + |
| + // Make sure that our assumptions about the existing proxy-related policies |
| + // are still correct. |
| + DCHECK( proxy_related_policies == 5 ); |
|
Joao da Silva
2011/05/31 14:50:23
Nit: extra spaces next to the parenthesis?
sfeuz
2011/06/03 08:30:35
Done.
|
| + |
| + // Connect the caches to the providers as a one-to-one mapping. |
| + for (unsigned int i = 0; i<n ; ++i) { |
|
Joao da Silva
2011/05/31 14:50:23
Nit: i < n (spaces)
sfeuz
2011/06/03 08:30:35
Done.
|
| + providers[i].reset(new CloudPolicyProvider( |
| + list, |
| + CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY)); |
| + providers[i].get()->set_cache(caches + i); |
| + } |
| + |
| + CreateCombiningCloudPolicyProvider(); |
| + |
| + for (unsigned int i = 0; i < n; ++i) |
| + AddCloudPolicyProvider(providers[i].get()); |
| + |
| + MockConfigurationPolicyStore store; |
| + Provide(&store); |
| + |
| + // The final compilation should have all policies but the proxy-policies set |
| + // to NULL. Of the proxy-related policies only |kPolicyProxyMode| is set. |
| + for (current = list->begin; current != list->end; ++current) { |
| + bool is_proxy_policy = false; |
| + for (unsigned int i = 0;i < proxy_related_policies; ++i) { |
| + if (current->policy_type == proxy_policies[i]) { |
| + is_proxy_policy = true; |
| + break; |
| + } |
| + } |
| + |
| + 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); |
| + DCHECK(result); |
|
Joao da Silva
2011/05/31 14:50:23
Why not EXPECT_TRUE?
sfeuz
2011/06/03 08:30:35
Done. I tried to make a distinction between test-r
|
| + EXPECT_EQ(string_value, "cache 1"); |
| + } else if (is_proxy_policy) { |
| + 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); |
| + DCHECK(result); |
| + EXPECT_TRUE(boolean_value); |
| + } else { |
| + EXPECT_FALSE(value); |
| + } |
| + } |
| +} |
| + |
| +// No caches behind CloudPolicyProviders. |
| +TEST_F(CombiningCloudPolicyProviderTest, NoCaches) { |
| + |
| + // |n| denotes the number of instances of CloudPolicyProvider, which are mixed |
| + // together by one instance of CombiningCloudPolicyProvider. |
| + // None of the CloudPolicyProvider instances will have assigned a cache. |
| + const unsigned int n = 75; |
| + const ConfigurationPolicyProvider::PolicyDefinitionList* list = |
| + policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(); |
| + const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current; |
| + |
| + scoped_ptr<CloudPolicyProvider> providers[n]; |
| + |
| + for (unsigned int i = 0; i<n ; ++i) { |
|
Joao da Silva
2011/05/31 14:50:23
Nit: i < n (spaces)
sfeuz
2011/06/03 08:30:35
Obsolete.
|
| + providers[i].reset(new CloudPolicyProvider( |
| + list, |
| + CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY)); |
| + } |
| + |
| + CreateCombiningCloudPolicyProvider(list); |
| + |
| + MockConfigurationPolicyStore store; |
| + for (unsigned int i = 0; i < n; ++i) { |
| + AddCloudPolicyProvider(providers[i].get()); |
| + Provide(&store); |
| + } |
| + |
| + // The final compilation should have no policies set. |
| + current = list->begin; |
| + for (current = list->begin; current != list->end; ++current) |
| + EXPECT_FALSE(store.Get(current->policy_type)); |
| +} |
| + |
| +// Having many different CloudPolicyProviders adding them incrementally. |
| +TEST_F(CombiningCloudPolicyProviderTest, MultipleProviders) { |
| + |
| + // |n| denotes the number of instances of CloudPolicyProvider, which are mixed |
| + // together by one instance of CombiningCloudPolicyProvider. |
| + // Every other instance is set to be initialized (starting with a |
| + // non-initialized one). |
| + // Each instance of CloudPolicyProvider will have its own cache as a |
| + // backend and the i-th instance will serve i policies and come at position i |
| + // in the list of CombiningCloudPolicyProvider. Thus in the end there should |
| + // be exactly two policies applied per initialized instance. |
| + const unsigned int n = 101; |
| + |
| + const char* key_template = "Policy %03u"; |
| + const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current; |
| + |
| + // Numbers bigger than 1000 will mess with the key_template. |
| + DCHECK(n - arraysize(proxy_policies) < 1000); |
|
Joao da Silva
2011/05/31 14:50:23
EXPECT_TRUE?
sfeuz
2011/06/03 08:30:35
It is a DCHECK because this actually checks if som
|
| + |
| + // |simple_list| is a policy list with entries of the form |
| + // {(ConfigurationPolicyType)(7), Value::TYPE_INTEGER, "Policy 007"}. |
| + ConfigurationPolicyProvider::PolicyDefinitionList::Entry entries[n]; |
| + |
| + // Note that key_template is exactly one char longer than the resulting keys, |
| + // thus making the arrays correctly sized (including the trailing \0). |
| + const unsigned int key_length = strlen(key_template); |
| + char keys[n][key_length]; |
| + unsigned int counter = 0; |
| + for (unsigned int i = 0; i < n; ++counter) { |
| + bool is_proxy_policy = false; |
| + for (unsigned int j = 0;j < arraysize(proxy_policies); ++j) { |
|
Joao da Silva
2011/05/31 14:50:23
Nit: space after j = 0;
sfeuz
2011/06/03 08:30:35
Done.
|
| + if ((ConfigurationPolicyType)counter == proxy_policies[j]) { |
| + is_proxy_policy = true; |
| + break; |
| + } |
| + } |
| + |
| + // We do not want to interfere with the proxy related policies since they |
| + // are treated as a special case inside CombiningCloudPolicyProvider. |
| + if (is_proxy_policy) |
| + continue; |
| + |
| + snprintf(keys[i], key_length, key_template, counter); |
| + entries[i].policy_type = (ConfigurationPolicyType)counter; |
| + entries[i].value_type = Value::TYPE_INTEGER; |
| + entries[i].name = (const char*)keys[i]; |
| + ++i; |
| + } |
| + ConfigurationPolicyProvider::PolicyDefinitionList simple_list = |
| + {entries, |
| + entries+n}; |
| + const int max_counter = counter; |
| + |
| + MockCloudPolicyCacheBase caches[n]; |
| + scoped_ptr<CloudPolicyProvider> providers[n]; |
| + |
| + // Prepare |cache[i]| to serve the first i policies form |simple_list|. |
| + for (unsigned int i = 0; i < n; ++i) { |
| + current = simple_list.begin; |
| + for (unsigned int j = 0; j <= i; ++j, ++current) { |
| + // Set a unique value. |
| + caches[i].mandatory_policy()->Set( |
| + current->policy_type, |
| + Value::CreateIntegerValue(i*max_counter + (int)current->policy_type)); |
| + caches[i].recommended_policy()->Set( |
| + current->policy_type, |
| + Value::CreateIntegerValue(i*max_counter + (int)current->policy_type)); |
| + if (i&1) |
| + caches[i].set_initialized(); |
| + else |
| + caches[i].set_uninitialized(); |
| + } |
| + } |
| + |
| + // Connect the caches to the providers as a one-to-one mapping. |
| + for (unsigned int i = 0; i<n ; ++i) { |
|
Joao da Silva
2011/05/31 14:50:23
Nit: i < n (spaces)
sfeuz
2011/06/03 08:30:35
Obsolete.
|
| + providers[i].reset(new CloudPolicyProvider( |
| + (const ConfigurationPolicyProvider::PolicyDefinitionList*) &simple_list, |
| + CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY)); |
| + providers[i].get()->set_cache(caches + i); |
| + } |
| + |
| + CreateCombiningCloudPolicyProvider(&simple_list); |
| + |
| + // We expect that every new arriving provider only can serve its last two |
| + // policies and only if it is inizialized. |
| + MockConfigurationPolicyStore store; |
| + current = simple_list.begin; |
| + for (unsigned int i = 0; i < n; ++i) { |
| + if (caches[i].initialization_complete()) { |
| + EXPECT_CALL( |
| + store, |
| + Apply(current->policy_type, |
| + IntegerValueMatcher((int)(i*max_counter + |
| + (int)current->policy_type)))) |
| + .Times(n-i); |
| + ++current; |
| + |
| + EXPECT_CALL( |
| + store, |
| + Apply(current->policy_type, |
| + IntegerValueMatcher((int)(i*max_counter + |
| + (int)current->policy_type)))) |
| + .Times(n-i); |
| + ++current; |
| + } |
| + } |
| + |
| + current = simple_list.begin; |
| + for (unsigned int i = 0; i < n; ++i) { |
| + AddCloudPolicyProvider(providers[i].get()); |
| + Provide(&store); |
| + } |
| + |
| + // The final compilation should have exactly two policies per active provider |
| + // set. |
| + current = simple_list.begin; |
| + for (unsigned int i = 0; i < n; ++i, ++current) { |
| + if (caches[i].initialization_complete()) { |
| + EXPECT_THAT( |
| + store.Get(current->policy_type), |
| + IntegerValueMatcher((int)(i*max_counter + |
| + (int)current->policy_type))); |
| + } 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_THAT( |
| + store.Get(current->policy_type), |
| + IntegerValueMatcher((int)((i+1)*max_counter + |
| + (int)current->policy_type))); |
| + } else { |
| + EXPECT_FALSE(store.Get(current->policy_type)); |
| + } |
| + } |
| + } |
| +} |
| + |
| +} // namespace policy |