root/components/policy/core/common/configuration_policy_provider_test.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SetUp
  2. TearDown
  3. RegisterSchema
  4. scope_
  5. policy_level
  6. policy_scope
  7. Install3rdPartyPolicy
  8. SetUp
  9. TearDown
  10. CheckValue
  11. TEST_P
  12. TEST_P
  13. TEST_P
  14. TEST_P
  15. TEST_P
  16. TEST_P
  17. TEST_P
  18. Configuration3rdPartyPolicyProviderTest
  19. Configuration3rdPartyPolicyProviderTest
  20. TEST_P

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/policy/core/common/configuration_policy_provider_test.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/values.h"
#include "components/policy/core/common/configuration_policy_provider.h"
#include "components/policy/core/common/external_data_fetcher.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_bundle.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
#include "testing/gmock/include/gmock/gmock.h"

using ::testing::Mock;
using ::testing::_;

namespace policy {

const char kTestChromeSchema[] =
    "{"
    "  \"type\": \"object\","
    "  \"properties\": {"
    "    \"StringPolicy\": { \"type\": \"string\" },"
    "    \"BooleanPolicy\": { \"type\": \"boolean\" },"
    "    \"IntegerPolicy\": { \"type\": \"integer\" },"
    "    \"StringListPolicy\": {"
    "      \"type\": \"array\","
    "      \"items\": { \"type\": \"string\" }"
    "    },"
    "    \"DictionaryPolicy\": {"
    "      \"type\": \"object\","
    "      \"properties\": {"
    "        \"bool\": { \"type\": \"boolean\" },"
    "        \"double\": { \"type\": \"number\" },"
    "        \"int\": { \"type\": \"integer\" },"
    "        \"string\": { \"type\": \"string\" },"
    "        \"array\": {"
    "          \"type\": \"array\","
    "          \"items\": { \"type\": \"string\" }"
    "        },"
    "        \"dictionary\": {"
    "          \"type\": \"object\","
    "          \"properties\": {"
    "            \"sub\": { \"type\": \"string\" },"
    "            \"sublist\": {"
    "              \"type\": \"array\","
    "              \"items\": {"
    "                \"type\": \"object\","
    "                \"properties\": {"
    "                  \"aaa\": { \"type\": \"integer\" },"
    "                  \"bbb\": { \"type\": \"integer\" },"
    "                  \"ccc\": { \"type\": \"string\" },"
    "                  \"ddd\": { \"type\": \"string\" }"
    "                }"
    "              }"
    "            }"
    "          }"
    "        },"
    "        \"list\": {"
    "          \"type\": \"array\","
    "          \"items\": {"
    "            \"type\": \"object\","
    "            \"properties\": {"
    "              \"subdictindex\": { \"type\": \"integer\" },"
    "              \"subdict\": {"
    "                \"type\": \"object\","
    "                \"properties\": {"
    "                  \"bool\": { \"type\": \"boolean\" },"
    "                  \"double\": { \"type\": \"number\" },"
    "                  \"int\": { \"type\": \"integer\" },"
    "                  \"string\": { \"type\": \"string\" }"
    "                }"
    "              }"
    "            }"
    "          }"
    "        },"
    "        \"dict\": {"
    "          \"type\": \"object\","
    "          \"properties\": {"
    "            \"bool\": { \"type\": \"boolean\" },"
    "            \"double\": { \"type\": \"number\" },"
    "            \"int\": { \"type\": \"integer\" },"
    "            \"string\": { \"type\": \"string\" },"
    "            \"list\": {"
    "              \"type\": \"array\","
    "              \"items\": {"
    "                \"type\": \"object\","
    "                \"properties\": {"
    "                  \"subdictindex\": { \"type\": \"integer\" },"
    "                  \"subdict\": {"
    "                    \"type\": \"object\","
    "                    \"properties\": {"
    "                      \"bool\": { \"type\": \"boolean\" },"
    "                      \"double\": { \"type\": \"number\" },"
    "                      \"int\": { \"type\": \"integer\" },"
    "                      \"string\": { \"type\": \"string\" }"
    "                    }"
    "                  }"
    "                }"
    "              }"
    "            }"
    "          }"
    "        }"
    "      }"
    "    }"
    "  }"
    "}";

namespace test_keys {

const char kKeyString[] = "StringPolicy";
const char kKeyBoolean[] = "BooleanPolicy";
const char kKeyInteger[] = "IntegerPolicy";
const char kKeyStringList[] = "StringListPolicy";
const char kKeyDictionary[] = "DictionaryPolicy";

}  // namespace test_keys

PolicyTestBase::PolicyTestBase() {}

PolicyTestBase::~PolicyTestBase() {}

void PolicyTestBase::SetUp() {
  const PolicyNamespace ns(POLICY_DOMAIN_CHROME, "");
  ASSERT_TRUE(RegisterSchema(ns, kTestChromeSchema));
}

void PolicyTestBase::TearDown() {
  loop_.RunUntilIdle();
}

bool PolicyTestBase::RegisterSchema(const PolicyNamespace& ns,
                                    const std::string& schema_string) {
  std::string error;
  Schema schema = Schema::Parse(schema_string, &error);
  if (schema.valid()) {
    schema_registry_.RegisterComponent(ns, schema);
    return true;
  }
  ADD_FAILURE() << error;
  return false;
}

PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level,
                                                     PolicyScope scope)
    : level_(level), scope_(scope) {}

