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/diff_encoder.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 {
16
17 // Generated with:
18 // echo 'Hello World' | hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
19 const uint8_t kHelloWorld[] = {
20 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a,
21 };
22
23 } // namespace
24
25 namespace bsdiff {
26
27 class DiffEncoderTest : public testing::Test {
28 protected:
SetUp()29 void SetUp() {
30 // By default, set the encoder to kHelloWorld to kHelloWorld.
31 diff_encoder_.reset(new DiffEncoder(&fake_patch_, kHelloWorld,
32 sizeof(kHelloWorld), kHelloWorld,
33 sizeof(kHelloWorld)));
34 }
35
36 FakePatchWriter fake_patch_;
37 std::unique_ptr<DiffEncoder> diff_encoder_;
38 };
39
TEST_F(DiffEncoderTest,CreateEmptyPatchTest)40 TEST_F(DiffEncoderTest, CreateEmptyPatchTest) {
41 diff_encoder_.reset(new DiffEncoder(&fake_patch_, nullptr, 0, nullptr, 0));
42 EXPECT_TRUE(diff_encoder_->Init());
43 EXPECT_TRUE(diff_encoder_->Close());
44
45 // Both diff and extra stream must be empty stream, and not control entries.
46 EXPECT_EQ(0U, fake_patch_.entries().size());
47 EXPECT_TRUE(fake_patch_.diff_stream().empty());
48 EXPECT_TRUE(fake_patch_.extra_stream().empty());
49 }
50
TEST_F(DiffEncoderTest,AllInExtraStreamTest)51 TEST_F(DiffEncoderTest, AllInExtraStreamTest) {
52 diff_encoder_.reset(new DiffEncoder(&fake_patch_, nullptr, 0, kHelloWorld,
53 sizeof(kHelloWorld)));
54 EXPECT_TRUE(diff_encoder_->Init());
55
56 // Write to the extra stream in two parts: first 5 bytes, then the rest.
57 EXPECT_TRUE(diff_encoder_->AddControlEntry(ControlEntry(0, 5, 0)));
58 EXPECT_TRUE(diff_encoder_->AddControlEntry(
59 ControlEntry(0, sizeof(kHelloWorld) - 5, 0)));
60 EXPECT_TRUE(diff_encoder_->Close());
61
62 EXPECT_EQ(2U, fake_patch_.entries().size());
63 EXPECT_TRUE(fake_patch_.diff_stream().empty());
64 std::vector<uint8_t> hello_world(kHelloWorld,
65 kHelloWorld + sizeof(kHelloWorld));
66 EXPECT_EQ(hello_world, fake_patch_.extra_stream());
67 }
68
TEST_F(DiffEncoderTest,AllInDiffStreamTest)69 TEST_F(DiffEncoderTest, AllInDiffStreamTest) {
70 EXPECT_TRUE(diff_encoder_->Init());
71 EXPECT_TRUE(
72 diff_encoder_->AddControlEntry(ControlEntry(sizeof(kHelloWorld), 0, 0)));
73 EXPECT_TRUE(diff_encoder_->Close());
74
75 EXPECT_EQ(std::vector<uint8_t>(sizeof(kHelloWorld), 0),
76 fake_patch_.diff_stream());
77 EXPECT_TRUE(fake_patch_.extra_stream().empty());
78 }
79
TEST_F(DiffEncoderTest,OldPosNegativeErrorTest)80 TEST_F(DiffEncoderTest, OldPosNegativeErrorTest) {
81 EXPECT_TRUE(diff_encoder_->Init());
82 // Referencing negative values in oldpos is fine, until you use them.
83 EXPECT_TRUE(diff_encoder_->AddControlEntry(ControlEntry(0, 0, -5)));
84 EXPECT_TRUE(diff_encoder_->AddControlEntry(ControlEntry(0, 0, 2)));
85 EXPECT_FALSE(diff_encoder_->AddControlEntry(ControlEntry(1, 0, 0)));
86 }
87
88 // Test that using an oldpos past the end of the file fails.
TEST_F(DiffEncoderTest,OldPosTooBigErrorTest)89 TEST_F(DiffEncoderTest, OldPosTooBigErrorTest) {
90 EXPECT_TRUE(diff_encoder_->Init());
91 EXPECT_TRUE(
92 diff_encoder_->AddControlEntry(ControlEntry(0, 0, sizeof(kHelloWorld))));
93 EXPECT_FALSE(diff_encoder_->AddControlEntry(ControlEntry(1, 0, 0)));
94 }
95
96 // Test that diffing against a section of the old file past the end of the file
97 // fails.
TEST_F(DiffEncoderTest,OldPosPlusSizeTooBigErrorTest)98 TEST_F(DiffEncoderTest, OldPosPlusSizeTooBigErrorTest) {
99 EXPECT_TRUE(diff_encoder_->Init());
100 // The oldpos is set to a range inside the word, the we try to copy past the
101 // end of it.
102 EXPECT_TRUE(diff_encoder_->AddControlEntry(
103 ControlEntry(0, 0, sizeof(kHelloWorld) - 3)));
104 EXPECT_FALSE(
105 diff_encoder_->AddControlEntry(ControlEntry(sizeof(kHelloWorld), 0, 0)));
106 }
107
TEST_F(DiffEncoderTest,ExtraStreamTooBigErrorTest)108 TEST_F(DiffEncoderTest, ExtraStreamTooBigErrorTest) {
109 EXPECT_TRUE(diff_encoder_->Init());
110 EXPECT_TRUE(diff_encoder_->AddControlEntry(ControlEntry(3, 0, 0)));
111 // This writes too many bytes in the stream because we already have 3 bytes.
112 EXPECT_FALSE(
113 diff_encoder_->AddControlEntry(ControlEntry(0, sizeof(kHelloWorld), 0)));
114 }
115
116 } // namespace bsdiff
117