xref: /aosp_15_r20/external/zucchini/patch_read_write_unittest.cc (revision a03ca8b91e029cd15055c20c78c2e087c84792e4)
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