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 |