Home | History | Annotate | Download | only in policy
      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