Home | History | Annotate | Download | only in safe_browsing
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/safe_browsing/safe_browsing_store.h"
      6 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
      7 
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 namespace {
     11 
     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)));
     18 
     19   // Equal is not less.
     20   EXPECT_FALSE(SBAddPrefixLess(SBAddPrefix(10, 1), SBAddPrefix(10, 1)));
     21 }
     22 
     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));
     32   one.prefix = 1;
     33   one.full_hash[sizeof(int32)] = 1;
     34   onetwo.prefix = 1;
     35   onetwo.full_hash[sizeof(int32)] = 2;
     36   two.prefix = 2;
     37 
     38   const base::Time now = base::Time::Now();
     39 
     40   // add_id dominates.
     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)));
     45 
     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)));
     51 
     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)));
     57 
     58   // Equal is not less-than.
     59   EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(10, now, one),
     60                                    SBAddFullHash(10, now, one)));
     61 }
     62 
     63 TEST(SafeBrowsingStoreTest, SBSubPrefixLess) {
     64   // add_id dominates.
     65   EXPECT_TRUE(SBAddPrefixLess(SBSubPrefix(12, 10, 2), SBSubPrefix(9, 11, 1)));
     66   EXPECT_FALSE(SBAddPrefixLess(SBSubPrefix(12, 11, 2), SBSubPrefix(9, 10, 1)));
     67 
     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)));
     71 
     72   // Equal is not less-than.
     73   EXPECT_FALSE(SBAddPrefixLess(SBSubPrefix(12, 10, 1), SBSubPrefix(12, 10, 1)));
     74 
     75   // chunk_id doesn't matter.
     76 }
     77 
     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));
     83   one.prefix = 1;
     84   one.full_hash[sizeof(int32)] = 1;
     85   onetwo.prefix = 1;
     86   onetwo.full_hash[sizeof(int32)] = 2;
     87   two.prefix = 2;
     88 
     89   // add_id dominates.
     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)));
     94 
     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)));
    100 
    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)));
    106 
    107   // Equal is not less-than.
    108   EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 10, one),
    109                                    SBSubFullHash(9, 10, one)));
    110 }
    111 
    112 // SBProcessSubs does a lot of iteration, run through empty just to
    113 // make sure degenerate cases work.
    114 TEST(SafeBrowsingStoreTest, SBProcessSubsEmpty) {
    115   std::vector<SBAddPrefix> add_prefixes;
    116   std::vector<SBAddFullHash> add_hashes;
    117   std::vector<SBSubPrefix> sub_prefixes;
    118   std::vector<SBSubFullHash> sub_hashes;
    119 
    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());
    127 }
    128 
    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 int kAddChunk1 = 1;  // Use different chunk numbers just in case.
    136   const int kSubChunk1 = 2;
    137 
    138   // Construct some full hashes which share prefix with another.
    139   SBFullHash kHash1mod1 = kHash1;
    140   kHash1mod1.full_hash[sizeof(kHash1mod1.full_hash) - 1] ++;
    141   SBFullHash kHash1mod2 = kHash1mod1;
    142   kHash1mod2.full_hash[sizeof(kHash1mod2.full_hash) - 1] ++;
    143   SBFullHash kHash1mod3 = kHash1mod2;
    144   kHash1mod3.full_hash[sizeof(kHash1mod3.full_hash) - 1] ++;
    145 
    146   std::vector<SBAddPrefix> add_prefixes;
    147   std::vector<SBAddFullHash> add_hashes;
    148   std::vector<SBSubPrefix> sub_prefixes;
    149   std::vector<SBSubFullHash> sub_hashes;
    150 
    151   // An add with prefix and a couple hashes, plus a sub for the prefix
    152   // and a couple sub hashes.  The sub should knock all of them out.
    153   add_prefixes.push_back(SBAddPrefix(kAddChunk1, kHash1.prefix));
    154   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash1));
    155   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash1mod1));
    156   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash1.prefix));
    157   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash1mod2));
    158   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash1mod3));
    159 
    160   // An add with no corresponding sub.  Both items should be retained.
    161   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash2));
    162   add_prefixes.push_back(SBAddPrefix(kAddChunk1, kHash2.prefix));
    163 
    164   // A sub with no corresponding add.  Both items should be retained.
    165   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash3));
    166   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash3.prefix));
    167 
    168   const base::hash_set<int32> no_deletions;
    169   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
    170                 no_deletions, no_deletions);
    171 
    172   EXPECT_EQ(1U, add_prefixes.size());
    173   EXPECT_EQ(kAddChunk1, add_prefixes[0].chunk_id);
    174   EXPECT_EQ(kHash2.prefix, add_prefixes[0].prefix);
    175 
    176   EXPECT_EQ(1U, add_hashes.size());
    177   EXPECT_EQ(kAddChunk1, add_hashes[0].chunk_id);
    178   EXPECT_TRUE(SBFullHashEq(kHash2, add_hashes[0].full_hash));
    179 
    180   EXPECT_EQ(1U, sub_prefixes.size());
    181   EXPECT_EQ(kSubChunk1, sub_prefixes[0].chunk_id);
    182   EXPECT_EQ(kAddChunk1, sub_prefixes[0].add_chunk_id);
    183   EXPECT_EQ(kHash3.prefix, sub_prefixes[0].add_prefix);
    184 
    185   EXPECT_EQ(1U, sub_hashes.size());
    186   EXPECT_EQ(kSubChunk1, sub_hashes[0].chunk_id);
    187   EXPECT_EQ(kAddChunk1, sub_hashes[0].add_chunk_id);
    188   EXPECT_TRUE(SBFullHashEq(kHash3, sub_hashes[0].full_hash));
    189 }
    190 
    191 // Test chunk deletions, and ordering of deletions WRT subs knocking
    192 // out adds.
    193 TEST(SafeBrowsingStoreTest, SBProcessSubsDeleteChunk) {
    194   const base::Time kNow = base::Time::Now();
    195   const SBFullHash kHash1(SBFullHashFromString("one"));
    196   const SBFullHash kHash2(SBFullHashFromString("two"));
    197   const SBFullHash kHash3(SBFullHashFromString("three"));
    198   const int kAddChunk1 = 1;  // Use different chunk numbers just in case.
    199   const int kSubChunk1 = 2;
    200 
    201   // Construct some full hashes which share prefix with another.
    202   SBFullHash kHash1mod1 = kHash1;
    203   kHash1mod1.full_hash[sizeof(kHash1mod1.full_hash) - 1] ++;
    204   SBFullHash kHash1mod2 = kHash1mod1;
    205   kHash1mod2.full_hash[sizeof(kHash1mod2.full_hash) - 1] ++;
    206   SBFullHash kHash1mod3 = kHash1mod2;
    207   kHash1mod3.full_hash[sizeof(kHash1mod3.full_hash) - 1] ++;
    208 
    209   std::vector<SBAddPrefix> add_prefixes;
    210   std::vector<SBAddFullHash> add_hashes;
    211   std::vector<SBSubPrefix> sub_prefixes;
    212   std::vector<SBSubFullHash> sub_hashes;
    213 
    214   // An add with prefix and a couple hashes, plus a sub for the prefix
    215   // and a couple sub hashes.  The sub should knock all of them out.
    216   add_prefixes.push_back(SBAddPrefix(kAddChunk1, kHash1.prefix));
    217   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash1));
    218   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash1mod1));
    219   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash1.prefix));
    220   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash1mod2));
    221   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash1mod3));
    222 
    223   // An add with no corresponding sub.  Both items should be retained.
    224   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash2));
    225   add_prefixes.push_back(SBAddPrefix(kAddChunk1, kHash2.prefix));
    226 
    227   // A sub with no corresponding add.  Both items should be retained.
    228   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash3));
    229   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash3.prefix));
    230 
    231   const base::hash_set<int32> no_deletions;
    232   base::hash_set<int32> add_deletions;
    233   add_deletions.insert(kAddChunk1);
    234   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
    235                 add_deletions, no_deletions);
    236 
    237   EXPECT_TRUE(add_prefixes.empty());
    238   EXPECT_TRUE(add_hashes.empty());
    239 
    240   EXPECT_EQ(1U, sub_prefixes.size());
    241   EXPECT_EQ(kSubChunk1, sub_prefixes[0].chunk_id);
    242   EXPECT_EQ(kAddChunk1, sub_prefixes[0].add_chunk_id);
    243   EXPECT_EQ(kHash3.prefix, sub_prefixes[0].add_prefix);
    244 
    245   EXPECT_EQ(1U, sub_hashes.size());
    246   EXPECT_EQ(kSubChunk1, sub_hashes[0].chunk_id);
    247   EXPECT_EQ(kAddChunk1, sub_hashes[0].add_chunk_id);
    248   EXPECT_TRUE(SBFullHashEq(kHash3, sub_hashes[0].full_hash));
    249 
    250   base::hash_set<int32> sub_deletions;
    251   sub_deletions.insert(kSubChunk1);
    252   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
    253                 no_deletions, sub_deletions);
    254 
    255   EXPECT_TRUE(add_prefixes.empty());
    256   EXPECT_TRUE(add_hashes.empty());
    257   EXPECT_TRUE(sub_prefixes.empty());
    258   EXPECT_TRUE(sub_hashes.empty());
    259 }
    260 
    261 TEST(SafeBrowsingStoreTest, Y2K38) {
    262   const base::Time now = base::Time::Now();
    263   const base::Time future = now + base::TimeDelta::FromDays(3*365);
    264 
    265   // TODO: Fix file format before 2035.
    266   EXPECT_GT(static_cast<int32>(future.ToTimeT()), 0)
    267     << " (int32)time_t is running out.";
    268 }
    269 
    270 }  // namespace
    271