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..460f8f67480da750c7e117006591cb50827881d3 |
--- /dev/null |
+++ b/chrome/browser/policy/cloud_policy_provider_unittest.cc |
@@ -0,0 +1,375 @@ |
+// 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" |
+ |
+namespace policy { |
+ |
+namespace { |
+ |
+ConfigurationPolicyType proxy_policies[]= { kPolicyProxyMode, |
+ kPolicyProxyServerMode, |
+ kPolicyProxyServer, |
+ kPolicyProxyPacUrl, |
+ kPolicyProxyBypassList }; |
+ |
+bool is_proxy_policy(ConfigurationPolicyType policy) { |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
This is duplicated code. Can we somehow share?
sfeuz
2011/06/13 06:53:53
Made it private static of CloudPolicyProvider.
wdy
|
+ const unsigned int n = arraysize(proxy_policies); |
+ for (unsigned int i = 0; i < n; ++i) |
+ if (proxy_policies[i] == policy) |
+ return true; |
+ return false; |
+} |
+ |
+} // namespace |
+ |
+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() { |
+ initialization_complete_ = true; |
+ } |
+ |
+ void set_uninitialized() { |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
why not merge these two into set_initialized(bool)
sfeuz
2011/06/13 06:53:53
Done.
|
+ initialization_complete_ = false; |
+ } |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
DISALLOW_COPY_AND_ASSIGN
sfeuz
2011/06/13 06:53:53
Done.
|
+}; |
+ |
+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); |
+ } |
+ |
+ private: |
+ scoped_ptr<CloudPolicyProvider> cloud_policy_provider_; |
+}; |
+ |
+// Proxy setting distributed over multiple caches. |
+TEST_F(CloudPolicyProviderTest, |
+ ProxySettingDistributedOverMultipleCaches) { |
+ const unsigned int proxy_related_policies = arraysize(proxy_policies); |
+ |
+ // 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(); |
+ 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(); |
+ caches[1].raw_mandatory_policy()->Set(kPolicyProxyMode, |
+ Value::CreateStringValue("cache 1")); |
+ caches[2].set_initialized(); |
+ caches[2].raw_mandatory_policy()->Set(kPolicyProxyServerMode, |
+ Value::CreateIntegerValue(2)); |
+ caches[3].set_initialized(); |
+ caches[3].raw_mandatory_policy()->Set(kPolicyProxyServer, |
+ Value::CreateStringValue("cache 3")); |
+ caches[4].set_initialized(); |
+ caches[4].raw_mandatory_policy()->Set(kPolicyProxyPacUrl, |
+ Value::CreateStringValue("cache 4")); |
+ caches[5].set_initialized(); |
+ 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(testing::_,testing::_)).Times(testing::AnyNumber()); |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace after comma
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
It is common practice to import the symbols in tes
sfeuz
2011/06/13 06:53:53
Done.
sfeuz
2011/06/13 06:53:53
Done.
|
+ 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); |
+ DCHECK(result); |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
Why DCHECK instead of EXPECT_TRUE()?
sfeuz
2011/06/13 06:53:53
Done.
|
+ EXPECT_TRUE(boolean_value); |
+ } else { |
+ EXPECT_FALSE(value); |
+ } |
+ } |
+} |
+ |
+// Having many different caches adding them to the end incrementally. |
+TEST_F(CloudPolicyProviderTest, MultipleCaches) { |
+ // |n| denotes the number of caches, which are mixed together by one |
+ // instance of CloudPolicyProvider. 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 unsigned int n = 101; |
+ const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current; |
+ |
+ // Numbers bigger than 1000 will mess with the key names. |
+ DCHECK(n - arraysize(proxy_policies) < 1000); |
+ |
+ // Prepare the PolicyDefinitionList |simple_list| with entries of the form |
+ // {(ConfigurationPolicyType)(7), Value::TYPE_INTEGER, "007"}. |
+ ConfigurationPolicyProvider::PolicyDefinitionList::Entry entries[n]; |
+ |
+ // The size of the keys depends on their format. Currently they are of the |
+ // form "007" needing 4 characters including the terminal \0. |
+ char keys[n][4]; |
+ unsigned int counter = 0; |
+ for (unsigned int i = 0; i < n; ++counter) { |
+ |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
no newline here.
sfeuz
2011/06/13 06:53:53
Done.
|
+ // We do not want to interfere with the proxy related policies since they |
+ // are treated as a special case inside CloudPolicyProvider. |
+ if (is_proxy_policy((ConfigurationPolicyType)counter)) |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
casting integers to enum members seems like a bad
sfeuz
2011/06/13 06:53:53
Done.
|
+ continue; |
+ |
+ base::snprintf(keys[i], 4, "%03u", counter); |
+ entries[i].policy_type = (ConfigurationPolicyType)counter; |
+ entries[i].value_type = Value::TYPE_INTEGER; |
+ entries[i].name = (const char*)keys[i]; |
+ ++i; |
+ } |
+ const int max_counter = counter; |
+ ConfigurationPolicyProvider::PolicyDefinitionList simple_list = |
+ {entries, |
+ entries+n}; |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace around +, after { and before }
sfeuz
2011/06/13 06:53:53
Done.
|
+ |
+ // Prepare |cache[i]| to serve the first i policies form |simple_list|. |
+ MockCloudPolicyCacheBase caches[n]; |
+ 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].raw_recommended_policy()->Set( |
+ current->policy_type, |
+ Value::CreateIntegerValue(i*max_counter + |
+ (int)current->policy_type)); |
+ caches[i].raw_mandatory_policy()->Set( |
+ current->policy_type, |
+ Value::CreateIntegerValue(i*max_counter + |
+ (int)current->policy_type)); |
+ if (i&1) |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace around &
sfeuz
2011/06/13 06:53:53
Done.
|
+ caches[i].set_initialized(); |
+ else |
+ caches[i].set_uninitialized(); |
+ } |
+ } |
+ |
+ // 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: |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespcae before :
sfeuz
2011/06/13 06:53:53
Done.
|
+ CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY; |
+ CreateCloudPolicyProvider(&simple_list,level); |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace after comma
sfeuz
2011/06/13 06:53:53
Done.
|
+ MockConfigurationPolicyStore store; |
+ current = simple_list.begin; |
+ for (unsigned int i = 0; i < n; ++i) |
+ AppendCache(&caches[i]); |
+ |
+ EXPECT_CALL(store, Apply(testing::_,testing::_)).Times( |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
see my comment on importing symbols from testing::
sfeuz
2011/06/13 06:53:53
Done.
|
+ testing::AnyNumber()); |
+ Provide(&store); |
+ |
+ // The final compilation should have exactly two policies per active cache |
+ // set. |
+ current = simple_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*max_counter + (int)current->policy_type; |
+ 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)*max_counter + (int)current->policy_type; |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace around + and * and after cast
sfeuz
2011/06/13 06:53:53
Done.
|
+ int integer_value; |
+ bool result = value->GetAsInteger(&integer_value); |
+ EXPECT_TRUE(result); |
+ EXPECT_EQ(integer_value, expected); |
+ } |
+ } |
+ } |
+} |
+ |
+// Combining two PolicyMaps. |
+TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsSame) { |
+ const int n = 1000; |
+ PolicyMap A, B, C; |
+ CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); |
+ |
+ for (int i=0; i < n; ++i) |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace around =
sfeuz
2011/06/13 06:53:53
Done.
|
+ if (!is_proxy_policy((ConfigurationPolicyType)i)) |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace after cast (also below)
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
Again, can we just use a static PolicyDefinitionMa
sfeuz
2011/06/13 06:53:53
Done.
sfeuz
2011/06/13 06:53:53
Done.
|
+ A.Set((ConfigurationPolicyType)i,Value::CreateIntegerValue(i)); |
+ |
+ for (int i=0; i < n; ++i) |
+ if (!is_proxy_policy((ConfigurationPolicyType)i)) |
+ B.Set((ConfigurationPolicyType)i,Value::CreateIntegerValue(-1*i)); |
+ |
+ CombineTwoPolicyMaps(A,B,&C); |
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace after , (I'll stop commenting on missin
sfeuz
2011/06/13 06:53:53
Done.
|
+ 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) { |
+ const int n = 1000; |
+ PolicyMap A, B, C; |
+ CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); |
+ |
+ for (int i=0; i < n; ++i) { |
+ if (is_proxy_policy((ConfigurationPolicyType)(2*i)) || |
+ is_proxy_policy((ConfigurationPolicyType)(2*i+1))) { |
+ continue; |
+ } |
+ A.Set((ConfigurationPolicyType)(2*i),Value::CreateIntegerValue(2*i)); |
+ B.Set((ConfigurationPolicyType)(2*i),Value::CreateIntegerValue(-2*i)); |
+ B.Set((ConfigurationPolicyType)(2*i+1),Value::CreateIntegerValue(-2*i-1)); |
+ } |
+ |
+ CombineTwoPolicyMaps(A,B,&C); |
+ |
+ for (int i=0; i < 2*n; ++i) { |
+ if (const Value* value = C.Get((ConfigurationPolicyType)i)) { |
+ 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 = arraysize(proxy_policies); |
+ const int a_value = 1; |
+ const int b_value = -1; |
+ PolicyMap A, B, C; |
+ CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); |
+ |
+ A.Set(proxy_policies[0], Value::CreateIntegerValue(a_value)); |
+ for (int i=1; i < n; ++i) |
+ B.Set(proxy_policies[i], Value::CreateIntegerValue(b_value)); |
+ |
+ CombineTwoPolicyMaps(A,B,&C); |
+ |
+ EXPECT_TRUE(A.Equals(C)); |
+ EXPECT_FALSE(B.Equals(C)); |
+} |
+ |
+} // namespace policy |