Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / protocol_parser_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 <string>
6
7 #include "base/strings/stringprintf.h"
8 #include "base/time/time.h"
9 #include "chrome/browser/safe_browsing/protocol_parser.h"
10 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace {
14
15 #if defined(OS_ANDROID)
16 const char kDefaultPhishList[] = "goog-mobilephish-shavar";
17 const char kDefaultMalwareList[] = "goog-mobilemalware-shavar";
18 #else
19 const char kDefaultPhishList[] = "goog-phish-shavar";
20 const char kDefaultMalwareList[] = "goog-malware-shavar";
21 #endif
22
23 // Test parsing one add chunk.
24 TEST(SafeBrowsingProtocolParsingTest, TestAddChunk) {
25   const char kRawAddChunk[] = {
26     '\0', '\0', '\0', '\x1C',  // 32-bit payload length in network byte order.
27     '\x08',                    // field 1, wire format varint
28     '\x01',                    // chunk_number varint 1
29     '\x22',                    // field 4, wire format length-delimited
30     '\x18',                    // varint length 24
31     '1', '1', '1', '1',        // 4-byte prefixes
32     '2', '2', '2', '2',
33     '3', '3', '3', '3',
34     '4', '4', '4', '4',
35     '8', '8', '8', '8',
36     '9', '9', '9', '9',
37   };
38
39   ScopedVector<SBChunkData> chunks;
40   EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
41                                         &chunks));
42   ASSERT_EQ(1U, chunks.size());
43   EXPECT_EQ(1, chunks[0]->ChunkNumber());
44   EXPECT_TRUE(chunks[0]->IsAdd());
45   EXPECT_FALSE(chunks[0]->IsSub());
46   EXPECT_TRUE(chunks[0]->IsPrefix());
47   EXPECT_FALSE(chunks[0]->IsFullHash());
48   ASSERT_EQ(6U, chunks[0]->PrefixCount());
49   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
50   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
51   EXPECT_EQ(0x33333333U, chunks[0]->PrefixAt(2));  // 3333
52   EXPECT_EQ(0x34343434U, chunks[0]->PrefixAt(3));  // 4444
53   EXPECT_EQ(0x38383838U, chunks[0]->PrefixAt(4));  // 8888
54   EXPECT_EQ(0x39393939U, chunks[0]->PrefixAt(5));  // 9999
55 }
56
57 // Test parsing one add chunk with full hashes.
58 TEST(SafeBrowsingProtocolParsingTest, TestAddFullChunk) {
59   const char kRawAddChunk[] = {
60     '\0', '\0', '\0', '\x46',  // 32-bit payload length in network byte order.
61     '\x08',                    // field 1, wire format varint
62     '\x01',                    // chunk_number varint 1
63     '\x18',                    // field 3, wire format varint
64     '\x01',                    // enum PrefixType == FULL_32B
65     '\x22',                    // field 4, wire format length-delimited
66     '\x40',                    // varint length 64 (2 full hashes)
67
68     '0', '1', '0', '1', '0', '1', '0', '1',
69     '0', '1', '0', '1', '0', '1', '0', '1',
70     '0', '1', '0', '1', '0', '1', '0', '1',
71     '0', '1', '0', '1', '0', '1', '0', '1',
72
73     '2', '3', '2', '3', '2', '3', '2', '3',
74     '2', '3', '2', '3', '2', '3', '2', '3',
75     '2', '3', '2', '3', '2', '3', '2', '3',
76     '2', '3', '2', '3', '2', '3', '2', '3',
77   };
78
79   SBFullHash full_hash1, full_hash2;
80   for (int i = 0; i < 32; ++i) {
81     full_hash1.full_hash[i] = i % 2 ? '1' : '0';
82     full_hash2.full_hash[i] = i % 2 ? '3' : '2';
83   }
84
85   ScopedVector<SBChunkData> chunks;
86   EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
87                                         &chunks));
88   ASSERT_EQ(1U, chunks.size());
89   EXPECT_EQ(1, chunks[0]->ChunkNumber());
90   EXPECT_TRUE(chunks[0]->IsAdd());
91   EXPECT_FALSE(chunks[0]->IsSub());
92   EXPECT_FALSE(chunks[0]->IsPrefix());
93   EXPECT_TRUE(chunks[0]->IsFullHash());
94
95   ASSERT_EQ(2U, chunks[0]->FullHashCount());
96   EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1));
97   EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2));
98 }
99
100 // Test parsing multiple add chunks. We'll use the same chunk as above, and add
101 // one more after it.
102 TEST(SafeBrowsingProtocolParsingTest, TestAddChunks) {
103   const char kRawAddChunk[] = {
104     '\0', '\0', '\0', '\x1C',  // 32-bit payload length in network byte order.
105     '\x08',                    // field 1, wire format varint
106     '\x01',                    // chunk_number varint 1
107     '\x22',                    // field 4, wire format length-delimited
108     '\x18',                    // varint length 24
109
110     '1', '1', '1', '1',        // 4-byte prefixes
111     '2', '2', '2', '2',
112     '3', '3', '3', '3',
113     '4', '4', '4', '4',
114     '8', '8', '8', '8',
115     '9', '9', '9', '9',
116
117     '\0', '\0', '\0', '\x0C',  // 32-bit payload length in network byte order.
118     '\x08',                    // field 1, wire format varint
119     '\x02',                    // chunk_number varint 1
120     '\x22',                    // field 4, wire format length-delimited
121     '\x08',                    // varint length 8
122     'p', 'p', 'p', 'p',        // 4-byte prefixes
123     'g', 'g', 'g', 'g',
124   };
125
126   ScopedVector<SBChunkData> chunks;
127   EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
128                                         &chunks));
129   ASSERT_EQ(2U, chunks.size());
130
131   EXPECT_EQ(1, chunks[0]->ChunkNumber());
132   EXPECT_TRUE(chunks[0]->IsAdd());
133   EXPECT_FALSE(chunks[0]->IsSub());
134   EXPECT_TRUE(chunks[0]->IsPrefix());
135   EXPECT_FALSE(chunks[0]->IsFullHash());
136   ASSERT_EQ(6U, chunks[0]->PrefixCount());
137   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
138   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
139   EXPECT_EQ(0x33333333U, chunks[0]->PrefixAt(2));  // 3333
140   EXPECT_EQ(0x34343434U, chunks[0]->PrefixAt(3));  // 4444
141   EXPECT_EQ(0x38383838U, chunks[0]->PrefixAt(4));  // 8888
142   EXPECT_EQ(0x39393939U, chunks[0]->PrefixAt(5));  // 9999
143
144   EXPECT_EQ(2, chunks[1]->ChunkNumber());
145   EXPECT_TRUE(chunks[1]->IsAdd());
146   EXPECT_FALSE(chunks[1]->IsSub());
147   EXPECT_TRUE(chunks[1]->IsPrefix());
148   EXPECT_FALSE(chunks[1]->IsFullHash());
149   ASSERT_EQ(2U, chunks[1]->PrefixCount());
150   EXPECT_EQ(0x70707070U, chunks[1]->PrefixAt(0));  // pppp
151   EXPECT_EQ(0x67676767U, chunks[1]->PrefixAt(1));  // gggg
152 }
153
154 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedPrefixChunk) {
155   // This chunk delares there are 6 prefixes but actually only contains 3.
156   const char kRawAddChunk[] = {
157     '\0', '\0', '\0', '\x1C',  // 32-bit payload length in network byte order.
158     '\x08',                    // field 1, wire format varint
159     '\x01',                    // chunk_number varint 1
160     '\x22',                    // field 4, wire format length-delimited
161     '\x18',                    // varint length 24
162     '1', '1', '1', '1',        // 4-byte prefixes
163     '2', '2', '2', '2',
164     '3', '3', '3', '3',
165   };
166
167   ScopedVector<SBChunkData> chunks;
168   EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
169                                          &chunks));
170 }
171
172 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedFullHashChunk) {
173   // This chunk delares there are two full hashes but there is only one.
174   const char kRawAddChunk[] = {
175     '\0', '\0', '\0', '\x46',  // 32-bit payload length in network byte order.
176     '\x08',                    // field 1, wire format varint
177     '\x01',                    // chunk_number varint 1
178     '\x18',                    // field 3, wire format varint
179     '\x01',                    // enum PrefixType == FULL_32B
180     '\x22',                    // field 4, wire format length-delimited
181     '\x40',                    // varint length 64 (2 full hashes)
182
183     '0', '1', '0', '1', '0', '1', '0', '1',
184     '0', '1', '0', '1', '0', '1', '0', '1',
185     '0', '1', '0', '1', '0', '1', '0', '1',
186     '0', '1', '0', '1', '0', '1', '0', '1',
187   };
188
189   ScopedVector<SBChunkData> chunks;
190   EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
191                                          &chunks));
192 }
193
194 TEST(SafeBrowsingProtocolParsingTest, TestHugeChunk) {
195   // This chunk delares there are 6 prefixes but actually only contains 3.
196   const char kRawAddChunk[] = {
197     '\x1', '\0', '\0', '\0',   // 32-bit payload length in network byte order.
198     '\x08',                    // field 1, wire format varint
199     '\x01',                    // chunk_number varint 1
200     '\x22',                    // field 4, wire format length-delimited
201     '\x18',                    // varint length 24
202     '1', '1', '1', '1',        // 4-byte prefixes
203     '2', '2', '2', '2',
204     '3', '3', '3', '3',
205   };
206
207   ScopedVector<SBChunkData> chunks;
208   EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
209                                          &chunks));
210 }
211
212 // Test parsing one sub chunk.
213 TEST(SafeBrowsingProtocolParsingTest, TestSubChunk) {
214   const char kRawSubChunk[] = {
215     '\0', '\0', '\0', '\x12',  // 32-bit payload length in network byte order
216     '\x08',                    // field 1, wire format varint
217     '\x03',                    // chunk_number varint 3
218     '\x10',                    // field 2, wire format varint
219     '\x01',                    // enum ChunkType == SUB
220     '\x22',                    // field 4, wire format length-delimited
221     '\x08',                    // varint length 8 (2 prefixes)
222     '1', '1', '1', '1',        // 4-byte prefixes
223     '2', '2', '2', '2',
224     '\x2a',                    // field 5, wire format length-delimited
225     '\x02',                    // varint length 2 (2 add-chunk numbers)
226     '\x07', '\x09',            // varint 7, varint 9
227   };
228
229   ScopedVector<SBChunkData> chunks;
230   EXPECT_TRUE(safe_browsing::ParseChunk(kRawSubChunk, sizeof(kRawSubChunk),
231                                         &chunks));
232   ASSERT_EQ(1U, chunks.size());
233   EXPECT_EQ(3, chunks[0]->ChunkNumber());
234   EXPECT_FALSE(chunks[0]->IsAdd());
235   EXPECT_TRUE(chunks[0]->IsSub());
236   EXPECT_TRUE(chunks[0]->IsPrefix());
237   EXPECT_FALSE(chunks[0]->IsFullHash());
238   ASSERT_EQ(2U, chunks[0]->PrefixCount());
239   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
240   EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0));
241   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
242   EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1));
243 }
244
245 // Test parsing one sub chunk with full hashes.
246 TEST(SafeBrowsingProtocolParsingTest, TestSubFullChunk) {
247   const char kRawSubChunk[] = {
248     '\0', '\0', '\0', '\x4C',  // 32-bit payload length in network byte order.
249     '\x08',                    // field 1, wire format varint
250     '\x02',                    // chunk_number varint 2
251     '\x10',                    // field 2, wire format varint
252     '\x01',                    // enum ChunkType == SUB
253     '\x18',                    // field 3, wire format varint
254     '\x01',                    // enum PrefixType == FULL_32B
255     '\x22',                    // field 4, wire format length-delimited
256     '\x40',                    // varint length 64 (2 full hashes)
257
258     '0', '1', '0', '1', '0', '1', '0', '1',
259     '0', '1', '0', '1', '0', '1', '0', '1',
260     '0', '1', '0', '1', '0', '1', '0', '1',
261     '0', '1', '0', '1', '0', '1', '0', '1',
262
263     '2', '3', '2', '3', '2', '3', '2', '3',
264     '2', '3', '2', '3', '2', '3', '2', '3',
265     '2', '3', '2', '3', '2', '3', '2', '3',
266     '2', '3', '2', '3', '2', '3', '2', '3',
267
268     '\x2a',                    // field 5, wire format length-delimited
269     '\x02',                    // varint length 2 (2 add-chunk numbers)
270     '\x07', '\x09',            // varint 7, varint 9
271   };
272
273   SBFullHash full_hash1, full_hash2;
274   for (int i = 0; i < 32; ++i) {
275     full_hash1.full_hash[i] = i % 2 ? '1' : '0';
276     full_hash2.full_hash[i] = i % 2 ? '3' : '2';
277   }
278
279   ScopedVector<SBChunkData> chunks;
280   EXPECT_TRUE(safe_browsing::ParseChunk(kRawSubChunk, sizeof(kRawSubChunk),
281                                         &chunks));
282   ASSERT_EQ(1U, chunks.size());
283   EXPECT_EQ(2, chunks[0]->ChunkNumber());
284   EXPECT_FALSE(chunks[0]->IsAdd());
285   EXPECT_TRUE(chunks[0]->IsSub());
286   EXPECT_FALSE(chunks[0]->IsPrefix());
287   EXPECT_TRUE(chunks[0]->IsFullHash());
288
289   ASSERT_EQ(2U, chunks[0]->FullHashCount());
290   EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1));
291   EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0));
292   EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2));
293   EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1));
294 }
295
296 // Test parsing the SafeBrowsing update response.
297 TEST(SafeBrowsingProtocolParsingTest, TestChunkDelete) {
298   std::string add_del("n:1700\ni:phishy\nad:1-7,43-597,44444,99999\n"
299                       "i:malware\nsd:21-27,42,171717\n");
300
301   size_t next_query_sec = 0;
302   bool reset = false;
303   std::vector<SBChunkDelete> deletes;
304   std::vector<ChunkUrl> urls;
305   EXPECT_TRUE(safe_browsing::ParseUpdate(add_del.data(), add_del.length(),
306                                          &next_query_sec, &reset,
307                                          &deletes, &urls));
308
309   EXPECT_TRUE(urls.empty());
310   EXPECT_FALSE(reset);
311   EXPECT_EQ(1700U, next_query_sec);
312   ASSERT_EQ(2U, deletes.size());
313
314   ASSERT_EQ(4U, deletes[0].chunk_del.size());
315   EXPECT_TRUE(deletes[0].chunk_del[0] == ChunkRange(1, 7));
316   EXPECT_TRUE(deletes[0].chunk_del[1] == ChunkRange(43, 597));
317   EXPECT_TRUE(deletes[0].chunk_del[2] == ChunkRange(44444));
318   EXPECT_TRUE(deletes[0].chunk_del[3] == ChunkRange(99999));
319
320   ASSERT_EQ(3U, deletes[1].chunk_del.size());
321   EXPECT_TRUE(deletes[1].chunk_del[0] == ChunkRange(21, 27));
322   EXPECT_TRUE(deletes[1].chunk_del[1] == ChunkRange(42));
323   EXPECT_TRUE(deletes[1].chunk_del[2] == ChunkRange(171717));
324
325   // An update response with missing list name.
326   next_query_sec = 0;
327   deletes.clear();
328   urls.clear();
329   add_del = "n:1700\nad:1-7,43-597,44444,99999\ni:malware\nsd:4,21-27171717\n";
330   EXPECT_FALSE(safe_browsing::ParseUpdate(add_del.data(), add_del.length(),
331                                           &next_query_sec, &reset,
332                                           &deletes, &urls));
333 }
334
335 // Test parsing the SafeBrowsing update response.
336 TEST(SafeBrowsingProtocolParsingTest, TestRedirects) {
337   const std::string redirects(base::StringPrintf(
338       "i:%s\n"
339       "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1\n"
340       "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2\n"
341       "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3\n"
342       "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689,"
343       "8691-8731,8733-8786\n",
344       kDefaultMalwareList));
345
346   size_t next_query_sec = 0;
347   bool reset = false;
348   std::vector<SBChunkDelete> deletes;
349   std::vector<ChunkUrl> urls;
350   EXPECT_TRUE(safe_browsing::ParseUpdate(redirects.data(), redirects.length(),
351                                          &next_query_sec, &reset,
352                                          &deletes, &urls));
353   EXPECT_FALSE(reset);
354   EXPECT_EQ(0U, next_query_sec);
355   EXPECT_TRUE(deletes.empty());
356
357   ASSERT_EQ(4U, urls.size());
358   EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1",
359             urls[0].url);
360   EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2",
361             urls[1].url);
362   EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3",
363             urls[2].url);
364   EXPECT_EQ("s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:"
365             "8641-8689,8691-8731,8733-8786",
366             urls[3].url);
367 }
368
369 // Test parsing various SafeBrowsing protocol headers.
370 TEST(SafeBrowsingProtocolParsingTest, TestNextQueryTime) {
371   std::string headers("n:1800\ni:goog-white-shavar\n");
372   size_t next_query_sec = 0;
373   bool reset = false;
374   std::vector<SBChunkDelete> deletes;
375   std::vector<ChunkUrl> urls;
376   EXPECT_TRUE(safe_browsing::ParseUpdate(headers.data(), headers.length(),
377                                          &next_query_sec, &reset,
378                                          &deletes, &urls));
379
380   EXPECT_EQ(1800U, next_query_sec);
381   EXPECT_FALSE(reset);
382   EXPECT_TRUE(deletes.empty());
383   EXPECT_TRUE(urls.empty());
384 }
385
386 // Test parsing data from a GetHashRequest
387 TEST(SafeBrowsingProtocolParsingTest, TestGetHash) {
388   const std::string get_hash(base::StringPrintf(
389       "45\n"
390       "%s:32:3\n"
391       "00112233445566778899aabbccddeeff"
392       "00001111222233334444555566667777"
393       "ffffeeeeddddccccbbbbaaaa99998888",
394       kDefaultPhishList));
395   std::vector<SBFullHashResult> full_hashes;
396   base::TimeDelta cache_lifetime;
397   EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash.data(), get_hash.length(),
398                                           &cache_lifetime, &full_hashes));
399
400   ASSERT_EQ(3U, full_hashes.size());
401   EXPECT_EQ(memcmp(&full_hashes[0].hash,
402                    "00112233445566778899aabbccddeeff",
403                    sizeof(SBFullHash)), 0);
404   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id);
405   EXPECT_EQ(memcmp(&full_hashes[1].hash,
406                    "00001111222233334444555566667777",
407                    sizeof(SBFullHash)), 0);
408   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[1].list_id);
409   EXPECT_EQ(memcmp(&full_hashes[2].hash,
410                    "ffffeeeeddddccccbbbbaaaa99998888",
411                    sizeof(SBFullHash)), 0);
412   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[2].list_id);
413
414   // Test multiple lists in the GetHash results.
415   const std::string get_hash2(base::StringPrintf(
416       "45\n"
417       "%s:32:1\n"
418       "00112233445566778899aabbccddeeff"
419       "%s:32:2\n"
420       "cafebeefcafebeefdeaddeaddeaddead"
421       "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
422       kDefaultPhishList,
423       kDefaultMalwareList));
424   EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash2.data(), get_hash2.length(),
425                                           &cache_lifetime, &full_hashes));
426
427   ASSERT_EQ(3U, full_hashes.size());
428   EXPECT_EQ(memcmp(&full_hashes[0].hash,
429                    "00112233445566778899aabbccddeeff",
430                    sizeof(SBFullHash)), 0);
431   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id);
432   EXPECT_EQ(memcmp(&full_hashes[1].hash,
433                    "cafebeefcafebeefdeaddeaddeaddead",
434                    sizeof(SBFullHash)), 0);
435   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id);
436   EXPECT_EQ(memcmp(&full_hashes[2].hash,
437                    "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
438                    sizeof(SBFullHash)), 0);
439   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[2].list_id);
440
441   // Test metadata parsing.
442   // TODO(shess): Currently the code doesn't actually put the metadata anywhere,
443   // this is just testing that metadata doesn't break parsing.
444   const std::string get_hash3(base::StringPrintf(
445       "45\n"
446       "%s:32:2:m\n"
447       "zzzzyyyyxxxxwwwwvvvvuuuuttttssss"
448       "00112233445566778899aabbccddeeff"
449       "2\nab2\nxy"
450       "%s:32:1\n"
451       "cafebeefcafebeefdeaddeaddeaddead",
452       kDefaultMalwareList,
453       kDefaultPhishList));
454   EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash3.data(), get_hash3.length(),
455                                           &cache_lifetime, &full_hashes));
456
457   ASSERT_EQ(3U, full_hashes.size());
458   EXPECT_EQ(memcmp(&full_hashes[0].hash,
459                    "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
460                    sizeof(SBFullHash)), 0);
461   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[0].list_id);
462   EXPECT_EQ(memcmp(&full_hashes[1].hash,
463                    "00112233445566778899aabbccddeeff",
464                    sizeof(SBFullHash)), 0);
465   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id);
466   EXPECT_EQ(memcmp(&full_hashes[2].hash,
467                    "cafebeefcafebeefdeaddeaddeaddead",
468                    sizeof(SBFullHash)), 0);
469   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[2].list_id);
470 }
471
472 TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownList) {
473   std::string hash_response(base::StringPrintf(
474       "45\n"
475       "%s:32:1\n"
476       "12345678901234567890123456789012"
477       "googpub-phish-shavar:32:1\n"
478       "09876543210987654321098765432109",
479       kDefaultPhishList));
480   std::vector<SBFullHashResult> full_hashes;
481   base::TimeDelta cache_lifetime;
482   EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response.data(),
483                                           hash_response.size(),
484                                           &cache_lifetime,
485                                           &full_hashes));
486
487   ASSERT_EQ(1U, full_hashes.size());
488   EXPECT_EQ(memcmp("12345678901234567890123456789012",
489                    &full_hashes[0].hash, sizeof(SBFullHash)), 0);
490   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id);
491
492   hash_response += base::StringPrintf(
493       "%s:32:1\n"
494       "abcdefghijklmnopqrstuvwxyz123457",
495       kDefaultMalwareList);
496   full_hashes.clear();
497   EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response.data(),
498                                           hash_response.size(),
499                                           &cache_lifetime,
500                                           &full_hashes));
501
502   EXPECT_EQ(2U, full_hashes.size());
503   EXPECT_EQ(memcmp("12345678901234567890123456789012",
504                    &full_hashes[0].hash, sizeof(SBFullHash)), 0);
505   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id);
506   EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457",
507                    &full_hashes[1].hash, sizeof(SBFullHash)), 0);
508   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id);
509 }
510
511 TEST(SafeBrowsingProtocolParsingTest, TestFormatHash) {
512   std::vector<SBPrefix> prefixes;
513   prefixes.push_back(0x34333231);
514   prefixes.push_back(0x64636261);
515   prefixes.push_back(0x73727170);
516
517   EXPECT_EQ("4:12\n1234abcdpqrs", safe_browsing::FormatGetHash(prefixes));
518 }
519
520 TEST(SafeBrowsingProtocolParsingTest, TestReset) {
521   std::string update("n:1800\ni:phishy\nr:pleasereset\n");
522
523   bool reset = false;
524   size_t next_update = 0;
525   std::vector<SBChunkDelete> deletes;
526   std::vector<ChunkUrl> urls;
527   EXPECT_TRUE(safe_browsing::ParseUpdate(update.data(), update.size(),
528                                          &next_update, &reset,
529                                          &deletes, &urls));
530   EXPECT_TRUE(reset);
531 }
532
533 // The SafeBrowsing service will occasionally send zero length chunks so that
534 // client requests will have longer contiguous chunk number ranges, and thus
535 // reduce the request size.
536 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeAddChunk) {
537   const char kEmptyAddChunk[] = {
538     '\0', '\0', '\0', '\x02',  // 32-bit payload length in network byte order.
539     '\x08',                    // field 1, wire format varint
540     '\x02',                    // chunk_number varint 2
541   };
542
543   ScopedVector<SBChunkData> chunks;
544   EXPECT_TRUE(safe_browsing::ParseChunk(kEmptyAddChunk, sizeof(kEmptyAddChunk),
545                                         &chunks));
546   ASSERT_EQ(1U, chunks.size());
547   EXPECT_EQ(2, chunks[0]->ChunkNumber());
548   EXPECT_TRUE(chunks[0]->IsAdd());
549   EXPECT_FALSE(chunks[0]->IsSub());
550   EXPECT_TRUE(chunks[0]->IsPrefix());
551   EXPECT_FALSE(chunks[0]->IsFullHash());
552   EXPECT_EQ(0U, chunks[0]->PrefixCount());
553
554   // Now test a zero size chunk in between normal chunks.
555   chunks.clear();
556   const char kAddChunks[] = {
557     '\0', '\0', '\0', '\x0C',  // 32-bit payload length in network byte order.
558     '\x08',                    // field 1, wire format varint
559     '\x01',                    // chunk_number varint 1
560     '\x22',                    // field 4, wire format length-delimited
561     '\x08',                    // varint length 8
562
563     '1', '1', '1', '1',        // 4-byte prefixes
564     '2', '2', '2', '2',
565
566     '\0', '\0', '\0', '\x02',  // 32-bit payload length in network byte order.
567     '\x08',                    // field 1, wire format varint
568     '\x02',                    // chunk_number varint 2
569
570     '\0', '\0', '\0', '\x08',  // 32-bit payload length in network byte order.
571     '\x08',                    // field 1, wire format varint
572     '\x03',                    // chunk_number varint 3
573     '\x22',                    // field 4, wire format length-delimited
574     '\x04',                    // varint length 8
575     'p', 'p', 'p', 'p',        // 4-byte prefixes
576   };
577   EXPECT_TRUE(safe_browsing::ParseChunk(kAddChunks, sizeof(kAddChunks),
578                                         &chunks));
579   ASSERT_EQ(3U, chunks.size());
580
581   EXPECT_EQ(1, chunks[0]->ChunkNumber());
582   EXPECT_TRUE(chunks[0]->IsAdd());
583   EXPECT_FALSE(chunks[0]->IsSub());
584   EXPECT_TRUE(chunks[0]->IsPrefix());
585   EXPECT_FALSE(chunks[0]->IsFullHash());
586   ASSERT_EQ(2U, chunks[0]->PrefixCount());
587   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
588   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
589
590   EXPECT_EQ(2, chunks[1]->ChunkNumber());
591   EXPECT_TRUE(chunks[1]->IsAdd());
592   EXPECT_FALSE(chunks[1]->IsSub());
593   EXPECT_TRUE(chunks[1]->IsPrefix());
594   EXPECT_FALSE(chunks[1]->IsFullHash());
595   EXPECT_EQ(0U, chunks[1]->PrefixCount());
596
597   EXPECT_EQ(3, chunks[2]->ChunkNumber());
598   EXPECT_TRUE(chunks[2]->IsAdd());
599   EXPECT_FALSE(chunks[2]->IsSub());
600   EXPECT_TRUE(chunks[2]->IsPrefix());
601   EXPECT_FALSE(chunks[2]->IsFullHash());
602   ASSERT_EQ(1U, chunks[2]->PrefixCount());
603   EXPECT_EQ(0x70707070U, chunks[2]->PrefixAt(0));  // pppp
604 }
605
606 // Test parsing a zero sized sub chunk.
607 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeSubChunk) {
608   const char kEmptySubChunk[] = {
609     '\0', '\0', '\0', '\x04',  // 32-bit payload length in network byte order.
610     '\x08',                    // field 1, wire format varint
611     '\x02',                    // chunk_number varint 2
612     '\x10',                    // field 2, wire format varint
613     '\x01',                    // enum ChunkType == SUB
614   };
615
616   ScopedVector<SBChunkData> chunks;
617   EXPECT_TRUE(safe_browsing::ParseChunk(kEmptySubChunk, sizeof(kEmptySubChunk),
618                                         &chunks));
619   ASSERT_EQ(1U, chunks.size());
620   EXPECT_EQ(2, chunks[0]->ChunkNumber());
621   EXPECT_FALSE(chunks[0]->IsAdd());
622   EXPECT_TRUE(chunks[0]->IsSub());
623   EXPECT_TRUE(chunks[0]->IsPrefix());
624   EXPECT_FALSE(chunks[0]->IsFullHash());
625   EXPECT_EQ(0U, chunks[0]->PrefixCount());
626
627   // Test parsing a zero sized sub chunk mixed in with content carrying chunks.
628   chunks.clear();
629   const char kSubChunks[] = {
630     '\0', '\0', '\0', '\x12',  // 32-bit payload length in network byte order.
631     '\x08',                    // field 1, wire format varint
632     '\x01',                    // chunk_number varint 1
633     '\x10',                    // field 2, wire format varint
634     '\x01',                    // enum ChunkType == SUB
635     '\x22',                    // field 4, wire format length-delimited
636     '\x08',                    // varint length 8
637     '1', '1', '1', '1',        // 4-byte prefixes
638     '2', '2', '2', '2',
639     '\x2a',                    // field 5, wire format length-delimited
640     '\x02',                    // varint length 2 (2 add-chunk numbers)
641     '\x07', '\x09',            // varint 7, varint 9
642
643     '\0', '\0', '\0', '\x04',  // 32-bit payload length in network byte order.
644     '\x08',                    // field 1, wire format varint
645     '\x02',                    // chunk_number varint 2
646     '\x10',                    // field 2, wire format varint
647     '\x01',                    // enum ChunkType == SUB
648
649     '\0', '\0', '\0', '\x0D',  // 32-bit payload length in network byte order.
650     '\x08',                    // field 1, wire format varint
651     '\x03',                    // chunk_number varint 3
652     '\x10',                    // field 2, wire format varint
653     '\x01',                    // enum ChunkType == SUB
654     '\x22',                    // field 4, wire format length-delimited
655     '\x04',                    // varint length 8
656     'p', 'p', 'p', 'p',        // 4-byte prefix
657     '\x2a',                    // field 5, wire format length-delimited
658     '\x01',                    // varint length 1 (1 add-chunk numbers)
659     '\x0B',                    // varint 11
660   };
661
662   EXPECT_TRUE(safe_browsing::ParseChunk(kSubChunks, sizeof(kSubChunks),
663                                         &chunks));
664   ASSERT_EQ(3U, chunks.size());
665
666   EXPECT_EQ(1, chunks[0]->ChunkNumber());
667   EXPECT_FALSE(chunks[0]->IsAdd());
668   EXPECT_TRUE(chunks[0]->IsSub());
669   EXPECT_TRUE(chunks[0]->IsPrefix());
670   EXPECT_FALSE(chunks[0]->IsFullHash());
671   ASSERT_EQ(2U, chunks[0]->PrefixCount());
672   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
673   EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0));
674   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
675   EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1));
676
677   EXPECT_EQ(2, chunks[1]->ChunkNumber());
678   EXPECT_FALSE(chunks[0]->IsAdd());
679   EXPECT_TRUE(chunks[0]->IsSub());
680   EXPECT_TRUE(chunks[1]->IsPrefix());
681   EXPECT_FALSE(chunks[1]->IsFullHash());
682   EXPECT_EQ(0U, chunks[1]->PrefixCount());
683
684   EXPECT_EQ(3, chunks[2]->ChunkNumber());
685   EXPECT_FALSE(chunks[0]->IsAdd());
686   EXPECT_TRUE(chunks[0]->IsSub());
687   EXPECT_TRUE(chunks[2]->IsPrefix());
688   EXPECT_FALSE(chunks[2]->IsFullHash());
689   ASSERT_EQ(1U, chunks[2]->PrefixCount());
690   EXPECT_EQ(0x70707070U, chunks[2]->PrefixAt(0));  // pppp
691   EXPECT_EQ(11, chunks[2]->AddChunkNumberAt(0));
692 }
693
694 }  // namespace