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