1 // Copyright 2013 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.
5 #include "components/policy/core/common/configuration_policy_provider_test.h"
8 #include "base/callback.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/values.h"
11 #include "components/policy/core/common/configuration_policy_provider.h"
12 #include "components/policy/core/common/external_data_fetcher.h"
13 #include "components/policy/core/common/mock_configuration_policy_provider.h"
14 #include "components/policy/core/common/policy_bundle.h"
15 #include "components/policy/core/common/policy_map.h"
16 #include "components/policy/core/common/policy_namespace.h"
17 #include "testing/gmock/include/gmock/gmock.h"
19 using ::testing::Mock
;
24 const char kTestChromeSchema
[] =
26 " \"type\": \"object\","
28 " \"StringPolicy\": { \"type\": \"string\" },"
29 " \"BooleanPolicy\": { \"type\": \"boolean\" },"
30 " \"IntegerPolicy\": { \"type\": \"integer\" },"
31 " \"StringListPolicy\": {"
32 " \"type\": \"array\","
33 " \"items\": { \"type\": \"string\" }"
35 " \"DictionaryPolicy\": {"
36 " \"type\": \"object\","
38 " \"bool\": { \"type\": \"boolean\" },"
39 " \"double\": { \"type\": \"number\" },"
40 " \"int\": { \"type\": \"integer\" },"
41 " \"string\": { \"type\": \"string\" },"
43 " \"type\": \"array\","
44 " \"items\": { \"type\": \"string\" }"
47 " \"type\": \"object\","
49 " \"sub\": { \"type\": \"string\" },"
51 " \"type\": \"array\","
53 " \"type\": \"object\","
55 " \"aaa\": { \"type\": \"integer\" },"
56 " \"bbb\": { \"type\": \"integer\" },"
57 " \"ccc\": { \"type\": \"string\" },"
58 " \"ddd\": { \"type\": \"string\" }"
65 " \"type\": \"array\","
67 " \"type\": \"object\","
69 " \"subdictindex\": { \"type\": \"integer\" },"
71 " \"type\": \"object\","
73 " \"bool\": { \"type\": \"boolean\" },"
74 " \"double\": { \"type\": \"number\" },"
75 " \"int\": { \"type\": \"integer\" },"
76 " \"string\": { \"type\": \"string\" }"
83 " \"type\": \"object\","
85 " \"bool\": { \"type\": \"boolean\" },"
86 " \"double\": { \"type\": \"number\" },"
87 " \"int\": { \"type\": \"integer\" },"
88 " \"string\": { \"type\": \"string\" },"
90 " \"type\": \"array\","
92 " \"type\": \"object\","
94 " \"subdictindex\": { \"type\": \"integer\" },"
96 " \"type\": \"object\","
98 " \"bool\": { \"type\": \"boolean\" },"
99 " \"double\": { \"type\": \"number\" },"
100 " \"int\": { \"type\": \"integer\" },"
101 " \"string\": { \"type\": \"string\" }"
114 namespace test_keys
{
116 const char kKeyString
[] = "StringPolicy";
117 const char kKeyBoolean
[] = "BooleanPolicy";
118 const char kKeyInteger
[] = "IntegerPolicy";
119 const char kKeyStringList
[] = "StringListPolicy";
120 const char kKeyDictionary
[] = "DictionaryPolicy";
122 } // namespace test_keys
124 PolicyTestBase::PolicyTestBase() {}
126 PolicyTestBase::~PolicyTestBase() {}
128 void PolicyTestBase::SetUp() {
129 const PolicyNamespace
ns(POLICY_DOMAIN_CHROME
, "");
130 ASSERT_TRUE(RegisterSchema(ns
, kTestChromeSchema
));
133 void PolicyTestBase::TearDown() {
134 loop_
.RunUntilIdle();
137 bool PolicyTestBase::RegisterSchema(const PolicyNamespace
& ns
,
138 const std::string
& schema_string
) {
140 Schema schema
= Schema::Parse(schema_string
, &error
);
141 if (schema
.valid()) {
142 schema_registry_
.RegisterComponent(ns
, schema
);
145 ADD_FAILURE() << error
;
149 PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level
,
151 : level_(level
), scope_(scope
) {}
153 PolicyProviderTestHarness::~PolicyProviderTestHarness() {}
155 PolicyLevel
PolicyProviderTestHarness::policy_level() const {
159 PolicyScope
PolicyProviderTestHarness::policy_scope() const {
163 void PolicyProviderTestHarness::Install3rdPartyPolicy(
164 const base::DictionaryValue
* policies
) {
168 ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {}
170 ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {}
172 void ConfigurationPolicyProviderTest::SetUp() {
173 PolicyTestBase::SetUp();
175 test_harness_
.reset((*GetParam())());
176 test_harness_
->SetUp();
178 const PolicyNamespace
chrome_ns(POLICY_DOMAIN_CHROME
, "");
179 Schema chrome_schema
= *schema_registry_
.schema_map()->GetSchema(chrome_ns
);
180 Schema extension_schema
=
181 chrome_schema
.GetKnownProperty(test_keys::kKeyDictionary
);
182 ASSERT_TRUE(extension_schema
.valid());
183 schema_registry_
.RegisterComponent(
184 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
185 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
187 schema_registry_
.RegisterComponent(
188 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
189 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
191 schema_registry_
.RegisterComponent(
192 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
193 "cccccccccccccccccccccccccccccccc"),
196 provider_
.reset(test_harness_
->CreateProvider(&schema_registry_
,
197 loop_
.message_loop_proxy()));
198 provider_
->Init(&schema_registry_
);
199 // Some providers do a reload on init. Make sure any notifications generated
201 loop_
.RunUntilIdle();
203 const PolicyBundle kEmptyBundle
;
204 EXPECT_TRUE(provider_
->policies().Equals(kEmptyBundle
));
207 void ConfigurationPolicyProviderTest::TearDown() {
208 // Give providers the chance to clean up after themselves on the file thread.
209 provider_
->Shutdown();
212 PolicyTestBase::TearDown();
215 void ConfigurationPolicyProviderTest::CheckValue(
216 const char* policy_name
,
217 const base::Value
& expected_value
,
218 base::Closure install_value
) {
219 // Install the value, reload policy and check the provider for the value.
221 provider_
->RefreshPolicies();
222 loop_
.RunUntilIdle();
223 PolicyBundle expected_bundle
;
224 expected_bundle
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
226 test_harness_
->policy_level(),
227 test_harness_
->policy_scope(),
228 expected_value
.DeepCopy(),
230 EXPECT_TRUE(provider_
->policies().Equals(expected_bundle
));
231 // TODO(joaodasilva): set the policy in the POLICY_DOMAIN_EXTENSIONS too,
232 // and extend the |expected_bundle|, once all providers are ready.
235 TEST_P(ConfigurationPolicyProviderTest
, Empty
) {
236 provider_
->RefreshPolicies();
237 loop_
.RunUntilIdle();
238 const PolicyBundle kEmptyBundle
;
239 EXPECT_TRUE(provider_
->policies().Equals(kEmptyBundle
));
242 TEST_P(ConfigurationPolicyProviderTest
, StringValue
) {
243 const char kTestString
[] = "string_value";
244 base::StringValue
expected_value(kTestString
);
245 CheckValue(test_keys::kKeyString
,
247 base::Bind(&PolicyProviderTestHarness::InstallStringPolicy
,
248 base::Unretained(test_harness_
.get()),
249 test_keys::kKeyString
,
253 TEST_P(ConfigurationPolicyProviderTest
, BooleanValue
) {
254 base::FundamentalValue
expected_value(true);
255 CheckValue(test_keys::kKeyBoolean
,
257 base::Bind(&PolicyProviderTestHarness::InstallBooleanPolicy
,
258 base::Unretained(test_harness_
.get()),
259 test_keys::kKeyBoolean
,
263 TEST_P(ConfigurationPolicyProviderTest
, IntegerValue
) {
264 base::FundamentalValue
expected_value(42);
265 CheckValue(test_keys::kKeyInteger
,
267 base::Bind(&PolicyProviderTestHarness::InstallIntegerPolicy
,
268 base::Unretained(test_harness_
.get()),
269 test_keys::kKeyInteger
,
273 TEST_P(ConfigurationPolicyProviderTest
, StringListValue
) {
274 base::ListValue expected_value
;
275 expected_value
.Set(0U, base::Value::CreateStringValue("first"));
276 expected_value
.Set(1U, base::Value::CreateStringValue("second"));
277 CheckValue(test_keys::kKeyStringList
,
279 base::Bind(&PolicyProviderTestHarness::InstallStringListPolicy
,
280 base::Unretained(test_harness_
.get()),
281 test_keys::kKeyStringList
,
285 TEST_P(ConfigurationPolicyProviderTest
, DictionaryValue
) {
286 base::DictionaryValue expected_value
;
287 expected_value
.SetBoolean("bool", true);
288 expected_value
.SetDouble("double", 123.456);
289 expected_value
.SetInteger("int", 123);
290 expected_value
.SetString("string", "omg");
292 base::ListValue
* list
= new base::ListValue();
293 list
->Set(0U, base::Value::CreateStringValue("first"));
294 list
->Set(1U, base::Value::CreateStringValue("second"));
295 expected_value
.Set("array", list
);
297 base::DictionaryValue
* dict
= new base::DictionaryValue();
298 dict
->SetString("sub", "value");
299 list
= new base::ListValue();
300 base::DictionaryValue
* sub
= new base::DictionaryValue();
301 sub
->SetInteger("aaa", 111);
302 sub
->SetInteger("bbb", 222);
304 sub
= new base::DictionaryValue();
305 sub
->SetString("ccc", "333");
306 sub
->SetString("ddd", "444");
308 dict
->Set("sublist", list
);
309 expected_value
.Set("dictionary", dict
);
311 CheckValue(test_keys::kKeyDictionary
,
313 base::Bind(&PolicyProviderTestHarness::InstallDictionaryPolicy
,
314 base::Unretained(test_harness_
.get()),
315 test_keys::kKeyDictionary
,
319 TEST_P(ConfigurationPolicyProviderTest
, RefreshPolicies
) {
321 EXPECT_TRUE(provider_
->policies().Equals(bundle
));
323 // OnUpdatePolicy is called even when there are no changes.
324 MockConfigurationPolicyObserver observer
;
325 provider_
->AddObserver(&observer
);
326 EXPECT_CALL(observer
, OnUpdatePolicy(provider_
.get())).Times(1);
327 provider_
->RefreshPolicies();
328 loop_
.RunUntilIdle();
329 Mock::VerifyAndClearExpectations(&observer
);
331 EXPECT_TRUE(provider_
->policies().Equals(bundle
));
333 // OnUpdatePolicy is called when there are changes.
334 test_harness_
->InstallStringPolicy(test_keys::kKeyString
, "value");
335 EXPECT_CALL(observer
, OnUpdatePolicy(provider_
.get())).Times(1);
336 provider_
->RefreshPolicies();
337 loop_
.RunUntilIdle();
338 Mock::VerifyAndClearExpectations(&observer
);
340 bundle
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
341 .Set(test_keys::kKeyString
,
342 test_harness_
->policy_level(),
343 test_harness_
->policy_scope(),
344 base::Value::CreateStringValue("value"),
346 EXPECT_TRUE(provider_
->policies().Equals(bundle
));
347 provider_
->RemoveObserver(&observer
);
350 Configuration3rdPartyPolicyProviderTest::
351 Configuration3rdPartyPolicyProviderTest() {}
353 Configuration3rdPartyPolicyProviderTest::
354 ~Configuration3rdPartyPolicyProviderTest() {}
356 TEST_P(Configuration3rdPartyPolicyProviderTest
, Load3rdParty
) {
357 base::DictionaryValue policy_dict
;
358 policy_dict
.SetBoolean("bool", true);
359 policy_dict
.SetDouble("double", 123.456);
360 policy_dict
.SetInteger("int", 789);
361 policy_dict
.SetString("string", "string value");
363 base::ListValue
* list
= new base::ListValue();
364 for (int i
= 0; i
< 2; ++i
) {
365 base::DictionaryValue
* dict
= new base::DictionaryValue();
366 dict
->SetInteger("subdictindex", i
);
367 dict
->Set("subdict", policy_dict
.DeepCopy());
370 policy_dict
.Set("list", list
);
371 policy_dict
.Set("dict", policy_dict
.DeepCopy());
373 // Install these policies as a Chrome policy.
374 test_harness_
->InstallDictionaryPolicy(test_keys::kKeyDictionary
,
376 // Install them as 3rd party policies too.
377 base::DictionaryValue policy_3rdparty
;
378 policy_3rdparty
.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
379 policy_dict
.DeepCopy());
380 policy_3rdparty
.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
381 policy_dict
.DeepCopy());
382 // Install invalid 3rd party policies that shouldn't be loaded. These also
383 // help detecting memory leaks in the code paths that detect invalid input.
384 policy_3rdparty
.Set("invalid-domain.component", policy_dict
.DeepCopy());
385 policy_3rdparty
.Set("extensions.cccccccccccccccccccccccccccccccc",
386 base::Value::CreateStringValue("invalid-value"));
387 test_harness_
->Install3rdPartyPolicy(&policy_3rdparty
);
389 provider_
->RefreshPolicies();
390 loop_
.RunUntilIdle();
392 PolicyMap expected_policy
;
393 expected_policy
.Set(test_keys::kKeyDictionary
,
394 test_harness_
->policy_level(),
395 test_harness_
->policy_scope(),
396 policy_dict
.DeepCopy(),
398 PolicyBundle expected_bundle
;
399 expected_bundle
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
400 .CopyFrom(expected_policy
);
401 expected_policy
.Clear();
402 expected_policy
.LoadFrom(&policy_dict
,
403 test_harness_
->policy_level(),
404 test_harness_
->policy_scope());
405 expected_bundle
.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
406 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
407 .CopyFrom(expected_policy
);
408 expected_bundle
.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
409 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
410 .CopyFrom(expected_policy
);
411 EXPECT_TRUE(provider_
->policies().Equals(expected_bundle
));
414 } // namespace policy