1*a03ca8b9SKrzysztof Kosiński // Copyright 2017 The Chromium Authors. All rights reserved.
2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be
3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file.
4*a03ca8b9SKrzysztof Kosiński
5*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/patch_reader.h"
6*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/patch_writer.h"
7*a03ca8b9SKrzysztof Kosiński
8*a03ca8b9SKrzysztof Kosiński #include <stddef.h>
9*a03ca8b9SKrzysztof Kosiński #include <stdint.h>
10*a03ca8b9SKrzysztof Kosiński
11*a03ca8b9SKrzysztof Kosiński #include <utility>
12*a03ca8b9SKrzysztof Kosiński #include <vector>
13*a03ca8b9SKrzysztof Kosiński
14*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/version_info.h"
15*a03ca8b9SKrzysztof Kosiński #include "testing/gtest/include/gtest/gtest.h"
16*a03ca8b9SKrzysztof Kosiński
17*a03ca8b9SKrzysztof Kosiński namespace zucchini {
18*a03ca8b9SKrzysztof Kosiński
19*a03ca8b9SKrzysztof Kosiński namespace {
20*a03ca8b9SKrzysztof Kosiński
21*a03ca8b9SKrzysztof Kosiński // Used for initialization of raw test data.
22*a03ca8b9SKrzysztof Kosiński using ByteVector = std::vector<uint8_t>;
23*a03ca8b9SKrzysztof Kosiński
24*a03ca8b9SKrzysztof Kosiński // Helper function that creates an object of type |T| and intializes it from
25*a03ca8b9SKrzysztof Kosiński // data in |buffer|. Ensures initialization is successful. |buffer| is passed as
26*a03ca8b9SKrzysztof Kosiński // pointer to avoid passing a temporay, which can causes dangling references.
27*a03ca8b9SKrzysztof Kosiński template <class T>
TestInitialize(const ByteVector * buffer)28*a03ca8b9SKrzysztof Kosiński T TestInitialize(const ByteVector* buffer) {
29*a03ca8b9SKrzysztof Kosiński T value;
30*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(buffer->data(), buffer->size());
31*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(value.Initialize(&buffer_source));
32*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(buffer_source.empty()); // Make sure all data has been consumed
33*a03ca8b9SKrzysztof Kosiński return value;
34*a03ca8b9SKrzysztof Kosiński }
35*a03ca8b9SKrzysztof Kosiński
36*a03ca8b9SKrzysztof Kosiński // Helper function that creates an object of type |T| and tries to intialize it
37*a03ca8b9SKrzysztof Kosiński // from invalid data in |buffer|, expecting the operation to fail. |buffer| is
38*a03ca8b9SKrzysztof Kosiński // passed as pointer to avoid passing a temporary, which can causes dangling
39*a03ca8b9SKrzysztof Kosiński // references.
40*a03ca8b9SKrzysztof Kosiński template <class T>
TestInvalidInitialize(const ByteVector * buffer)41*a03ca8b9SKrzysztof Kosiński void TestInvalidInitialize(const ByteVector* buffer) {
42*a03ca8b9SKrzysztof Kosiński T value;
43*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(buffer->data(), buffer->size());
44*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(value.Initialize(&buffer_source));
45*a03ca8b9SKrzysztof Kosiński }
46*a03ca8b9SKrzysztof Kosiński
47*a03ca8b9SKrzysztof Kosiński // Helper function that serializes |value| into a buffer. Ensures that
48*a03ca8b9SKrzysztof Kosiński // serialization is successful and that the result matches |expected|.
49*a03ca8b9SKrzysztof Kosiński template <class T>
TestSerialize(const ByteVector & expected,const T & value)50*a03ca8b9SKrzysztof Kosiński void TestSerialize(const ByteVector& expected, const T& value) {
51*a03ca8b9SKrzysztof Kosiński size_t size = value.SerializedSize();
52*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(expected.size(), size);
53*a03ca8b9SKrzysztof Kosiński ByteVector buffer(size);
54*a03ca8b9SKrzysztof Kosiński BufferSink buffer_sink(buffer.data(), buffer.size());
55*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(value.SerializeInto(&buffer_sink));
56*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(expected, buffer);
57*a03ca8b9SKrzysztof Kosiński }
58*a03ca8b9SKrzysztof Kosiński
CreatePatchElement()59*a03ca8b9SKrzysztof Kosiński ByteVector CreatePatchElement() {
60*a03ca8b9SKrzysztof Kosiński return {
61*a03ca8b9SKrzysztof Kosiński // PatchElementHeader
62*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // old_offset
63*a03ca8b9SKrzysztof Kosiński 0x51, 0, 0, 0, // old_length
64*a03ca8b9SKrzysztof Kosiński 0x03, 0, 0, 0, // new_offset
65*a03ca8b9SKrzysztof Kosiński 0x13, 0, 0, 0, // new_length
66*a03ca8b9SKrzysztof Kosiński 'P', 'x', '8', '6', // exe_type = EXE_TYPE_WIN32_X86
67*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, // element version
68*a03ca8b9SKrzysztof Kosiński // EquivalenceSource
69*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // src_skip size
70*a03ca8b9SKrzysztof Kosiński 0x10, // src_skip content
71*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // dst_skip size
72*a03ca8b9SKrzysztof Kosiński 0x00, // dst_skip content
73*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // copy_count size
74*a03ca8b9SKrzysztof Kosiński 0x12, // copy_count content
75*a03ca8b9SKrzysztof Kosiński // ExtraDataSource
76*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // extra_data size
77*a03ca8b9SKrzysztof Kosiński 0x13, // extra_data content
78*a03ca8b9SKrzysztof Kosiński // RawDeltaSource
79*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // raw_delta_skip size
80*a03ca8b9SKrzysztof Kosiński 0x14, // raw_delta_skip content
81*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // raw_delta_diff size
82*a03ca8b9SKrzysztof Kosiński 0x15, // raw_delta_diff content
83*a03ca8b9SKrzysztof Kosiński // ReferenceDeltaSource
84*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // reference_delta size
85*a03ca8b9SKrzysztof Kosiński 0x16, // reference_delta content
86*a03ca8b9SKrzysztof Kosiński // PatchElementReader
87*a03ca8b9SKrzysztof Kosiński 2, 0, 0, 0, // pool count
88*a03ca8b9SKrzysztof Kosiński 0, // pool_tag
89*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // extra_targets size
90*a03ca8b9SKrzysztof Kosiński 0x17, // extra_targets content
91*a03ca8b9SKrzysztof Kosiński 2, // pool_tag
92*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // extra_targets size
93*a03ca8b9SKrzysztof Kosiński 0x18, // extra_targets content
94*a03ca8b9SKrzysztof Kosiński };
95*a03ca8b9SKrzysztof Kosiński }
96*a03ca8b9SKrzysztof Kosiński
CreateElementMatch()97*a03ca8b9SKrzysztof Kosiński ByteVector CreateElementMatch() {
98*a03ca8b9SKrzysztof Kosiński return {
99*a03ca8b9SKrzysztof Kosiński // PatchElementHeader
100*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // old_offset
101*a03ca8b9SKrzysztof Kosiński 0x02, 0, 0, 0, // old_length
102*a03ca8b9SKrzysztof Kosiński 0x03, 0, 0, 0, // new_offset
103*a03ca8b9SKrzysztof Kosiński 0x04, 0, 0, 0, // new_length
104*a03ca8b9SKrzysztof Kosiński 'D', 'E', 'X', ' ', // exe_type = kExeTypeDex
105*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, // element version
106*a03ca8b9SKrzysztof Kosiński };
107*a03ca8b9SKrzysztof Kosiński }
108*a03ca8b9SKrzysztof Kosiński
109*a03ca8b9SKrzysztof Kosiński // Helper to mutate test |data| (e.g., from CreatePatchElement()) at |idx| from
110*a03ca8b9SKrzysztof Kosiński // |from_val| (as sanity check) to |to_val|.
ModifyByte(size_t idx,uint8_t from_val,uint8_t to_val,std::vector<uint8_t> * data)111*a03ca8b9SKrzysztof Kosiński void ModifyByte(size_t idx,
112*a03ca8b9SKrzysztof Kosiński uint8_t from_val,
113*a03ca8b9SKrzysztof Kosiński uint8_t to_val,
114*a03ca8b9SKrzysztof Kosiński std::vector<uint8_t>* data) {
115*a03ca8b9SKrzysztof Kosiński ASSERT_EQ(from_val, (*data)[idx]);
116*a03ca8b9SKrzysztof Kosiński (*data)[idx] = to_val;
117*a03ca8b9SKrzysztof Kosiński }
118*a03ca8b9SKrzysztof Kosiński
119*a03ca8b9SKrzysztof Kosiński } // namespace
120*a03ca8b9SKrzysztof Kosiński
operator ==(const ByteVector & a,ConstBufferView b)121*a03ca8b9SKrzysztof Kosiński bool operator==(const ByteVector& a, ConstBufferView b) {
122*a03ca8b9SKrzysztof Kosiński return a == ByteVector(b.begin(), b.end());
123*a03ca8b9SKrzysztof Kosiński }
124*a03ca8b9SKrzysztof Kosiński
TEST(PatchTest,ParseSerializeElementMatch)125*a03ca8b9SKrzysztof Kosiński TEST(PatchTest, ParseSerializeElementMatch) {
126*a03ca8b9SKrzysztof Kosiński ByteVector data = CreateElementMatch();
127*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(data.data(), data.size());
128*a03ca8b9SKrzysztof Kosiński ElementMatch element_match = {};
129*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(patch::ParseElementMatch(&buffer_source, &element_match));
130*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kExeTypeDex, element_match.exe_type());
131*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kExeTypeDex, element_match.old_element.exe_type);
132*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kExeTypeDex, element_match.new_element.exe_type);
133*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x1U, element_match.old_element.offset);
134*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x2U, element_match.old_element.size);
135*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x3U, element_match.new_element.offset);
136*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x4U, element_match.new_element.size);
137*a03ca8b9SKrzysztof Kosiński
138*a03ca8b9SKrzysztof Kosiński size_t size = patch::SerializedElementMatchSize(element_match);
139*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(data.size(), size);
140*a03ca8b9SKrzysztof Kosiński ByteVector buffer(size);
141*a03ca8b9SKrzysztof Kosiński BufferSink buffer_sink(buffer.data(), buffer.size());
142*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(patch::SerializeElementMatch(element_match, &buffer_sink));
143*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(data, buffer);
144*a03ca8b9SKrzysztof Kosiński }
145*a03ca8b9SKrzysztof Kosiński
TEST(PatchTest,ParseElementMatchTooSmall)146*a03ca8b9SKrzysztof Kosiński TEST(PatchTest, ParseElementMatchTooSmall) {
147*a03ca8b9SKrzysztof Kosiński ByteVector data = {4};
148*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(data.data(), data.size());
149*a03ca8b9SKrzysztof Kosiński ElementMatch element_match = {};
150*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match));
151*a03ca8b9SKrzysztof Kosiński }
152*a03ca8b9SKrzysztof Kosiński
TEST(PatchTest,ParseElementMatchNoLength)153*a03ca8b9SKrzysztof Kosiński TEST(PatchTest, ParseElementMatchNoLength) {
154*a03ca8b9SKrzysztof Kosiński // Set old_length to 0 to trigger an error.
155*a03ca8b9SKrzysztof Kosiński {
156*a03ca8b9SKrzysztof Kosiński ByteVector data = CreateElementMatch();
157*a03ca8b9SKrzysztof Kosiński // old_length := 0.
158*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, old_length), 0x02, 0x00, &data);
159*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(data.data(), data.size());
160*a03ca8b9SKrzysztof Kosiński ElementMatch element_match = {};
161*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match));
162*a03ca8b9SKrzysztof Kosiński }
163*a03ca8b9SKrzysztof Kosiński // Set new_length to 0 to trigger an error.
164*a03ca8b9SKrzysztof Kosiński {
165*a03ca8b9SKrzysztof Kosiński ByteVector data = CreateElementMatch();
166*a03ca8b9SKrzysztof Kosiński // new_length := 0.
167*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, new_length), 0x04, 0x00, &data);
168*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(data.data(), data.size());
169*a03ca8b9SKrzysztof Kosiński ElementMatch element_match = {};
170*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match));
171*a03ca8b9SKrzysztof Kosiński }
172*a03ca8b9SKrzysztof Kosiński // Set both new_length and old_length to 0 to trigger an error.
173*a03ca8b9SKrzysztof Kosiński {
174*a03ca8b9SKrzysztof Kosiński ByteVector data = CreateElementMatch();
175*a03ca8b9SKrzysztof Kosiński // old_length := 0.
176*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, old_length), 0x02, 0x00, &data);
177*a03ca8b9SKrzysztof Kosiński // new_length := 0.
178*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, new_length), 0x04, 0x00, &data);
179*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(data.data(), data.size());
180*a03ca8b9SKrzysztof Kosiński ElementMatch element_match = {};
181*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match));
182*a03ca8b9SKrzysztof Kosiński }
183*a03ca8b9SKrzysztof Kosiński }
184*a03ca8b9SKrzysztof Kosiński
TEST(PatchTest,ParseSerializeElementMatchExeMismatch)185*a03ca8b9SKrzysztof Kosiński TEST(PatchTest, ParseSerializeElementMatchExeMismatch) {
186*a03ca8b9SKrzysztof Kosiński ByteVector buffer(28);
187*a03ca8b9SKrzysztof Kosiński BufferSink buffer_sink(buffer.data(), buffer.size());
188*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(patch::SerializeElementMatch(
189*a03ca8b9SKrzysztof Kosiński ElementMatch{{{1, 2}, kExeTypeNoOp}, {{3, 4}, kExeTypeWin32X86}},
190*a03ca8b9SKrzysztof Kosiński &buffer_sink));
191*a03ca8b9SKrzysztof Kosiński }
192*a03ca8b9SKrzysztof Kosiński
TEST(PatchTest,SerializeElementMatchTooSmall)193*a03ca8b9SKrzysztof Kosiński TEST(PatchTest, SerializeElementMatchTooSmall) {
194*a03ca8b9SKrzysztof Kosiński ByteVector buffer(4);
195*a03ca8b9SKrzysztof Kosiński BufferSink buffer_sink(buffer.data(), buffer.size());
196*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(patch::SerializeElementMatch(
197*a03ca8b9SKrzysztof Kosiński ElementMatch{{{1, 2}, kExeTypeDex}, {{3, 4}, kExeTypeDex}},
198*a03ca8b9SKrzysztof Kosiński &buffer_sink));
199*a03ca8b9SKrzysztof Kosiński }
200*a03ca8b9SKrzysztof Kosiński
TEST(PatchTest,ParseSerializeBuffer)201*a03ca8b9SKrzysztof Kosiński TEST(PatchTest, ParseSerializeBuffer) {
202*a03ca8b9SKrzysztof Kosiński auto TestSerialize = [](const ByteVector& expected, const ByteVector& value) {
203*a03ca8b9SKrzysztof Kosiński size_t size = patch::SerializedBufferSize(value);
204*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(expected.size(), size);
205*a03ca8b9SKrzysztof Kosiński ByteVector buffer(size);
206*a03ca8b9SKrzysztof Kosiński BufferSink buffer_sink(buffer.data(), buffer.size());
207*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(patch::SerializeBuffer(value, &buffer_sink));
208*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(expected, buffer);
209*a03ca8b9SKrzysztof Kosiński };
210*a03ca8b9SKrzysztof Kosiński
211*a03ca8b9SKrzysztof Kosiński // |data| is passed as pointer to avoid passing a temporay, which can causes
212*a03ca8b9SKrzysztof Kosiński // dangling references.
213*a03ca8b9SKrzysztof Kosiński auto TestParse = [](const ByteVector* data) {
214*a03ca8b9SKrzysztof Kosiński BufferSource value;
215*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(data->data(), data->size());
216*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(patch::ParseBuffer(&buffer_source, &value));
217*a03ca8b9SKrzysztof Kosiński // Make sure all data has been consumed.
218*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(buffer_source.empty());
219*a03ca8b9SKrzysztof Kosiński return value;
220*a03ca8b9SKrzysztof Kosiński };
221*a03ca8b9SKrzysztof Kosiński
222*a03ca8b9SKrzysztof Kosiński ByteVector data = {
223*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // size
224*a03ca8b9SKrzysztof Kosiński };
225*a03ca8b9SKrzysztof Kosiński BufferSource buffer = TestParse(&data);
226*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(buffer.empty());
227*a03ca8b9SKrzysztof Kosiński TestSerialize(data, ByteVector({}));
228*a03ca8b9SKrzysztof Kosiński
229*a03ca8b9SKrzysztof Kosiński data = {
230*a03ca8b9SKrzysztof Kosiński 3, 0, 0, 0, // size
231*a03ca8b9SKrzysztof Kosiński 1, 2, 3 // content
232*a03ca8b9SKrzysztof Kosiński };
233*a03ca8b9SKrzysztof Kosiński buffer = TestParse(&data);
234*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(3U, buffer.size());
235*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({1, 2, 3}), ByteVector(buffer.begin(), buffer.end()));
236*a03ca8b9SKrzysztof Kosiński TestSerialize(data, ByteVector({1, 2, 3}));
237*a03ca8b9SKrzysztof Kosiński
238*a03ca8b9SKrzysztof Kosiński // Ill-formed input.
239*a03ca8b9SKrzysztof Kosiński data = {
240*a03ca8b9SKrzysztof Kosiński 3, 0, 0, 0, // size
241*a03ca8b9SKrzysztof Kosiński 1, 2 // insufficient content
242*a03ca8b9SKrzysztof Kosiński };
243*a03ca8b9SKrzysztof Kosiński BufferSource value;
244*a03ca8b9SKrzysztof Kosiński BufferSource buffer_source(data.data(), data.size());
245*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(patch::ParseBuffer(&buffer_source, &value));
246*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(value.empty());
247*a03ca8b9SKrzysztof Kosiński }
248*a03ca8b9SKrzysztof Kosiński
TEST(PatchTest,SerializeBufferTooSmall)249*a03ca8b9SKrzysztof Kosiński TEST(PatchTest, SerializeBufferTooSmall) {
250*a03ca8b9SKrzysztof Kosiński ByteVector buffer(3);
251*a03ca8b9SKrzysztof Kosiński BufferSink buffer_sink(buffer.data(), buffer.size());
252*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(patch::SerializeBuffer(ByteVector(), &buffer_sink));
253*a03ca8b9SKrzysztof Kosiński }
254*a03ca8b9SKrzysztof Kosiński
TEST(EquivalenceSinkSourceTest,Empty)255*a03ca8b9SKrzysztof Kosiński TEST(EquivalenceSinkSourceTest, Empty) {
256*a03ca8b9SKrzysztof Kosiński ByteVector data = {
257*a03ca8b9SKrzysztof Kosiński // EquivalenceSource
258*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // src_skip size
259*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // dst_skip size
260*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // copy_count size
261*a03ca8b9SKrzysztof Kosiński };
262*a03ca8b9SKrzysztof Kosiński EquivalenceSource equivalence_source =
263*a03ca8b9SKrzysztof Kosiński TestInitialize<EquivalenceSource>(&data);
264*a03ca8b9SKrzysztof Kosiński
265*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(equivalence_source.GetNext());
266*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(equivalence_source.Done());
267*a03ca8b9SKrzysztof Kosiński
268*a03ca8b9SKrzysztof Kosiński TestSerialize(data, EquivalenceSink());
269*a03ca8b9SKrzysztof Kosiński }
270*a03ca8b9SKrzysztof Kosiński
TEST(EquivalenceSourceSinkTest,Normal)271*a03ca8b9SKrzysztof Kosiński TEST(EquivalenceSourceSinkTest, Normal) {
272*a03ca8b9SKrzysztof Kosiński ByteVector data = {
273*a03ca8b9SKrzysztof Kosiński // EquivalenceSource
274*a03ca8b9SKrzysztof Kosiński 2, 0, 0, 0, // src_skip size
275*a03ca8b9SKrzysztof Kosiński 6, 7, // src_skip content
276*a03ca8b9SKrzysztof Kosiński 2, 0, 0, 0, // dst_skip size
277*a03ca8b9SKrzysztof Kosiński 7, 1, // dst_skip content
278*a03ca8b9SKrzysztof Kosiński 2, 0, 0, 0, // copy_count size
279*a03ca8b9SKrzysztof Kosiński 2, 1 // copy_count content
280*a03ca8b9SKrzysztof Kosiński };
281*a03ca8b9SKrzysztof Kosiński EquivalenceSource equivalence_source =
282*a03ca8b9SKrzysztof Kosiński TestInitialize<EquivalenceSource>(&data);
283*a03ca8b9SKrzysztof Kosiński auto equivalence = equivalence_source.GetNext();
284*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(equivalence_source.Done());
285*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(equivalence.has_value());
286*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(offset_t(3), equivalence->src_offset);
287*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(offset_t(7), equivalence->dst_offset);
288*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(offset_t(2), equivalence->length);
289*a03ca8b9SKrzysztof Kosiński
290*a03ca8b9SKrzysztof Kosiński equivalence = equivalence_source.GetNext();
291*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(equivalence_source.Done());
292*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(equivalence.has_value());
293*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(offset_t(1), equivalence->src_offset);
294*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(offset_t(10), equivalence->dst_offset);
295*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(offset_t(1), equivalence->length);
296*a03ca8b9SKrzysztof Kosiński
297*a03ca8b9SKrzysztof Kosiński equivalence = equivalence_source.GetNext();
298*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(equivalence.has_value());
299*a03ca8b9SKrzysztof Kosiński
300*a03ca8b9SKrzysztof Kosiński EquivalenceSink equivalence_sink;
301*a03ca8b9SKrzysztof Kosiński equivalence_sink.PutNext(Equivalence{3, 7, 2});
302*a03ca8b9SKrzysztof Kosiński equivalence_sink.PutNext(Equivalence{1, 10, 1});
303*a03ca8b9SKrzysztof Kosiński TestSerialize(data, equivalence_sink);
304*a03ca8b9SKrzysztof Kosiński }
305*a03ca8b9SKrzysztof Kosiński
TEST(ExtraDataSourceSinkTest,Empty)306*a03ca8b9SKrzysztof Kosiński TEST(ExtraDataSourceSinkTest, Empty) {
307*a03ca8b9SKrzysztof Kosiński ByteVector data = {
308*a03ca8b9SKrzysztof Kosiński // ExtraDataSource
309*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // extra_data size
310*a03ca8b9SKrzysztof Kosiński };
311*a03ca8b9SKrzysztof Kosiński ExtraDataSource extra_data_source = TestInitialize<ExtraDataSource>(&data);
312*a03ca8b9SKrzysztof Kosiński
313*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(extra_data_source.GetNext(2));
314*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(extra_data_source.Done());
315*a03ca8b9SKrzysztof Kosiński
316*a03ca8b9SKrzysztof Kosiński TestSerialize(data, ExtraDataSink());
317*a03ca8b9SKrzysztof Kosiński }
318*a03ca8b9SKrzysztof Kosiński
TEST(ExtraDataSourceSinkTest,Normal)319*a03ca8b9SKrzysztof Kosiński TEST(ExtraDataSourceSinkTest, Normal) {
320*a03ca8b9SKrzysztof Kosiński ByteVector data = {
321*a03ca8b9SKrzysztof Kosiński // ExtraDataSource
322*a03ca8b9SKrzysztof Kosiński 5, 0, 0, 0, // extra_data size
323*a03ca8b9SKrzysztof Kosiński 1, 2, 3, 4, 5, // extra_data content
324*a03ca8b9SKrzysztof Kosiński };
325*a03ca8b9SKrzysztof Kosiński ExtraDataSource extra_data_source = TestInitialize<ExtraDataSource>(&data);
326*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(extra_data_source.Done());
327*a03ca8b9SKrzysztof Kosiński
328*a03ca8b9SKrzysztof Kosiński auto extra_data = extra_data_source.GetNext(3);
329*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(extra_data_source.Done());
330*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(extra_data.has_value());
331*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(size_t(3), extra_data->size());
332*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({1, 2, 3}),
333*a03ca8b9SKrzysztof Kosiński ByteVector(extra_data->begin(), extra_data->end()));
334*a03ca8b9SKrzysztof Kosiński
335*a03ca8b9SKrzysztof Kosiński extra_data = extra_data_source.GetNext(2);
336*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(extra_data_source.Done());
337*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(extra_data.has_value());
338*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({4, 5}),
339*a03ca8b9SKrzysztof Kosiński ByteVector(extra_data->begin(), extra_data->end()));
340*a03ca8b9SKrzysztof Kosiński
341*a03ca8b9SKrzysztof Kosiński extra_data = extra_data_source.GetNext(2);
342*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(extra_data.has_value());
343*a03ca8b9SKrzysztof Kosiński
344*a03ca8b9SKrzysztof Kosiński ExtraDataSink extra_data_sink;
345*a03ca8b9SKrzysztof Kosiński
346*a03ca8b9SKrzysztof Kosiński ByteVector content = {1, 2, 3};
347*a03ca8b9SKrzysztof Kosiński extra_data_sink.PutNext({content.data(), content.size()});
348*a03ca8b9SKrzysztof Kosiński content = {4, 5};
349*a03ca8b9SKrzysztof Kosiński extra_data_sink.PutNext({content.data(), content.size()});
350*a03ca8b9SKrzysztof Kosiński TestSerialize(data, extra_data_sink);
351*a03ca8b9SKrzysztof Kosiński }
352*a03ca8b9SKrzysztof Kosiński
TEST(RawDeltaSourceSinkTest,Empty)353*a03ca8b9SKrzysztof Kosiński TEST(RawDeltaSourceSinkTest, Empty) {
354*a03ca8b9SKrzysztof Kosiński ByteVector data = {
355*a03ca8b9SKrzysztof Kosiński // RawDeltaSource
356*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_skip size
357*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_diff size
358*a03ca8b9SKrzysztof Kosiński };
359*a03ca8b9SKrzysztof Kosiński RawDeltaSource raw_delta_source = TestInitialize<RawDeltaSource>(&data);
360*a03ca8b9SKrzysztof Kosiński
361*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(raw_delta_source.GetNext());
362*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(raw_delta_source.Done());
363*a03ca8b9SKrzysztof Kosiński
364*a03ca8b9SKrzysztof Kosiński TestSerialize(data, RawDeltaSink());
365*a03ca8b9SKrzysztof Kosiński }
366*a03ca8b9SKrzysztof Kosiński
TEST(RawDeltaSinkSourceSinkTest,Normal)367*a03ca8b9SKrzysztof Kosiński TEST(RawDeltaSinkSourceSinkTest, Normal) {
368*a03ca8b9SKrzysztof Kosiński ByteVector data = {
369*a03ca8b9SKrzysztof Kosiński // RawDeltaSource
370*a03ca8b9SKrzysztof Kosiński 3, 0, 0, 0, // raw_delta_skip size
371*a03ca8b9SKrzysztof Kosiński 1, 3, 0, // raw_delta_skip content
372*a03ca8b9SKrzysztof Kosiński 3, 0, 0, 0, // raw_delta_diff size
373*a03ca8b9SKrzysztof Kosiński 42, 24, 235, // raw_delta_diff content
374*a03ca8b9SKrzysztof Kosiński };
375*a03ca8b9SKrzysztof Kosiński RawDeltaSource raw_delta_source = TestInitialize<RawDeltaSource>(&data);
376*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(raw_delta_source.Done());
377*a03ca8b9SKrzysztof Kosiński
378*a03ca8b9SKrzysztof Kosiński auto raw_delta = raw_delta_source.GetNext();
379*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(raw_delta_source.Done());
380*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(raw_delta.has_value());
381*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(1U, raw_delta->copy_offset);
382*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(42, raw_delta->diff);
383*a03ca8b9SKrzysztof Kosiński
384*a03ca8b9SKrzysztof Kosiński raw_delta = raw_delta_source.GetNext();
385*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(raw_delta_source.Done());
386*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(raw_delta.has_value());
387*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(5U, raw_delta->copy_offset);
388*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(24, raw_delta->diff);
389*a03ca8b9SKrzysztof Kosiński
390*a03ca8b9SKrzysztof Kosiński raw_delta = raw_delta_source.GetNext();
391*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(raw_delta_source.Done());
392*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(raw_delta.has_value());
393*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(6U, raw_delta->copy_offset);
394*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(-21, raw_delta->diff);
395*a03ca8b9SKrzysztof Kosiński
396*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(raw_delta_source.GetNext());
397*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(raw_delta_source.Done());
398*a03ca8b9SKrzysztof Kosiński
399*a03ca8b9SKrzysztof Kosiński RawDeltaSink raw_delta_sink;
400*a03ca8b9SKrzysztof Kosiński raw_delta_sink.PutNext({1, 42});
401*a03ca8b9SKrzysztof Kosiński raw_delta_sink.PutNext({5, 24});
402*a03ca8b9SKrzysztof Kosiński raw_delta_sink.PutNext({6, -21});
403*a03ca8b9SKrzysztof Kosiński TestSerialize(data, raw_delta_sink);
404*a03ca8b9SKrzysztof Kosiński }
405*a03ca8b9SKrzysztof Kosiński
TEST(RawDeltaSourceSinkTest,InvalidContent)406*a03ca8b9SKrzysztof Kosiński TEST(RawDeltaSourceSinkTest, InvalidContent) {
407*a03ca8b9SKrzysztof Kosiński ByteVector data = {
408*a03ca8b9SKrzysztof Kosiński // RawDeltaSource
409*a03ca8b9SKrzysztof Kosiński 2, 0, 0, 0, // raw_delta_skip size
410*a03ca8b9SKrzysztof Kosiński 1, 3, // raw_delta_skip content
411*a03ca8b9SKrzysztof Kosiński 2, 0, 0, 0, // raw_delta_diff size
412*a03ca8b9SKrzysztof Kosiński 0, 4, // raw_delta_diff content
413*a03ca8b9SKrzysztof Kosiński };
414*a03ca8b9SKrzysztof Kosiński RawDeltaSource raw_delta_source = TestInitialize<RawDeltaSource>(&data);
415*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(raw_delta_source.GetNext());
416*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(raw_delta_source.Done());
417*a03ca8b9SKrzysztof Kosiński }
418*a03ca8b9SKrzysztof Kosiński
TEST(ReferenceDeltaSourceSinkTest,Empty)419*a03ca8b9SKrzysztof Kosiński TEST(ReferenceDeltaSourceSinkTest, Empty) {
420*a03ca8b9SKrzysztof Kosiński ByteVector data = {
421*a03ca8b9SKrzysztof Kosiński // ReferenceDeltaSource
422*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // reference_delta size
423*a03ca8b9SKrzysztof Kosiński };
424*a03ca8b9SKrzysztof Kosiński ReferenceDeltaSource reference_delta_source =
425*a03ca8b9SKrzysztof Kosiński TestInitialize<ReferenceDeltaSource>(&data);
426*a03ca8b9SKrzysztof Kosiński
427*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(reference_delta_source.GetNext());
428*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(reference_delta_source.Done());
429*a03ca8b9SKrzysztof Kosiński
430*a03ca8b9SKrzysztof Kosiński TestSerialize(data, ReferenceDeltaSink());
431*a03ca8b9SKrzysztof Kosiński }
432*a03ca8b9SKrzysztof Kosiński
TEST(ReferenceDeltaSourceSinkTest,Normal)433*a03ca8b9SKrzysztof Kosiński TEST(ReferenceDeltaSourceSinkTest, Normal) {
434*a03ca8b9SKrzysztof Kosiński ByteVector data = {
435*a03ca8b9SKrzysztof Kosiński // ReferenceDeltaSource
436*a03ca8b9SKrzysztof Kosiński 2, 0, 0, 0, // reference_delta size
437*a03ca8b9SKrzysztof Kosiński 84, 47, // reference_delta content
438*a03ca8b9SKrzysztof Kosiński };
439*a03ca8b9SKrzysztof Kosiński ReferenceDeltaSource reference_delta_source =
440*a03ca8b9SKrzysztof Kosiński TestInitialize<ReferenceDeltaSource>(&data);
441*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(reference_delta_source.Done());
442*a03ca8b9SKrzysztof Kosiński
443*a03ca8b9SKrzysztof Kosiński auto delta = reference_delta_source.GetNext();
444*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(reference_delta_source.Done());
445*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(delta.has_value());
446*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(42, *delta);
447*a03ca8b9SKrzysztof Kosiński
448*a03ca8b9SKrzysztof Kosiński delta = reference_delta_source.GetNext();
449*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(reference_delta_source.Done());
450*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(delta.has_value());
451*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(-24, *delta);
452*a03ca8b9SKrzysztof Kosiński
453*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(reference_delta_source.GetNext());
454*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(reference_delta_source.Done());
455*a03ca8b9SKrzysztof Kosiński
456*a03ca8b9SKrzysztof Kosiński ReferenceDeltaSink reference_delta;
457*a03ca8b9SKrzysztof Kosiński reference_delta.PutNext(42);
458*a03ca8b9SKrzysztof Kosiński reference_delta.PutNext(-24);
459*a03ca8b9SKrzysztof Kosiński TestSerialize(data, reference_delta);
460*a03ca8b9SKrzysztof Kosiński }
461*a03ca8b9SKrzysztof Kosiński
TEST(TargetSourceSinkTest,Empty)462*a03ca8b9SKrzysztof Kosiński TEST(TargetSourceSinkTest, Empty) {
463*a03ca8b9SKrzysztof Kosiński ByteVector data = {
464*a03ca8b9SKrzysztof Kosiński // TargetSource
465*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // extra_targets size
466*a03ca8b9SKrzysztof Kosiński };
467*a03ca8b9SKrzysztof Kosiński TargetSource target_source = TestInitialize<TargetSource>(&data);
468*a03ca8b9SKrzysztof Kosiński
469*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(target_source.GetNext());
470*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(target_source.Done());
471*a03ca8b9SKrzysztof Kosiński
472*a03ca8b9SKrzysztof Kosiński TestSerialize(data, TargetSink());
473*a03ca8b9SKrzysztof Kosiński }
474*a03ca8b9SKrzysztof Kosiński
TEST(TargetSourceSinkTest,Normal)475*a03ca8b9SKrzysztof Kosiński TEST(TargetSourceSinkTest, Normal) {
476*a03ca8b9SKrzysztof Kosiński ByteVector data = {
477*a03ca8b9SKrzysztof Kosiński // TargetSource
478*a03ca8b9SKrzysztof Kosiński 2, 0, 0, 0, // extra_targets size
479*a03ca8b9SKrzysztof Kosiński 3, 1, // extra_targets content
480*a03ca8b9SKrzysztof Kosiński };
481*a03ca8b9SKrzysztof Kosiński TargetSource target_source = TestInitialize<TargetSource>(&data);
482*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(target_source.Done());
483*a03ca8b9SKrzysztof Kosiński
484*a03ca8b9SKrzysztof Kosiński auto target = target_source.GetNext();
485*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(target_source.Done());
486*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(target.has_value());
487*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(3U, *target);
488*a03ca8b9SKrzysztof Kosiński
489*a03ca8b9SKrzysztof Kosiński target = target_source.GetNext();
490*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(target_source.Done());
491*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(target.has_value());
492*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(5U, *target);
493*a03ca8b9SKrzysztof Kosiński
494*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(target_source.GetNext());
495*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(target_source.Done());
496*a03ca8b9SKrzysztof Kosiński
497*a03ca8b9SKrzysztof Kosiński TargetSink target_sink;
498*a03ca8b9SKrzysztof Kosiński target_sink.PutNext(3);
499*a03ca8b9SKrzysztof Kosiński target_sink.PutNext(5);
500*a03ca8b9SKrzysztof Kosiński TestSerialize(data, target_sink);
501*a03ca8b9SKrzysztof Kosiński }
502*a03ca8b9SKrzysztof Kosiński
TEST(PatchElementTest,Normal)503*a03ca8b9SKrzysztof Kosiński TEST(PatchElementTest, Normal) {
504*a03ca8b9SKrzysztof Kosiński ByteVector data = CreatePatchElement();
505*a03ca8b9SKrzysztof Kosiński
506*a03ca8b9SKrzysztof Kosiński PatchElementReader patch_element_reader =
507*a03ca8b9SKrzysztof Kosiński TestInitialize<PatchElementReader>(&data);
508*a03ca8b9SKrzysztof Kosiński
509*a03ca8b9SKrzysztof Kosiński ElementMatch element_match = patch_element_reader.element_match();
510*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kExeTypeWin32X86, element_match.exe_type());
511*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kExeTypeWin32X86, element_match.old_element.exe_type);
512*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kExeTypeWin32X86, element_match.new_element.exe_type);
513*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x1U, element_match.old_element.offset);
514*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x51U, element_match.old_element.size);
515*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x3U, element_match.new_element.offset);
516*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x13U, element_match.new_element.size);
517*a03ca8b9SKrzysztof Kosiński
518*a03ca8b9SKrzysztof Kosiński EquivalenceSource equivalence_source =
519*a03ca8b9SKrzysztof Kosiński patch_element_reader.GetEquivalenceSource();
520*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x10}), equivalence_source.src_skip());
521*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x00}), equivalence_source.dst_skip());
522*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x12}), equivalence_source.copy_count());
523*a03ca8b9SKrzysztof Kosiński
524*a03ca8b9SKrzysztof Kosiński ExtraDataSource extra_data_source = patch_element_reader.GetExtraDataSource();
525*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x13}), extra_data_source.extra_data());
526*a03ca8b9SKrzysztof Kosiński
527*a03ca8b9SKrzysztof Kosiński RawDeltaSource raw_delta_source = patch_element_reader.GetRawDeltaSource();
528*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x14}), raw_delta_source.raw_delta_skip());
529*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x15}), raw_delta_source.raw_delta_diff());
530*a03ca8b9SKrzysztof Kosiński
531*a03ca8b9SKrzysztof Kosiński ReferenceDeltaSource reference_delta_source =
532*a03ca8b9SKrzysztof Kosiński patch_element_reader.GetReferenceDeltaSource();
533*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x16}), reference_delta_source.reference_delta());
534*a03ca8b9SKrzysztof Kosiński
535*a03ca8b9SKrzysztof Kosiński TargetSource target_source1 =
536*a03ca8b9SKrzysztof Kosiński patch_element_reader.GetExtraTargetSource(PoolTag(0));
537*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x17}), target_source1.extra_targets());
538*a03ca8b9SKrzysztof Kosiński TargetSource target_source2 =
539*a03ca8b9SKrzysztof Kosiński patch_element_reader.GetExtraTargetSource(PoolTag(1));
540*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({}), target_source2.extra_targets());
541*a03ca8b9SKrzysztof Kosiński TargetSource target_source3 =
542*a03ca8b9SKrzysztof Kosiński patch_element_reader.GetExtraTargetSource(PoolTag(2));
543*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(ByteVector({0x18}), target_source3.extra_targets());
544*a03ca8b9SKrzysztof Kosiński
545*a03ca8b9SKrzysztof Kosiński PatchElementWriter patch_element_writer(element_match);
546*a03ca8b9SKrzysztof Kosiński
547*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetEquivalenceSink(
548*a03ca8b9SKrzysztof Kosiński EquivalenceSink({0x10}, {0x00}, {0x12}));
549*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetExtraDataSink(ExtraDataSink({0x13}));
550*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetRawDeltaSink(RawDeltaSink({0x14}, {0x15}));
551*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetReferenceDeltaSink(ReferenceDeltaSink({0x16}));
552*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetTargetSink(PoolTag(0), TargetSink({0x17}));
553*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetTargetSink(PoolTag(2), TargetSink({0x18}));
554*a03ca8b9SKrzysztof Kosiński TestSerialize(data, patch_element_writer);
555*a03ca8b9SKrzysztof Kosiński }
556*a03ca8b9SKrzysztof Kosiński
TEST(PatchElementTest,BadEquivalence)557*a03ca8b9SKrzysztof Kosiński TEST(PatchElementTest, BadEquivalence) {
558*a03ca8b9SKrzysztof Kosiński // If the "old" element is too small then the test should fail.
559*a03ca8b9SKrzysztof Kosiński {
560*a03ca8b9SKrzysztof Kosiński ByteVector data = CreatePatchElement();
561*a03ca8b9SKrzysztof Kosiński // old_length := 0x4 (too small).
562*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, old_length), 0x51, 0x04, &data);
563*a03ca8b9SKrzysztof Kosiński TestInvalidInitialize<PatchElementReader>(&data);
564*a03ca8b9SKrzysztof Kosiński }
565*a03ca8b9SKrzysztof Kosiński
566*a03ca8b9SKrzysztof Kosiński // If the "new" element is too small then the test should fail.
567*a03ca8b9SKrzysztof Kosiński {
568*a03ca8b9SKrzysztof Kosiński ByteVector data = CreatePatchElement();
569*a03ca8b9SKrzysztof Kosiński // new_length := 0x5 (too small).
570*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, new_length), 0x13, 0x05, &data);
571*a03ca8b9SKrzysztof Kosiński TestInvalidInitialize<PatchElementReader>(&data);
572*a03ca8b9SKrzysztof Kosiński }
573*a03ca8b9SKrzysztof Kosiński }
574*a03ca8b9SKrzysztof Kosiński
TEST(PatchElementTest,WrongExtraData)575*a03ca8b9SKrzysztof Kosiński TEST(PatchElementTest, WrongExtraData) {
576*a03ca8b9SKrzysztof Kosiński // Make "new" too large so insufficient extra data exists to cover the image.
577*a03ca8b9SKrzysztof Kosiński {
578*a03ca8b9SKrzysztof Kosiński ByteVector data = CreatePatchElement();
579*a03ca8b9SKrzysztof Kosiński // new_length := 0x14 (too large).
580*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, new_length), 0x13, 0x14, &data);
581*a03ca8b9SKrzysztof Kosiński TestInvalidInitialize<PatchElementReader>(&data);
582*a03ca8b9SKrzysztof Kosiński }
583*a03ca8b9SKrzysztof Kosiński // Make "new" too small so there is too much extra data.
584*a03ca8b9SKrzysztof Kosiński {
585*a03ca8b9SKrzysztof Kosiński ByteVector data = CreatePatchElement();
586*a03ca8b9SKrzysztof Kosiński // new_length := 0x12 (too small).
587*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, new_length), 0x13, 0x12, &data);
588*a03ca8b9SKrzysztof Kosiński TestInvalidInitialize<PatchElementReader>(&data);
589*a03ca8b9SKrzysztof Kosiński }
590*a03ca8b9SKrzysztof Kosiński }
591*a03ca8b9SKrzysztof Kosiński
TEST(PatchElementTest,WrongVersion)592*a03ca8b9SKrzysztof Kosiński TEST(PatchElementTest, WrongVersion) {
593*a03ca8b9SKrzysztof Kosiński // Bump element version to 2.
594*a03ca8b9SKrzysztof Kosiński {
595*a03ca8b9SKrzysztof Kosiński ByteVector data = CreatePatchElement();
596*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, version), 0x01, 0x02, &data);
597*a03ca8b9SKrzysztof Kosiński TestInvalidInitialize<PatchElementReader>(&data);
598*a03ca8b9SKrzysztof Kosiński }
599*a03ca8b9SKrzysztof Kosiński // Bump element version to 0.
600*a03ca8b9SKrzysztof Kosiński {
601*a03ca8b9SKrzysztof Kosiński ByteVector data = CreatePatchElement();
602*a03ca8b9SKrzysztof Kosiński ModifyByte(offsetof(PatchElementHeader, version), 0x01, 0x00, &data);
603*a03ca8b9SKrzysztof Kosiński TestInvalidInitialize<PatchElementReader>(&data);
604*a03ca8b9SKrzysztof Kosiński }
605*a03ca8b9SKrzysztof Kosiński }
606*a03ca8b9SKrzysztof Kosiński
TEST(EnsemblePatchTest,RawPatch)607*a03ca8b9SKrzysztof Kosiński TEST(EnsemblePatchTest, RawPatch) {
608*a03ca8b9SKrzysztof Kosiński ByteVector data = {
609*a03ca8b9SKrzysztof Kosiński // PatchHeader
610*a03ca8b9SKrzysztof Kosiński 0x5A, 0x75, 0x63, 0x63, // magic
611*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, 0x00, 0x00, // major/minor version
612*a03ca8b9SKrzysztof Kosiński 0x10, 0x32, 0x54, 0x76, // old_size
613*a03ca8b9SKrzysztof Kosiński 0x00, 0x11, 0x22, 0x33, // old_crc
614*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // new_size
615*a03ca8b9SKrzysztof Kosiński 0x44, 0x55, 0x66, 0x77, // new_crc
616*a03ca8b9SKrzysztof Kosiński
617*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // number of element
618*a03ca8b9SKrzysztof Kosiński
619*a03ca8b9SKrzysztof Kosiński // PatchElementHeader
620*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // old_offset
621*a03ca8b9SKrzysztof Kosiński 0x02, 0, 0, 0, // old_length
622*a03ca8b9SKrzysztof Kosiński 0x00, 0, 0, 0, // new_offset
623*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // new_length
624*a03ca8b9SKrzysztof Kosiński 'P', 'x', '8', '6', // exe_type = EXE_TYPE_WIN32_X8
625*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, // element version
626*a03ca8b9SKrzysztof Kosiński // EquivalenceSource
627*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // src_skip size
628*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // dst_skip size
629*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // copy_count size
630*a03ca8b9SKrzysztof Kosiński // ExtraDataSource
631*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // extra_data size
632*a03ca8b9SKrzysztof Kosiński 0x04, // extra_data content
633*a03ca8b9SKrzysztof Kosiński // RawDeltaSource
634*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_skip size
635*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_diff size
636*a03ca8b9SKrzysztof Kosiński // ReferenceDeltaSource
637*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // reference_delta size
638*a03ca8b9SKrzysztof Kosiński // PatchElementReader
639*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // pool count
640*a03ca8b9SKrzysztof Kosiński };
641*a03ca8b9SKrzysztof Kosiński
642*a03ca8b9SKrzysztof Kosiński EnsemblePatchReader ensemble_patch_reader =
643*a03ca8b9SKrzysztof Kosiński TestInitialize<EnsemblePatchReader>(&data);
644*a03ca8b9SKrzysztof Kosiński
645*a03ca8b9SKrzysztof Kosiński PatchHeader header = ensemble_patch_reader.header();
646*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(PatchHeader::kMagic, header.magic);
647*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kMajorVersion, header.major_version);
648*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kMinorVersion, header.minor_version);
649*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x76543210U, header.old_size);
650*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x33221100U, header.old_crc);
651*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x01U, header.new_size);
652*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0x77665544U, header.new_crc);
653*a03ca8b9SKrzysztof Kosiński
654*a03ca8b9SKrzysztof Kosiński const std::vector<PatchElementReader>& elements =
655*a03ca8b9SKrzysztof Kosiński ensemble_patch_reader.elements();
656*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(size_t(1), elements.size());
657*a03ca8b9SKrzysztof Kosiński
658*a03ca8b9SKrzysztof Kosiński EnsemblePatchWriter ensemble_patch_writer(header);
659*a03ca8b9SKrzysztof Kosiński PatchElementWriter patch_element_writer(elements[0].element_match());
660*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetEquivalenceSink({});
661*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetExtraDataSink(ExtraDataSink({0x04}));
662*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetRawDeltaSink({});
663*a03ca8b9SKrzysztof Kosiński patch_element_writer.SetReferenceDeltaSink({});
664*a03ca8b9SKrzysztof Kosiński ensemble_patch_writer.AddElement(std::move(patch_element_writer));
665*a03ca8b9SKrzysztof Kosiński
666*a03ca8b9SKrzysztof Kosiński TestSerialize(data, ensemble_patch_writer);
667*a03ca8b9SKrzysztof Kosiński }
668*a03ca8b9SKrzysztof Kosiński
TEST(EnsemblePatchTest,CheckFile)669*a03ca8b9SKrzysztof Kosiński TEST(EnsemblePatchTest, CheckFile) {
670*a03ca8b9SKrzysztof Kosiński ByteVector data = {
671*a03ca8b9SKrzysztof Kosiński // PatchHeader
672*a03ca8b9SKrzysztof Kosiński 0x5A, 0x75, 0x63, 0x63, // magic
673*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, 0x00, 0x00, // major/minor version
674*a03ca8b9SKrzysztof Kosiński 0x05, 0x00, 0x00, 0x00, // old_size
675*a03ca8b9SKrzysztof Kosiński 0xDF, 0x13, 0xE4, 0x10, // old_crc
676*a03ca8b9SKrzysztof Kosiński 0x03, 0x00, 0x00, 0x00, // new_size
677*a03ca8b9SKrzysztof Kosiński 0xDC, 0xF7, 0x00, 0x40, // new_crc
678*a03ca8b9SKrzysztof Kosiński
679*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // number of element
680*a03ca8b9SKrzysztof Kosiński
681*a03ca8b9SKrzysztof Kosiński // PatchElementHeader
682*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // old_offset
683*a03ca8b9SKrzysztof Kosiński 0x02, 0, 0, 0, // old_length
684*a03ca8b9SKrzysztof Kosiński 0x00, 0, 0, 0, // new_offset
685*a03ca8b9SKrzysztof Kosiński 0x03, 0, 0, 0, // new_length
686*a03ca8b9SKrzysztof Kosiński 'P', 'x', '8', '6', // exe_type = EXE_TYPE_WIN32_X86
687*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, // element version
688*a03ca8b9SKrzysztof Kosiński // EquivalenceSource
689*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // src_skip size
690*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // dst_skip size
691*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // copy_count size
692*a03ca8b9SKrzysztof Kosiński // ExtraDataSource
693*a03ca8b9SKrzysztof Kosiński 0x03, 0, 0, 0, // extra_data size
694*a03ca8b9SKrzysztof Kosiński 'A', 'B', 'C', // extra_data content
695*a03ca8b9SKrzysztof Kosiński // RawDeltaSource
696*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_skip size
697*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_diff size
698*a03ca8b9SKrzysztof Kosiński // ReferenceDeltaSource
699*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // reference_delta size
700*a03ca8b9SKrzysztof Kosiński // PatchElementReader
701*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // pool count
702*a03ca8b9SKrzysztof Kosiński };
703*a03ca8b9SKrzysztof Kosiński
704*a03ca8b9SKrzysztof Kosiński EnsemblePatchReader ensemble_patch_reader =
705*a03ca8b9SKrzysztof Kosiński TestInitialize<EnsemblePatchReader>(&data);
706*a03ca8b9SKrzysztof Kosiński
707*a03ca8b9SKrzysztof Kosiński ByteVector old_file = {0x10, 0x32, 0x54, 0x76, 0x98};
708*a03ca8b9SKrzysztof Kosiński ByteVector new_file = {0xBA, 0xDC, 0xFE};
709*a03ca8b9SKrzysztof Kosiński
710*a03ca8b9SKrzysztof Kosiński ConstBufferView old_image(old_file.data(), old_file.size());
711*a03ca8b9SKrzysztof Kosiński ConstBufferView new_image(new_file.data(), new_file.size());
712*a03ca8b9SKrzysztof Kosiński
713*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(ensemble_patch_reader.CheckOldFile(old_image));
714*a03ca8b9SKrzysztof Kosiński EXPECT_TRUE(ensemble_patch_reader.CheckNewFile(new_image));
715*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(ensemble_patch_reader.CheckOldFile(new_image));
716*a03ca8b9SKrzysztof Kosiński EXPECT_FALSE(ensemble_patch_reader.CheckNewFile(old_image));
717*a03ca8b9SKrzysztof Kosiński }
718*a03ca8b9SKrzysztof Kosiński
TEST(EnsemblePatchTest,InvalidMagic)719*a03ca8b9SKrzysztof Kosiński TEST(EnsemblePatchTest, InvalidMagic) {
720*a03ca8b9SKrzysztof Kosiński ByteVector data = {
721*a03ca8b9SKrzysztof Kosiński // PatchHeader
722*a03ca8b9SKrzysztof Kosiński 0x42, 0x42, 0x42, 0x42, // magic
723*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, 0x00, 0x00, // major/minor version
724*a03ca8b9SKrzysztof Kosiński 0x10, 0x32, 0x54, 0x76, // old_size
725*a03ca8b9SKrzysztof Kosiński 0x00, 0x11, 0x22, 0x33, // old_crc
726*a03ca8b9SKrzysztof Kosiński 0x03, 0x00, 0x00, 0x00, // new_size
727*a03ca8b9SKrzysztof Kosiński 0x44, 0x55, 0x66, 0x77, // new_crc
728*a03ca8b9SKrzysztof Kosiński
729*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // number of element
730*a03ca8b9SKrzysztof Kosiński
731*a03ca8b9SKrzysztof Kosiński // PatchElementHeader
732*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // old_offset
733*a03ca8b9SKrzysztof Kosiński 0x02, 0, 0, 0, // old_length
734*a03ca8b9SKrzysztof Kosiński 0x00, 0, 0, 0, // new_offset
735*a03ca8b9SKrzysztof Kosiński 0x03, 0, 0, 0, // new_length
736*a03ca8b9SKrzysztof Kosiński 'P', 'x', '8', '6', // exe_type = EXE_TYPE_WIN32_X86
737*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, // element version
738*a03ca8b9SKrzysztof Kosiński // EquivalenceSource
739*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // src_skip size
740*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // dst_skip size
741*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // copy_count size
742*a03ca8b9SKrzysztof Kosiński // ExtraDataSource
743*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // extra_data size
744*a03ca8b9SKrzysztof Kosiński // RawDeltaSource
745*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_skip size
746*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_diff size
747*a03ca8b9SKrzysztof Kosiński // ReferenceDeltaSource
748*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // reference_delta size
749*a03ca8b9SKrzysztof Kosiński // PatchElementReader
750*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // pool count
751*a03ca8b9SKrzysztof Kosiński };
752*a03ca8b9SKrzysztof Kosiński
753*a03ca8b9SKrzysztof Kosiński TestInvalidInitialize<EnsemblePatchReader>(&data);
754*a03ca8b9SKrzysztof Kosiński }
755*a03ca8b9SKrzysztof Kosiński
TEST(EnsemblePatchTest,InvalidVersion)756*a03ca8b9SKrzysztof Kosiński TEST(EnsemblePatchTest, InvalidVersion) {
757*a03ca8b9SKrzysztof Kosiński ByteVector data = {
758*a03ca8b9SKrzysztof Kosiński // PatchHeader
759*a03ca8b9SKrzysztof Kosiński 0x5A, 0x75, 0x63, 0x63, // magic
760*a03ca8b9SKrzysztof Kosiński 0x02, 0x01, 0x00, 0x00, // major/minor version
761*a03ca8b9SKrzysztof Kosiński 0x10, 0x32, 0x54, 0x76, // old_size
762*a03ca8b9SKrzysztof Kosiński 0x00, 0x11, 0x22, 0x33, // old_crc
763*a03ca8b9SKrzysztof Kosiński 0x03, 0x00, 0x00, 0x00, // new_size
764*a03ca8b9SKrzysztof Kosiński 0x44, 0x55, 0x66, 0x77, // new_crc
765*a03ca8b9SKrzysztof Kosiński
766*a03ca8b9SKrzysztof Kosiński 1, 0, 0, 0, // number of element
767*a03ca8b9SKrzysztof Kosiński
768*a03ca8b9SKrzysztof Kosiński // PatchElementHeader
769*a03ca8b9SKrzysztof Kosiński 0x01, 0, 0, 0, // old_offset
770*a03ca8b9SKrzysztof Kosiński 0x02, 0, 0, 0, // old_length
771*a03ca8b9SKrzysztof Kosiński 0x00, 0, 0, 0, // new_offset
772*a03ca8b9SKrzysztof Kosiński 0x03, 0, 0, 0, // new_length
773*a03ca8b9SKrzysztof Kosiński 'P', 'x', '8', '6', // exe_type = EXE_TYPE_WIN32_X86
774*a03ca8b9SKrzysztof Kosiński 0x01, 0x00, // element version
775*a03ca8b9SKrzysztof Kosiński // EquivalenceSource
776*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // src_skip size
777*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // dst_skip size
778*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // copy_count size
779*a03ca8b9SKrzysztof Kosiński // ExtraDataSource
780*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // extra_data size
781*a03ca8b9SKrzysztof Kosiński // RawDeltaSource
782*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_skip size
783*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // raw_delta_diff size
784*a03ca8b9SKrzysztof Kosiński // ReferenceDeltaSource
785*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // reference_delta size
786*a03ca8b9SKrzysztof Kosiński // PatchElementReader
787*a03ca8b9SKrzysztof Kosiński 0, 0, 0, 0, // pool count
788*a03ca8b9SKrzysztof Kosiński };
789*a03ca8b9SKrzysztof Kosiński
790*a03ca8b9SKrzysztof Kosiński TestInvalidInitialize<EnsemblePatchReader>(&data);
791*a03ca8b9SKrzysztof Kosiński }
792*a03ca8b9SKrzysztof Kosiński
793*a03ca8b9SKrzysztof Kosiński } // namespace zucchini
794