PolicyProviderTestHarness::~PolicyProviderTestHarness() {}

PolicyLevel PolicyProviderTestHarness::policy_level() const {
  return level_;
}

PolicyScope PolicyProviderTestHarness::policy_scope() const {
  return scope_;
}

void PolicyProviderTestHarness::Install3rdPartyPolicy(
    const base::DictionaryValue* policies) {
  FAIL();
}

ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {}

ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {}

void ConfigurationPolicyProviderTest::SetUp() {
  PolicyTestBase::SetUp();

  test_harness_.reset((*GetParam())());
  test_harness_->SetUp();

  const PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
  Schema chrome_schema = *schema_registry_.schema_map()->GetSchema(chrome_ns);
  Schema extension_schema =
      chrome_schema.GetKnownProperty(test_keys::kKeyDictionary);
  ASSERT_TRUE(extension_schema.valid());
  schema_registry_.RegisterComponent(
      PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
                      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
      extension_schema);
  schema_registry_.RegisterComponent(
      PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
                      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
      extension_schema);
  schema_registry_.RegisterComponent(
      PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
                      "cccccccccccccccccccccccccccccccc"),
      extension_schema);

  provider_.reset(test_harness_->CreateProvider(&schema_registry_,
                                                loop_.message_loop_proxy()));
  provider_->Init(&schema_registry_);
  // Some providers do a reload on init. Make sure any notifications generated
  // are fired now.
  loop_.RunUntilIdle();

  const PolicyBundle kEmptyBundle;
  EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle));
}

void ConfigurationPolicyProviderTest::TearDown() {
  // Give providers the chance to clean up after themselves on the file thread.
  provider_->Shutdown();
  provider_.reset();

  PolicyTestBase::TearDown();
}

void ConfigurationPolicyProviderTest::CheckValue(
    const char* policy_name,
    const base::Value& expected_value,
    base::Closure install_value) {
  // Install the value, reload policy and check the provider for the value.
  install_value.Run();
  provider_->RefreshPolicies();
  loop_.RunUntilIdle();
  PolicyBundle expected_bundle;
  expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
      .Set(policy_name,
           test_harness_->policy_level(),
           test_harness_->policy_scope(),
           expected_value.DeepCopy(),
           NULL);
  EXPECT_TRUE(provider_->policies().Equals(expected_bundle));
  // TODO(joaodasilva): set the policy in the POLICY_DOMAIN_EXTENSIONS too,
  // and extend the |expected_bundle|, once all providers are ready.
}

TEST_P(ConfigurationPolicyProviderTest, Empty) {
  provider_->RefreshPolicies();
  loop_.RunUntilIdle();
  const PolicyBundle kEmptyBundle;
  EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle));
}

TEST_P(ConfigurationPolicyProviderTest, StringValue) {
  const char kTestString[] = "string_value";
  base::StringValue expected_value(kTestString);
  CheckValue(test_keys::kKeyString,
             expected_value,
             base::Bind(&PolicyProviderTestHarness::InstallStringPolicy,
                        base::Unretained(test_harness_.get()),
                        test_keys::kKeyString,
                        kTestString));
}

TEST_P(ConfigurationPolicyProviderTest, BooleanValue) {
  base::FundamentalValue expected_value(true);
  CheckValue(test_keys::kKeyBoolean,
             expected_value,
             base::Bind(&PolicyProviderTestHarness::InstallBooleanPolicy,
                        base::Unretained(test_harness_.get()),
                        test_keys::kKeyBoolean,
                        true));
}

TEST_P(ConfigurationPolicyProviderTest, IntegerValue) {
  base::FundamentalValue expected_value(42);
  CheckValue(test_keys::kKeyInteger,
             expected_value,
             base::Bind(&PolicyProviderTestHarness::InstallIntegerPolicy,
                        base::Unretained(test_harness_.get()),
                        test_keys::kKeyInteger,
                        42));
}

TEST_P(ConfigurationPolicyProviderTest, StringListValue) {
  base::ListValue expected_value;
  expected_value.Set(0U, base::Value::CreateStringValue("first"));
  expected_value.Set(1U, base::Value::CreateStringValue("second"));
  CheckValue(test_keys::kKeyStringList,
             expected_value,
             base::Bind(&PolicyProviderTestHarness::InstallStringListPolicy,
                        base::Unretained(test_harness_.get()),
                        test_keys::kKeyStringList,
                        &expected_value));
}

