Home | History | Annotate | Download | only in safe_browsing
      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 // Program to test the SafeBrowsing protocol parsing v2.1.
      6 
      7 #include <map>
      8 #include <string>
      9 
     10 #include "base/strings/stringprintf.h"
     11 #include "chrome/browser/safe_browsing/protocol_parser.h"
     12 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 // Test parsing one add chunk.
     16 TEST(SafeBrowsingProtocolParsingTest, TestAddChunk) {
     17   std::string add_chunk("a:1:4:35\naaaax1111\0032222333344447777\00288889999");
     18   add_chunk[13] = '\0';
     19 
     20   // Run the parse.
     21   SafeBrowsingProtocolParser parser;
     22   SBChunkList chunks;
     23   bool result = parser.ParseChunk(
     24       safe_browsing_util::kMalwareList,
     25       add_chunk.data(),
     26       static_cast<int>(add_chunk.length()),
     27       &chunks);
     28   EXPECT_TRUE(result);
     29   EXPECT_EQ(chunks.size(), 1U);
     30   EXPECT_EQ(chunks[0].chunk_number, 1);
     31   EXPECT_EQ(chunks[0].hosts.size(), 3U);
     32 
     33   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
     34   SBEntry* entry = chunks[0].hosts[0].entry;
     35   EXPECT_TRUE(entry->IsAdd());
     36   EXPECT_TRUE(entry->IsPrefix());
     37   EXPECT_EQ(entry->prefix_count(), 0);
     38 
     39   EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131);
     40   entry = chunks[0].hosts[1].entry;
     41   EXPECT_TRUE(entry->IsAdd());
     42   EXPECT_TRUE(entry->IsPrefix());
     43   EXPECT_EQ(entry->prefix_count(), 3);
     44   EXPECT_EQ(entry->PrefixAt(0), 0x32323232);
     45   EXPECT_EQ(entry->PrefixAt(1), 0x33333333);
     46   EXPECT_EQ(entry->PrefixAt(2), 0x34343434);
     47 
     48   EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737);
     49   entry = chunks[0].hosts[2].entry;
     50   EXPECT_TRUE(entry->IsAdd());
     51   EXPECT_TRUE(entry->IsPrefix());
     52   EXPECT_EQ(entry->prefix_count(), 2);
     53   EXPECT_EQ(entry->PrefixAt(0), 0x38383838);
     54   EXPECT_EQ(entry->PrefixAt(1), 0x39393939);
     55 }
     56 
     57 // Test parsing one add chunk with full hashes.
     58 TEST(SafeBrowsingProtocolParsingTest, TestAddFullChunk) {
     59   std::string add_chunk("a:1:32:69\naaaa");
     60   add_chunk.push_back(2);
     61 
     62   SBFullHash full_hash1, full_hash2;
     63   for (int i = 0; i < 32; ++i) {
     64     full_hash1.full_hash[i] = i % 2 ? 1 : 2;
     65     full_hash2.full_hash[i] = i % 2 ? 3 : 4;
     66   }
     67 
     68   add_chunk.append(full_hash1.full_hash, 32);
     69   add_chunk.append(full_hash2.full_hash, 32);
     70 
     71   // Run the parse.
     72   SafeBrowsingProtocolParser parser;
     73   SBChunkList chunks;
     74   bool result = parser.ParseChunk(
     75       safe_browsing_util::kMalwareList,
     76       add_chunk.data(),
     77       static_cast<int>(add_chunk.length()),
     78       &chunks);
     79   EXPECT_TRUE(result);
     80   EXPECT_EQ(chunks.size(), 1U);
     81   EXPECT_EQ(chunks[0].chunk_number, 1);
     82   EXPECT_EQ(chunks[0].hosts.size(), 1U);
     83 
     84   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
     85   SBEntry* entry = chunks[0].hosts[0].entry;
     86   EXPECT_TRUE(entry->IsAdd());
     87   EXPECT_FALSE(entry->IsPrefix());
     88   EXPECT_EQ(entry->prefix_count(), 2);
     89   EXPECT_TRUE(entry->FullHashAt(0) == full_hash1);
     90   EXPECT_TRUE(entry->FullHashAt(1) == full_hash2);
     91 }
     92 
     93 // Test parsing multiple add chunks. We'll use the same chunk as above, and add
     94 // one more after it.
     95 TEST(SafeBrowsingProtocolParsingTest, TestAddChunks) {
     96   std::string add_chunk("a:1:4:35\naaaax1111\0032222333344447777\00288889999"
     97                         "a:2:4:13\n5555\002ppppgggg");
     98   add_chunk[13] = '\0';
     99 
    100   // Run the parse.
    101   SafeBrowsingProtocolParser parser;
    102   SBChunkList chunks;
    103   bool result = parser.ParseChunk(
    104       safe_browsing_util::kMalwareList,
    105       add_chunk.data(),
    106       static_cast<int>(add_chunk.length()),
    107       &chunks);
    108   EXPECT_TRUE(result);
    109   EXPECT_EQ(chunks.size(), 2U);
    110   EXPECT_EQ(chunks[0].chunk_number, 1);
    111   EXPECT_EQ(chunks[0].hosts.size(), 3U);
    112 
    113   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
    114   SBEntry* entry = chunks[0].hosts[0].entry;
    115   EXPECT_TRUE(entry->IsAdd());
    116   EXPECT_TRUE(entry->IsPrefix());
    117   EXPECT_EQ(entry->prefix_count(), 0);
    118 
    119   EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131);
    120   entry = chunks[0].hosts[1].entry;
    121   EXPECT_TRUE(entry->IsAdd());
    122   EXPECT_TRUE(entry->IsPrefix());
    123   EXPECT_EQ(entry->prefix_count(), 3);
    124   EXPECT_EQ(entry->PrefixAt(0), 0x32323232);
    125   EXPECT_EQ(entry->PrefixAt(1), 0x33333333);
    126   EXPECT_EQ(entry->PrefixAt(2), 0x34343434);
    127 
    128   EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737);
    129   entry = chunks[0].hosts[2].entry;
    130   EXPECT_TRUE(entry->IsAdd());
    131   EXPECT_TRUE(entry->IsPrefix());
    132   EXPECT_EQ(entry->prefix_count(), 2);
    133   EXPECT_EQ(entry->PrefixAt(0), 0x38383838);
    134   EXPECT_EQ(entry->PrefixAt(1), 0x39393939);
    135 
    136 
    137   EXPECT_EQ(chunks[1].chunk_number, 2);
    138   EXPECT_EQ(chunks[1].hosts.size(), 1U);
    139 
    140   EXPECT_EQ(chunks[1].hosts[0].host, 0x35353535);
    141   entry = chunks[1].hosts[0].entry;
    142   EXPECT_TRUE(entry->IsAdd());
    143   EXPECT_TRUE(entry->IsPrefix());
    144   EXPECT_EQ(entry->prefix_count(), 2);
    145   EXPECT_EQ(entry->PrefixAt(0), 0x70707070);
    146   EXPECT_EQ(entry->PrefixAt(1), 0x67676767);
    147 }
    148 
    149 // Test parsing one add chunk where a hostkey spans several entries.
    150 TEST(SafeBrowsingProtocolParsingTest, TestAddBigChunk) {
    151   std::string add_chunk("a:1:4:1050\naaaaX");
    152   add_chunk[add_chunk.size() - 1] |= 0xFF;
    153   for (int i = 0; i < 255; ++i)
    154     add_chunk.append(base::StringPrintf("%04d", i));
    155 
    156   add_chunk.append("aaaa");
    157   add_chunk.push_back(5);
    158   for (int i = 0; i < 5; ++i)
    159     add_chunk.append(base::StringPrintf("001%d", i));
    160 
    161   SafeBrowsingProtocolParser parser;
    162   SBChunkList chunks;
    163   bool result = parser.ParseChunk(
    164       safe_browsing_util::kMalwareList,
    165       add_chunk.data(),
    166       static_cast<int>(add_chunk.length()),
    167       &chunks);
    168   EXPECT_TRUE(result);
    169   EXPECT_EQ(chunks.size(), 1U);
    170   EXPECT_EQ(chunks[0].chunk_number, 1);
    171 
    172   EXPECT_EQ(chunks[0].hosts.size(), 2U);
    173 
    174   const SBChunkHost& host0 = chunks[0].hosts[0];
    175   EXPECT_EQ(host0.host, 0x61616161);
    176   EXPECT_EQ(host0.entry->prefix_count(), 255);
    177 
    178   const SBChunkHost& host1 = chunks[0].hosts[1];
    179   EXPECT_EQ(host1.host, 0x61616161);
    180   EXPECT_EQ(host1.entry->prefix_count(), 5);
    181 }
    182 
    183 // Test to make sure we could deal with truncated bin hash chunk.
    184 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedBinHashChunk) {
    185   // This chunk delares there are 4 prefixes but actually only contains 2.
    186   const char add_chunk[] = "a:1:4:16\n11112222";
    187   SafeBrowsingProtocolParser parser;
    188   SBChunkList chunks;
    189   bool result = parser.ParseChunk(safe_browsing_util::kBinHashList,
    190                                   add_chunk,
    191                                   static_cast<int>(sizeof(add_chunk)),
    192                                   &chunks);
    193   EXPECT_FALSE(result);
    194   EXPECT_EQ(chunks.size(), 0U);
    195 }
    196 
    197 // Test to make sure we could deal with truncated malwarelist chunk.
    198 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedUrlHashChunk) {
    199   // This chunk delares there are 4 prefixes but actually only contains 2.
    200   const char add_chunk[] = "a:1:4:21\naaaa\00411112222";
    201   SafeBrowsingProtocolParser parser;
    202   SBChunkList chunks;
    203 
    204   // For safe_browsing_util::kMalwareList.
    205   bool result = parser.ParseChunk(safe_browsing_util::kMalwareList,
    206                                   add_chunk,
    207                                   static_cast<int>(sizeof(add_chunk)),
    208                                   &chunks);
    209   EXPECT_FALSE(result);
    210   EXPECT_EQ(chunks.size(), 0U);
    211 
    212   // For safe_browsing_util::kPhishingList.
    213   result = parser.ParseChunk(safe_browsing_util::kPhishingList,
    214                              add_chunk,
    215                              static_cast<int>(sizeof(add_chunk)),
    216                              &chunks);
    217   EXPECT_FALSE(result);
    218   EXPECT_EQ(chunks.size(), 0U);
    219 
    220   // For safe_browsing_util::kBinUrlList.
    221   result = parser.ParseChunk(safe_browsing_util::kBinUrlList,
    222                              add_chunk,
    223                              static_cast<int>(sizeof(add_chunk)),
    224                              &chunks);
    225   EXPECT_FALSE(result);
    226   EXPECT_EQ(chunks.size(), 0U);
    227 }
    228 
    229 // Test to verify handling of a truncated chunk header.
    230 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedHeader) {
    231   std::string truncated_chunks("a:1:4:0\na:");
    232 
    233   // Run the parser.
    234   SafeBrowsingProtocolParser parser;
    235   SBChunkList chunks;
    236   bool result = parser.ParseChunk(
    237       safe_browsing_util::kMalwareList,
    238       truncated_chunks.data(),
    239       static_cast<int>(truncated_chunks.length()),
    240       &chunks);
    241   EXPECT_FALSE(result);
    242 }
    243 
    244 // Test parsing one sub chunk.
    245 TEST(SafeBrowsingProtocolParsingTest, TestSubChunk) {
    246   std::string sub_chunk("s:9:4:59\naaaaxkkkk1111\003"
    247                         "zzzz2222zzzz3333zzzz4444"
    248                         "7777\002yyyy8888yyyy9999");
    249   sub_chunk[13] = '\0';
    250 
    251   // Run the parse.
    252   SafeBrowsingProtocolParser parser;
    253   SBChunkList chunks;
    254   bool result = parser.ParseChunk(
    255       safe_browsing_util::kMalwareList,
    256       sub_chunk.data(),
    257       static_cast<int>(sub_chunk.length()),
    258       &chunks);
    259   EXPECT_TRUE(result);
    260   EXPECT_EQ(chunks.size(), 1U);
    261   EXPECT_EQ(chunks[0].chunk_number, 9);
    262   EXPECT_EQ(chunks[0].hosts.size(), 3U);
    263 
    264   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
    265   SBEntry* entry = chunks[0].hosts[0].entry;
    266   EXPECT_TRUE(entry->IsSub());
    267   EXPECT_TRUE(entry->IsPrefix());
    268   EXPECT_EQ(entry->chunk_id(), 0x6b6b6b6b);
    269   EXPECT_EQ(entry->prefix_count(), 0);
    270 
    271   EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131);
    272   entry = chunks[0].hosts[1].entry;
    273   EXPECT_TRUE(entry->IsSub());
    274   EXPECT_TRUE(entry->IsPrefix());
    275   EXPECT_EQ(entry->prefix_count(), 3);
    276   EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x7a7a7a7a);
    277   EXPECT_EQ(entry->PrefixAt(0), 0x32323232);
    278   EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x7a7a7a7a);
    279   EXPECT_EQ(entry->PrefixAt(1), 0x33333333);
    280   EXPECT_EQ(entry->ChunkIdAtPrefix(2), 0x7a7a7a7a);
    281   EXPECT_EQ(entry->PrefixAt(2), 0x34343434);
    282 
    283   EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737);
    284   entry = chunks[0].hosts[2].entry;
    285   EXPECT_TRUE(entry->IsSub());
    286   EXPECT_TRUE(entry->IsPrefix());
    287   EXPECT_EQ(entry->prefix_count(), 2);
    288   EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x79797979);
    289   EXPECT_EQ(entry->PrefixAt(0), 0x38383838);
    290   EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x79797979);
    291   EXPECT_EQ(entry->PrefixAt(1), 0x39393939);
    292 }
    293 
    294 // Test parsing one sub chunk with full hashes.
    295 TEST(SafeBrowsingProtocolParsingTest, TestSubFullChunk) {
    296   std::string sub_chunk("s:1:32:77\naaaa");
    297   sub_chunk.push_back(2);
    298 
    299   SBFullHash full_hash1, full_hash2;
    300   for (int i = 0; i < 32; ++i) {
    301     full_hash1.full_hash[i] = i % 2 ? 1 : 2;
    302     full_hash2.full_hash[i] = i % 2 ? 3 : 4;
    303   }
    304 
    305   sub_chunk.append("yyyy");
    306   sub_chunk.append(full_hash1.full_hash, 32);
    307   sub_chunk.append("zzzz");
    308   sub_chunk.append(full_hash2.full_hash, 32);
    309 
    310   // Run the parse.
    311   SafeBrowsingProtocolParser parser;
    312   SBChunkList chunks;
    313   bool result = parser.ParseChunk(
    314       safe_browsing_util::kMalwareList,
    315       sub_chunk.data(),
    316       static_cast<int>(sub_chunk.length()),
    317       &chunks);
    318   EXPECT_TRUE(result);
    319   EXPECT_EQ(chunks.size(), 1U);
    320   EXPECT_EQ(chunks[0].chunk_number, 1);
    321   EXPECT_EQ(chunks[0].hosts.size(), 1U);
    322 
    323   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
    324   SBEntry* entry = chunks[0].hosts[0].entry;
    325   EXPECT_TRUE(entry->IsSub());
    326   EXPECT_FALSE(entry->IsPrefix());
    327   EXPECT_EQ(entry->prefix_count(), 2);
    328   EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x79797979);
    329   EXPECT_TRUE(entry->FullHashAt(0) == full_hash1);
    330   EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x7a7a7a7a);
    331   EXPECT_TRUE(entry->FullHashAt(1) == full_hash2);
    332 }
    333 
    334 // Test parsing the SafeBrowsing update response.
    335 TEST(SafeBrowsingProtocolParsingTest, TestChunkDelete) {
    336   std::string add_del("n:1700\ni:phishy\nad:1-7,43-597,44444,99999\n"
    337                       "i:malware\nsd:21-27,42,171717\n");
    338 
    339   SafeBrowsingProtocolParser parser;
    340   int next_query_sec = 0;
    341   bool reset = false;
    342   std::vector<SBChunkDelete> deletes;
    343   std::vector<ChunkUrl> urls;
    344   EXPECT_TRUE(parser.ParseUpdate(add_del.data(),
    345                                  static_cast<int>(add_del.length()),
    346                                  &next_query_sec, &reset, &deletes, &urls));
    347 
    348   EXPECT_TRUE(urls.empty());
    349   EXPECT_FALSE(reset);
    350   EXPECT_EQ(next_query_sec, 1700);
    351   EXPECT_EQ(deletes.size(), 2U);
    352 
    353   EXPECT_EQ(deletes[0].chunk_del.size(), 4U);
    354   EXPECT_TRUE(deletes[0].chunk_del[0] == ChunkRange(1, 7));
    355   EXPECT_TRUE(deletes[0].chunk_del[1] == ChunkRange(43, 597));
    356   EXPECT_TRUE(deletes[0].chunk_del[2] == ChunkRange(44444));
    357   EXPECT_TRUE(deletes[0].chunk_del[3] == ChunkRange(99999));
    358 
    359   EXPECT_EQ(deletes[1].chunk_del.size(), 3U);
    360   EXPECT_TRUE(deletes[1].chunk_del[0] == ChunkRange(21, 27));
    361   EXPECT_TRUE(deletes[1].chunk_del[1] == ChunkRange(42));
    362   EXPECT_TRUE(deletes[1].chunk_del[2] == ChunkRange(171717));
    363 
    364   // An update response with missing list name.
    365 
    366   next_query_sec = 0;
    367   deletes.clear();
    368   urls.clear();
    369   add_del = "n:1700\nad:1-7,43-597,44444,99999\ni:malware\nsd:4,21-27171717\n";
    370   EXPECT_FALSE(parser.ParseUpdate(add_del.data(),
    371                                   static_cast<int>(add_del.length()),
    372                                   &next_query_sec, &reset, &deletes, &urls));
    373 }
    374 
    375 // Test parsing the SafeBrowsing update response.
    376 TEST(SafeBrowsingProtocolParsingTest, TestRedirects) {
    377   std::string redirects("i:goog-malware-shavar\n"
    378     "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1\n"
    379     "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2\n"
    380     "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3\n"
    381     "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689,"
    382     "8691-8731,8733-8786\n");
    383 
    384   SafeBrowsingProtocolParser parser;
    385   int next_query_sec = 0;
    386   bool reset = false;
    387   std::vector<SBChunkDelete> deletes;
    388   std::vector<ChunkUrl> urls;
    389   EXPECT_TRUE(parser.ParseUpdate(redirects.data(),
    390                                  static_cast<int>(redirects.length()),
    391                                  &next_query_sec, &reset, &deletes, &urls));
    392 
    393   EXPECT_FALSE(reset);
    394   EXPECT_EQ(urls.size(), 4U);
    395   EXPECT_EQ(urls[0].url,
    396       "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1");
    397   EXPECT_EQ(urls[1].url,
    398       "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2");
    399   EXPECT_EQ(urls[2].url,
    400       "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3");
    401   EXPECT_EQ(urls[3].url,
    402       "s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689,"
    403       "8691-8731,8733-8786");
    404   EXPECT_EQ(next_query_sec, 0);
    405   EXPECT_TRUE(deletes.empty());
    406 }
    407 
    408 // Test parsing various SafeBrowsing protocol headers.
    409 TEST(SafeBrowsingProtocolParsingTest, TestNextQueryTime) {
    410   std::string headers("n:1800\ni:goog-white-shavar\n");
    411   SafeBrowsingProtocolParser parser;
    412   int next_query_sec = 0;
    413   bool reset = false;
    414   std::vector<SBChunkDelete> deletes;
    415   std::vector<ChunkUrl> urls;
    416   EXPECT_TRUE(parser.ParseUpdate(headers.data(),
    417                                  static_cast<int>(headers.length()),
    418                                  &next_query_sec, &reset, &deletes, &urls));
    419 
    420   EXPECT_EQ(next_query_sec, 1800);
    421   EXPECT_FALSE(reset);
    422   EXPECT_TRUE(deletes.empty());
    423   EXPECT_TRUE(urls.empty());
    424 }
    425 
    426 // Test parsing data from a GetHashRequest
    427 TEST(SafeBrowsingProtocolParsingTest, TestGetHash) {
    428   std::string get_hash("goog-phish-shavar:19:96\n"
    429                        "00112233445566778899aabbccddeeff"
    430                        "00001111222233334444555566667777"
    431                        "ffffeeeeddddccccbbbbaaaa99998888");
    432   std::vector<SBFullHashResult> full_hashes;
    433   SafeBrowsingProtocolParser parser;
    434   EXPECT_TRUE(parser.ParseGetHash(get_hash.data(),
    435                                   static_cast<int>(get_hash.length()),
    436                                   &full_hashes));
    437 
    438   EXPECT_EQ(full_hashes.size(), 3U);
    439   EXPECT_EQ(memcmp(&full_hashes[0].hash,
    440                    "00112233445566778899aabbccddeeff",
    441                    sizeof(SBFullHash)), 0);
    442   EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar");
    443   EXPECT_EQ(memcmp(&full_hashes[1].hash,
    444                    "00001111222233334444555566667777",
    445                    sizeof(SBFullHash)), 0);
    446   EXPECT_EQ(full_hashes[1].list_name, "goog-phish-shavar");
    447   EXPECT_EQ(memcmp(&full_hashes[2].hash,
    448                    "ffffeeeeddddccccbbbbaaaa99998888",
    449                    sizeof(SBFullHash)), 0);
    450   EXPECT_EQ(full_hashes[2].list_name, "goog-phish-shavar");
    451 
    452   // Test multiple lists in the GetHash results.
    453   std::string get_hash2("goog-phish-shavar:19:32\n"
    454                         "00112233445566778899aabbccddeeff"
    455                         "goog-malware-shavar:19:64\n"
    456                         "cafebeefcafebeefdeaddeaddeaddead"
    457                         "zzzzyyyyxxxxwwwwvvvvuuuuttttssss");
    458   EXPECT_TRUE(parser.ParseGetHash(get_hash2.data(),
    459                                   static_cast<int>(get_hash2.length()),
    460                                   &full_hashes));
    461 
    462   EXPECT_EQ(full_hashes.size(), 3U);
    463   EXPECT_EQ(memcmp(&full_hashes[0].hash,
    464                    "00112233445566778899aabbccddeeff",
    465                    sizeof(SBFullHash)), 0);
    466   EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar");
    467   EXPECT_EQ(memcmp(&full_hashes[1].hash,
    468                    "cafebeefcafebeefdeaddeaddeaddead",
    469                    sizeof(SBFullHash)), 0);
    470   EXPECT_EQ(full_hashes[1].list_name, "goog-malware-shavar");
    471   EXPECT_EQ(memcmp(&full_hashes[2].hash,
    472                    "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
    473                    sizeof(SBFullHash)), 0);
    474   EXPECT_EQ(full_hashes[2].list_name, "goog-malware-shavar");
    475 }
    476 
    477 TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownList) {
    478   std::string hash_response = "goog-phish-shavar:1:32\n"
    479                               "12345678901234567890123456789012"
    480                               "googpub-phish-shavar:19:32\n"
    481                               "09876543210987654321098765432109";
    482   std::vector<SBFullHashResult> full_hashes;
    483   SafeBrowsingProtocolParser parser;
    484   EXPECT_TRUE(parser.ParseGetHash(hash_response.data(),
    485                                   hash_response.size(),
    486                                   &full_hashes));
    487 
    488   EXPECT_EQ(full_hashes.size(), 1U);
    489   EXPECT_EQ(memcmp("12345678901234567890123456789012",
    490                    &full_hashes[0].hash, sizeof(SBFullHash)), 0);
    491   EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar");
    492   EXPECT_EQ(full_hashes[0].add_chunk_id, 1);
    493 
    494   hash_response += "goog-malware-shavar:7:32\n"
    495                    "abcdefghijklmnopqrstuvwxyz123457";
    496   full_hashes.clear();
    497   EXPECT_TRUE(parser.ParseGetHash(hash_response.data(),
    498                                   hash_response.size(),
    499                                   &full_hashes));
    500 
    501   EXPECT_EQ(full_hashes.size(), 2U);
    502   EXPECT_EQ(memcmp("12345678901234567890123456789012",
    503                    &full_hashes[0].hash, sizeof(SBFullHash)), 0);
    504   EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar");
    505   EXPECT_EQ(full_hashes[0].add_chunk_id, 1);
    506   EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457",
    507                    &full_hashes[1].hash, sizeof(SBFullHash)), 0);
    508   EXPECT_EQ(full_hashes[1].list_name, "goog-malware-shavar");
    509   EXPECT_EQ(full_hashes[1].add_chunk_id, 7);
    510 }
    511 
    512 TEST(SafeBrowsingProtocolParsingTest, TestFormatHash) {
    513   SafeBrowsingProtocolParser parser;
    514   std::vector<SBPrefix> prefixes;
    515   std::string get_hash;
    516 
    517   prefixes.push_back(0x34333231);
    518   prefixes.push_back(0x64636261);
    519   prefixes.push_back(0x73727170);
    520 
    521   parser.FormatGetHash(prefixes, &get_hash);
    522   EXPECT_EQ(get_hash, "4:12\n1234abcdpqrs");
    523 }
    524 
    525 TEST(SafeBrowsingProtocolParsingTest, TestReset) {
    526   SafeBrowsingProtocolParser parser;
    527   std::string update("n:1800\ni:phishy\nr:pleasereset\n");
    528 
    529   bool reset = false;
    530   int next_update = -1;
    531   std::vector<SBChunkDelete> deletes;
    532   std::vector<ChunkUrl> urls;
    533   EXPECT_TRUE(parser.ParseUpdate(update.data(),
    534                                  static_cast<int>(update.size()),
    535                                  &next_update, &reset, &deletes, &urls));
    536   EXPECT_TRUE(reset);
    537 }
    538 
    539 // The SafeBrowsing service will occasionally send zero length chunks so that
    540 // client requests will have longer contiguous chunk number ranges, and thus
    541 // reduce the request size.
    542 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeAddChunk) {
    543   std::string add_chunk("a:1:4:0\n");
    544   SafeBrowsingProtocolParser parser;
    545   SBChunkList chunks;
    546 
    547   bool result = parser.ParseChunk(
    548       safe_browsing_util::kMalwareList,
    549       add_chunk.data(),
    550       static_cast<int>(add_chunk.length()),
    551       &chunks);
    552   EXPECT_TRUE(result);
    553   EXPECT_EQ(chunks.size(), 1U);
    554   EXPECT_EQ(chunks[0].chunk_number, 1);
    555   EXPECT_EQ(chunks[0].hosts.size(), 0U);
    556 
    557   // Now test a zero size chunk in between normal chunks.
    558   chunks.clear();
    559   std::string add_chunks("a:1:4:18\n1234\001abcd5678\001wxyz"
    560                          "a:2:4:0\n"
    561                          "a:3:4:9\ncafe\001beef");
    562   result = parser.ParseChunk(
    563       safe_browsing_util::kMalwareList,
    564       add_chunks.data(),
    565       static_cast<int>(add_chunks.length()),
    566       &chunks);
    567   EXPECT_TRUE(result);
    568   EXPECT_EQ(chunks.size(), 3U);
    569 
    570   // See that each chunk has the right content.
    571   EXPECT_EQ(chunks[0].chunk_number, 1);
    572   EXPECT_EQ(chunks[0].hosts.size(), 2U);
    573   EXPECT_EQ(chunks[0].hosts[0].host, 0x34333231);
    574   EXPECT_EQ(chunks[0].hosts[0].entry->PrefixAt(0), 0x64636261);
    575   EXPECT_EQ(chunks[0].hosts[1].host, 0x38373635);
    576   EXPECT_EQ(chunks[0].hosts[1].entry->PrefixAt(0), 0x7a797877);
    577 
    578   EXPECT_EQ(chunks[1].chunk_number, 2);
    579   EXPECT_EQ(chunks[1].hosts.size(), 0U);
    580 
    581   EXPECT_EQ(chunks[2].chunk_number, 3);
    582   EXPECT_EQ(chunks[2].hosts.size(), 1U);
    583   EXPECT_EQ(chunks[2].hosts[0].host, 0x65666163);
    584   EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x66656562);
    585 }
    586 
    587 // Test parsing a zero sized sub chunk.
    588 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeSubChunk) {
    589   std::string sub_chunk("s:9:4:0\n");
    590   SafeBrowsingProtocolParser parser;
    591   SBChunkList chunks;
    592 
    593   bool result = parser.ParseChunk(
    594       safe_browsing_util::kMalwareList,
    595       sub_chunk.data(),
    596       static_cast<int>(sub_chunk.length()),
    597       &chunks);
    598   EXPECT_TRUE(result);
    599   EXPECT_EQ(chunks.size(), 1U);
    600   EXPECT_EQ(chunks[0].chunk_number, 9);
    601   EXPECT_EQ(chunks[0].hosts.size(), 0U);
    602   chunks.clear();
    603 
    604   // Test parsing a zero sized sub chunk mixed in with content carrying chunks.
    605   std::string sub_chunks("s:1:4:9\nabcdxwxyz"
    606                          "s:2:4:0\n"
    607                          "s:3:4:26\nefgh\0011234pqrscafe\0015678lmno");
    608   sub_chunks[12] = '\0';
    609 
    610   result = parser.ParseChunk(
    611       safe_browsing_util::kMalwareList,
    612       sub_chunks.data(),
    613       static_cast<int>(sub_chunks.length()),
    614       &chunks);
    615   EXPECT_TRUE(result);
    616 
    617   EXPECT_EQ(chunks[0].chunk_number, 1);
    618   EXPECT_EQ(chunks[0].hosts.size(), 1U);
    619   EXPECT_EQ(chunks[0].hosts[0].host, 0x64636261);
    620   EXPECT_EQ(chunks[0].hosts[0].entry->prefix_count(), 0);
    621 
    622   EXPECT_EQ(chunks[1].chunk_number, 2);
    623   EXPECT_EQ(chunks[1].hosts.size(), 0U);
    624 
    625   EXPECT_EQ(chunks[2].chunk_number, 3);
    626   EXPECT_EQ(chunks[2].hosts.size(), 2U);
    627   EXPECT_EQ(chunks[2].hosts[0].host, 0x68676665);
    628   EXPECT_EQ(chunks[2].hosts[0].entry->prefix_count(), 1);
    629   EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x73727170);
    630   EXPECT_EQ(chunks[2].hosts[0].entry->ChunkIdAtPrefix(0), 0x31323334);
    631   EXPECT_EQ(chunks[2].hosts[1].host, 0x65666163);
    632   EXPECT_EQ(chunks[2].hosts[1].entry->prefix_count(), 1);
    633   EXPECT_EQ(chunks[2].hosts[1].entry->PrefixAt(0), 0x6f6e6d6c);
    634   EXPECT_EQ(chunks[2].hosts[1].entry->ChunkIdAtPrefix(0), 0x35363738);
    635 }
    636 
    637 TEST(SafeBrowsingProtocolParsingTest, TestAddBinHashChunks) {
    638   std::string add_chunk("a:1:4:16\naaaabbbbccccdddd"
    639                         "a:2:4:8\n11112222");
    640   // Run the parse.
    641   SafeBrowsingProtocolParser parser;
    642   SBChunkList chunks;
    643   bool result = parser.ParseChunk(
    644       safe_browsing_util::kBinHashList,
    645       add_chunk.data(),
    646       static_cast<int>(add_chunk.length()),
    647       &chunks);
    648   EXPECT_TRUE(result);
    649   EXPECT_EQ(chunks.size(), 2U);
    650   EXPECT_EQ(chunks[0].chunk_number, 1);
    651   EXPECT_EQ(chunks[0].hosts.size(), 1U);
    652 
    653   EXPECT_EQ(chunks[0].hosts[0].host, 0);
    654   SBEntry* entry = chunks[0].hosts[0].entry;
    655   EXPECT_TRUE(entry->IsAdd());
    656   EXPECT_TRUE(entry->IsPrefix());
    657   EXPECT_EQ(entry->prefix_count(), 4);
    658 
    659   EXPECT_EQ(chunks[1].chunk_number, 2);
    660   EXPECT_EQ(chunks[1].hosts.size(), 1U);
    661 
    662   EXPECT_EQ(chunks[1].hosts[0].host, 0);
    663   entry = chunks[1].hosts[0].entry;
    664   EXPECT_TRUE(entry->IsAdd());
    665   EXPECT_TRUE(entry->IsPrefix());
    666   EXPECT_EQ(entry->prefix_count(), 2);
    667   EXPECT_EQ(entry->PrefixAt(0), 0x31313131);
    668   EXPECT_EQ(entry->PrefixAt(1), 0x32323232);
    669 }
    670 
    671 // Test parsing one add chunk where a hostkey spans several entries.
    672 TEST(SafeBrowsingProtocolParsingTest, TestAddBigBinHashChunk) {
    673   std::string add_chunk("a:1:4:1028\n");
    674   for (int i = 0; i < 257; ++i)
    675     add_chunk.append(base::StringPrintf("%04d", i));
    676 
    677   SafeBrowsingProtocolParser parser;
    678   SBChunkList chunks;
    679   bool result = parser.ParseChunk(
    680       safe_browsing_util::kBinHashList,
    681       add_chunk.data(),
    682       static_cast<int>(add_chunk.length()),
    683       &chunks);
    684   EXPECT_TRUE(result);
    685   EXPECT_EQ(chunks.size(), 1U);
    686   EXPECT_EQ(chunks[0].chunk_number, 1);
    687 
    688   EXPECT_EQ(chunks[0].hosts.size(), 1U);
    689 
    690   const SBChunkHost& host0 = chunks[0].hosts[0];
    691   EXPECT_EQ(host0.host, 0);
    692   EXPECT_EQ(host0.entry->prefix_count(), 257);
    693 }
    694 
    695 // Test parsing one sub chunk.
    696 TEST(SafeBrowsingProtocolParsingTest, TestSubBinHashChunk) {
    697   std::string sub_chunk("s:9:4:16\n1111mmmm2222nnnn");
    698 
    699   // Run the parser.
    700   SafeBrowsingProtocolParser parser;
    701   SBChunkList chunks;
    702   bool result = parser.ParseChunk(
    703       safe_browsing_util::kBinHashList,
    704       sub_chunk.data(),
    705       static_cast<int>(sub_chunk.length()),
    706       &chunks);
    707   EXPECT_TRUE(result);
    708   EXPECT_EQ(chunks.size(), 1U);
    709   EXPECT_EQ(chunks[0].chunk_number, 9);
    710   EXPECT_EQ(chunks[0].hosts.size(), 1U);
    711 
    712   EXPECT_EQ(chunks[0].hosts[0].host, 0);
    713   SBEntry* entry = chunks[0].hosts[0].entry;
    714   EXPECT_TRUE(entry->IsSub());
    715   EXPECT_TRUE(entry->IsPrefix());
    716   EXPECT_EQ(entry->prefix_count(), 2);
    717   EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x31313131);
    718   EXPECT_EQ(entry->PrefixAt(0), 0x6d6d6d6d);
    719   EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x32323232);
    720   EXPECT_EQ(entry->PrefixAt(1), 0x6e6e6e6e);
    721 }
    722 
    723 TEST(SafeBrowsingProtocolParsingTest, TestAddDownloadWhitelistChunk) {
    724   std::string add_chunk("a:1:32:32\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    725                         "a:2:32:64\nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    726                         "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
    727   // Run the parse.
    728   SafeBrowsingProtocolParser parser;
    729   SBChunkList chunks;
    730   bool result = parser.ParseChunk(
    731       safe_browsing_util::kDownloadWhiteList,
    732       add_chunk.data(),
    733       static_cast<int>(add_chunk.length()),
    734       &chunks);
    735   EXPECT_TRUE(result);
    736   EXPECT_EQ(chunks.size(), 2U);
    737   EXPECT_EQ(chunks[0].chunk_number, 1);
    738   EXPECT_EQ(chunks[0].hosts.size(), 1U);
    739   EXPECT_EQ(chunks[0].hosts[0].host, 0);
    740   SBEntry* entry = chunks[0].hosts[0].entry;
    741   EXPECT_TRUE(entry->IsAdd());
    742   EXPECT_FALSE(entry->IsPrefix());
    743   EXPECT_EQ(entry->prefix_count(), 1);
    744   SBFullHash full;
    745   memcpy(full.full_hash, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 32);
    746   EXPECT_TRUE(entry->FullHashAt(0) == full);
    747 
    748   EXPECT_EQ(chunks[1].chunk_number, 2);
    749   EXPECT_EQ(chunks[1].hosts.size(), 1U);
    750   EXPECT_EQ(chunks[1].hosts[0].host, 0);
    751   entry = chunks[1].hosts[0].entry;
    752   EXPECT_TRUE(entry->IsAdd());
    753   EXPECT_FALSE(entry->IsPrefix());
    754   EXPECT_EQ(entry->prefix_count(), 2);
    755   memcpy(full.full_hash, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", 32);
    756   EXPECT_TRUE(entry->FullHashAt(0) == full);
    757   memcpy(full.full_hash, "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 32);
    758   EXPECT_TRUE(entry->FullHashAt(1) == full);
    759 }
    760 
    761 // Test parsing one sub chunk.
    762 TEST(SafeBrowsingProtocolParsingTest, TestSubDownloadWhitelistChunk) {
    763   std::string sub_chunk("s:1:32:36\n1111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    764 
    765   // Run the parser.
    766   SafeBrowsingProtocolParser parser;
    767   SBChunkList chunks;
    768   bool result = parser.ParseChunk(
    769       safe_browsing_util::kDownloadWhiteList,
    770       sub_chunk.data(),
    771       static_cast<int>(sub_chunk.length()),
    772       &chunks);
    773   ASSERT_TRUE(result);
    774   ASSERT_EQ(chunks.size(), 1U);
    775   EXPECT_EQ(chunks[0].chunk_number, 1);
    776   EXPECT_EQ(chunks[0].hosts.size(), 1U);
    777 
    778   EXPECT_EQ(chunks[0].hosts[0].host, 0);
    779   SBEntry* entry = chunks[0].hosts[0].entry;
    780   EXPECT_TRUE(entry->IsSub());
    781   ASSERT_FALSE(entry->IsPrefix());
    782   ASSERT_EQ(entry->prefix_count(), 1);
    783   EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x31313131);
    784   SBFullHash full;
    785   memcpy(full.full_hash, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 32);
    786   EXPECT_TRUE(entry->FullHashAt(0) == full);
    787 }
    788 
    789 // There should be one test case for every list added here.  Each list
    790 // chunk data should contain exactly one add chunk and one sub chunk.
    791 TEST(SafeBrowsingProtocolParsingTest, TestAllLists) {
    792   std::map<std::string, std::string> add_testdata;
    793   // goog-*-shavar lists have a host-key followed by one or more prefixes.
    794   add_testdata[safe_browsing_util::kMalwareList] = std::string(
    795       "a:129057:4:34\n\xd9\xb8\xb2\x14\x00\xe4""B7P\x00\xaf\x91"
    796       "{\xd7\x01\xad\xa6\xb5""X\xbb\xcf""F\xcf\x00\xf7""A\xbd"
    797       "p\x00\xab\xd7\x89\xd3\x00", 48);
    798   add_testdata[safe_browsing_util::kPhishingList] = std::string(
    799       "a:301377:4:9\n\xdb\xe0\xaa\x8e\x01\x85\xba\xb2\x9e", 22);
    800   add_testdata[safe_browsing_util::kBinUrlList] = std::string(
    801       "a:19420:4:18\n_\x92\x9e\xcd\x01\x03""}I\xa2\\3\xe6""h\x01\xee"
    802       "H\xf6\xe4", 31);
    803   add_testdata[safe_browsing_util::kSideEffectFreeWhitelist] = std::string(
    804       "a:1818:4:9\n\x85\xd0\xfe""i\x01""}\x98\xb1\xe5", 20);
    805   // goog-*-digestvar lists have no host-key data.
    806   add_testdata[safe_browsing_util::kBinHashList] = std::string(
    807       "a:5:4:4\nBBBB", 12);
    808   add_testdata[safe_browsing_util::kExtensionBlacklist] = std::string(
    809       "a:81:4:8\nhleedfcc", 17);
    810   // goog-*-sha256 lists have host-keys but they only contains
    811   // full-length entires.
    812   add_testdata[safe_browsing_util::kCsdWhiteList] = std::string(
    813       "a:35:32:37\n\x06\xf9\xb1\xaf\x01\x06\xf9\xb1\xaf""5\xc""9!\x17\x1e"
    814       "*-\xc9"",*>YSl6\xf9""B\xb8\x96""O\x98""r\xf2\xd5\x8d\xe3""T\x99", 48);
    815   // goog-*-digest256 has no host-keys and contains only full-length
    816   // hashes.
    817   add_testdata[safe_browsing_util::kDownloadWhiteList] = std::string(
    818       "a:42:32:32\n\xc8\xec\x9f\x9c\x9b\x9a"",\x82""G:F(\xe9\xad\x9c""b$\x8a"
    819       "\xba""%\x19\xae""c\x03\x87""~\xd1\xd3""bvC\xfd", 43);
    820   add_testdata[safe_browsing_util::kIPBlacklist] = std::string(
    821       "a:12:32:32\n8\x99\x17\xda\xec""+i`\x1a\xb3""8pVh\n$\x01\xd1\x12"
    822       ":\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 43);
    823 
    824   std::map<std::string, std::string> sub_testdata;
    825   // goog-*-shavar lists have a host-key, add number followed by zero or more
    826   // prefixes.
    827   sub_testdata[safe_browsing_util::kMalwareList] = std::string(
    828       "s:122930:4:9\n\x85""!_\x13\x00\x00\x01\xf1\xa2", 22);
    829   sub_testdata[safe_browsing_util::kPhishingList] = std::string(
    830       "s:150181:4:9\nr\x90""zt\x00\x00\x04\x9f""@", 22);
    831   sub_testdata[safe_browsing_util::kBinUrlList] = std::string(
    832       "s:3:4:13\nHOST\x01""####BBBB", 22);
    833   sub_testdata[safe_browsing_util::kSideEffectFreeWhitelist] = std::string(
    834       "s:4:4:9\nHOST\x00""####", 17);
    835   // goog-*-digestvar lists have no host-key data.
    836   sub_testdata[safe_browsing_util::kBinHashList] = std::string(
    837       "s:5:4:8\n####BBBB", 16);
    838   sub_testdata[safe_browsing_util::kExtensionBlacklist] = std::string(
    839       "s:3:4:8\n\x00\x00\x00""%pgkc", 16);
    840   // goog-*-sha256 lists have host-keys but they only contains
    841   // full-length entires.
    842   sub_testdata[safe_browsing_util::kCsdWhiteList] = std::string(
    843       "s:1:32:41\n\x1a""\"[\n\x01\x00\x00\x00\x15\x1""a\"[\n\xe9\x81""P\x11"
    844       "LR\xcb""3\x00""B\x90\xb3\x15""K\xf5\xdc\xd0""V\xc2""aI\x1e""-\xc8"
    845       "\xce"":\t\x01", 51);
    846   // goog-*-digest256 has no host-keys and contains only full-length
    847   // hashes.
    848   sub_testdata[safe_browsing_util::kDownloadWhiteList] = std::string(
    849       "s:15:32:36\n\x00\x00\x00""-\x12""!\xa2\x8d""z\x80""a\xfb\x14\xff"
    850       "f\x13\x18\xcc\xdb\xbd\xc0\xb1""~\xd6\x82""[\xf6\xdc\xa1\x81"
    851       "TI%\xef""C\xab", 47);
    852   sub_testdata[safe_browsing_util::kIPBlacklist] = std::string(
    853       "s:13:32:108\n\x00\x00\x00\rL2\x1e\xc6""P3\x94\x1f\xf1""Cv\x18\x9d\xdf"
    854       "ih4M.c\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r_"
    855       "\xfd\xbe""v\x87\xba""'\x1d\x12\r\xc0\xde""B\xc8""{a\xe7\x07""u\x11\x80"
    856       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tz\xfe\xdb"
    857       "h\t\x08\xc5""dd\x9""ag\xee\xf5\x83\x91""@\xd9\xa4""i*\x80\x00\x00\x00"
    858       "\x00\x00\x00\x00\x00\x00\x00\x00", 120);
    859 
    860   SafeBrowsingProtocolParser parser;
    861   for (size_t i = 0; i < arraysize(safe_browsing_util::kAllLists); ++i) {
    862     std::string listname = safe_browsing_util::kAllLists[i];
    863 
    864     {
    865       ASSERT_EQ(add_testdata.count(listname), 1U)
    866           << "Missing add chunk test case for Safe Browsing list: " << listname;
    867       const std::string& chunk_data = add_testdata[listname];
    868       SBChunkList chunks;
    869       EXPECT_TRUE(parser.ParseChunk(listname,
    870                                     chunk_data.data(),
    871                                     static_cast<int>(chunk_data.length()),
    872                                     &chunks))
    873           << "Unable to parse add chunk data for listname: "
    874           << listname;
    875       ASSERT_EQ(chunks.size(), 1U);
    876       EXPECT_TRUE(chunks[0].is_add);
    877     }
    878     {
    879       ASSERT_EQ(sub_testdata.count(listname), 1U)
    880           << "Missing sub chunk test case for Safe Browsing list: " << listname;
    881       const std::string& chunk_data = sub_testdata[listname];
    882       SBChunkList chunks;
    883       EXPECT_TRUE(parser.ParseChunk(listname,
    884                                     chunk_data.data(),
    885                                     static_cast<int>(chunk_data.length()),
    886                                     &chunks))
    887           << "Unable to parse sub chunk data for listname: "
    888           << listname;
    889       ASSERT_EQ(chunks.size(), 1U);
    890       EXPECT_FALSE(chunks[0].is_add);
    891     }
    892   }
    893 }
    894