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