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