1// Copyright (c) 2012 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 "base/compiler_specific.h" 6#include "base/files/file_util.h" 7#include "base/files/scoped_temp_dir.h" 8#include "base/json/json_string_value_serializer.h" 9#include "base/memory/ref_counted.h" 10#include "base/message_loop/message_loop.h" 11#include "base/message_loop/message_loop_proxy.h" 12#include "base/sequenced_task_runner.h" 13#include "base/strings/string_number_conversions.h" 14#include "base/values.h" 15#include "components/policy/core/common/async_policy_provider.h" 16#include "components/policy/core/common/config_dir_policy_loader.h" 17#include "components/policy/core/common/configuration_policy_provider_test.h" 18#include "components/policy/core/common/policy_bundle.h" 19#include "components/policy/core/common/policy_map.h" 20 21namespace policy { 22 23namespace { 24 25// Subdirectory of the config dir that contains mandatory policies. 26const base::FilePath::CharType kMandatoryPath[] = FILE_PATH_LITERAL("managed"); 27 28class TestHarness : public PolicyProviderTestHarness { 29 public: 30 TestHarness(); 31 virtual ~TestHarness(); 32 33 virtual void SetUp() OVERRIDE; 34 35 virtual ConfigurationPolicyProvider* CreateProvider( 36 SchemaRegistry* registry, 37 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE; 38 39 virtual void InstallEmptyPolicy() OVERRIDE; 40 virtual void InstallStringPolicy(const std::string& policy_name, 41 const std::string& policy_value) OVERRIDE; 42 virtual void InstallIntegerPolicy(const std::string& policy_name, 43 int policy_value) OVERRIDE; 44 virtual void InstallBooleanPolicy(const std::string& policy_name, 45 bool policy_value) OVERRIDE; 46 virtual void InstallStringListPolicy( 47 const std::string& policy_name, 48 const base::ListValue* policy_value) OVERRIDE; 49 virtual void InstallDictionaryPolicy( 50 const std::string& policy_name, 51 const base::DictionaryValue* policy_value) OVERRIDE; 52 virtual void Install3rdPartyPolicy( 53 const base::DictionaryValue* policies) OVERRIDE; 54 55 const base::FilePath& test_dir() { return test_dir_.path(); } 56 57 // JSON-encode a dictionary and write it to a file. 58 void WriteConfigFile(const base::DictionaryValue& dict, 59 const std::string& file_name); 60 61 // Returns a unique name for a policy file. Each subsequent call returns a new 62 // name that comes lexicographically after the previous one. 63 std::string NextConfigFileName(); 64 65 static PolicyProviderTestHarness* Create(); 66 67 private: 68 base::ScopedTempDir test_dir_; 69 int next_policy_file_index_; 70 71 DISALLOW_COPY_AND_ASSIGN(TestHarness); 72}; 73 74TestHarness::TestHarness() 75 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE), 76 next_policy_file_index_(100) {} 77 78TestHarness::~TestHarness() {} 79 80void TestHarness::SetUp() { 81 ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); 82} 83 84ConfigurationPolicyProvider* TestHarness::CreateProvider( 85 SchemaRegistry* registry, 86 scoped_refptr<base::SequencedTaskRunner> task_runner) { 87 scoped_ptr<AsyncPolicyLoader> loader(new ConfigDirPolicyLoader( 88 task_runner, test_dir(), POLICY_SCOPE_MACHINE)); 89 return new AsyncPolicyProvider(registry, loader.Pass()); 90} 91 92void TestHarness::InstallEmptyPolicy() { 93 base::DictionaryValue dict; 94 WriteConfigFile(dict, NextConfigFileName()); 95} 96 97void TestHarness::InstallStringPolicy(const std::string& policy_name, 98 const std::string& policy_value) { 99 base::DictionaryValue dict; 100 dict.SetString(policy_name, policy_value); 101 WriteConfigFile(dict, NextConfigFileName()); 102} 103 104void TestHarness::InstallIntegerPolicy(const std::string& policy_name, 105 int policy_value) { 106 base::DictionaryValue dict; 107 dict.SetInteger(policy_name, policy_value); 108 WriteConfigFile(dict, NextConfigFileName()); 109} 110 111void TestHarness::InstallBooleanPolicy(const std::string& policy_name, 112 bool policy_value) { 113 base::DictionaryValue dict; 114 dict.SetBoolean(policy_name, policy_value); 115 WriteConfigFile(dict, NextConfigFileName()); 116} 117 118void TestHarness::InstallStringListPolicy(const std::string& policy_name, 119 const base::ListValue* policy_value) { 120 base::DictionaryValue dict; 121 dict.Set(policy_name, policy_value->DeepCopy()); 122 WriteConfigFile(dict, NextConfigFileName()); 123} 124 125void TestHarness::InstallDictionaryPolicy( 126 const std::string& policy_name, 127 const base::DictionaryValue* policy_value) { 128 base::DictionaryValue dict; 129 dict.Set(policy_name, policy_value->DeepCopy()); 130 WriteConfigFile(dict, NextConfigFileName()); 131} 132 133void TestHarness::Install3rdPartyPolicy(const base::DictionaryValue* policies) { 134 base::DictionaryValue dict; 135 dict.Set("3rdparty", policies->DeepCopy()); 136 WriteConfigFile(dict, NextConfigFileName()); 137} 138 139void TestHarness::WriteConfigFile(const base::DictionaryValue& dict, 140 const std::string& file_name) { 141 std::string data; 142 JSONStringValueSerializer serializer(&data); 143 serializer.Serialize(dict); 144 const base::FilePath mandatory_dir(test_dir().Append(kMandatoryPath)); 145 ASSERT_TRUE(base::CreateDirectory(mandatory_dir)); 146 const base::FilePath file_path(mandatory_dir.AppendASCII(file_name)); 147 ASSERT_EQ((int) data.size(), 148 base::WriteFile(file_path, data.c_str(), data.size())); 149} 150 151std::string TestHarness::NextConfigFileName() { 152 EXPECT_LE(next_policy_file_index_, 999); 153 return std::string("policy") + base::IntToString(next_policy_file_index_++); 154} 155 156// static 157PolicyProviderTestHarness* TestHarness::Create() { 158 return new TestHarness(); 159} 160 161} // namespace 162 163// Instantiate abstract test case for basic policy reading tests. 164INSTANTIATE_TEST_CASE_P( 165 ConfigDirPolicyLoaderTest, 166 ConfigurationPolicyProviderTest, 167 testing::Values(TestHarness::Create)); 168 169// Instantiate abstract test case for 3rd party policy reading tests. 170INSTANTIATE_TEST_CASE_P( 171 ConfigDir3rdPartyPolicyLoaderTest, 172 Configuration3rdPartyPolicyProviderTest, 173 testing::Values(TestHarness::Create)); 174 175// Some tests that exercise special functionality in ConfigDirPolicyLoader. 176class ConfigDirPolicyLoaderTest : public PolicyTestBase { 177 protected: 178 virtual void SetUp() OVERRIDE { 179 PolicyTestBase::SetUp(); 180 harness_.SetUp(); 181 } 182 183 TestHarness harness_; 184}; 185 186// The preferences dictionary is expected to be empty when there are no files to 187// load. 188TEST_F(ConfigDirPolicyLoaderTest, ReadPrefsEmpty) { 189 ConfigDirPolicyLoader loader( 190 loop_.message_loop_proxy(), harness_.test_dir(), POLICY_SCOPE_MACHINE); 191 scoped_ptr<PolicyBundle> bundle(loader.Load()); 192 ASSERT_TRUE(bundle.get()); 193 const PolicyBundle kEmptyBundle; 194 EXPECT_TRUE(bundle->Equals(kEmptyBundle)); 195} 196 197// Reading from a non-existent directory should result in an empty preferences 198// dictionary. 199TEST_F(ConfigDirPolicyLoaderTest, ReadPrefsNonExistentDirectory) { 200 base::FilePath non_existent_dir( 201 harness_.test_dir().Append(FILE_PATH_LITERAL("not_there"))); 202 ConfigDirPolicyLoader loader( 203 loop_.message_loop_proxy(), non_existent_dir, POLICY_SCOPE_MACHINE); 204 scoped_ptr<PolicyBundle> bundle(loader.Load()); 205 ASSERT_TRUE(bundle.get()); 206 const PolicyBundle kEmptyBundle; 207 EXPECT_TRUE(bundle->Equals(kEmptyBundle)); 208} 209 210// Test merging values from different files. 211TEST_F(ConfigDirPolicyLoaderTest, ReadPrefsMergePrefs) { 212 // Write a bunch of data files in order to increase the chance to detect the 213 // provider not respecting lexicographic ordering when reading them. Since the 214 // filesystem may return files in arbitrary order, there is no way to be sure, 215 // but this is better than nothing. 216 base::DictionaryValue test_dict_bar; 217 test_dict_bar.SetString("HomepageLocation", "http://bar.com"); 218 for (unsigned int i = 1; i <= 4; ++i) 219 harness_.WriteConfigFile(test_dict_bar, base::IntToString(i)); 220 base::DictionaryValue test_dict_foo; 221 test_dict_foo.SetString("HomepageLocation", "http://foo.com"); 222 harness_.WriteConfigFile(test_dict_foo, "9"); 223 for (unsigned int i = 5; i <= 8; ++i) 224 harness_.WriteConfigFile(test_dict_bar, base::IntToString(i)); 225 226 ConfigDirPolicyLoader loader( 227 loop_.message_loop_proxy(), harness_.test_dir(), POLICY_SCOPE_USER); 228 scoped_ptr<PolicyBundle> bundle(loader.Load()); 229 ASSERT_TRUE(bundle.get()); 230 PolicyBundle expected_bundle; 231 expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 232 .LoadFrom(&test_dict_foo, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); 233 EXPECT_TRUE(bundle->Equals(expected_bundle)); 234} 235 236} // namespace policy 237