|  | // Copyright 2015 The Chromium OS Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "bsdiff/bsdiff.h" | 
|  |  | 
|  | #include <gtest/gtest.h> | 
|  | #include <algorithm> | 
|  | #include <random> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "bsdiff/fake_patch_writer.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Generate deterministic random data in the output buffer. The buffer must be | 
|  | // already allocated with the desired size. The data generated depends on the | 
|  | // selected size. | 
|  | void GenerateRandomBuffer(std::vector<uint8_t>* buffer) { | 
|  | std::minstd_rand prng(1234 + buffer->size()); | 
|  | std::generate(buffer->begin(), buffer->end(), prng); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | namespace bsdiff { | 
|  |  | 
|  | class BsdiffTest : public testing::Test { | 
|  | protected: | 
|  | BsdiffTest() = default; | 
|  | ~BsdiffTest() override = default; | 
|  |  | 
|  | void RunBsdiff() { | 
|  | EXPECT_EQ(0, bsdiff(old_file_.data(), old_file_.size(), new_file_.data(), | 
|  | new_file_.size(), min_len_, &patch_writer_, nullptr)); | 
|  | } | 
|  |  | 
|  | std::vector<uint8_t> old_file_; | 
|  | std::vector<uint8_t> new_file_; | 
|  | size_t min_len_ = 0;  // 0 means the default. | 
|  | FakePatchWriter patch_writer_; | 
|  | }; | 
|  |  | 
|  | // Check that a file with no changes has a very small patch (no extra data). | 
|  | TEST_F(BsdiffTest, EqualEmptyFiles) { | 
|  | // Empty old and new files. | 
|  | RunBsdiff(); | 
|  |  | 
|  | // No entries should be generated on an empty new file. | 
|  | EXPECT_TRUE(patch_writer_.entries().empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(BsdiffTest, EqualSmallFiles) { | 
|  | std::string some_text = "Hello world!"; | 
|  | old_file_.insert(old_file_.begin(), some_text.begin(), some_text.end()); | 
|  | new_file_.insert(new_file_.begin(), some_text.begin(), some_text.end()); | 
|  | RunBsdiff(); | 
|  |  | 
|  | EXPECT_EQ(1U, patch_writer_.entries().size()); | 
|  | ControlEntry entry = patch_writer_.entries()[0]; | 
|  | EXPECT_EQ(some_text.size(), entry.diff_size); | 
|  | EXPECT_EQ(0U, entry.extra_size); | 
|  | } | 
|  |  | 
|  | TEST_F(BsdiffTest, FileWithSmallErrorsTest) { | 
|  | old_file_.resize(100); | 
|  | GenerateRandomBuffer(&old_file_); | 
|  | new_file_ = old_file_; | 
|  | // Break a few bytes somewhere in the middle. | 
|  | new_file_[20]++; | 
|  | new_file_[30] += 2; | 
|  | new_file_[31] += 2; | 
|  |  | 
|  | RunBsdiff(); | 
|  |  | 
|  | // We expect that the result has only one entry with all in the diff stream | 
|  | // since the two files are very similar. | 
|  | EXPECT_EQ(1U, patch_writer_.entries().size()); | 
|  | ControlEntry entry = patch_writer_.entries()[0]; | 
|  | EXPECT_EQ(100U, entry.diff_size); | 
|  | EXPECT_EQ(0U, entry.extra_size); | 
|  | } | 
|  |  | 
|  | TEST_F(BsdiffTest, MinLengthConsideredTest) { | 
|  | old_file_.resize(100); | 
|  | GenerateRandomBuffer(&old_file_); | 
|  | new_file_ = old_file_; | 
|  | // Copy the first 10 bytes to the middle. | 
|  | for (size_t i = 0; i < 10; i++) { | 
|  | new_file_[50 + i] = old_file_[i]; | 
|  | } | 
|  |  | 
|  | min_len_ = 12; | 
|  | RunBsdiff(); | 
|  |  | 
|  | // We expect that the 10 bytes in the middle that match the beginning are | 
|  | // ignored and just emitted as diff data because the min_len is bigger than | 
|  | // 10. | 
|  | EXPECT_EQ(1U, patch_writer_.entries().size()); | 
|  | ControlEntry entry = patch_writer_.entries()[0]; | 
|  | EXPECT_EQ(100U, entry.diff_size); | 
|  | EXPECT_EQ(0U, entry.extra_size); | 
|  | } | 
|  |  | 
|  | }  // namespace bsdiff |