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_impl.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 using testing::AnyNumber; | |
15 using testing::_; | |
16 | |
17 namespace policy { | |
18 | |
19 class MockCloudPolicyCache : public CloudPolicyCacheBase { | |
20 public: | |
21 MockCloudPolicyCache() {} | |
22 virtual ~MockCloudPolicyCache() {} | |
23 | |
24 // CloudPolicyCacheBase Implementation. | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
lower-case: implementation
gfeher
2011/06/22 19:18:34
Done.
| |
25 void Load() {} | |
26 void SetPolicy(const em::PolicyFetchResponse& policy) {} | |
27 bool DecodePolicyData(const em::PolicyData& policy_data, | |
28 PolicyMap* mandatory, | |
29 PolicyMap* recommended) { | |
30 return true; | |
31 } | |
32 | |
33 // Non-const accessors for underlying PolicyMaps. | |
34 PolicyMap* raw_mandatory_policy() { | |
35 return &mandatory_policy_; | |
36 } | |
37 | |
38 PolicyMap* raw_recommended_policy() { | |
39 return &recommended_policy_; | |
40 } | |
41 | |
42 void SetUnmanaged() { | |
43 is_unmanaged_ = true; | |
44 } | |
45 | |
46 void set_initialized(bool initialized) { | |
47 initialization_complete_ = initialized; | |
48 } | |
49 | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
private:
gfeher
2011/06/22 19:18:34
Done.
| |
50 DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyCache); | |
51 }; | |
52 | |
53 class CloudPolicyProviderTest : public testing::Test { | |
54 protected: | |
55 void CreateCloudPolicyProvider( | |
56 const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, | |
57 CloudPolicyCacheBase::PolicyLevel level) { | |
58 cloud_policy_provider_.reset( | |
59 new CloudPolicyProviderImpl(policy_list, level)); | |
60 } | |
61 | |
62 void CreateCloudPolicyProvider( | |
63 CloudPolicyCacheBase::PolicyLevel level) { | |
64 CreateCloudPolicyProvider( | |
65 policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), | |
66 level); | |
67 } | |
68 | |
69 void Provide(ConfigurationPolicyStoreInterface* store) { | |
70 DCHECK(cloud_policy_provider_.get()); | |
71 cloud_policy_provider_->Provide(store); | |
72 } | |
73 | |
74 void AppendCache(CloudPolicyCacheBase* cache) { | |
75 DCHECK(cloud_policy_provider_.get()); | |
76 cloud_policy_provider_->AppendCache(cache); | |
77 } | |
78 | |
79 void PrependCache(CloudPolicyCacheBase* cache) { | |
80 DCHECK(cloud_policy_provider_.get()); | |
81 cloud_policy_provider_->PrependCache(cache); | |
82 } | |
83 | |
84 void CombineTwoPolicyMaps(const PolicyMap& base, | |
85 const PolicyMap& overlay, | |
86 PolicyMap* out_map) { | |
87 DCHECK(cloud_policy_provider_.get()); | |
88 cloud_policy_provider_->CombineTwoPolicyMaps(base, overlay, out_map); | |
89 } | |
90 | |
91 ConfigurationPolicyProvider::PolicyDefinitionList* simple_list() { | |
92 return simple_list_.get(); | |
93 } | |
94 | |
95 ConfigurationPolicyType simple_list_policy_type(int id) { | |
96 DCHECK(id < simple_list_length_); | |
97 return simple_list_->begin[id].policy_type; | |
98 } | |
99 | |
100 int simple_list_length() { | |
101 return simple_list_length_; | |
102 } | |
103 | |
104 int proxy_policy_count() { | |
105 return CloudPolicyProviderImpl::proxy_policy_count(); | |
106 } | |
107 | |
108 bool is_proxy_policy(ConfigurationPolicyType policy) { | |
109 return CloudPolicyProviderImpl::is_proxy_policy(policy); | |
110 } | |
111 | |
112 ConfigurationPolicyType get_proxy_policy(int i) { | |
113 DCHECK(i < proxy_policy_count()); | |
114 return CloudPolicyProviderImpl::proxy_policies[i]; | |
115 } | |
116 | |
117 virtual void SetUp() { | |
118 // Extract all non-proxy policies from the default chrome policy definition | |
119 // list but set all the types to integer. The names of policies are not | |
120 // modified, and they are not used later in these tests. | |
121 const ConfigurationPolicyProvider::PolicyDefinitionList* real_list = | |
122 ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(); | |
123 const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current; | |
124 | |
125 // Count the number of non-proxy policies. | |
126 simple_list_length_ = 0; | |
127 for (current = real_list->begin; current != real_list->end; ++current) { | |
128 if (!CloudPolicyProviderImpl::is_proxy_policy(current->policy_type)) { | |
129 ++simple_list_length_; | |
130 } | |
131 } | |
132 | |
133 int counter = 0; | |
134 simple_list_.reset(new ConfigurationPolicyProvider::PolicyDefinitionList); | |
135 entries_.reset( | |
136 new ConfigurationPolicyProvider::PolicyDefinitionList::Entry[ | |
137 simple_list_length_]); | |
138 for (current = real_list->begin; current != real_list->end; ++current) { | |
139 if (CloudPolicyProviderImpl::is_proxy_policy(current->policy_type)) | |
140 continue; | |
141 | |
142 entries_[counter].policy_type = current->policy_type; | |
143 entries_[counter].value_type = Value::TYPE_INTEGER; | |
144 entries_[counter].name = current->name; | |
145 | |
146 ++counter; | |
147 } | |
148 | |
149 simple_list_->begin = entries_.get(); | |
150 simple_list_->end = entries_.get() + simple_list_length_; | |
151 } | |
152 | |
153 virtual void TearDown() { | |
154 simple_list_.reset(); | |
155 entries_.reset(); | |
156 } | |
157 | |
158 // Verify the test scenario of MultipleCaches | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
period.
gfeher
2011/06/22 19:18:34
Done.
| |
159 void VerifyMultipleCaches(MockCloudPolicyCache caches[], | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
I don't like this verification code. It's hard to
gfeher
2011/06/22 19:18:34
Done.
| |
160 CloudPolicyCacheBase::PolicyLevel level) { | |
161 CreateCloudPolicyProvider(simple_list(), level); | |
162 MockConfigurationPolicyStore store; | |
163 for (int i = 0; i < simple_list_length(); ++i) | |
164 AppendCache(&caches[i]); | |
165 | |
166 EXPECT_CALL(store, Apply(_, _)).Times(AnyNumber()); | |
167 Provide(&store); | |
168 | |
169 const int n = simple_list_length(); | |
170 // The final compilation should have exactly two policies per active cache | |
171 // set. | |
172 for (int i = 0; i < n; ++i) { | |
173 const Value* value = store.Get(simple_list_policy_type(i)); | |
174 if (i == n - 1 && !caches[i].initialization_complete()) { | |
175 // If the last provider is not initialized, then the last policy | |
176 // is not provided by anyone. | |
177 EXPECT_EQ(NULL, value); | |
178 break; | |
179 } | |
180 ASSERT_TRUE(value != NULL); | |
181 int policy_value; | |
182 EXPECT_TRUE(value->GetAsInteger(&policy_value)); | |
183 int originating_cache = policy_value / n; | |
184 int policy_id = policy_value % n; | |
185 EXPECT_EQ(i, policy_id) << "Policy identifier mismatch"; | |
186 if (caches[i].initialization_complete()) { | |
187 // Initialized caches will have their corresponding policy set. | |
188 EXPECT_EQ(i, originating_cache) << "Providing cache mismatch."; | |
189 } else { | |
190 // For non-initialized providers the corresponding value will be set by | |
191 // the next provider. (The last provider is handled elsewhere.) | |
192 EXPECT_EQ(i + 1, originating_cache) << "Providing cache mismatch."; | |
193 } | |
194 } | |
195 } | |
196 | |
197 private: | |
198 scoped_ptr<CloudPolicyProviderImpl> cloud_policy_provider_; | |
199 | |
200 // A list of policies to be used in tests: it has some simplifications to | |
201 // make testing more easy: it doesn't have proxy policies and all the | |
202 // policies have the type of integer. | |
203 scoped_ptr<ConfigurationPolicyProvider::PolicyDefinitionList> simple_list_; | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
Why is this so complicated? Can't we just declare
gfeher
2011/06/22 19:18:34
We can go even deeper...
| |
204 int simple_list_length_; | |
205 | |
206 // The following members own the internal parts of simple_list_, therefore | |
207 // they may only be freed after simple_list_ is freed. | |
208 scoped_array<ConfigurationPolicyProvider::PolicyDefinitionList::Entry> | |
209 entries_; | |
210 }; | |
211 | |
212 // Proxy setting distributed over multiple caches. | |
213 TEST_F(CloudPolicyProviderTest, | |
214 ProxySettingDistributedOverMultipleCaches) { | |
215 const int proxy_related_policies = proxy_policy_count(); | |
216 | |
217 // There are |proxy_related_policies|+1 caches and they are mixed together by | |
218 // one instance of CloudPolicyProvider. The first cache has some policies but | |
219 // no proxy-related ones. The following caches have each one proxy-policy set. | |
220 const int n = proxy_related_policies + 1; | |
221 | |
222 // Make sure that our assumptions about the existing proxy-related policies | |
223 // are still correct. | |
224 DCHECK(proxy_related_policies == 5); | |
225 | |
226 scoped_array<MockCloudPolicyCache> caches(new MockCloudPolicyCache[n]); | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
Just put 5 instead of n and delete all the cruft a
gfeher
2011/06/22 19:18:34
Done.
| |
227 | |
228 const ConfigurationPolicyProvider::PolicyDefinitionList* list = | |
229 policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(); | |
230 const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current; | |
231 | |
232 // Prepare |cache[0]| to serve some non-proxy policies. | |
233 caches[0].set_initialized(true); | |
234 caches[0].raw_mandatory_policy()->Set(kPolicyShowHomeButton, | |
235 Value::CreateBooleanValue(true)); | |
236 caches[0].raw_mandatory_policy()->Set(kPolicyIncognitoEnabled, | |
237 Value::CreateBooleanValue(true)); | |
238 caches[0].raw_mandatory_policy()->Set(kPolicyTranslateEnabled, | |
239 Value::CreateBooleanValue(true)); | |
240 | |
241 // Prepare the other caches to serve one proxy-policy each. | |
242 caches[1].set_initialized(true); | |
243 caches[1].raw_mandatory_policy()->Set(kPolicyProxyMode, | |
244 Value::CreateStringValue("cache 1")); | |
245 caches[2].set_initialized(true); | |
246 caches[2].raw_mandatory_policy()->Set(kPolicyProxyServerMode, | |
247 Value::CreateIntegerValue(2)); | |
248 caches[3].set_initialized(true); | |
249 caches[3].raw_mandatory_policy()->Set(kPolicyProxyServer, | |
250 Value::CreateStringValue("cache 3")); | |
251 caches[4].set_initialized(true); | |
252 caches[4].raw_mandatory_policy()->Set(kPolicyProxyPacUrl, | |
253 Value::CreateStringValue("cache 4")); | |
254 caches[5].set_initialized(true); | |
255 caches[5].raw_mandatory_policy()->Set(kPolicyProxyMode, | |
256 Value::CreateStringValue("cache 5")); | |
257 | |
258 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY); | |
259 | |
260 // Prepend from the end. | |
261 for (int i = 0; i < n; ++i) | |
262 PrependCache(&caches[n-i-1]); | |
263 | |
264 MockConfigurationPolicyStore store; | |
265 EXPECT_CALL(store, Apply(_, _)).Times(AnyNumber()); | |
266 Provide(&store); | |
267 | |
268 // The final compilation should have some policies set to true. From the proxy | |
269 // related policies only |kPolicyProxyMode| should be set. | |
270 for (current = list->begin; current != list->end; ++current) { | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
let's just write down what exact expectation we ha
gfeher
2011/06/22 19:18:34
Done.
| |
271 const Value* value = store.Get(current->policy_type); | |
272 if (current->policy_type == kPolicyProxyMode) { | |
273 EXPECT_TRUE(value); | |
274 std::string string_value; | |
275 bool result = value->GetAsString(&string_value); | |
276 EXPECT_TRUE(result); | |
277 EXPECT_EQ(string_value, "cache 1"); | |
278 } else if (is_proxy_policy(current->policy_type)) { | |
279 EXPECT_FALSE(value); | |
280 } else if (current->policy_type == kPolicyShowHomeButton || | |
281 current->policy_type == kPolicyIncognitoEnabled || | |
282 current->policy_type == kPolicyTranslateEnabled) { | |
283 EXPECT_TRUE(value); | |
284 bool boolean_value = false; | |
285 EXPECT_TRUE(value->GetAsBoolean(&boolean_value)); | |
286 EXPECT_TRUE(boolean_value); | |
287 } else { | |
288 EXPECT_FALSE(value); | |
289 } | |
290 } | |
291 } | |
292 | |
293 // Having many different caches adding them to the end incrementally. | |
294 TEST_F(CloudPolicyProviderTest, MultipleCaches) { | |
295 const int n = simple_list_length(); | |
296 // We set up as many caches as non-proxy policies (n). We configure them | |
297 // according to the following pattern: | |
298 // The i-th cache will serve i policies and be at position i in the list | |
299 // of CloudPolicyProvider. | |
300 // The i-th cache will be set to initialized iff i % 2 == 1 | |
301 // Thus in the end there should be exactly two policies applied per | |
302 // initialized cache. | |
303 // The j-th policy of the i-th cache will be set to i * n + j, thus | |
304 // given a policy value of x, x / n gives us the cache that provided it and | |
305 // x % n should give its own identifier. | |
306 // Prepare |cache[i]| to serve the first i policies from |list|. | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
Again, I find this too complicated. Why not just c
gfeher
2011/06/22 19:18:34
Done.
| |
307 scoped_array<MockCloudPolicyCache> caches(new MockCloudPolicyCache[n]); | |
308 for (int cache_id = 0; cache_id < n; ++cache_id) { | |
309 for (int policy_id = 0; policy_id <= cache_id; ++policy_id) { | |
310 // Set a unique value. | |
311 caches[cache_id].raw_recommended_policy()->Set( | |
312 simple_list_policy_type(policy_id), | |
313 Value::CreateIntegerValue(cache_id * n + policy_id)); | |
314 caches[cache_id].raw_mandatory_policy()->Set( | |
315 simple_list_policy_type(policy_id), | |
316 Value::CreateIntegerValue(cache_id * n + policy_id)); | |
317 | |
318 // Odd numbered caches are initialized and evens are not. | |
319 caches[cache_id].set_initialized(cache_id % 2); | |
320 } | |
321 } | |
322 | |
323 // Verify that the provider provides policies according to the expected | |
324 // pattern. | |
325 VerifyMultipleCaches(caches.get(), | |
326 CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
327 VerifyMultipleCaches(caches.get(), | |
328 CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY); | |
329 } | |
330 | |
331 // Combining two PolicyMaps. | |
332 TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsSame) { | |
333 PolicyMap A, B, C; | |
334 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
335 for (int i = 0; i < simple_list_length(); ++i) { | |
336 A.Set(simple_list_policy_type(i), Value::CreateIntegerValue(i)); | |
337 B.Set(simple_list_policy_type(i), Value::CreateIntegerValue(-1 * i)); | |
338 } | |
339 CombineTwoPolicyMaps(A, B, &C); | |
340 EXPECT_TRUE(A.Equals(C)); | |
341 } | |
342 | |
343 TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsEmpty) { | |
344 PolicyMap A, B, C; | |
345 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
346 CombineTwoPolicyMaps(A, B, &C); | |
347 EXPECT_TRUE(C.empty()); | |
348 } | |
349 | |
350 TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsPartial) { | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
What additional coverage does this test give over
gfeher
2011/06/22 19:18:34
If this doesn't fail but MultipleCaches does, then
| |
351 PolicyMap A, B, C; | |
352 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
353 | |
354 for (int i = 0; i < simple_list_length(); ++i) { | |
355 B.Set(simple_list_policy_type(i), Value::CreateIntegerValue(-i)); | |
356 if (i % 2 == 0) | |
357 A.Set(simple_list_policy_type(i), Value::CreateIntegerValue(i)); | |
358 } | |
359 | |
360 CombineTwoPolicyMaps(A, B, &C); | |
361 | |
362 for (int i = 0; i < simple_list_length(); ++i) { | |
363 if (const Value* value = C.Get(simple_list_policy_type(i))) { | |
364 int int_value; | |
365 EXPECT_TRUE(value->GetAsInteger(&int_value)); | |
366 if (i % 2 == 1) { | |
367 EXPECT_EQ(int_value, -1 * i); | |
368 } else { | |
369 EXPECT_EQ(int_value, i); | |
370 } | |
371 } | |
372 } | |
373 } | |
374 | |
375 TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsProxies) { | |
376 const int n = proxy_policy_count(); | |
377 const int a_value = 1; | |
378 const int b_value = -1; | |
379 PolicyMap A, B, C; | |
380 CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); | |
381 | |
382 A.Set(get_proxy_policy(0), Value::CreateIntegerValue(a_value)); | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
Why not just use a static constant here?
gfeher
2011/06/22 19:18:34
Done.
| |
383 for (int i = 1; i < n; ++i) | |
384 B.Set(get_proxy_policy(i), Value::CreateIntegerValue(b_value)); | |
Mattias Nissler (ping if slow)
2011/06/21 20:09:56
and here, and unroll the loop?
gfeher
2011/06/22 19:18:34
Done.
| |
385 | |
386 CombineTwoPolicyMaps(A, B, &C); | |
387 | |
388 EXPECT_TRUE(A.Equals(C)); | |
389 EXPECT_FALSE(B.Equals(C)); | |
390 } | |
391 | |
392 } // namespace policy | |
OLD | NEW |