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
3 // found in the LICENSE file.
5 #include "chrome/browser/safe_browsing/safe_browsing_store.h"
6 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
8 #include "testing/gtest/include/gtest/gtest.h"
12 TEST(SafeBrowsingStoreTest
, SBAddPrefixLess
) {
13 // chunk_id then prefix.
14 EXPECT_TRUE(SBAddPrefixLess(SBAddPrefix(10, 1), SBAddPrefix(11, 1)));
15 EXPECT_FALSE(SBAddPrefixLess(SBAddPrefix(11, 1), SBAddPrefix(10, 1)));
16 EXPECT_TRUE(SBAddPrefixLess(SBAddPrefix(10, 1), SBAddPrefix(10, 2)));
17 EXPECT_FALSE(SBAddPrefixLess(SBAddPrefix(10, 2), SBAddPrefix(10, 1)));
20 EXPECT_FALSE(SBAddPrefixLess(SBAddPrefix(10, 1), SBAddPrefix(10, 1)));
23 TEST(SafeBrowsingStoreTest
, SBAddPrefixHashLess
) {
24 // The first four bytes of SBFullHash can be read as an int32, which
25 // means that byte-ordering issues can come up. To test this, |one|
26 // and |two| differ in the prefix, while |one| and |onetwo| have the
27 // same prefix, but differ in the byte after the prefix.
28 SBFullHash one
, onetwo
, two
;
29 memset(&one
, 0, sizeof(one
));
30 memset(&onetwo
, 0, sizeof(onetwo
));
31 memset(&two
, 0, sizeof(two
));
33 one
.full_hash
[sizeof(int32
)] = 1;
35 onetwo
.full_hash
[sizeof(int32
)] = 2;
38 const base::Time now
= base::Time::Now();
41 EXPECT_TRUE(SBAddPrefixHashLess(SBAddFullHash(10, now
, two
),
42 SBAddFullHash(11, now
, one
)));
43 EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(11, now
, two
),
44 SBAddFullHash(10, now
, one
)));
46 // After add_id, prefix.
47 EXPECT_TRUE(SBAddPrefixHashLess(SBAddFullHash(10, now
, one
),
48 SBAddFullHash(10, now
, two
)));
49 EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(10, now
, two
),
50 SBAddFullHash(10, now
, one
)));
52 // After prefix, full hash.
53 EXPECT_TRUE(SBAddPrefixHashLess(SBAddFullHash(10, now
, one
),
54 SBAddFullHash(10, now
, onetwo
)));
55 EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(10, now
, onetwo
),
56 SBAddFullHash(10, now
, one
)));
58 // Equal is not less-than.
59 EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(10, now
, one
),
60 SBAddFullHash(10, now
, one
)));
63 TEST(SafeBrowsingStoreTest
, SBSubPrefixLess
) {
65 EXPECT_TRUE(SBAddPrefixLess(SBSubPrefix(12, 10, 2), SBSubPrefix(9, 11, 1)));
66 EXPECT_FALSE(SBAddPrefixLess(SBSubPrefix(12, 11, 2), SBSubPrefix(9, 10, 1)));
68 // After add_id, prefix.
69 EXPECT_TRUE(SBAddPrefixLess(SBSubPrefix(12, 10, 1), SBSubPrefix(9, 10, 2)));
70 EXPECT_FALSE(SBAddPrefixLess(SBSubPrefix(12, 10, 2), SBSubPrefix(9, 10, 1)));
72 // Equal is not less-than.
73 EXPECT_FALSE(SBAddPrefixLess(SBSubPrefix(12, 10, 1), SBSubPrefix(12, 10, 1)));
75 // chunk_id doesn't matter.
78 TEST(SafeBrowsingStoreTest
, SBSubFullHashLess
) {
79 SBFullHash one
, onetwo
, two
;
80 memset(&one
, 0, sizeof(one
));
81 memset(&onetwo
, 0, sizeof(onetwo
));
82 memset(&two
, 0, sizeof(two
));
84 one
.full_hash
[sizeof(int32
)] = 1;
86 onetwo
.full_hash
[sizeof(int32
)] = 2;
90 EXPECT_TRUE(SBAddPrefixHashLess(SBSubFullHash(12, 10, two
),
91 SBSubFullHash(9, 11, one
)));
92 EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 11, two
),
93 SBSubFullHash(9, 10, one
)));
95 // After add_id, prefix.
96 EXPECT_TRUE(SBAddPrefixHashLess(SBSubFullHash(12, 10, one
),
97 SBSubFullHash(9, 10, two
)));
98 EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 10, two
),
99 SBSubFullHash(9, 10, one
)));
101 // After prefix, full_hash.
102 EXPECT_TRUE(SBAddPrefixHashLess(SBSubFullHash(12, 10, one
),
103 SBSubFullHash(9, 10, onetwo
)));
104 EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 10, onetwo
),
105 SBSubFullHash(9, 10, one
)));
107 // Equal is not less-than.
108 EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 10, one
),
109 SBSubFullHash(9, 10, one
)));
112 // SBProcessSubs does a lot of iteration, run through empty just to
113 // make sure degenerate cases work.
114 TEST(SafeBrowsingStoreTest
, SBProcessSubsEmpty
) {
115 SBAddPrefixes add_prefixes
;
116 std::vector
<SBAddFullHash
> add_hashes
;
117 SBSubPrefixes sub_prefixes
;
118 std::vector
<SBSubFullHash
> sub_hashes
;
120 const base::hash_set
<int32
> no_deletions
;
121 SBProcessSubs(&add_prefixes
, &sub_prefixes
, &add_hashes
, &sub_hashes
,
122 no_deletions
, no_deletions
);
123 EXPECT_TRUE(add_prefixes
.empty());
124 EXPECT_TRUE(sub_prefixes
.empty());
125 EXPECT_TRUE(add_hashes
.empty());
126 EXPECT_TRUE(sub_hashes
.empty());
129 // Test that subs knock out adds.
130 TEST(SafeBrowsingStoreTest
, SBProcessSubsKnockout
) {
131 const base::Time kNow
= base::Time::Now();
132 const SBFullHash
kHash1(SBFullHashFromString("one"));
133 const SBFullHash
kHash2(SBFullHashFromString("two"));
134 const SBFullHash
kHash3(SBFullHashFromString("three"));
135 const SBFullHash
kHash4(SBFullHashFromString("four"));
136 const int kAddChunk1
= 1; // Use different chunk numbers just in case.
137 const int kSubChunk1
= 2;
139 // Construct some full hashes which share prefix with another.
140 SBFullHash kHash1mod1
= kHash1
;
141 kHash1mod1
.full_hash
[sizeof(kHash1mod1
.full_hash
) - 1] ++;
142 SBFullHash kHash1mod2
= kHash1mod1
;
143 kHash1mod2
.full_hash
[sizeof(kHash1mod2
.full_hash
) - 1] ++;
144 SBFullHash kHash1mod3
= kHash1mod2
;
145 kHash1mod3
.full_hash
[sizeof(kHash1mod3
.full_hash
) - 1] ++;
147 // A second full-hash for the full-hash-sub test.
148 SBFullHash kHash4mod
= kHash4
;
149 kHash4mod
.full_hash
[sizeof(kHash4mod
.full_hash
) - 1] ++;
151 SBAddPrefixes add_prefixes
;
152 std::vector
<SBAddFullHash
> add_hashes
;
153 SBSubPrefixes sub_prefixes
;
154 std::vector
<SBSubFullHash
> sub_hashes
;
156 // An add with prefix and a couple hashes, plus a sub for the prefix
157 // and a couple sub hashes. The sub should knock all of them out.
158 add_prefixes
.push_back(SBAddPrefix(kAddChunk1
, kHash1
.prefix
));
159 add_hashes
.push_back(SBAddFullHash(kAddChunk1
, kNow
, kHash1
));
160 add_hashes
.push_back(SBAddFullHash(kAddChunk1
, kNow
, kHash1mod1
));
161 sub_prefixes
.push_back(SBSubPrefix(kSubChunk1
, kAddChunk1
, kHash1
.prefix
));
162 sub_hashes
.push_back(SBSubFullHash(kSubChunk1
, kAddChunk1
, kHash1mod2
));
163 sub_hashes
.push_back(SBSubFullHash(kSubChunk1
, kAddChunk1
, kHash1mod3
));
165 // An add with no corresponding sub. Both items should be retained.
166 add_hashes
.push_back(SBAddFullHash(kAddChunk1
, kNow
, kHash2
));
167 add_prefixes
.push_back(SBAddPrefix(kAddChunk1
, kHash2
.prefix
));
169 // A sub with no corresponding add. Both items should be retained.
170 sub_hashes
.push_back(SBSubFullHash(kSubChunk1
, kAddChunk1
, kHash3
));
171 sub_prefixes
.push_back(SBSubPrefix(kSubChunk1
, kAddChunk1
, kHash3
.prefix
));
173 // An add with prefix and a couple hashes, plus a sub for one of the
175 add_prefixes
.push_back(SBAddPrefix(kAddChunk1
, kHash4
.prefix
));
176 add_hashes
.push_back(SBAddFullHash(kAddChunk1
, kNow
, kHash4
));
177 add_hashes
.push_back(SBAddFullHash(kAddChunk1
, kNow
, kHash4mod
));
178 sub_hashes
.push_back(SBSubFullHash(kSubChunk1
, kAddChunk1
, kHash4mod
));
180 const base::hash_set
<int32
> no_deletions
;
181 SBProcessSubs(&add_prefixes
, &sub_prefixes
, &add_hashes
, &sub_hashes
,
182 no_deletions
, no_deletions
);
184 ASSERT_LE(2U, add_prefixes
.size());
185 EXPECT_EQ(2U, add_prefixes
.size());
186 EXPECT_EQ(kAddChunk1
, add_prefixes
[0].chunk_id
);
187 EXPECT_EQ(kHash2
.prefix
, add_prefixes
[0].prefix
);
188 EXPECT_EQ(kAddChunk1
, add_prefixes
[1].chunk_id
);
189 EXPECT_EQ(kHash4
.prefix
, add_prefixes
[1].prefix
);
191 ASSERT_LE(2U, add_hashes
.size());
192 EXPECT_EQ(2U, add_hashes
.size());
193 EXPECT_EQ(kAddChunk1
, add_hashes
[0].chunk_id
);
194 EXPECT_TRUE(SBFullHashEq(kHash2
, add_hashes
[0].full_hash
));
195 EXPECT_EQ(kAddChunk1
, add_hashes
[1].chunk_id
);
196 EXPECT_TRUE(SBFullHashEq(kHash4
, add_hashes
[1].full_hash
));
198 ASSERT_LE(1U, sub_prefixes
.size());
199 EXPECT_EQ(1U, sub_prefixes
.size());
200 EXPECT_EQ(kSubChunk1
, sub_prefixes
[0].chunk_id
);
201 EXPECT_EQ(kAddChunk1
, sub_prefixes
[0].add_chunk_id
);
202 EXPECT_EQ(kHash3
.prefix
, sub_prefixes
[0].add_prefix
);
204 ASSERT_LE(1U, sub_hashes
.size());
205 EXPECT_EQ(1U, sub_hashes
.size());
206 EXPECT_EQ(kSubChunk1
, sub_hashes
[0].chunk_id
);
207 EXPECT_EQ(kAddChunk1
, sub_hashes
[0].add_chunk_id
);
208 EXPECT_TRUE(SBFullHashEq(kHash3
, sub_hashes
[0].full_hash
));
211 // Test chunk deletions, and ordering of deletions WRT subs knocking
213 TEST(SafeBrowsingStoreTest
, SBProcessSubsDeleteChunk
) {
214 const base::Time kNow
= base::Time::Now();
215 const SBFullHash
kHash1(SBFullHashFromString("one"));
216 const SBFullHash
kHash2(SBFullHashFromString("two"));
217 const SBFullHash
kHash3(SBFullHashFromString("three"));
218 const int kAddChunk1
= 1; // Use different chunk numbers just in case.
219 const int kSubChunk1
= 2;
221 // Construct some full hashes which share prefix with another.
222 SBFullHash kHash1mod1
= kHash1
;
223 kHash1mod1
.full_hash
[sizeof(kHash1mod1
.full_hash
) - 1] ++;
224 SBFullHash kHash1mod2
= kHash1mod1
;
225 kHash1mod2
.full_hash
[sizeof(kHash1mod2
.full_hash
) - 1] ++;
226 SBFullHash kHash1mod3
= kHash1mod2
;
227 kHash1mod3
.full_hash
[sizeof(kHash1mod3
.full_hash
) - 1] ++;
229 SBAddPrefixes add_prefixes
;
230 std::vector
<SBAddFullHash
> add_hashes
;
231 SBSubPrefixes sub_prefixes
;
232 std::vector
<SBSubFullHash
> sub_hashes
;
234 // An add with prefix and a couple hashes, plus a sub for the prefix
235 // and a couple sub hashes. The sub should knock all of them out.
236 add_prefixes
.push_back(SBAddPrefix(kAddChunk1
, kHash1
.prefix
));
237 add_hashes
.push_back(SBAddFullHash(kAddChunk1
, kNow
, kHash1
));
238 add_hashes
.push_back(SBAddFullHash(kAddChunk1
, kNow
, kHash1mod1
));
239 sub_prefixes
.push_back(SBSubPrefix(kSubChunk1
, kAddChunk1
, kHash1
.prefix
));
240 sub_hashes
.push_back(SBSubFullHash(kSubChunk1
, kAddChunk1
, kHash1mod2
));
241 sub_hashes
.push_back(SBSubFullHash(kSubChunk1
, kAddChunk1
, kHash1mod3
));
243 // An add with no corresponding sub. Both items should be retained.
244 add_hashes
.push_back(SBAddFullHash(kAddChunk1
, kNow
, kHash2
));
245 add_prefixes
.push_back(SBAddPrefix(kAddChunk1
, kHash2
.prefix
));
247 // A sub with no corresponding add. Both items should be retained.
248 sub_hashes
.push_back(SBSubFullHash(kSubChunk1
, kAddChunk1
, kHash3
));
249 sub_prefixes
.push_back(SBSubPrefix(kSubChunk1
, kAddChunk1
, kHash3
.prefix
));
251 const base::hash_set
<int32
> no_deletions
;
252 base::hash_set
<int32
> add_deletions
;
253 add_deletions
.insert(kAddChunk1
);
254 SBProcessSubs(&add_prefixes
, &sub_prefixes
, &add_hashes
, &sub_hashes
,
255 add_deletions
, no_deletions
);
257 EXPECT_TRUE(add_prefixes
.empty());
258 EXPECT_TRUE(add_hashes
.empty());
260 EXPECT_EQ(1U, sub_prefixes
.size());
261 EXPECT_EQ(kSubChunk1
, sub_prefixes
[0].chunk_id
);
262 EXPECT_EQ(kAddChunk1
, sub_prefixes
[0].add_chunk_id
);
263 EXPECT_EQ(kHash3
.prefix
, sub_prefixes
[0].add_prefix
);
265 EXPECT_EQ(1U, sub_hashes
.size());
266 EXPECT_EQ(kSubChunk1
, sub_hashes
[0].chunk_id
);
267 EXPECT_EQ(kAddChunk1
, sub_hashes
[0].add_chunk_id
);
268 EXPECT_TRUE(SBFullHashEq(kHash3
, sub_hashes
[0].full_hash
));
270 base::hash_set
<int32
> sub_deletions
;
271 sub_deletions
.insert(kSubChunk1
);
272 SBProcessSubs(&add_prefixes
, &sub_prefixes
, &add_hashes
, &sub_hashes
,
273 no_deletions
, sub_deletions
);
275 EXPECT_TRUE(add_prefixes
.empty());
276 EXPECT_TRUE(add_hashes
.empty());
277 EXPECT_TRUE(sub_prefixes
.empty());
278 EXPECT_TRUE(sub_hashes
.empty());
281 TEST(SafeBrowsingStoreTest
, Y2K38
) {
282 const base::Time now
= base::Time::Now();
283 const base::Time future
= now
+ base::TimeDelta::FromDays(3*365);
285 // TODO: Fix file format before 2035.
286 EXPECT_GT(static_cast<int32
>(future
.ToTimeT()), 0)
287 << " (int32)time_t is running out.";