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. 4 5 #include "chrome/browser/chromeos/policy/cloud_external_data_store.h" 6 7 #include "base/compiler_specific.h" 8 #include "base/files/scoped_temp_dir.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/test/test_simple_task_runner.h" 11 #include "components/policy/core/common/cloud/resource_cache.h" 12 #include "crypto/sha2.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace policy { 16 17 namespace { 18 19 const char kKey1[] = "Key 1"; 20 const char kKey2[] = "Key 2"; 21 const char kPolicy1[] = "Test policy 1"; 22 const char kPolicy2[] = "Test policy 2"; 23 const char kData1[] = "Testing data 1"; 24 const char kData2[] = "Testing data 2"; 25 const char kURL[] = "http://localhost"; 26 const size_t kMaxSize = 100; 27 28 } // namespace 29 30 class CouldExternalDataStoreTest : public testing::Test { 31 public: 32 CouldExternalDataStoreTest(); 33 34 virtual void SetUp() OVERRIDE; 35 36 protected: 37 const std::string kData1Hash; 38 const std::string kData2Hash; 39 40 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; 41 base::ScopedTempDir temp_dir_; 42 scoped_ptr<ResourceCache> resource_cache_; 43 44 DISALLOW_COPY_AND_ASSIGN(CouldExternalDataStoreTest); 45 }; 46 47 CouldExternalDataStoreTest::CouldExternalDataStoreTest() 48 : kData1Hash(crypto::SHA256HashString(kData1)), 49 kData2Hash(crypto::SHA256HashString(kData2)), 50 task_runner_(new base::TestSimpleTaskRunner) { 51 } 52 53 void CouldExternalDataStoreTest::SetUp() { 54 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 55 resource_cache_.reset(new ResourceCache(temp_dir_.path(), task_runner_)); 56 } 57 58 TEST_F(CouldExternalDataStoreTest, StoreAndLoad) { 59 // Write an entry to a store. 60 CloudExternalDataStore store(kKey1, task_runner_, resource_cache_.get()); 61 EXPECT_TRUE(store.Store(kPolicy1, kData1Hash, kData1)); 62 63 // Check that loading and verifying the entry against an invalid hash fails. 64 std::string data; 65 EXPECT_FALSE(store.Load(kPolicy1, kData2Hash, kMaxSize, &data)); 66 67 // Check that loading and verifying the entry against its hash succeeds. 68 EXPECT_TRUE(store.Load(kPolicy1, kData1Hash, kMaxSize, &data)); 69 EXPECT_EQ(kData1, data); 70 } 71 72 TEST_F(CouldExternalDataStoreTest, StoreTooLargeAndLoad) { 73 // Write an entry to a store. 74 CloudExternalDataStore store(kKey1, task_runner_, resource_cache_.get()); 75 EXPECT_TRUE(store.Store(kPolicy1, kData1Hash, kData2)); 76 77 // Check that the entry has been written to the resource cache backing the 78 // store. 79 std::map<std::string, std::string> contents; 80 resource_cache_->LoadAllSubkeys(kKey1, &contents); 81 ASSERT_EQ(1u, contents.size()); 82 EXPECT_EQ(kData2, contents.begin()->second); 83 84 // Check that loading the entry fails when the maximum allowed data size is 85 // smaller than the entry size. 86 std::string data; 87 EXPECT_FALSE(store.Load(kPolicy1, kData1Hash, 1, &data)); 88 89 // Verify that the oversized entry has been detected and removed from the 90 // resource cache. 91 resource_cache_->LoadAllSubkeys(kKey1, &contents); 92 EXPECT_TRUE(contents.empty()); 93 } 94 95 TEST_F(CouldExternalDataStoreTest, StoreInvalidAndLoad) { 96 // Construct a store entry whose hash and contents do not match. 97 CloudExternalDataStore store(kKey1, task_runner_, resource_cache_.get()); 98 EXPECT_TRUE(store.Store(kPolicy1, kData1Hash, kData2)); 99 100 // Check that the entry has been written to the resource cache backing the 101 // store. 102 std::map<std::string, std::string> contents; 103 resource_cache_->LoadAllSubkeys(kKey1, &contents); 104 ASSERT_EQ(1u, contents.size()); 105 EXPECT_EQ(kData2, contents.begin()->second); 106 107 // Check that loading and verifying the entry against its hash fails. 108 std::string data; 109 EXPECT_FALSE(store.Load(kPolicy1, kData1Hash, kMaxSize, &data)); 110 111 // Verify that the corrupted entry has been detected and removed from the 112 // resource cache. 113 resource_cache_->LoadAllSubkeys(kKey1, &contents); 114 EXPECT_TRUE(contents.empty()); 115 } 116 117 TEST_F(CouldExternalDataStoreTest, Prune) { 118 // Write two entries to a store. 119 CloudExternalDataStore store(kKey1, task_runner_, resource_cache_.get()); 120 EXPECT_TRUE(store.Store(kPolicy1, kData1Hash, kData1)); 121 EXPECT_TRUE(store.Store(kPolicy2, kData2Hash, kData2)); 122 123 // Check that loading and verifying the entries against their hashes succeeds. 124 std::string data; 125 EXPECT_TRUE(store.Load(kPolicy1, kData1Hash, kMaxSize, &data)); 126 EXPECT_EQ(kData1, data); 127 EXPECT_TRUE(store.Load(kPolicy2, kData2Hash, kMaxSize, &data)); 128 EXPECT_EQ(kData2, data); 129 130 // Prune the store, allowing only an entry for the first policy with its 131 // current hash to be kept. 132 CloudExternalDataManager::Metadata metadata; 133 metadata[kPolicy1] = 134 CloudExternalDataManager::MetadataEntry(kURL, kData1Hash); 135 store.Prune(metadata); 136 137 // Check that the entry for the second policy has been removed from the 138 // resource cache backing the store. 139 std::map<std::string, std::string> contents; 140 resource_cache_->LoadAllSubkeys(kKey1, &contents); 141 ASSERT_EQ(1u, contents.size()); 142 EXPECT_EQ(kData1, contents.begin()->second); 143 144 // Prune the store, allowing only an entry for the first policy with a 145 // different hash to be kept. 146 metadata[kPolicy1] = 147 CloudExternalDataManager::MetadataEntry(kURL, kData2Hash); 148 store.Prune(metadata); 149 150 // Check that the entry for the first policy has been removed from the 151 // resource cache. 152 resource_cache_->LoadAllSubkeys(kKey1, &contents); 153 EXPECT_TRUE(contents.empty()); 154 } 155 156 TEST_F(CouldExternalDataStoreTest, SharedCache) { 157 // Write entries to two stores for two different cache_keys sharing a cache. 158 CloudExternalDataStore store1(kKey1, task_runner_, resource_cache_.get()); 159 EXPECT_TRUE(store1.Store(kPolicy1, kData1Hash, kData1)); 160 CloudExternalDataStore store2(kKey2, task_runner_, resource_cache_.get()); 161 EXPECT_TRUE(store2.Store(kPolicy2, kData2Hash, kData2)); 162 163 // Check that the entries have been assigned to the correct keys in the 164 // resource cache backing the stores. 165 std::map<std::string, std::string> contents; 166 resource_cache_->LoadAllSubkeys(kKey1, &contents); 167 ASSERT_EQ(1u, contents.size()); 168 EXPECT_EQ(kData1, contents.begin()->second); 169 resource_cache_->LoadAllSubkeys(kKey2, &contents); 170 ASSERT_EQ(1u, contents.size()); 171 EXPECT_EQ(kData2, contents.begin()->second); 172 173 // Check that each entry can be loaded from the correct store. 174 std::string data; 175 EXPECT_TRUE(store1.Load(kPolicy1, kData1Hash, kMaxSize, &data)); 176 EXPECT_EQ(kData1, data); 177 EXPECT_FALSE(store1.Load(kPolicy2, kData2Hash, kMaxSize, &data)); 178 179 EXPECT_FALSE(store2.Load(kPolicy1, kData1Hash, kMaxSize, &data)); 180 EXPECT_TRUE(store2.Load(kPolicy2, kData2Hash, kMaxSize, &data)); 181 EXPECT_EQ(kData2, data); 182 183 // Prune the first store, allowing no entries to be kept. 184 CloudExternalDataManager::Metadata metadata; 185 store1.Prune(metadata); 186 187 // Check that the part of the resource cache backing the first store is empty. 188 resource_cache_->LoadAllSubkeys(kKey1, &contents); 189 EXPECT_TRUE(contents.empty()); 190 191 // Check that the part of the resource cache backing the second store is 192 // unaffected. 193 resource_cache_->LoadAllSubkeys(kKey2, &contents); 194 ASSERT_EQ(1u, contents.size()); 195 EXPECT_EQ(kData2, contents.begin()->second); 196 } 197 198 } // namespace policy 199