Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / prefix_set_unittest.cc
index 27b9ff5..e537ad9 100644 (file)
 #include "base/logging.h"
 #include "base/md5.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
 #include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "chrome/common/chrome_paths.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -22,6 +26,10 @@ namespace {
 const SBPrefix kHighBitClear = 1000u * 1000u * 1000u;
 const SBPrefix kHighBitSet = 3u * 1000u * 1000u * 1000u;
 
+}  // namespace
+
+namespace safe_browsing {
+
 class PrefixSetTest : public PlatformTest {
  protected:
   // Constants for the v1 format.
@@ -29,7 +37,8 @@ class PrefixSetTest : public PlatformTest {
   static const size_t kVersionOffset = 1 * sizeof(uint32);
   static const size_t kIndexSizeOffset = 2 * sizeof(uint32);
   static const size_t kDeltasSizeOffset = 3 * sizeof(uint32);
-  static const size_t kPayloadOffset = 4 * sizeof(uint32);
+  static const size_t kFullHashesSizeOffset = 4 * sizeof(uint32);
+  static const size_t kPayloadOffset = 5 * sizeof(uint32);
 
   // Generate a set of random prefixes to share between tests.  For
   // most tests this generation was a large fraction of the test time.
@@ -63,7 +72,7 @@ class PrefixSetTest : public PlatformTest {
   // Check that all elements of |prefixes| are in |prefix_set|, and
   // that nearby elements are not (for lack of a more sensible set of
   // items to check for absence).
-  static void CheckPrefixes(const safe_browsing::PrefixSet& prefix_set,
+  static void CheckPrefixes(const PrefixSet& prefix_set,
                             const std::vector<SBPrefix> &prefixes) {
     // The set can generate the prefixes it believes it has, so that's
     // a good starting point.
@@ -74,15 +83,15 @@ class PrefixSetTest : public PlatformTest {
     EXPECT_TRUE(std::equal(check.begin(), check.end(), prefixes_copy.begin()));
 
     for (size_t i = 0; i < prefixes.size(); ++i) {
-      EXPECT_TRUE(prefix_set.Exists(prefixes[i]));
+      EXPECT_TRUE(prefix_set.PrefixExists(prefixes[i]));
 
       const SBPrefix left_sibling = prefixes[i] - 1;
       if (check.count(left_sibling) == 0)
-        EXPECT_FALSE(prefix_set.Exists(left_sibling));
+        EXPECT_FALSE(prefix_set.PrefixExists(left_sibling));
 
       const SBPrefix right_sibling = prefixes[i] + 1;
       if (check.count(right_sibling) == 0)
-        EXPECT_FALSE(prefix_set.Exists(right_sibling));
+        EXPECT_FALSE(prefix_set.PrefixExists(right_sibling));
     }
   }
 
@@ -95,8 +104,8 @@ class PrefixSetTest : public PlatformTest {
 
     base::FilePath filename = temp_dir_.path().AppendASCII("PrefixSetTest");
 
-    safe_browsing::PrefixSetBuilder builder(shared_prefixes_);
-    if (!builder.GetPrefixSet()->WriteFile(filename))
+    PrefixSetBuilder builder(shared_prefixes_);
+    if (!builder.GetPrefixSetNoHashes()->WriteFile(filename))
       return false;
 
     *filenamep = filename;
@@ -165,6 +174,33 @@ class PrefixSetTest : public PlatformTest {
     ASSERT_EQ(new_size_64, size_64);
   }
 
+  // Fill |prefixes| with values read from a reference file.  The reference file
+  // was generated from a specific |shared_prefixes_|.
+  bool ReadReferencePrefixes(std::vector<SBPrefix>* prefixes) {
+    const char kRefname[] = "PrefixSetRef";
+    base::FilePath ref_path;
+    if (!PathService::Get(chrome::DIR_TEST_DATA, &ref_path))
+      return false;
+    ref_path = ref_path.AppendASCII("SafeBrowsing");
+    ref_path = ref_path.AppendASCII(kRefname);
+
+    base::ScopedFILE file(base::OpenFile(ref_path, "r"));
+    if (!file.get())
+      return false;
+    char buf[1024];
+    while (fgets(buf, sizeof(buf), file.get())) {
+      std::string trimmed;
+      if (base::TRIM_TRAILING !=
+          base::TrimWhitespace(buf, base::TRIM_ALL, &trimmed))
+        return false;
+      unsigned prefix;
+      if (!base::StringToUint(trimmed, &prefix))
+        return false;
+      prefixes->push_back(prefix);
+    }
+    return true;
+  }
+
   // Tests should not modify this shared resource.
   static std::vector<SBPrefix> shared_prefixes_;
 
@@ -175,28 +211,28 @@ std::vector<SBPrefix> PrefixSetTest::shared_prefixes_;
 
 // Test that a small sparse random input works.
 TEST_F(PrefixSetTest, Baseline) {
-  safe_browsing::PrefixSetBuilder builder(shared_prefixes_);
-  CheckPrefixes(*builder.GetPrefixSet(), shared_prefixes_);
+  PrefixSetBuilder builder(shared_prefixes_);
+  CheckPrefixes(*builder.GetPrefixSetNoHashes(), shared_prefixes_);
 }
 
 // Test that the empty set doesn't appear to have anything in it.
 TEST_F(PrefixSetTest, Empty) {
   const std::vector<SBPrefix> empty;
-  safe_browsing::PrefixSetBuilder builder(empty);
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set = builder.GetPrefixSet();
+  PrefixSetBuilder builder(empty);
+  scoped_ptr<PrefixSet> prefix_set = builder.GetPrefixSetNoHashes();
   for (size_t i = 0; i < shared_prefixes_.size(); ++i) {
-    EXPECT_FALSE(prefix_set->Exists(shared_prefixes_[i]));
+    EXPECT_FALSE(prefix_set->PrefixExists(shared_prefixes_[i]));
   }
 }
 
 // Single-element set should work fine.
 TEST_F(PrefixSetTest, OneElement) {
   const std::vector<SBPrefix> prefixes(100, 0u);
-  safe_browsing::PrefixSetBuilder builder(prefixes);
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set = builder.GetPrefixSet();
-  EXPECT_FALSE(prefix_set->Exists(static_cast<SBPrefix>(-1)));
-  EXPECT_TRUE(prefix_set->Exists(prefixes[0]));
-  EXPECT_FALSE(prefix_set->Exists(1u));
+  PrefixSetBuilder builder(prefixes);
+  scoped_ptr<PrefixSet> prefix_set = builder.GetPrefixSetNoHashes();
+  EXPECT_FALSE(prefix_set->PrefixExists(static_cast<SBPrefix>(-1)));
+  EXPECT_TRUE(prefix_set->PrefixExists(prefixes[0]));
+  EXPECT_FALSE(prefix_set->PrefixExists(1u));
 
   // Check that |GetPrefixes()| returns the same set of prefixes as
   // was passed in.
@@ -222,8 +258,8 @@ TEST_F(PrefixSetTest, IntMinMax) {
   prefixes.push_back(0xFFFFFFFF);
 
   std::sort(prefixes.begin(), prefixes.end());
-  safe_browsing::PrefixSetBuilder builder(prefixes);
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set = builder.GetPrefixSet();
+  PrefixSetBuilder builder(prefixes);
+  scoped_ptr<PrefixSet> prefix_set = builder.GetPrefixSetNoHashes();
 
   // Check that |GetPrefixes()| returns the same set of prefixes as
   // was passed in.
@@ -245,8 +281,8 @@ TEST_F(PrefixSetTest, AllBig) {
   }
 
   std::sort(prefixes.begin(), prefixes.end());
-  safe_browsing::PrefixSetBuilder builder(prefixes);
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set = builder.GetPrefixSet();
+  PrefixSetBuilder builder(prefixes);
+  scoped_ptr<PrefixSet> prefix_set = builder.GetPrefixSetNoHashes();
 
   // Check that |GetPrefixes()| returns the same set of prefixes as
   // was passed in.
@@ -258,12 +294,11 @@ TEST_F(PrefixSetTest, AllBig) {
                          prefixes_copy.begin()));
 }
 
-// Use artificial inputs to test various edge cases in Exists().
-// Items before the lowest item aren't present.  Items after the
-// largest item aren't present.  Create a sequence of items with
-// deltas above and below 2^16, and make sure they're all present.
-// Create a very long sequence with deltas below 2^16 to test crossing
-// |kMaxRun|.
+// Use artificial inputs to test various edge cases in PrefixExists().  Items
+// before the lowest item aren't present.  Items after the largest item aren't
+// present.  Create a sequence of items with deltas above and below 2^16, and
+// make sure they're all present.  Create a very long sequence with deltas below
+// 2^16 to test crossing |kMaxRun|.
 TEST_F(PrefixSetTest, EdgeCases) {
   std::vector<SBPrefix> prefixes;
 
@@ -300,8 +335,8 @@ TEST_F(PrefixSetTest, EdgeCases) {
   }
 
   std::sort(prefixes.begin(), prefixes.end());
-  safe_browsing::PrefixSetBuilder builder(prefixes);
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set = builder.GetPrefixSet();
+  PrefixSetBuilder builder(prefixes);
+  scoped_ptr<PrefixSet> prefix_set = builder.GetPrefixSetNoHashes();
 
   // Check that |GetPrefixes()| returns the same set of prefixes as
   // was passed in.
@@ -313,17 +348,17 @@ TEST_F(PrefixSetTest, EdgeCases) {
                          prefixes_copy.begin()));
 
   // Items before and after the set are not present, and don't crash.
-  EXPECT_FALSE(prefix_set->Exists(kHighBitSet - 100));
-  EXPECT_FALSE(prefix_set->Exists(kHighBitClear + 100));
+  EXPECT_FALSE(prefix_set->PrefixExists(kHighBitSet - 100));
+  EXPECT_FALSE(prefix_set->PrefixExists(kHighBitClear + 100));
 
   // Check that the set correctly flags all of the inputs, and also
   // check items just above and below the inputs to make sure they
   // aren't present.
   for (size_t i = 0; i < prefixes.size(); ++i) {
-    EXPECT_TRUE(prefix_set->Exists(prefixes[i]));
+    EXPECT_TRUE(prefix_set->PrefixExists(prefixes[i]));
 
-    EXPECT_FALSE(prefix_set->Exists(prefixes[i] - 1));
-    EXPECT_FALSE(prefix_set->Exists(prefixes[i] + 1));
+    EXPECT_FALSE(prefix_set->PrefixExists(prefixes[i] - 1));
+    EXPECT_FALSE(prefix_set->PrefixExists(prefixes[i] + 1));
   }
 }
 
@@ -335,8 +370,7 @@ TEST_F(PrefixSetTest, ReadWrite) {
   // the prefixes.  Leaves the path in |filename|.
   {
     ASSERT_TRUE(GetPrefixSetFile(&filename));
-    scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-        safe_browsing::PrefixSet::LoadFile(filename);
+    scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
     ASSERT_TRUE(prefix_set.get());
     CheckPrefixes(*prefix_set, shared_prefixes_);
   }
@@ -347,11 +381,10 @@ TEST_F(PrefixSetTest, ReadWrite) {
     prefixes.push_back(kHighBitClear);
     prefixes.push_back(kHighBitSet);
 
-    safe_browsing::PrefixSetBuilder builder(prefixes);
-    ASSERT_TRUE(builder.GetPrefixSet()->WriteFile(filename));
+    PrefixSetBuilder builder(prefixes);
+    ASSERT_TRUE(builder.GetPrefixSetNoHashes()->WriteFile(filename));
 
-    scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-        safe_browsing::PrefixSet::LoadFile(filename);
+    scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
     ASSERT_TRUE(prefix_set.get());
     CheckPrefixes(*prefix_set, prefixes);
   }
@@ -359,14 +392,45 @@ TEST_F(PrefixSetTest, ReadWrite) {
   // Test writing and reading an empty set.
   {
     std::vector<SBPrefix> prefixes;
-    safe_browsing::PrefixSetBuilder builder(prefixes);
-    ASSERT_TRUE(builder.GetPrefixSet()->WriteFile(filename));
+    PrefixSetBuilder builder(prefixes);
+    ASSERT_TRUE(builder.GetPrefixSetNoHashes()->WriteFile(filename));
 
-    scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-        safe_browsing::PrefixSet::LoadFile(filename);
+    scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
     ASSERT_TRUE(prefix_set.get());
     CheckPrefixes(*prefix_set, prefixes);
   }
+
+  // Test that full hashes are persisted.
+  {
+    std::vector<SBFullHash> hashes;
+    hashes.push_back(SBFullHashForString("one"));
+    hashes.push_back(SBFullHashForString("two"));
+    hashes.push_back(SBFullHashForString("three"));
+
+    std::vector<SBPrefix> prefixes(shared_prefixes_);
+
+    // Remove any collisions from the prefixes.
+    for (size_t i = 0; i < hashes.size(); ++i) {
+      std::vector<SBPrefix>::iterator iter =
+          std::lower_bound(prefixes.begin(), prefixes.end(), hashes[i].prefix);
+      if (iter != prefixes.end() && *iter == hashes[i].prefix)
+        prefixes.erase(iter);
+    }
+
+    PrefixSetBuilder builder(prefixes);
+    ASSERT_TRUE(builder.GetPrefixSet(hashes)->WriteFile(filename));
+
+    scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
+    ASSERT_TRUE(prefix_set.get());
+    CheckPrefixes(*prefix_set, prefixes);
+
+    EXPECT_TRUE(prefix_set->Exists(hashes[0]));
+    EXPECT_TRUE(prefix_set->Exists(hashes[1]));
+    EXPECT_TRUE(prefix_set->Exists(hashes[2]));
+    EXPECT_FALSE(prefix_set->PrefixExists(hashes[0].prefix));
+    EXPECT_FALSE(prefix_set->PrefixExists(hashes[1].prefix));
+    EXPECT_FALSE(prefix_set->PrefixExists(hashes[2].prefix));
+  }
 }
 
 // Check that |CleanChecksum()| makes an acceptable checksum.
@@ -378,8 +442,7 @@ TEST_F(PrefixSetTest, CorruptionHelpers) {
   base::ScopedFILE file(base::OpenFile(filename, "r+b"));
   IncrementIntAt(file.get(), kPayloadOffset, 1);
   file.reset();
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 
   // Fix up the checksum and it will read successfully (though the
@@ -387,31 +450,29 @@ TEST_F(PrefixSetTest, CorruptionHelpers) {
   file.reset(base::OpenFile(filename, "r+b"));
   CleanChecksum(file.get());
   file.reset();
-  prefix_set = safe_browsing::PrefixSet::LoadFile(filename);
+  prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_TRUE(prefix_set.get());
 }
 
-// Bad |index_| size is caught by the sanity check.
+// Bad magic is caught by the sanity check.
 TEST_F(PrefixSetTest, CorruptionMagic) {
   base::FilePath filename;
   ASSERT_TRUE(GetPrefixSetFile(&filename));
 
   ASSERT_NO_FATAL_FAILURE(
       ModifyAndCleanChecksum(filename, kMagicOffset, 1));
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 }
 
-// Bad |index_| size is caught by the sanity check.
+// Bad version is caught by the sanity check.
 TEST_F(PrefixSetTest, CorruptionVersion) {
   base::FilePath filename;
   ASSERT_TRUE(GetPrefixSetFile(&filename));
 
   ASSERT_NO_FATAL_FAILURE(
-      ModifyAndCleanChecksum(filename, kVersionOffset, 1));
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+      ModifyAndCleanChecksum(filename, kVersionOffset, 10));
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 }
 
@@ -422,8 +483,7 @@ TEST_F(PrefixSetTest, CorruptionIndexSize) {
 
   ASSERT_NO_FATAL_FAILURE(
       ModifyAndCleanChecksum(filename, kIndexSizeOffset, 1));
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 }
 
@@ -434,8 +494,18 @@ TEST_F(PrefixSetTest, CorruptionDeltasSize) {
 
   ASSERT_NO_FATAL_FAILURE(
       ModifyAndCleanChecksum(filename, kDeltasSizeOffset, 1));
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
+  ASSERT_FALSE(prefix_set.get());
+}
+
+// Bad |full_hashes_| size is caught by the sanity check.
+TEST_F(PrefixSetTest, CorruptionFullHashesSize) {
+  base::FilePath filename;
+  ASSERT_TRUE(GetPrefixSetFile(&filename));
+
+  ASSERT_NO_FATAL_FAILURE(
+      ModifyAndCleanChecksum(filename, kFullHashesSizeOffset, 1));
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 }
 
@@ -448,8 +518,7 @@ TEST_F(PrefixSetTest, CorruptionPayload) {
   base::ScopedFILE file(base::OpenFile(filename, "r+b"));
   ASSERT_NO_FATAL_FAILURE(IncrementIntAt(file.get(), 666, 1));
   file.reset();
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 }
 
@@ -464,8 +533,7 @@ TEST_F(PrefixSetTest, CorruptionDigest) {
   long digest_offset = static_cast<long>(size_64 - sizeof(base::MD5Digest));
   ASSERT_NO_FATAL_FAILURE(IncrementIntAt(file.get(), digest_offset, 1));
   file.reset();
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 }
 
@@ -479,8 +547,7 @@ TEST_F(PrefixSetTest, CorruptionExcess) {
   const char buf[] = "im in ur base, killing ur d00dz.";
   ASSERT_EQ(strlen(buf), fwrite(buf, 1, strlen(buf), file.get()));
   file.reset();
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 }
 
@@ -522,11 +589,46 @@ TEST_F(PrefixSetTest, SizeTRecovery) {
   CleanChecksum(file.get());
   file.reset();  // Flush updates.
 
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_FALSE(prefix_set.get());
 }
 
+// Test Exists() against full hashes passed to builder.
+TEST_F(PrefixSetTest, FullHashBuild) {
+  const SBFullHash kHash1 = SBFullHashForString("one");
+  const SBFullHash kHash2 = SBFullHashForString("two");
+  const SBFullHash kHash3 = SBFullHashForString("three");
+  const SBFullHash kHash4 = SBFullHashForString("four");
+  const SBFullHash kHash5 = SBFullHashForString("five");
+  const SBFullHash kHash6 = SBFullHashForString("six");
+
+  std::vector<SBPrefix> prefixes;
+  prefixes.push_back(kHash1.prefix);
+  prefixes.push_back(kHash2.prefix);
+  std::sort(prefixes.begin(), prefixes.end());
+
+  std::vector<SBFullHash> hashes;
+  hashes.push_back(kHash4);
+  hashes.push_back(kHash5);
+
+  PrefixSetBuilder builder(prefixes);
+  scoped_ptr<PrefixSet> prefix_set = builder.GetPrefixSet(hashes);
+
+  EXPECT_TRUE(prefix_set->Exists(kHash1));
+  EXPECT_TRUE(prefix_set->Exists(kHash2));
+  EXPECT_FALSE(prefix_set->Exists(kHash3));
+  EXPECT_TRUE(prefix_set->Exists(kHash4));
+  EXPECT_TRUE(prefix_set->Exists(kHash5));
+  EXPECT_FALSE(prefix_set->Exists(kHash6));
+
+  EXPECT_TRUE(prefix_set->PrefixExists(kHash1.prefix));
+  EXPECT_TRUE(prefix_set->PrefixExists(kHash2.prefix));
+  EXPECT_FALSE(prefix_set->PrefixExists(kHash3.prefix));
+  EXPECT_FALSE(prefix_set->PrefixExists(kHash4.prefix));
+  EXPECT_FALSE(prefix_set->PrefixExists(kHash5.prefix));
+  EXPECT_FALSE(prefix_set->PrefixExists(kHash6.prefix));
+}
+
 // Test that a version 1 file is re-ordered correctly on read.
 TEST_F(PrefixSetTest, ReadWriteSigned) {
   base::FilePath filename;
@@ -568,18 +670,17 @@ TEST_F(PrefixSetTest, ReadWriteSigned) {
   CleanChecksum(file.get());
   file.reset();  // Flush updates.
 
-  scoped_ptr<safe_browsing::PrefixSet> prefix_set =
-      safe_browsing::PrefixSet::LoadFile(filename);
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename);
   ASSERT_TRUE(prefix_set.get());
 
-  // |Exists()| uses |std::upper_bound()| to find a starting point, which
+  // |PrefixExists()| uses |std::upper_bound()| to find a starting point, which
   // assumes |index_| is sorted.  Depending on how |upper_bound()| is
   // implemented, if the actual list is sorted by |int32|, then one of these
   // test pairs should fail.
-  EXPECT_TRUE(prefix_set->Exists(1000u));
-  EXPECT_TRUE(prefix_set->Exists(1023u));
-  EXPECT_TRUE(prefix_set->Exists(static_cast<uint32>(-1000)));
-  EXPECT_TRUE(prefix_set->Exists(static_cast<uint32>(-1000 + 23)));
+  EXPECT_TRUE(prefix_set->PrefixExists(1000u));
+  EXPECT_TRUE(prefix_set->PrefixExists(1023u));
+  EXPECT_TRUE(prefix_set->PrefixExists(static_cast<uint32>(-1000)));
+  EXPECT_TRUE(prefix_set->PrefixExists(static_cast<uint32>(-1000 + 23)));
 
   std::vector<SBPrefix> prefixes_copy;
   prefix_set->GetPrefixes(&prefixes_copy);
@@ -590,4 +691,52 @@ TEST_F(PrefixSetTest, ReadWriteSigned) {
   EXPECT_EQ(prefixes_copy[3], static_cast<uint32>(-1000 + 23));
 }
 
-}  // namespace
+// Test that a golden v2 file can be read by the current code.  All platforms
+// generating v2 files are little-endian, so there is no point to testing this
+// transition if/when a big-endian port is added.
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+TEST_F(PrefixSetTest, Version2) {
+  std::vector<SBPrefix> ref_prefixes;
+  ASSERT_TRUE(ReadReferencePrefixes(&ref_prefixes));
+
+  const char kBasename[] = "PrefixSetVersion2";
+  base::FilePath golden_path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &golden_path));
+  golden_path = golden_path.AppendASCII("SafeBrowsing");
+  golden_path = golden_path.AppendASCII(kBasename);
+
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(golden_path);
+  ASSERT_TRUE(prefix_set.get());
+  CheckPrefixes(*prefix_set, ref_prefixes);
+}
+#endif
+
+// Test that a golden v3 file can be read by the current code.  All platforms
+// generating v3 files are little-endian, so there is no point to testing this
+// transition if/when a big-endian port is added.
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+TEST_F(PrefixSetTest, Version3) {
+  std::vector<SBPrefix> ref_prefixes;
+  ASSERT_TRUE(ReadReferencePrefixes(&ref_prefixes));
+
+  const char kBasename[] = "PrefixSetVersion3";
+  base::FilePath golden_path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &golden_path));
+  golden_path = golden_path.AppendASCII("SafeBrowsing");
+  golden_path = golden_path.AppendASCII(kBasename);
+
+  scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(golden_path);
+  ASSERT_TRUE(prefix_set.get());
+  CheckPrefixes(*prefix_set, ref_prefixes);
+
+  const SBFullHash kHash1 = SBFullHashForString("www.evil.com/malware.html");
+  const SBFullHash kHash2 = SBFullHashForString("www.evil.com/phishing.html");
+
+  EXPECT_TRUE(prefix_set->Exists(kHash1));
+  EXPECT_TRUE(prefix_set->Exists(kHash2));
+  EXPECT_FALSE(prefix_set->PrefixExists(kHash1.prefix));
+  EXPECT_FALSE(prefix_set->PrefixExists(kHash2.prefix));
+}
+#endif
+
+}  // namespace safe_browsing