Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/policy/cloud_policy_provider.h" | |
| 6 | |
| 7 #include "base/values.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "chrome/browser/policy/cloud_policy_cache_base.h" | |
| 10 #include "chrome/browser/policy/cloud_policy_provider.h" | |
| 11 #include "chrome/browser/policy/configuration_policy_pref_store.h" | |
| 12 #include "chrome/browser/policy/mock_configuration_policy_store.h" | |
| 13 #include "testing/gmock/include/gmock/gmock.h" | |
| 14 | |
| 15 namespace policy { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 ConfigurationPolicyType proxy_policies[]= { kPolicyProxyMode, | |
| 20 kPolicyProxyServerMode, | |
| 21 kPolicyProxyServer, | |
| 22 kPolicyProxyPacUrl, | |
| 23 kPolicyProxyBypassList }; | |
| 24 | |
| 25 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
| |
| 26 const unsigned int n = arraysize(proxy_policies); | |
| 27 for (unsigned int i = 0; i < n; ++i) | |
| 28 if (proxy_policies[i] == policy) | |
| 29 return true; | |
| 30 return false; | |
| 31 } | |
| 32 | |
| 33 } // namespace | |
| 34 | |
| 35 class MockCloudPolicyCacheBase : public CloudPolicyCacheBase { | |
| 36 public: | |
| 37 MockCloudPolicyCacheBase() {} | |
| 38 virtual ~MockCloudPolicyCacheBase() {} | |
| 39 | |
| 40 // CloudPolicyCacheBase Implementation. | |
| 41 void Load(){} | |
| 42 void SetPolicy(const em::PolicyFetchResponse& policy) {} | |
| 43 bool DecodePolicyData(const em::PolicyData& policy_data, | |
| 44 PolicyMap* mandatory, | |
| 45 PolicyMap* recommended) { | |
| 46 return true; | |
| 47 } | |
| 48 | |
| 49 // Non-const accessors for underlying PolicyMaps. | |
| 50 PolicyMap* raw_mandatory_policy() { | |
| 51 return &mandatory_policy_; | |
| 52 } | |
| 53 | |
| 54 PolicyMap* raw_recommended_policy() { | |
| 55 return &recommended_policy_; | |
| 56 } | |
| 57 | |
| 58 void SetUnmanaged() { | |
| 59 is_unmanaged_ = true; | |
| 60 } | |
| 61 | |
| 62 void set_initialized() { | |
| 63 initialization_complete_ = true; | |
| 64 } | |
| 65 | |
| 66 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.
| |
| 67 initialization_complete_ = false; | |
| 68 } | |
|
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
DISALLOW_COPY_AND_ASSIGN
sfeuz
2011/06/13 06:53:53
Done.
| |
| 69 }; | |
| 70 | |
| 71 class CloudPolicyProviderTest : public testing::Test { | |
| 72 public: | |
| 73 void CreateCloudPolicyProvider( | |
| 74 const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, | |
| 75 CloudPolicyCacheBase::PolicyLevel level) { | |
| 76 cloud_policy_provider_.reset(new CloudPolicyProvider(policy_list, level)); | |
| 77 } | |
| 78 | |
| 79 void CreateCloudPolicyProvider( | |
| 80 CloudPolicyCacheBase::PolicyLevel level) { | |
| 81 CreateCloudPolicyProvider( | |
| 82 policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), | |
| 83 level); | |
| 84 } | |
| 85 | |
| 86 void Provide(ConfigurationPolicyStoreInterface* store) { | |
| 87 DCHECK(cloud_policy_provider_.get()); | |
| 88 cloud_policy_provider_->Provide(store); | |
| 89 } | |
| 90 | |
| 91 void AppendCache(CloudPolicyCacheBase* cache) { | |
| 92 DCHECK(cloud_policy_provider_.get()); | |
| 93 cloud_policy_provider_->AppendCache(cache); | |
| 94 } | |
| 95 | |
| 96 void PrependCache(CloudPolicyCacheBase* cache) { | |
| 97 DCHECK(cloud_policy_provider_.get()); | |
| 98 cloud_policy_provider_->PrependCache(cache); | |
| 99 } | |
| 100 | |
| 101 void CombineTwoPolicyMaps(const PolicyMap& base, | |
| 102 const PolicyMap& overlay, | |
| 103 PolicyMap* out_map) { | |
| 104 DCHECK(cloud_policy_provider_.get()); | |
| 105 cloud_policy_provider_->CombineTwoPolicyMaps(base, overlay, out_map); | |
| 106 } | |
| 107 | |
| 108 private: | |
| 109 scoped_ptr<CloudPolicyProvider> cloud_policy_provider_; | |
| 110 }; | |
| 111 | |
| 112 // Proxy setting distributed over multiple caches. | |
| 113 TEST_F(CloudPolicyProviderTest, | |
| 114 ProxySettingDistributedOverMultipleCaches) { | |
| 115 const unsigned int proxy_related_policies = arraysize(proxy_policies); | |
| 116 | |
| 117 // There are |proxy_related_policies|+1 caches and they are mixed together by | |
| 118 // one instance of CloudPolicyProvider. The first cache has some policies but | |
| 119 // no proxy-related ones. The following caches have each one proxy-policy set. | |
| 120 const unsigned int n = proxy_related_policies + 1; | |
| 121 | |
| 122 // Make sure that our assumptions about the existing proxy-related policies | |
| 123 // are still correct. | |
| 124 DCHECK(proxy_related_policies == 5); | |
| 125 | |
| 126 MockCloudPolicyCacheBase caches[n]; | |
| 127 | |
| 128 const ConfigurationPolicyProvider::PolicyDefinitionList* list = | |
| 129 policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(); | |
| 130 const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current; | |
| 131 | |
| 132 // Prepare |cache[0]| to serve some non-proxy policies. | |
| 133 caches[0].set_initialized(); | |
| 134 caches[0].raw_mandatory_policy()->Set(kPolicyShowHomeButton, | |
| 135 Value::CreateBooleanValue(true)); | |
| 136 caches[0].raw_mandatory_policy()->Set(kPolicyIncognitoEnabled, | |
| 137 Value::CreateBooleanValue(true)); | |
| 138 caches[0].raw_mandatory_policy()->Set(kPolicyTranslateEnabled, | |
| 139 Value::CreateBooleanValue(true)); | |
| 140 | |
| 141 // Prepare the other caches to serve one proxy-policy each. | |
| 142 caches[1].set_initialized(); | |
| 143 caches[1].raw_mandatory_policy()->Set(kPolicyProxyMode, | |
| 144 Value::CreateStringValue("cache 1")); | |
| 145 caches[2].set_initialized(); | |
| 146 caches[2].raw_mandatory_policy()->Set(kPolicyProxyServerMode, | |
| 147 Value::CreateIntegerValue(2)); | |
| 148 caches[3].set_initialized(); | |
| 149 caches[3].raw_mandatory_policy()->Set(kPolicyProxyServer, | |
| 150 Value::CreateStringValue("cache 3")); | |
| 151 caches[4].set_initialized(); | |
| 152 caches[4].raw_mandatory_policy()->Set(kPolicyProxyPacUrl, | |
| 153 Value::CreateStringValue("cache 4")); | |
| 154 caches[5].set_initialized(); | |
| 155 caches[5].raw_mandatory_policy()->Set(kPolicyProxyMode, | |
| 156 Value::CreateStringValue("cache 5")); | |
| 157 | |
| 158 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY); | |
| 159 | |
| 160 // Prepend from the end. | |
| 161 for (unsigned int i = 0; i < n; ++i) | |
| 162 PrependCache(&caches[n-i-1]); | |
| 163 | |
| 164 MockConfigurationPolicyStore store; | |
| 165 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.
| |
| 166 Provide(&store); | |
| 167 | |
| 168 // The final compilation should have some policies set to true. From the proxy | |
| 169 // related policies only |kPolicyProxyMode| should be set. | |
| 170 for (current = list->begin; current != list->end; ++current) { | |
| 171 const Value* value = store.Get(current->policy_type); | |
| 172 if (current->policy_type == kPolicyProxyMode) { | |
| 173 EXPECT_TRUE(value); | |
| 174 std::string string_value; | |
| 175 bool result = value->GetAsString(&string_value); | |
| 176 EXPECT_TRUE(result); | |
| 177 EXPECT_EQ(string_value, "cache 1"); | |
| 178 } else if (is_proxy_policy(current->policy_type)) { | |
| 179 EXPECT_FALSE(value); | |
| 180 } else if (current->policy_type == kPolicyShowHomeButton || | |
| 181 current->policy_type == kPolicyIncognitoEnabled || | |
| 182 current->policy_type == kPolicyTranslateEnabled) { | |
| 183 EXPECT_TRUE(value); | |
| 184 bool boolean_value = false; | |
| 185 bool result = value->GetAsBoolean(&boolean_value); | |
| 186 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.
| |
| 187 EXPECT_TRUE(boolean_value); | |
| 188 } else { | |
| 189 EXPECT_FALSE(value); | |
| 190 } | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 // Having many different caches adding them to the end incrementally. | |
| 195 TEST_F(CloudPolicyProviderTest, MultipleCaches) { | |
| 196 // |n| denotes the number of caches, which are mixed together by one | |
| 197 // instance of CloudPolicyProvider. Every other cache is set to be | |
| 198 // initialized (starting with a non-initialized one). The i-th cache will | |
| 199 // serve i policies and be at position i in the list of CloudPolicyProvider. | |
| 200 // Thus in the end there should be exactly two policies/ applied per | |
| 201 // initialized cache. | |
| 202 const unsigned int n = 101; | |
| 203 const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current; | |
| 204 | |
| 205 // Numbers bigger than 1000 will mess with the key names. | |
| 206 DCHECK(n - arraysize(proxy_policies) < 1000); | |
| 207 | |
| 208 // Prepare the PolicyDefinitionList |simple_list| with entries of the form | |
| 209 // {(ConfigurationPolicyType)(7), Value::TYPE_INTEGER, "007"}. | |
| 210 ConfigurationPolicyProvider::PolicyDefinitionList::Entry entries[n]; | |
| 211 | |
| 212 // The size of the keys depends on their format. Currently they are of the | |
| 213 // form "007" needing 4 characters including the terminal \0. | |
| 214 char keys[n][4]; | |
| 215 unsigned int counter = 0; | |
| 216 for (unsigned int i = 0; i < n; ++counter) { | |
| 217 | |
|
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
no newline here.
sfeuz
2011/06/13 06:53:53
Done.
| |
| 218 // We do not want to interfere with the proxy related policies since they | |
| 219 // are treated as a special case inside CloudPolicyProvider. | |
| 220 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.
| |
| 221 continue; | |
| 222 | |
| 223 base::snprintf(keys[i], 4, "%03u", counter); | |
| 224 entries[i].policy_type = (ConfigurationPolicyType)counter; | |
| 225 entries[i].value_type = Value::TYPE_INTEGER; | |
| 226 entries[i].name = (const char*)keys[i]; | |
| 227 ++i; | |
| 228 } | |
| 229 const int max_counter = counter; | |
| 230 ConfigurationPolicyProvider::PolicyDefinitionList simple_list = | |
| 231 {entries, | |
| 232 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.
| |
| 233 | |
| 234 // Prepare |cache[i]| to serve the first i policies form |simple_list|. | |
| 235 MockCloudPolicyCacheBase caches[n]; | |
| 236 for (unsigned int i = 0; i < n; ++i) { | |
| 237 current = simple_list.begin; | |
| 238 for (unsigned int j = 0; j <= i; ++j, ++current) { | |
| 239 // Set a unique value. | |
| 240 caches[i].raw_recommended_policy()->Set( | |
| 241 current->policy_type, | |
| 242 Value::CreateIntegerValue(i*max_counter + | |
| 243 (int)current->policy_type)); | |
| 244 caches[i].raw_mandatory_policy()->Set( | |
| 245 current->policy_type, | |
| 246 Value::CreateIntegerValue(i*max_counter + | |
| 247 (int)current->policy_type)); | |
| 248 if (i&1) | |
|
Mattias Nissler (ping if slow)
2011/06/09 14:36:26
whitespace around &
sfeuz
2011/06/13 06:53:53
Done.
| |
| 249 caches[i].set_initialized(); | |
| 250 else | |
| 251 caches[i].set_uninitialized(); | |
| 252 } | |
| 253 } | |
| 254 | |
| 255 // Executed twice. Once for recommended and once for mandatory policy level. | |
| 256 for (int l = 0; l < 2; ++l) { | |
| 257 CloudPolicyCacheBase::PolicyLevel level = l ? | |
| 258 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.
| |
| 259 CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY; | |
| 260 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.
| |
| 261 MockConfigurationPolicyStore store; | |
| 262 current = simple_list.begin; | |
| 263 for (unsigned int i = 0; i < n; ++i) | |
| 264 AppendCache(&caches[i]); | |
| 265 | |
| 266 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.
| |
| 267 testing::AnyNumber()); | |
| 268 Provide(&store); | |
| 269 | |
| 270 // The final compilation should have exactly two policies per active cache | |
| 271 // set. | |
| 272 current = simple_list.begin; | |
| 273 for (unsigned int i = 0; i < n; ++i, ++current) { | |
| 274 // Initialized caches will have their corresponding policy set. | |
| 275 if (caches[i].initialization_complete()) { | |
| 276 const Value* value = store.Get(current->policy_type); | |
| 277 EXPECT_TRUE(value); | |
| 278 int expected = i*max_counter + (int)current->policy_type; | |
| 279 int integer_value; | |
| 280 bool result = value->GetAsInteger(&integer_value); | |
| 281 EXPECT_TRUE(result); | |
| 282 EXPECT_EQ(integer_value, expected); | |
| 283 } else { | |
| 284 | |
| 285 // For non-initialized providers the corresponding value will be set by | |
| 286 // the next provider, except if it is the last one. | |
| 287 if (i == n-1) { | |
| 288 EXPECT_FALSE(store.Get(current->policy_type)); | |
| 289 break; | |
| 290 } | |
| 291 | |
| 292 const Value* value = store.Get(current->policy_type); | |
| 293 EXPECT_TRUE(value); | |
| 294 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.
| |
| 295 int integer_value; | |
| 296 bool result = value->GetAsInteger(&integer_value); | |
| 297 EXPECT_TRUE(result); | |
| 298 EXPECT_EQ(integer_value, expected); | |
| 299 } | |
| 300 } | |
| 301 } | |
| 302 } | |
| 303 | |
| 304 // Combining two PolicyMaps. | |
| 305 TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsSame) { | |
| 306 const int n = 1000; | |
| 307 PolicyMap A, B, C; | |
| 308 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
| 309 | |
| 310 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.
| |
| 311 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.
| |
| 312 A.Set((ConfigurationPolicyType)i,Value::CreateIntegerValue(i)); | |
| 313 | |
| 314 for (int i=0; i < n; ++i) | |
| 315 if (!is_proxy_policy((ConfigurationPolicyType)i)) | |
| 316 B.Set((ConfigurationPolicyType)i,Value::CreateIntegerValue(-1*i)); | |
| 317 | |
| 318 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.
| |
| 319 EXPECT_TRUE(A.Equals(C)); | |
| 320 } | |
| 321 | |
| 322 TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsEmpty) { | |
| 323 PolicyMap A, B, C; | |
| 324 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
| 325 CombineTwoPolicyMaps(A,B,&C); | |
| 326 EXPECT_TRUE(C.empty()); | |
| 327 } | |
| 328 | |
| 329 TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsPartial) { | |
| 330 const int n = 1000; | |
| 331 PolicyMap A, B, C; | |
| 332 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
| 333 | |
| 334 for (int i=0; i < n; ++i) { | |
| 335 if (is_proxy_policy((ConfigurationPolicyType)(2*i)) || | |
| 336 is_proxy_policy((ConfigurationPolicyType)(2*i+1))) { | |
| 337 continue; | |
| 338 } | |
| 339 A.Set((ConfigurationPolicyType)(2*i),Value::CreateIntegerValue(2*i)); | |
| 340 B.Set((ConfigurationPolicyType)(2*i),Value::CreateIntegerValue(-2*i)); | |
| 341 B.Set((ConfigurationPolicyType)(2*i+1),Value::CreateIntegerValue(-2*i-1)); | |
| 342 } | |
| 343 | |
| 344 CombineTwoPolicyMaps(A,B,&C); | |
| 345 | |
| 346 for (int i=0; i < 2*n; ++i) { | |
| 347 if (const Value* value = C.Get((ConfigurationPolicyType)i)) { | |
| 348 int int_value; | |
| 349 EXPECT_TRUE(value->GetAsInteger(&int_value)); | |
| 350 if (i&1) | |
| 351 EXPECT_EQ(int_value, -1*i); | |
| 352 else | |
| 353 EXPECT_EQ(int_value, i); | |
| 354 } | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsProxies) { | |
| 359 const int n = arraysize(proxy_policies); | |
| 360 const int a_value = 1; | |
| 361 const int b_value = -1; | |
| 362 PolicyMap A, B, C; | |
| 363 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
| 364 | |
| 365 A.Set(proxy_policies[0], Value::CreateIntegerValue(a_value)); | |
| 366 for (int i=1; i < n; ++i) | |
| 367 B.Set(proxy_policies[i], Value::CreateIntegerValue(b_value)); | |
| 368 | |
| 369 CombineTwoPolicyMaps(A,B,&C); | |
| 370 | |
| 371 EXPECT_TRUE(A.Equals(C)); | |
| 372 EXPECT_FALSE(B.Equals(C)); | |
| 373 } | |
| 374 | |
| 375 } // namespace policy | |
| OLD | NEW |