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