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