Home | History | Annotate | Download | only in safe_browsing
      1 // Copyright (c) 2010 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/safe_browsing/safe_browsing_store_file.h"
      6 
      7 #include "base/callback.h"
      8 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
      9 #include "chrome/test/file_test_utils.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "testing/platform_test.h"
     12 
     13 namespace {
     14 
     15 const FilePath::CharType kFolderPrefix[] =
     16     FILE_PATH_LITERAL("SafeBrowsingTestStoreFile");
     17 
     18 class SafeBrowsingStoreFileTest : public PlatformTest {
     19  public:
     20   virtual void SetUp() {
     21     PlatformTest::SetUp();
     22 
     23     FilePath temp_dir;
     24     ASSERT_TRUE(file_util::CreateNewTempDirectory(kFolderPrefix, &temp_dir));
     25 
     26     file_deleter_.reset(new FileAutoDeleter(temp_dir));
     27 
     28     filename_ = temp_dir;
     29     filename_ = filename_.AppendASCII("SafeBrowsingTestStore");
     30     file_util::Delete(filename_, false);
     31 
     32     // Make sure an old temporary file isn't hanging around.
     33     const FilePath temp_file =
     34         SafeBrowsingStoreFile::TemporaryFileForFilename(filename_);
     35     file_util::Delete(temp_file, false);
     36 
     37     store_.reset(new SafeBrowsingStoreFile());
     38     store_->Init(filename_, NULL);
     39   }
     40   virtual void TearDown() {
     41     if (store_.get())
     42       store_->Delete();
     43     store_.reset();
     44     file_deleter_.reset();
     45 
     46     PlatformTest::TearDown();
     47   }
     48 
     49   void OnCorruptionDetected() {
     50     corruption_detected_ = true;
     51   }
     52 
     53   scoped_ptr<FileAutoDeleter> file_deleter_;
     54   FilePath filename_;
     55   scoped_ptr<SafeBrowsingStoreFile> store_;
     56   bool corruption_detected_;
     57 };
     58 
     59 TEST_STORE(SafeBrowsingStoreFileTest, store_.get(), filename_);
     60 
     61 // Test that Delete() deletes the temporary store, if present.
     62 TEST_F(SafeBrowsingStoreFileTest, DeleteTemp) {
     63     const FilePath temp_file =
     64         SafeBrowsingStoreFile::TemporaryFileForFilename(filename_);
     65 
     66   EXPECT_FALSE(file_util::PathExists(filename_));
     67   EXPECT_FALSE(file_util::PathExists(temp_file));
     68 
     69   // Starting a transaction creates a temporary file.
     70   EXPECT_TRUE(store_->BeginUpdate());
     71   EXPECT_TRUE(file_util::PathExists(temp_file));
     72 
     73   // Pull the rug out from under the existing store, simulating a
     74   // crash.
     75   store_.reset(new SafeBrowsingStoreFile());
     76   store_->Init(filename_, NULL);
     77   EXPECT_FALSE(file_util::PathExists(filename_));
     78   EXPECT_TRUE(file_util::PathExists(temp_file));
     79 
     80   // Make sure the temporary file is deleted.
     81   EXPECT_TRUE(store_->Delete());
     82   EXPECT_FALSE(file_util::PathExists(filename_));
     83   EXPECT_FALSE(file_util::PathExists(temp_file));
     84 }
     85 
     86 // Test basic corruption-handling.
     87 TEST_F(SafeBrowsingStoreFileTest, DetectsCorruption) {
     88   // Load a store with some data.
     89   SafeBrowsingStoreTestStorePrefix(store_.get());
     90 
     91   SafeBrowsingStoreFile test_store;
     92   test_store.Init(
     93       filename_,
     94       NewCallback(static_cast<SafeBrowsingStoreFileTest*>(this),
     95                   &SafeBrowsingStoreFileTest::OnCorruptionDetected));
     96 
     97   corruption_detected_ = false;
     98 
     99   // Can successfully open and read the store.
    100   std::vector<SBAddFullHash> pending_adds;
    101   std::set<SBPrefix> prefix_misses;
    102   std::vector<SBAddPrefix> orig_prefixes;
    103   std::vector<SBAddFullHash> orig_hashes;
    104   EXPECT_TRUE(test_store.BeginUpdate());
    105   EXPECT_TRUE(test_store.FinishUpdate(pending_adds, prefix_misses,
    106                                       &orig_prefixes, &orig_hashes));
    107   EXPECT_GT(orig_prefixes.size(), 0U);
    108   EXPECT_GT(orig_hashes.size(), 0U);
    109   EXPECT_FALSE(corruption_detected_);
    110 
    111   // Corrupt the store.
    112   file_util::ScopedFILE file(file_util::OpenFile(filename_, "rb+"));
    113   const long kOffset = 60;
    114   EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0);
    115   const int32 kZero = 0;
    116   int32 previous = kZero;
    117   EXPECT_EQ(fread(&previous, sizeof(previous), 1, file.get()), 1U);
    118   EXPECT_NE(previous, kZero);
    119   EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0);
    120   EXPECT_EQ(fwrite(&kZero, sizeof(kZero), 1, file.get()), 1U);
    121   file.reset();
    122 
    123   // Update fails and corruption callback is called.
    124   std::vector<SBAddPrefix> add_prefixes;
    125   std::vector<SBAddFullHash> add_hashes;
    126   corruption_detected_ = false;
    127   EXPECT_TRUE(test_store.BeginUpdate());
    128   EXPECT_FALSE(test_store.FinishUpdate(pending_adds, prefix_misses,
    129                                        &add_prefixes, &add_hashes));
    130   EXPECT_TRUE(corruption_detected_);
    131   EXPECT_EQ(add_prefixes.size(), 0U);
    132   EXPECT_EQ(add_hashes.size(), 0U);
    133 
    134   // Make it look like there is a lot of add-chunks-seen data.
    135   const long kAddChunkCountOffset = 2 * sizeof(int32);
    136   const int32 kLargeCount = 1000 * 1000 * 1000;
    137   file.reset(file_util::OpenFile(filename_, "rb+"));
    138   EXPECT_EQ(fseek(file.get(), kAddChunkCountOffset, SEEK_SET), 0);
    139   EXPECT_EQ(fwrite(&kLargeCount, sizeof(kLargeCount), 1, file.get()), 1U);
    140   file.reset();
    141 
    142   // Detects corruption and fails to even begin the update.
    143   corruption_detected_ = false;
    144   EXPECT_FALSE(test_store.BeginUpdate());
    145   EXPECT_TRUE(corruption_detected_);
    146 }
    147 
    148 }  // namespace
    149