OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h" | 5 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/md5.h" |
8 #include "base/scoped_temp_dir.h" | 9 #include "base/scoped_temp_dir.h" |
9 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h" | 10 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
11 #include "testing/platform_test.h" | 12 #include "testing/platform_test.h" |
12 | 13 |
13 namespace { | 14 namespace { |
14 | 15 |
15 const FilePath::CharType kFolderPrefix[] = | 16 const FilePath::CharType kFolderPrefix[] = |
16 FILE_PATH_LITERAL("SafeBrowsingTestStoreFile"); | 17 FILE_PATH_LITERAL("SafeBrowsingTestStoreFile"); |
17 | 18 |
18 class SafeBrowsingStoreFileTest : public PlatformTest { | 19 class SafeBrowsingStoreFileTest : public PlatformTest { |
19 public: | 20 public: |
20 virtual void SetUp() { | 21 virtual void SetUp() { |
21 PlatformTest::SetUp(); | 22 PlatformTest::SetUp(); |
22 | 23 |
23 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 24 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
24 | 25 |
25 filename_ = temp_dir_.path(); | 26 filename_ = temp_dir_.path(); |
26 filename_ = filename_.AppendASCII("SafeBrowsingTestStore"); | 27 filename_ = filename_.AppendASCII("SafeBrowsingTestStore"); |
27 | 28 |
28 store_.reset(new SafeBrowsingStoreFile()); | 29 store_.reset(new SafeBrowsingStoreFile()); |
29 store_->Init(filename_, base::Closure()); | 30 store_->Init(filename_, |
| 31 base::Bind(&SafeBrowsingStoreFileTest::OnCorruptionDetected, |
| 32 base::Unretained(this))); |
| 33 corruption_detected_ = false; |
30 } | 34 } |
31 virtual void TearDown() { | 35 virtual void TearDown() { |
32 if (store_.get()) | 36 if (store_.get()) |
33 store_->Delete(); | 37 store_->Delete(); |
34 store_.reset(); | 38 store_.reset(); |
35 | 39 |
36 PlatformTest::TearDown(); | 40 PlatformTest::TearDown(); |
37 } | 41 } |
38 | 42 |
39 void OnCorruptionDetected() { | 43 void OnCorruptionDetected() { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 EXPECT_TRUE(store_->Delete()); | 75 EXPECT_TRUE(store_->Delete()); |
72 EXPECT_FALSE(file_util::PathExists(filename_)); | 76 EXPECT_FALSE(file_util::PathExists(filename_)); |
73 EXPECT_FALSE(file_util::PathExists(temp_file)); | 77 EXPECT_FALSE(file_util::PathExists(temp_file)); |
74 } | 78 } |
75 | 79 |
76 // Test basic corruption-handling. | 80 // Test basic corruption-handling. |
77 TEST_F(SafeBrowsingStoreFileTest, DetectsCorruption) { | 81 TEST_F(SafeBrowsingStoreFileTest, DetectsCorruption) { |
78 // Load a store with some data. | 82 // Load a store with some data. |
79 SafeBrowsingStoreTestStorePrefix(store_.get()); | 83 SafeBrowsingStoreTestStorePrefix(store_.get()); |
80 | 84 |
81 SafeBrowsingStoreFile test_store; | |
82 test_store.Init( | |
83 filename_, | |
84 base::Bind(&SafeBrowsingStoreFileTest::OnCorruptionDetected, | |
85 base::Unretained(this))); | |
86 | |
87 corruption_detected_ = false; | |
88 | |
89 // Can successfully open and read the store. | 85 // Can successfully open and read the store. |
90 std::vector<SBAddFullHash> pending_adds; | 86 std::vector<SBAddFullHash> pending_adds; |
91 std::set<SBPrefix> prefix_misses; | 87 std::set<SBPrefix> prefix_misses; |
92 SBAddPrefixes orig_prefixes; | 88 SBAddPrefixes orig_prefixes; |
93 std::vector<SBAddFullHash> orig_hashes; | 89 std::vector<SBAddFullHash> orig_hashes; |
94 EXPECT_TRUE(test_store.BeginUpdate()); | 90 EXPECT_TRUE(store_->BeginUpdate()); |
95 EXPECT_TRUE(test_store.FinishUpdate(pending_adds, prefix_misses, | 91 EXPECT_TRUE(store_->FinishUpdate(pending_adds, prefix_misses, |
96 &orig_prefixes, &orig_hashes)); | 92 &orig_prefixes, &orig_hashes)); |
97 EXPECT_GT(orig_prefixes.size(), 0U); | 93 EXPECT_GT(orig_prefixes.size(), 0U); |
98 EXPECT_GT(orig_hashes.size(), 0U); | 94 EXPECT_GT(orig_hashes.size(), 0U); |
99 EXPECT_FALSE(corruption_detected_); | 95 EXPECT_FALSE(corruption_detected_); |
100 | 96 |
101 // Corrupt the store. | 97 // Corrupt the store. |
102 file_util::ScopedFILE file(file_util::OpenFile(filename_, "rb+")); | 98 file_util::ScopedFILE file(file_util::OpenFile(filename_, "rb+")); |
103 const long kOffset = 60; | 99 const long kOffset = 60; |
104 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); | 100 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); |
105 const int32 kZero = 0; | 101 const int32 kZero = 0; |
106 int32 previous = kZero; | 102 int32 previous = kZero; |
107 EXPECT_EQ(fread(&previous, sizeof(previous), 1, file.get()), 1U); | 103 EXPECT_EQ(fread(&previous, sizeof(previous), 1, file.get()), 1U); |
108 EXPECT_NE(previous, kZero); | 104 EXPECT_NE(previous, kZero); |
109 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); | 105 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); |
110 EXPECT_EQ(fwrite(&kZero, sizeof(kZero), 1, file.get()), 1U); | 106 EXPECT_EQ(fwrite(&kZero, sizeof(kZero), 1, file.get()), 1U); |
111 file.reset(); | 107 file.reset(); |
112 | 108 |
113 // Update fails and corruption callback is called. | 109 // Update fails and corruption callback is called. |
114 SBAddPrefixes add_prefixes; | 110 SBAddPrefixes add_prefixes; |
115 std::vector<SBAddFullHash> add_hashes; | 111 std::vector<SBAddFullHash> add_hashes; |
116 corruption_detected_ = false; | 112 corruption_detected_ = false; |
117 EXPECT_TRUE(test_store.BeginUpdate()); | 113 EXPECT_TRUE(store_->BeginUpdate()); |
118 EXPECT_FALSE(test_store.FinishUpdate(pending_adds, prefix_misses, | 114 EXPECT_FALSE(store_->FinishUpdate(pending_adds, prefix_misses, |
119 &add_prefixes, &add_hashes)); | 115 &add_prefixes, &add_hashes)); |
120 EXPECT_TRUE(corruption_detected_); | 116 EXPECT_TRUE(corruption_detected_); |
121 EXPECT_EQ(add_prefixes.size(), 0U); | 117 EXPECT_EQ(add_prefixes.size(), 0U); |
122 EXPECT_EQ(add_hashes.size(), 0U); | 118 EXPECT_EQ(add_hashes.size(), 0U); |
123 | 119 |
124 // Make it look like there is a lot of add-chunks-seen data. | 120 // Make it look like there is a lot of add-chunks-seen data. |
125 const long kAddChunkCountOffset = 2 * sizeof(int32); | 121 const long kAddChunkCountOffset = 2 * sizeof(int32); |
126 const int32 kLargeCount = 1000 * 1000 * 1000; | 122 const int32 kLargeCount = 1000 * 1000 * 1000; |
127 file.reset(file_util::OpenFile(filename_, "rb+")); | 123 file.reset(file_util::OpenFile(filename_, "rb+")); |
128 EXPECT_EQ(fseek(file.get(), kAddChunkCountOffset, SEEK_SET), 0); | 124 EXPECT_EQ(fseek(file.get(), kAddChunkCountOffset, SEEK_SET), 0); |
129 EXPECT_EQ(fwrite(&kLargeCount, sizeof(kLargeCount), 1, file.get()), 1U); | 125 EXPECT_EQ(fwrite(&kLargeCount, sizeof(kLargeCount), 1, file.get()), 1U); |
130 file.reset(); | 126 file.reset(); |
131 | 127 |
132 // Detects corruption and fails to even begin the update. | 128 // Detects corruption and fails to even begin the update. |
133 corruption_detected_ = false; | 129 corruption_detected_ = false; |
134 EXPECT_FALSE(test_store.BeginUpdate()); | 130 EXPECT_FALSE(store_->BeginUpdate()); |
135 EXPECT_TRUE(corruption_detected_); | 131 EXPECT_TRUE(corruption_detected_); |
136 } | 132 } |
137 | 133 |
| 134 TEST_F(SafeBrowsingStoreFileTest, CheckValidity) { |
| 135 // Empty store is valid. |
| 136 EXPECT_FALSE(file_util::PathExists(filename_)); |
| 137 ASSERT_TRUE(store_->BeginUpdate()); |
| 138 EXPECT_FALSE(corruption_detected_); |
| 139 EXPECT_TRUE(store_->CheckValidity()); |
| 140 EXPECT_FALSE(corruption_detected_); |
| 141 EXPECT_TRUE(store_->CancelUpdate()); |
| 142 |
| 143 // A store with some data is valid. |
| 144 EXPECT_FALSE(file_util::PathExists(filename_)); |
| 145 SafeBrowsingStoreTestStorePrefix(store_.get()); |
| 146 EXPECT_TRUE(file_util::PathExists(filename_)); |
| 147 ASSERT_TRUE(store_->BeginUpdate()); |
| 148 EXPECT_FALSE(corruption_detected_); |
| 149 EXPECT_TRUE(store_->CheckValidity()); |
| 150 EXPECT_FALSE(corruption_detected_); |
| 151 EXPECT_TRUE(store_->CancelUpdate()); |
| 152 } |
| 153 |
| 154 // Corrupt the payload. |
| 155 TEST_F(SafeBrowsingStoreFileTest, CheckValidityPayload) { |
| 156 SafeBrowsingStoreTestStorePrefix(store_.get()); |
| 157 EXPECT_TRUE(file_util::PathExists(filename_)); |
| 158 |
| 159 // 37 is the most random prime number. It's also past the header, |
| 160 // as corrupting the header would fail BeginUpdate() in which case |
| 161 // CheckValidity() cannot be called. |
| 162 const size_t kOffset = 37; |
| 163 |
| 164 { |
| 165 file_util::ScopedFILE file(file_util::OpenFile(filename_, "rb+")); |
| 166 EXPECT_EQ(0, fseek(file.get(), kOffset, SEEK_SET)); |
| 167 EXPECT_GE(fputs("hello", file.get()), 0); |
| 168 } |
| 169 ASSERT_TRUE(store_->BeginUpdate()); |
| 170 EXPECT_FALSE(corruption_detected_); |
| 171 EXPECT_FALSE(store_->CheckValidity()); |
| 172 EXPECT_TRUE(corruption_detected_); |
| 173 EXPECT_TRUE(store_->CancelUpdate()); |
| 174 } |
| 175 |
| 176 // Corrupt the checksum. |
| 177 TEST_F(SafeBrowsingStoreFileTest, CheckValidityChecksum) { |
| 178 SafeBrowsingStoreTestStorePrefix(store_.get()); |
| 179 EXPECT_TRUE(file_util::PathExists(filename_)); |
| 180 |
| 181 // An offset from the end of the file which is in the checksum. |
| 182 const int kOffset = -static_cast<int>(sizeof(base::MD5Digest)); |
| 183 |
| 184 { |
| 185 file_util::ScopedFILE file(file_util::OpenFile(filename_, "rb+")); |
| 186 EXPECT_EQ(0, fseek(file.get(), kOffset, SEEK_END)); |
| 187 EXPECT_GE(fputs("hello", file.get()), 0); |
| 188 } |
| 189 ASSERT_TRUE(store_->BeginUpdate()); |
| 190 EXPECT_FALSE(corruption_detected_); |
| 191 EXPECT_FALSE(store_->CheckValidity()); |
| 192 EXPECT_TRUE(corruption_detected_); |
| 193 EXPECT_TRUE(store_->CancelUpdate()); |
| 194 } |
| 195 |
138 } // namespace | 196 } // namespace |
OLD | NEW |