Home | History | Annotate | Download | only in bsdiff
      1 // Copyright 2015 The Chromium OS 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 "bsdiff/bsdiff.h"
      6 
      7 #include <gtest/gtest.h>
      8 #include <algorithm>
      9 #include <random>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "bsdiff/fake_patch_writer.h"
     14 
     15 namespace {
     16 
     17 // Generate deterministic random data in the output buffer. The buffer must be
     18 // already allocated with the desired size. The data generated depends on the
     19 // selected size.
     20 void GenerateRandomBuffer(std::vector<uint8_t>* buffer) {
     21   std::minstd_rand prng(1234 + buffer->size());
     22   std::generate(buffer->begin(), buffer->end(), prng);
     23 }
     24 
     25 }  // namespace
     26 
     27 namespace bsdiff {
     28 
     29 class BsdiffTest : public testing::Test {
     30  protected:
     31   BsdiffTest() = default;
     32   ~BsdiffTest() override = default;
     33 
     34   void RunBsdiff() {
     35     EXPECT_EQ(0, bsdiff(old_file_.data(), old_file_.size(), new_file_.data(),
     36                         new_file_.size(), min_len_, &patch_writer_, nullptr));
     37   }
     38 
     39   std::vector<uint8_t> old_file_;
     40   std::vector<uint8_t> new_file_;
     41   size_t min_len_ = 0;  // 0 means the default.
     42   FakePatchWriter patch_writer_;
     43 };
     44 
     45 // Check that a file with no changes has a very small patch (no extra data).
     46 TEST_F(BsdiffTest, EqualEmptyFiles) {
     47   // Empty old and new files.
     48   RunBsdiff();
     49 
     50   // No entries should be generated on an empty new file.
     51   EXPECT_TRUE(patch_writer_.entries().empty());
     52 }
     53 
     54 TEST_F(BsdiffTest, EqualSmallFiles) {
     55   std::string some_text = "Hello world!";
     56   old_file_.insert(old_file_.begin(), some_text.begin(), some_text.end());
     57   new_file_.insert(new_file_.begin(), some_text.begin(), some_text.end());
     58   RunBsdiff();
     59 
     60   EXPECT_EQ(1U, patch_writer_.entries().size());
     61   ControlEntry entry = patch_writer_.entries()[0];
     62   EXPECT_EQ(some_text.size(), entry.diff_size);
     63   EXPECT_EQ(0U, entry.extra_size);
     64 }
     65 
     66 TEST_F(BsdiffTest, FileWithSmallErrorsTest) {
     67   old_file_.resize(100);
     68   GenerateRandomBuffer(&old_file_);
     69   new_file_ = old_file_;
     70   // Break a few bytes somewhere in the middle.
     71   new_file_[20]++;
     72   new_file_[30] += 2;
     73   new_file_[31] += 2;
     74 
     75   RunBsdiff();
     76 
     77   // We expect that the result has only one entry with all in the diff stream
     78   // since the two files are very similar.
     79   EXPECT_EQ(1U, patch_writer_.entries().size());
     80   ControlEntry entry = patch_writer_.entries()[0];
     81   EXPECT_EQ(100U, entry.diff_size);
     82   EXPECT_EQ(0U, entry.extra_size);
     83 }
     84 
     85 TEST_F(BsdiffTest, MinLengthConsideredTest) {
     86   old_file_.resize(100);
     87   GenerateRandomBuffer(&old_file_);
     88   new_file_ = old_file_;
     89   // Copy the first 10 bytes to the middle.
     90   for (size_t i = 0; i < 10; i++) {
     91     new_file_[50 + i] = old_file_[i];
     92   }
     93 
     94   min_len_ = 12;
     95   RunBsdiff();
     96 
     97   // We expect that the 10 bytes in the middle that match the beginning are
     98   // ignored and just emitted as diff data because the min_len is bigger than
     99   // 10.
    100   EXPECT_EQ(1U, patch_writer_.entries().size());
    101   ControlEntry entry = patch_writer_.entries()[0];
    102   EXPECT_EQ(100U, entry.diff_size);
    103   EXPECT_EQ(0U, entry.extra_size);
    104 }
    105 
    106 }  // namespace bsdiff
    107