TEST_P(ConfigurationPolicyProviderTest, DictionaryValue) {
  base::DictionaryValue expected_value;
  expected_value.SetBoolean("bool", true);
  expected_value.SetDouble("double", 123.456);
  expected_value.SetInteger("int", 123);
  expected_value.SetString("string", "omg");

  base::ListValue* list = new base::ListValue();
  list->Set(0U, base::Value::CreateStringValue("first"));
  list->Set(1U, base::Value::CreateStringValue("second"));
  expected_value.Set("array", list);

  base::DictionaryValue* dict = new base::DictionaryValue();
  dict->SetString("sub", "value");
  list = new base::ListValue();
  base::DictionaryValue* sub = new base::DictionaryValue();
  sub->SetInteger("aaa", 111);
  sub->SetInteger("bbb", 222);
  list->Append(sub);
  sub = new base::DictionaryValue();
  sub->SetString("ccc", "333");
  sub->SetString("ddd", "444");
  list->Append(sub);
  dict->Set("sublist", list);
  expected_value.Set("dictionary", dict);

  CheckValue(test_keys::kKeyDictionary,
             expected_value,
             base::Bind(&PolicyProviderTestHarness::InstallDictionaryPolicy,
                        base::Unretained(test_harness_.get()),
                        test_keys::kKeyDictionary,
                        &expected_value));
}

TEST_P(ConfigurationPolicyProviderTest, RefreshPolicies) {
  PolicyBundle bundle;
  EXPECT_TRUE(provider_->policies().Equals(bundle));

  // OnUpdatePolicy is called even when there are no changes.
  MockConfigurationPolicyObserver observer;
  provider_->AddObserver(&observer);
  EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
  provider_->RefreshPolicies();
  loop_.RunUntilIdle();
  Mock::VerifyAndClearExpectations(&observer);

  EXPECT_TRUE(provider_->policies().Equals(bundle));

  // OnUpdatePolicy is called when there are changes.
  test_harness_->InstallStringPolicy(test_keys::kKeyString, "value");
  EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
  provider_->RefreshPolicies();
  loop_.RunUntilIdle();
  Mock::VerifyAndClearExpectations(&observer);

  bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
      .Set(test_keys::kKeyString,
           test_harness_->policy_level(),
           test_harness_->policy_scope(),
           base::Value::CreateStringValue("value"),
           NULL);
  EXPECT_TRUE(provider_->policies().Equals(bundle));
  provider_->RemoveObserver(&observer);
}

Configuration3rdPartyPolicyProviderTest::
    Configuration3rdPartyPolicyProviderTest() {}

Configuration3rdPartyPolicyProviderTest::
    ~Configuration3rdPartyPolicyProviderTest() {}

TEST_P(Configuration3rdPartyPolicyProviderTest, Load3rdParty) {
  base::DictionaryValue policy_dict;
  policy_dict.SetBoolean("bool", true);
  policy_dict.SetDouble("double", 123.456);
  policy_dict.SetInteger("int", 789);
  policy_dict.SetString("string", "string value");

  base::ListValue* list = new base::ListValue();
  for (int i = 0; i < 2; ++i) {
    base::DictionaryValue* dict = new base::DictionaryValue();
    dict->SetInteger("subdictindex", i);
    dict->Set("subdict", policy_dict.DeepCopy());
    list->Append(dict);
  }
  policy_dict.Set("list", list);
  policy_dict.Set("dict", policy_dict.DeepCopy());

  // Install these policies as a Chrome policy.
  test_harness_->InstallDictionaryPolicy(test_keys::kKeyDictionary,
                                         &policy_dict);
  // Install them as 3rd party policies too.
  base::DictionaryValue policy_3rdparty;
  policy_3rdparty.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                      policy_dict.DeepCopy());
  policy_3rdparty.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
                      policy_dict.DeepCopy());
  // Install invalid 3rd party policies that shouldn't be loaded. These also
  // help detecting memory leaks in the code paths that detect invalid input.
  policy_3rdparty.Set("invalid-domain.component", policy_dict.DeepCopy());
  policy_3rdparty.Set("extensions.cccccccccccccccccccccccccccccccc",
                      base::Value::CreateStringValue("invalid-value"));
  test_harness_->Install3rdPartyPolicy(&policy_3rdparty);

  provider_->RefreshPolicies();
  loop_.RunUntilIdle();

  PolicyMap expected_policy;
  expected_policy.Set(test_keys::kKeyDictionary,
                      test_harness_->policy_level(),
                      test_harness_->policy_scope(),
                      policy_dict.DeepCopy(),
                      NULL);
  PolicyBundle expected_bundle;
  expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
      .CopyFrom(expected_policy);
  expected_policy.Clear();
  expected_policy.LoadFrom(&policy_dict,
                           test_harness_->policy_level(),
                           test_harness_->policy_scope());
  expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
                                      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
      .CopyFrom(expected_policy);
  expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
                                      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
      .CopyFrom(expected_policy);
  EXPECT_TRUE(provider_->policies().Equals(expected_bundle));
}

}  // namespace policy

/* [<][>][^][v][top][bottom][index][help] */