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.
GenerateRandomBuffer(std::vector<uint8_t> * buffer)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
RunBsdiff()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).
TEST_F(BsdiffTest,EqualEmptyFiles)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
TEST_F(BsdiffTest,EqualSmallFiles)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
TEST_F(BsdiffTest,FileWithSmallErrorsTest)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
TEST_F(BsdiffTest,MinLengthConsideredTest)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