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