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