- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / safe_browsing_store_file_unittest.cc
1 // Copyright (c) 2012 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/bind.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/md5.h"
10 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "testing/platform_test.h"
13
14 namespace {
15
16 class SafeBrowsingStoreFileTest : public PlatformTest {
17  public:
18   virtual void SetUp() {
19     PlatformTest::SetUp();
20
21     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
22
23     filename_ = temp_dir_.path();
24     filename_ = filename_.AppendASCII("SafeBrowsingTestStore");
25
26     store_.reset(new SafeBrowsingStoreFile());
27     store_->Init(filename_,
28                  base::Bind(&SafeBrowsingStoreFileTest::OnCorruptionDetected,
29                             base::Unretained(this)));
30     corruption_detected_ = false;
31   }
32   virtual void TearDown() {
33     if (store_.get())
34       store_->Delete();
35     store_.reset();
36
37     PlatformTest::TearDown();
38   }
39
40   void OnCorruptionDetected() {
41     corruption_detected_ = true;
42   }
43
44   base::ScopedTempDir temp_dir_;
45   base::FilePath filename_;
46   scoped_ptr<SafeBrowsingStoreFile> store_;
47   bool corruption_detected_;
48 };
49
50 TEST_STORE(SafeBrowsingStoreFileTest, store_.get(), filename_);
51
52 // Test that Delete() deletes the temporary store, if present.
53 TEST_F(SafeBrowsingStoreFileTest, DeleteTemp) {
54   const base::FilePath temp_file =
55       SafeBrowsingStoreFile::TemporaryFileForFilename(filename_);
56
57   EXPECT_FALSE(base::PathExists(filename_));
58   EXPECT_FALSE(base::PathExists(temp_file));
59
60   // Starting a transaction creates a temporary file.
61   EXPECT_TRUE(store_->BeginUpdate());
62   EXPECT_TRUE(base::PathExists(temp_file));
63
64   // Pull the rug out from under the existing store, simulating a
65   // crash.
66   store_.reset(new SafeBrowsingStoreFile());
67   store_->Init(filename_, base::Closure());
68   EXPECT_FALSE(base::PathExists(filename_));
69   EXPECT_TRUE(base::PathExists(temp_file));
70
71   // Make sure the temporary file is deleted.
72   EXPECT_TRUE(store_->Delete());
73   EXPECT_FALSE(base::PathExists(filename_));
74   EXPECT_FALSE(base::PathExists(temp_file));
75 }
76
77 // Test basic corruption-handling.
78 TEST_F(SafeBrowsingStoreFileTest, DetectsCorruption) {
79   // Load a store with some data.
80   SafeBrowsingStoreTestStorePrefix(store_.get());
81
82   // Can successfully open and read the store.
83   std::vector<SBAddFullHash> pending_adds;
84   std::set<SBPrefix> prefix_misses;
85   SBAddPrefixes orig_prefixes;
86   std::vector<SBAddFullHash> orig_hashes;
87   EXPECT_TRUE(store_->BeginUpdate());
88   EXPECT_TRUE(store_->FinishUpdate(pending_adds, prefix_misses,
89                                    &orig_prefixes, &orig_hashes));
90   EXPECT_GT(orig_prefixes.size(), 0U);
91   EXPECT_GT(orig_hashes.size(), 0U);
92   EXPECT_FALSE(corruption_detected_);
93
94   // Corrupt the store.
95   file_util::ScopedFILE file(file_util::OpenFile(filename_, "rb+"));
96   const long kOffset = 60;
97   EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0);
98   const int32 kZero = 0;
99   int32 previous = kZero;
100   EXPECT_EQ(fread(&previous, sizeof(previous), 1, file.get()), 1U);
101   EXPECT_NE(previous, kZero);
102   EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0);
103   EXPECT_EQ(fwrite(&kZero, sizeof(kZero), 1, file.get()), 1U);
104   file.reset();
105
106   // Update fails and corruption callback is called.
107   SBAddPrefixes add_prefixes;
108   std::vector<SBAddFullHash> add_hashes;
109   corruption_detected_ = false;
110   EXPECT_TRUE(store_->BeginUpdate());
111   EXPECT_FALSE(store_->FinishUpdate(pending_adds, prefix_misses,
112                                     &add_prefixes, &add_hashes));
113   EXPECT_TRUE(corruption_detected_);
114   EXPECT_EQ(add_prefixes.size(), 0U);
115   EXPECT_EQ(add_hashes.size(), 0U);
116
117   // Make it look like there is a lot of add-chunks-seen data.
118   const long kAddChunkCountOffset = 2 * sizeof(int32);
119   const int32 kLargeCount = 1000 * 1000 * 1000;
120   file.reset(file_util::OpenFile(filename_, "rb+"));
121   EXPECT_EQ(fseek(file.get(), kAddChunkCountOffset, SEEK_SET), 0);
122   EXPECT_EQ(fwrite(&kLargeCount, sizeof(kLargeCount), 1, file.get()), 1U);
123   file.reset();
124
125   // Detects corruption and fails to even begin the update.
126   corruption_detected_ = false;
127   EXPECT_FALSE(store_->BeginUpdate());
128   EXPECT_TRUE(corruption_detected_);
129 }
130
131 TEST_F(SafeBrowsingStoreFileTest, CheckValidity) {
132   // Empty store is valid.
133   EXPECT_FALSE(base::PathExists(filename_));
134   ASSERT_TRUE(store_->BeginUpdate());
135   EXPECT_FALSE(corruption_detected_);
136   EXPECT_TRUE(store_->CheckValidity());
137   EXPECT_FALSE(corruption_detected_);
138   EXPECT_TRUE(store_->CancelUpdate());
139
140   // A store with some data is valid.
141   EXPECT_FALSE(base::PathExists(filename_));
142   SafeBrowsingStoreTestStorePrefix(store_.get());
143   EXPECT_TRUE(base::PathExists(filename_));
144   ASSERT_TRUE(store_->BeginUpdate());
145   EXPECT_FALSE(corruption_detected_);
146   EXPECT_TRUE(store_->CheckValidity());
147   EXPECT_FALSE(corruption_detected_);
148   EXPECT_TRUE(store_->CancelUpdate());
149 }
150
151 // Corrupt the payload.
152 TEST_F(SafeBrowsingStoreFileTest, CheckValidityPayload) {
153   SafeBrowsingStoreTestStorePrefix(store_.get());
154   EXPECT_TRUE(base::PathExists(filename_));
155
156   // 37 is the most random prime number.  It's also past the header,
157   // as corrupting the header would fail BeginUpdate() in which case
158   // CheckValidity() cannot be called.
159   const size_t kOffset = 37;
160
161   {
162     file_util::ScopedFILE file(file_util::OpenFile(filename_, "rb+"));
163     EXPECT_EQ(0, fseek(file.get(), kOffset, SEEK_SET));
164     EXPECT_GE(fputs("hello", file.get()), 0);
165   }
166   ASSERT_TRUE(store_->BeginUpdate());
167   EXPECT_FALSE(corruption_detected_);
168   EXPECT_FALSE(store_->CheckValidity());
169   EXPECT_TRUE(corruption_detected_);
170   EXPECT_TRUE(store_->CancelUpdate());
171 }
172
173 // Corrupt the checksum.
174 TEST_F(SafeBrowsingStoreFileTest, CheckValidityChecksum) {
175   SafeBrowsingStoreTestStorePrefix(store_.get());
176   EXPECT_TRUE(base::PathExists(filename_));
177
178   // An offset from the end of the file which is in the checksum.
179   const int kOffset = -static_cast<int>(sizeof(base::MD5Digest));
180
181   {
182     file_util::ScopedFILE file(file_util::OpenFile(filename_, "rb+"));
183     EXPECT_EQ(0, fseek(file.get(), kOffset, SEEK_END));
184     EXPECT_GE(fputs("hello", file.get()), 0);
185   }
186   ASSERT_TRUE(store_->BeginUpdate());
187   EXPECT_FALSE(corruption_detected_);
188   EXPECT_FALSE(store_->CheckValidity());
189   EXPECT_TRUE(corruption_detected_);
190   EXPECT_TRUE(store_->CancelUpdate());
191 }
192
193 }  // namespace