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/values.h"
10 #include "components/policy/core/common/configuration_policy_provider.h"
11 #include "components/policy/core/common/external_data_fetcher.h"
12 #include "components/policy/core/common/mock_configuration_policy_provider.h"
13 #include "components/policy/core/common/policy_bundle.h"
14 #include "components/policy/core/common/policy_map.h"
15 #include "components/policy/core/common/policy_namespace.h"
16 #include "testing/gmock/include/gmock/gmock.h"
18 using ::testing::Mock
;
23 const char kTestChromeSchema
[] =
25 " \"type\": \"object\","
27 " \"StringPolicy\": { \"type\": \"string\" },"
28 " \"BooleanPolicy\": { \"type\": \"boolean\" },"
29 " \"IntegerPolicy\": { \"type\": \"integer\" },"
30 " \"StringListPolicy\": {"
31 " \"type\": \"array\","
32 " \"items\": { \"type\": \"string\" }"
34 " \"DictionaryPolicy\": {"
35 " \"type\": \"object\","
37 " \"bool\": { \"type\": \"boolean\" },"
38 " \"double\": { \"type\": \"number\" },"
39 " \"int\": { \"type\": \"integer\" },"
40 " \"string\": { \"type\": \"string\" },"
42 " \"type\": \"array\","
43 " \"items\": { \"type\": \"string\" }"
46 " \"type\": \"object\","
48 " \"sub\": { \"type\": \"string\" },"
50 " \"type\": \"array\","
52 " \"type\": \"object\","
54 " \"aaa\": { \"type\": \"integer\" },"
55 " \"bbb\": { \"type\": \"integer\" },"
56 " \"ccc\": { \"type\": \"string\" },"
57 " \"ddd\": { \"type\": \"string\" }"
64 " \"type\": \"array\","
66 " \"type\": \"object\","
68 " \"subdictindex\": { \"type\": \"integer\" },"
70 " \"type\": \"object\","
72 " \"bool\": { \"type\": \"boolean\" },"
73 " \"double\": { \"type\": \"number\" },"
74 " \"int\": { \"type\": \"integer\" },"
75 " \"string\": { \"type\": \"string\" }"
82 " \"type\": \"object\","
84 " \"bool\": { \"type\": \"boolean\" },"
85 " \"double\": { \"type\": \"number\" },"
86 " \"int\": { \"type\": \"integer\" },"
87 " \"string\": { \"type\": \"string\" },"
89 " \"type\": \"array\","
91 " \"type\": \"object\","
93 " \"subdictindex\": { \"type\": \"integer\" },"
95 " \"type\": \"object\","
97 " \"bool\": { \"type\": \"boolean\" },"
98 " \"double\": { \"type\": \"number\" },"
99 " \"int\": { \"type\": \"integer\" },"
100 " \"string\": { \"type\": \"string\" }"
113 namespace test_keys
{
115 const char kKeyString
[] = "StringPolicy";
116 const char kKeyBoolean
[] = "BooleanPolicy";
117 const char kKeyInteger
[] = "IntegerPolicy";
118 const char kKeyStringList
[] = "StringListPolicy";
119 const char kKeyDictionary
[] = "DictionaryPolicy";
121 } // namespace test_keys
123 PolicyTestBase::PolicyTestBase() {}
125 PolicyTestBase::~PolicyTestBase() {}
127 void PolicyTestBase::SetUp() {
128 const PolicyNamespace
ns(POLICY_DOMAIN_CHROME
, "");
129 ASSERT_TRUE(RegisterSchema(ns
, kTestChromeSchema
));
132 void PolicyTestBase::TearDown() {
133 loop_
.RunUntilIdle();
136 bool PolicyTestBase::RegisterSchema(const PolicyNamespace
& ns
,
137 const std::string
& schema_string
) {
139 Schema schema
= Schema::Parse(schema_string
, &error
);
140 if (schema
.valid()) {
141 schema_registry_
.RegisterComponent(ns
, schema
);
144 ADD_FAILURE() << error
;
148 PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level
,
150 : level_(level
), scope_(scope
) {}
152 PolicyProviderTestHarness::~PolicyProviderTestHarness() {}
154 PolicyLevel
PolicyProviderTestHarness::policy_level() const {
158 PolicyScope
PolicyProviderTestHarness::policy_scope() const {
162 void PolicyProviderTestHarness::Install3rdPartyPolicy(
163 const base::DictionaryValue
* policies
) {
167 ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {}
169 ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {}
171 void ConfigurationPolicyProviderTest::SetUp() {
172 PolicyTestBase::SetUp();
174 test_harness_
.reset((*GetParam())());
175 test_harness_
->SetUp();
177 const PolicyNamespace
chrome_ns(POLICY_DOMAIN_CHROME
, "");
178 Schema chrome_schema
= *schema_registry_
.schema_map()->GetSchema(chrome_ns
);
179 Schema extension_schema
=
180 chrome_schema
.GetKnownProperty(test_keys::kKeyDictionary
);
181 ASSERT_TRUE(extension_schema
.valid());
182 schema_registry_
.RegisterComponent(
183 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
184 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
186 schema_registry_
.RegisterComponent(
187 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
188 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
190 schema_registry_
.RegisterComponent(
191 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
192 "cccccccccccccccccccccccccccccccc"),
196 test_harness_
->CreateProvider(&schema_registry_
, loop_
.task_runner()));
197 provider_
->Init(&schema_registry_
);
198 // Some providers do a reload on init. Make sure any notifications generated
200 loop_
.RunUntilIdle();
202 const PolicyBundle kEmptyBundle
;
203 EXPECT_TRUE(provider_
->policies().Equals(kEmptyBundle
));
206 void ConfigurationPolicyProviderTest::TearDown() {
207 // Give providers the chance to clean up after themselves on the file thread.
208 provider_
->Shutdown();
211 PolicyTestBase::TearDown();
214 void ConfigurationPolicyProviderTest::CheckValue(
215 const char* policy_name
,
216 const base::Value
& expected_value
,
217 base::Closure install_value
) {
218 // Install the value, reload policy and check the provider for the value.
220 provider_
->RefreshPolicies();
221 loop_
.RunUntilIdle();
222 PolicyBundle expected_bundle
;
223 expected_bundle
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
225 test_harness_
->policy_level(),
226 test_harness_
->policy_scope(),
227 expected_value
.DeepCopy(),
229 EXPECT_TRUE(provider_
->policies().Equals(expected_bundle
));
230 // TODO(joaodasilva): set the policy in the POLICY_DOMAIN_EXTENSIONS too,
231 // and extend the |expected_bundle|, once all providers are ready.
234 TEST_P(ConfigurationPolicyProviderTest
, Empty
) {
235 provider_
->RefreshPolicies();
236 loop_
.RunUntilIdle();
237 const PolicyBundle kEmptyBundle
;
238 EXPECT_TRUE(provider_
->policies().Equals(kEmptyBundle
));
241 TEST_P(ConfigurationPolicyProviderTest
, StringValue
) {
242 const char kTestString
[] = "string_value";
243 base::StringValue
expected_value(kTestString
);
244 CheckValue(test_keys::kKeyString
,
246 base::Bind(&PolicyProviderTestHarness::InstallStringPolicy
,
247 base::Unretained(test_harness_
.get()),
248 test_keys::kKeyString
,
252 TEST_P(ConfigurationPolicyProviderTest
, BooleanValue
) {
253 base::FundamentalValue
expected_value(true);
254 CheckValue(test_keys::kKeyBoolean
,
256 base::Bind(&PolicyProviderTestHarness::InstallBooleanPolicy
,
257 base::Unretained(test_harness_
.get()),
258 test_keys::kKeyBoolean
,
262 TEST_P(ConfigurationPolicyProviderTest
, IntegerValue
) {
263 base::FundamentalValue
expected_value(42);
264 CheckValue(test_keys::kKeyInteger
,
266 base::Bind(&PolicyProviderTestHarness::InstallIntegerPolicy
,
267 base::Unretained(test_harness_
.get()),
268 test_keys::kKeyInteger
,
272 TEST_P(ConfigurationPolicyProviderTest
, StringListValue
) {
273 base::ListValue expected_value
;
274 expected_value
.Set(0U, new base::StringValue("first"));
275 expected_value
.Set(1U, new base::StringValue("second"));
276 CheckValue(test_keys::kKeyStringList
,
278 base::Bind(&PolicyProviderTestHarness::InstallStringListPolicy
,
279 base::Unretained(test_harness_
.get()),
280 test_keys::kKeyStringList
,
284 TEST_P(ConfigurationPolicyProviderTest
, DictionaryValue
) {
285 base::DictionaryValue expected_value
;
286 expected_value
.SetBoolean("bool", true);
287 expected_value
.SetDouble("double", 123.456);
288 expected_value
.SetInteger("int", 123);
289 expected_value
.SetString("string", "omg");
291 base::ListValue
* list
= new base::ListValue();
292 list
->Set(0U, new base::StringValue("first"));
293 list
->Set(1U, new base::StringValue("second"));
294 expected_value
.Set("array", list
);
296 base::DictionaryValue
* dict
= new base::DictionaryValue();
297 dict
->SetString("sub", "value");
298 list
= new base::ListValue();
299 base::DictionaryValue
* sub
= new base::DictionaryValue();
300 sub
->SetInteger("aaa", 111);
301 sub
->SetInteger("bbb", 222);
303 sub
= new base::DictionaryValue();
304 sub
->SetString("ccc", "333");
305 sub
->SetString("ddd", "444");
307 dict
->Set("sublist", list
);
308 expected_value
.Set("dictionary", dict
);
310 CheckValue(test_keys::kKeyDictionary
,
312 base::Bind(&PolicyProviderTestHarness::InstallDictionaryPolicy
,
313 base::Unretained(test_harness_
.get()),
314 test_keys::kKeyDictionary
,
318 TEST_P(ConfigurationPolicyProviderTest
, RefreshPolicies
) {
320 EXPECT_TRUE(provider_
->policies().Equals(bundle
));
322 // OnUpdatePolicy is called even when there are no changes.
323 MockConfigurationPolicyObserver observer
;
324 provider_
->AddObserver(&observer
);
325 EXPECT_CALL(observer
, OnUpdatePolicy(provider_
.get())).Times(1);
326 provider_
->RefreshPolicies();
327 loop_
.RunUntilIdle();
328 Mock::VerifyAndClearExpectations(&observer
);
330 EXPECT_TRUE(provider_
->policies().Equals(bundle
));
332 // OnUpdatePolicy is called when there are changes.
333 test_harness_
->InstallStringPolicy(test_keys::kKeyString
, "value");
334 EXPECT_CALL(observer
, OnUpdatePolicy(provider_
.get())).Times(1);
335 provider_
->RefreshPolicies();
336 loop_
.RunUntilIdle();
337 Mock::VerifyAndClearExpectations(&observer
);
339 bundle
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
340 .Set(test_keys::kKeyString
,
341 test_harness_
->policy_level(),
342 test_harness_
->policy_scope(),
343 new base::StringValue("value"),
345 EXPECT_TRUE(provider_
->policies().Equals(bundle
));
346 provider_
->RemoveObserver(&observer
);
349 Configuration3rdPartyPolicyProviderTest::
350 Configuration3rdPartyPolicyProviderTest() {}
352 Configuration3rdPartyPolicyProviderTest::
353 ~Configuration3rdPartyPolicyProviderTest() {}
355 TEST_P(Configuration3rdPartyPolicyProviderTest
, Load3rdParty
) {
356 base::DictionaryValue policy_dict
;
357 policy_dict
.SetBoolean("bool", true);
358 policy_dict
.SetDouble("double", 123.456);
359 policy_dict
.SetInteger("int", 789);
360 policy_dict
.SetString("string", "string value");
362 base::ListValue
* list
= new base::ListValue();
363 for (int i
= 0; i
< 2; ++i
) {
364 base::DictionaryValue
* dict
= new base::DictionaryValue();
365 dict
->SetInteger("subdictindex", i
);
366 dict
->Set("subdict", policy_dict
.DeepCopy());
369 policy_dict
.Set("list", list
);
370 policy_dict
.Set("dict", policy_dict
.DeepCopy());
372 // Install these policies as a Chrome policy.
373 test_harness_
->InstallDictionaryPolicy(test_keys::kKeyDictionary
,
375 // Install them as 3rd party policies too.
376 base::DictionaryValue policy_3rdparty
;
377 policy_3rdparty
.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
378 policy_dict
.DeepCopy());
379 policy_3rdparty
.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
380 policy_dict
.DeepCopy());
381 // Install invalid 3rd party policies that shouldn't be loaded. These also
382 // help detecting memory leaks in the code paths that detect invalid input.
383 policy_3rdparty
.Set("invalid-domain.component", policy_dict
.DeepCopy());
384 policy_3rdparty
.Set("extensions.cccccccccccccccccccccccccccccccc",
385 new base::StringValue("invalid-value"));
386 test_harness_
->Install3rdPartyPolicy(&policy_3rdparty
);
388 provider_
->RefreshPolicies();
389 loop_
.RunUntilIdle();
391 PolicyMap expected_policy
;
392 expected_policy
.Set(test_keys::kKeyDictionary
,
393 test_harness_
->policy_level(),
394 test_harness_
->policy_scope(),
395 policy_dict
.DeepCopy(),
397 PolicyBundle expected_bundle
;
398 expected_bundle
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
399 .CopyFrom(expected_policy
);
400 expected_policy
.Clear();
401 expected_policy
.LoadFrom(&policy_dict
,
402 test_harness_
->policy_level(),
403 test_harness_
->policy_scope());
404 expected_bundle
.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
405 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
406 .CopyFrom(expected_policy
);
407 expected_bundle
.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
,
408 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
409 .CopyFrom(expected_policy
);
410 EXPECT_TRUE(provider_
->policies().Equals(expected_bundle
));
413 } // namespace policy