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.
5 #include "chrome/browser/chromeos/policy/cloud_external_data_store.h"
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"
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;
30 class CouldExternalDataStoreTest
: public testing::Test
{
32 CouldExternalDataStoreTest();
34 void SetUp() override
;
37 const std::string kData1Hash
;
38 const std::string kData2Hash
;
40 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
41 base::ScopedTempDir temp_dir_
;
42 scoped_ptr
<ResourceCache
> resource_cache_
;
45 DISALLOW_COPY_AND_ASSIGN(CouldExternalDataStoreTest
);
48 CouldExternalDataStoreTest::CouldExternalDataStoreTest()
49 : kData1Hash(crypto::SHA256HashString(kData1
)),
50 kData2Hash(crypto::SHA256HashString(kData2
)),
51 task_runner_(new base::TestSimpleTaskRunner
) {
54 void CouldExternalDataStoreTest::SetUp() {
55 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
56 resource_cache_
.reset(new ResourceCache(temp_dir_
.path(), task_runner_
));
59 TEST_F(CouldExternalDataStoreTest
, StoreAndLoad
) {
60 // Write an entry to a store.
61 CloudExternalDataStore
store(kKey1
, task_runner_
, resource_cache_
.get());
62 EXPECT_TRUE(store
.Store(kPolicy1
, kData1Hash
, kData1
));
64 // Check that loading and verifying the entry against an invalid hash fails.
66 EXPECT_FALSE(store
.Load(kPolicy1
, kData2Hash
, kMaxSize
, &data
));
68 // Check that loading and verifying the entry against its hash succeeds.
69 EXPECT_TRUE(store
.Load(kPolicy1
, kData1Hash
, kMaxSize
, &data
));
70 EXPECT_EQ(kData1
, data
);
73 TEST_F(CouldExternalDataStoreTest
, StoreTooLargeAndLoad
) {
74 // Write an entry to a store.
75 CloudExternalDataStore
store(kKey1
, task_runner_
, resource_cache_
.get());
76 EXPECT_TRUE(store
.Store(kPolicy1
, kData1Hash
, kData2
));
78 // Check that the entry has been written to the resource cache backing the
80 std::map
<std::string
, std::string
> contents
;
81 resource_cache_
->LoadAllSubkeys(kKey1
, &contents
);
82 ASSERT_EQ(1u, contents
.size());
83 EXPECT_EQ(kData2
, contents
.begin()->second
);
85 // Check that loading the entry fails when the maximum allowed data size is
86 // smaller than the entry size.
88 EXPECT_FALSE(store
.Load(kPolicy1
, kData1Hash
, 1, &data
));
90 // Verify that the oversized entry has been detected and removed from the
92 resource_cache_
->LoadAllSubkeys(kKey1
, &contents
);
93 EXPECT_TRUE(contents
.empty());
96 TEST_F(CouldExternalDataStoreTest
, StoreInvalidAndLoad
) {
97 // Construct a store entry whose hash and contents do not match.
98 CloudExternalDataStore
store(kKey1
, task_runner_
, resource_cache_
.get());
99 EXPECT_TRUE(store
.Store(kPolicy1
, kData1Hash
, kData2
));
101 // Check that the entry has been written to the resource cache backing the
103 std::map
<std::string
, std::string
> contents
;
104 resource_cache_
->LoadAllSubkeys(kKey1
, &contents
);
105 ASSERT_EQ(1u, contents
.size());
106 EXPECT_EQ(kData2
, contents
.begin()->second
);
108 // Check that loading and verifying the entry against its hash fails.
110 EXPECT_FALSE(store
.Load(kPolicy1
, kData1Hash
, kMaxSize
, &data
));
112 // Verify that the corrupted entry has been detected and removed from the
114 resource_cache_
->LoadAllSubkeys(kKey1
, &contents
);
115 EXPECT_TRUE(contents
.empty());
118 TEST_F(CouldExternalDataStoreTest
, Prune
) {
119 // Write two entries to a store.
120 CloudExternalDataStore
store(kKey1
, task_runner_
, resource_cache_
.get());
121 EXPECT_TRUE(store
.Store(kPolicy1
, kData1Hash
, kData1
));
122 EXPECT_TRUE(store
.Store(kPolicy2
, kData2Hash
, kData2
));
124 // Check that loading and verifying the entries against their hashes succeeds.
126 EXPECT_TRUE(store
.Load(kPolicy1
, kData1Hash
, kMaxSize
, &data
));
127 EXPECT_EQ(kData1
, data
);
128 EXPECT_TRUE(store
.Load(kPolicy2
, kData2Hash
, kMaxSize
, &data
));
129 EXPECT_EQ(kData2
, data
);
131 // Prune the store, allowing only an entry for the first policy with its
132 // current hash to be kept.
133 CloudExternalDataManager::Metadata metadata
;
135 CloudExternalDataManager::MetadataEntry(kURL
, kData1Hash
);
136 store
.Prune(metadata
);
138 // Check that the entry for the second policy has been removed from the
139 // resource cache backing the store.
140 std::map
<std::string
, std::string
> contents
;
141 resource_cache_
->LoadAllSubkeys(kKey1
, &contents
);
142 ASSERT_EQ(1u, contents
.size());
143 EXPECT_EQ(kData1
, contents
.begin()->second
);
145 // Prune the store, allowing only an entry for the first policy with a
146 // different hash to be kept.
148 CloudExternalDataManager::MetadataEntry(kURL
, kData2Hash
);
149 store
.Prune(metadata
);
151 // Check that the entry for the first policy has been removed from the
153 resource_cache_
->LoadAllSubkeys(kKey1
, &contents
);
154 EXPECT_TRUE(contents
.empty());
157 TEST_F(CouldExternalDataStoreTest
, SharedCache
) {
158 // Write entries to two stores for two different cache_keys sharing a cache.
159 CloudExternalDataStore
store1(kKey1
, task_runner_
, resource_cache_
.get());
160 EXPECT_TRUE(store1
.Store(kPolicy1
, kData1Hash
, kData1
));
161 CloudExternalDataStore
store2(kKey2
, task_runner_
, resource_cache_
.get());
162 EXPECT_TRUE(store2
.Store(kPolicy2
, kData2Hash
, kData2
));
164 // Check that the entries have been assigned to the correct keys in the
165 // resource cache backing the stores.
166 std::map
<std::string
, std::string
> contents
;
167 resource_cache_
->LoadAllSubkeys(kKey1
, &contents
);
168 ASSERT_EQ(1u, contents
.size());
169 EXPECT_EQ(kData1
, contents
.begin()->second
);
170 resource_cache_
->LoadAllSubkeys(kKey2
, &contents
);
171 ASSERT_EQ(1u, contents
.size());
172 EXPECT_EQ(kData2
, contents
.begin()->second
);
174 // Check that each entry can be loaded from the correct store.
176 EXPECT_TRUE(store1
.Load(kPolicy1
, kData1Hash
, kMaxSize
, &data
));
177 EXPECT_EQ(kData1
, data
);
178 EXPECT_FALSE(store1
.Load(kPolicy2
, kData2Hash
, kMaxSize
, &data
));
180 EXPECT_FALSE(store2
.Load(kPolicy1
, kData1Hash
, kMaxSize
, &data
));
181 EXPECT_TRUE(store2
.Load(kPolicy2
, kData2Hash
, kMaxSize
, &data
));
182 EXPECT_EQ(kData2
, data
);
184 // Prune the first store, allowing no entries to be kept.
185 CloudExternalDataManager::Metadata metadata
;
186 store1
.Prune(metadata
);
188 // Check that the part of the resource cache backing the first store is empty.
189 resource_cache_
->LoadAllSubkeys(kKey1
, &contents
);
190 EXPECT_TRUE(contents
.empty());
192 // Check that the part of the resource cache backing the second store is
194 resource_cache_
->LoadAllSubkeys(kKey2
, &contents
);
195 ASSERT_EQ(1u, contents
.size());
196 EXPECT_EQ(kData2
, contents
.begin()->second
);
199 } // namespace policy