1*a3a45f30SXin Li // Copyright 2017 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/split_patch_writer.h"
6*a3a45f30SXin Li
7*a3a45f30SXin Li #include <memory>
8*a3a45f30SXin Li #include <vector>
9*a3a45f30SXin Li
10*a3a45f30SXin Li #include <gtest/gtest.h>
11*a3a45f30SXin Li
12*a3a45f30SXin Li #include "bsdiff/fake_patch_writer.h"
13*a3a45f30SXin Li #include "bsdiff/test_utils.h"
14*a3a45f30SXin Li
15*a3a45f30SXin Li namespace bsdiff {
16*a3a45f30SXin Li
17*a3a45f30SXin Li class SplitPatchWriterTest : public testing::Test {
18*a3a45f30SXin Li protected:
SetUpForSize(size_t num_chunks,uint64_t new_chunk_size,size_t new_size)19*a3a45f30SXin Li void SetUpForSize(size_t num_chunks,
20*a3a45f30SXin Li uint64_t new_chunk_size,
21*a3a45f30SXin Li size_t new_size) {
22*a3a45f30SXin Li fake_patches_.resize(num_chunks);
23*a3a45f30SXin Li std::vector<PatchWriterInterface*> patches;
24*a3a45f30SXin Li for (auto& fake_patch : fake_patches_)
25*a3a45f30SXin Li patches.push_back(&fake_patch);
26*a3a45f30SXin Li
27*a3a45f30SXin Li patch_writer_.reset(new SplitPatchWriter(new_chunk_size, patches));
28*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->Init(new_size));
29*a3a45f30SXin Li }
30*a3a45f30SXin Li
31*a3a45f30SXin Li std::vector<FakePatchWriter> fake_patches_;
32*a3a45f30SXin Li std::unique_ptr<SplitPatchWriter> patch_writer_;
33*a3a45f30SXin Li };
34*a3a45f30SXin Li
TEST_F(SplitPatchWriterTest,InvalidNumberOfPatchesForSizeTest)35*a3a45f30SXin Li TEST_F(SplitPatchWriterTest, InvalidNumberOfPatchesForSizeTest) {
36*a3a45f30SXin Li FakePatchWriter p;
37*a3a45f30SXin Li std::vector<PatchWriterInterface*> patches = {&p};
38*a3a45f30SXin Li patch_writer_.reset(new SplitPatchWriter(10, patches));
39*a3a45f30SXin Li // We should have pass two patches.
40*a3a45f30SXin Li EXPECT_FALSE(patch_writer_->Init(15));
41*a3a45f30SXin Li }
42*a3a45f30SXin Li
43*a3a45f30SXin Li // A single empty patch is allowed.
TEST_F(SplitPatchWriterTest,NonSplitEmptyPatchTest)44*a3a45f30SXin Li TEST_F(SplitPatchWriterTest, NonSplitEmptyPatchTest) {
45*a3a45f30SXin Li SetUpForSize(1, 100, 0);
46*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->Close());
47*a3a45f30SXin Li
48*a3a45f30SXin Li EXPECT_TRUE(fake_patches_[0].entries().empty());
49*a3a45f30SXin Li }
50*a3a45f30SXin Li
51*a3a45f30SXin Li // Leaving patches at the end that are empty is considered an error.
TEST_F(SplitPatchWriterTest,NotAllPatchesWrittenErrorTest)52*a3a45f30SXin Li TEST_F(SplitPatchWriterTest, NotAllPatchesWrittenErrorTest) {
53*a3a45f30SXin Li SetUpForSize(2, 100, 200);
54*a3a45f30SXin Li // We write less than the amount needed for two patches, which should fail.
55*a3a45f30SXin Li EXPECT_FALSE(patch_writer_->Close());
56*a3a45f30SXin Li }
57*a3a45f30SXin Li
TEST_F(SplitPatchWriterTest,MissingDiffBytesErrorTest)58*a3a45f30SXin Li TEST_F(SplitPatchWriterTest, MissingDiffBytesErrorTest) {
59*a3a45f30SXin Li SetUpForSize(2, 10, 20);
60*a3a45f30SXin Li
61*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(15, 5, 0)));
62*a3a45f30SXin Li std::vector<uint8_t> zeros(20, 0);
63*a3a45f30SXin Li // We write 12 diff bytes instead of the expected 15. This should fail on
64*a3a45f30SXin Li // Close().
65*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->WriteDiffStream(zeros.data(), 12));
66*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->WriteExtraStream(zeros.data(), 5));
67*a3a45f30SXin Li EXPECT_FALSE(patch_writer_->Close());
68*a3a45f30SXin Li }
69*a3a45f30SXin Li
TEST_F(SplitPatchWriterTest,MissingExtraBytesErrorTest)70*a3a45f30SXin Li TEST_F(SplitPatchWriterTest, MissingExtraBytesErrorTest) {
71*a3a45f30SXin Li SetUpForSize(2, 10, 20);
72*a3a45f30SXin Li
73*a3a45f30SXin Li std::vector<uint8_t> zeros(20, 0);
74*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(5, 15, -5)));
75*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->WriteDiffStream(zeros.data(), 5));
76*a3a45f30SXin Li // We write a little less than the expected 15. This operation should succeed,
77*a3a45f30SXin Li // since we could write the rest later.
78*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->WriteExtraStream(zeros.data(), 10));
79*a3a45f30SXin Li EXPECT_FALSE(patch_writer_->Close());
80*a3a45f30SXin Li }
81*a3a45f30SXin Li
82*a3a45f30SXin Li // Test all sort of corner cases when splitting the ControlEntry across multiple
83*a3a45f30SXin Li // patches
TEST_F(SplitPatchWriterTest,SplitControlAcrossSeveralPatchesTest)84*a3a45f30SXin Li TEST_F(SplitPatchWriterTest, SplitControlAcrossSeveralPatchesTest) {
85*a3a45f30SXin Li SetUpForSize(4, 10, 40);
86*a3a45f30SXin Li // The middle control entry would be split in tree different patches.
87*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(5, 1, -5)));
88*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(4, 0, -4)));
89*a3a45f30SXin Li // old_pos at this point is 0. This is the end of the first patch.
90*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(6, 0, -1)));
91*a3a45f30SXin Li // old_pos at this point is 5.
92*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(1, 18, 2)));
93*a3a45f30SXin Li // old_pos at this point is 8.
94*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(1, 0, 1)));
95*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(4, 0, -5)));
96*a3a45f30SXin Li
97*a3a45f30SXin Li std::vector<uint8_t> zeros(40, 0);
98*a3a45f30SXin Li EXPECT_TRUE(
99*a3a45f30SXin Li patch_writer_->WriteDiffStream(zeros.data(), 5 + 4 + 6 + 1 + 1 + 4));
100*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->WriteExtraStream(zeros.data(), 1 + 18));
101*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->Close());
102*a3a45f30SXin Li
103*a3a45f30SXin Li EXPECT_EQ((std::vector<ControlEntry>{
104*a3a45f30SXin Li ControlEntry(5, 1, -5),
105*a3a45f30SXin Li ControlEntry(4, 0, 0), // (4, 0, -4) but the -4 is not needed.
106*a3a45f30SXin Li }),
107*a3a45f30SXin Li fake_patches_[0].entries());
108*a3a45f30SXin Li EXPECT_EQ((std::vector<ControlEntry>{
109*a3a45f30SXin Li // No need for dummy entry because the old_pos is already at 0.
110*a3a45f30SXin Li ControlEntry(6, 0, -1),
111*a3a45f30SXin Li ControlEntry(1, 3, 0), // the first part of (1, 18, 2)
112*a3a45f30SXin Li }),
113*a3a45f30SXin Li fake_patches_[1].entries());
114*a3a45f30SXin Li EXPECT_EQ((std::vector<ControlEntry>{
115*a3a45f30SXin Li // No need for dummy entry because the first entry is all in
116*a3a45f30SXin Li // the extra stream and this is the last entry.
117*a3a45f30SXin Li ControlEntry(0, 10, 0), // the middle part of (1, 18, 2)
118*a3a45f30SXin Li }),
119*a3a45f30SXin Li fake_patches_[2].entries());
120*a3a45f30SXin Li EXPECT_EQ((std::vector<ControlEntry>{
121*a3a45f30SXin Li // No need for dummy entry because the first entry is all in
122*a3a45f30SXin Li // the extra stream, so use that.
123*a3a45f30SXin Li ControlEntry(0, 5, 8), // the last part of (1, 18, 2), plus the
124*a3a45f30SXin Li // old_pos 5. 8 = 1 + 2 + 5.
125*a3a45f30SXin Li ControlEntry(1, 0, 1), // (1, 0, 1) copied
126*a3a45f30SXin Li ControlEntry(4, 0, 0), // (4, 0, -5) ignoring the offset.
127*a3a45f30SXin Li }),
128*a3a45f30SXin Li fake_patches_[3].entries());
129*a3a45f30SXin Li
130*a3a45f30SXin Li for (size_t i = 0; i < fake_patches_.size(); ++i) {
131*a3a45f30SXin Li EXPECT_EQ(10U, fake_patches_[i].new_size()) << "where i = " << i;
132*a3a45f30SXin Li }
133*a3a45f30SXin Li }
134*a3a45f30SXin Li
TEST_F(SplitPatchWriterTest,WriteStreamsAfterControlAcrossPatchesTest)135*a3a45f30SXin Li TEST_F(SplitPatchWriterTest, WriteStreamsAfterControlAcrossPatchesTest) {
136*a3a45f30SXin Li std::vector<uint8_t> numbers(40);
137*a3a45f30SXin Li for (size_t i = 0; i < numbers.size(); ++i)
138*a3a45f30SXin Li numbers[i] = 'A' + i;
139*a3a45f30SXin Li
140*a3a45f30SXin Li SetUpForSize(4, 10, 40);
141*a3a45f30SXin Li // The sequence is 15 diff, 10 extra, 15 diff.
142*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(15, 10, 0)));
143*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->AddControlEntry(ControlEntry(15, 0, 0)));
144*a3a45f30SXin Li // Numbers [0, 30) for the diff stream, and [30, 40) for the extra stream.
145*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->WriteDiffStream(numbers.data(), 30));
146*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->WriteExtraStream(numbers.data() + 30, 10));
147*a3a45f30SXin Li EXPECT_TRUE(patch_writer_->Close());
148*a3a45f30SXin Li
149*a3a45f30SXin Li EXPECT_EQ(std::vector<uint8_t>(numbers.begin(), numbers.begin() + 10),
150*a3a45f30SXin Li fake_patches_[0].diff_stream());
151*a3a45f30SXin Li EXPECT_TRUE(fake_patches_[0].extra_stream().empty());
152*a3a45f30SXin Li
153*a3a45f30SXin Li // 5 diff, then 5 extra.
154*a3a45f30SXin Li EXPECT_EQ(std::vector<uint8_t>(numbers.begin() + 10, numbers.begin() + 15),
155*a3a45f30SXin Li fake_patches_[1].diff_stream());
156*a3a45f30SXin Li EXPECT_EQ(std::vector<uint8_t>(numbers.begin() + 30, numbers.begin() + 35),
157*a3a45f30SXin Li fake_patches_[1].extra_stream());
158*a3a45f30SXin Li
159*a3a45f30SXin Li // 5 extra, then 5 diff.
160*a3a45f30SXin Li EXPECT_EQ(std::vector<uint8_t>(numbers.begin() + 15, numbers.begin() + 20),
161*a3a45f30SXin Li fake_patches_[2].diff_stream());
162*a3a45f30SXin Li EXPECT_EQ(std::vector<uint8_t>(numbers.begin() + 35, numbers.begin() + 40),
163*a3a45f30SXin Li fake_patches_[2].extra_stream());
164*a3a45f30SXin Li
165*a3a45f30SXin Li EXPECT_EQ(std::vector<uint8_t>(numbers.begin() + 20, numbers.begin() + 30),
166*a3a45f30SXin Li fake_patches_[3].diff_stream());
167*a3a45f30SXin Li EXPECT_TRUE(fake_patches_[3].extra_stream().empty());
168*a3a45f30SXin Li }
169*a3a45f30SXin Li
170*a3a45f30SXin Li } // namespace bsdiff
171