OLD | NEW |
| (Empty) |
1 // Copyright 2008 Google Inc. | |
2 // Author: Lincoln Smith | |
3 // | |
4 // Licensed under the Apache License, Version 2.0 (the "License"); | |
5 // you may not use this file except in compliance with the License. | |
6 // You may obtain a copy of the License at | |
7 // | |
8 // http://www.apache.org/licenses/LICENSE-2.0 | |
9 // | |
10 // Unless required by applicable law or agreed to in writing, software | |
11 // distributed under the License is distributed on an "AS IS" BASIS, | |
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 // See the License for the specific language governing permissions and | |
14 // limitations under the License. | |
15 | |
16 #include <config.h> | |
17 #include "google/vcdecoder.h" | |
18 #include <cstdlib> // free, posix_memalign | |
19 #include <cstring> // memcpy | |
20 #include <string> | |
21 #include "checksum.h" | |
22 #include "codetable.h" | |
23 #include "testing.h" | |
24 #include "varint_bigendian.h" | |
25 #include "vcdiff_defs.h" | |
26 | |
27 #ifdef HAVE_MALLOC_H | |
28 #include <malloc.h> | |
29 #endif // HAVE_MALLOC_H | |
30 | |
31 #ifdef HAVE_SYS_MMAN_H | |
32 #define _XOPEN_SOURCE 600 // posix_memalign | |
33 #include <sys/mman.h> // mprotect | |
34 #endif // HAVE_SYS_MMAN_H | |
35 | |
36 #ifdef HAVE_UNISTD_H | |
37 #include <unistd.h> // getpagesize | |
38 #endif // HAVE_UNISTD_H | |
39 | |
40 namespace open_vcdiff { | |
41 namespace { | |
42 | |
43 using std::string; | |
44 | |
45 // A base class used for all the decoder tests. Most tests use the same | |
46 // dictionary and target and construct the delta file in the same way. | |
47 // Those elements are provided as string members and can be modified or | |
48 // overwritten by each specific decoder test as needed. | |
49 class VCDiffDecoderTest : public testing::Test { | |
50 protected: | |
51 static const char kStandardFileHeader[]; | |
52 static const char kInterleavedFileHeader[]; | |
53 static const char kDictionary[]; | |
54 static const char kExpectedTarget[]; | |
55 static const char kExpectedAnnotatedTarget[]; | |
56 | |
57 VCDiffDecoderTest(); | |
58 | |
59 virtual ~VCDiffDecoderTest() {} | |
60 | |
61 virtual void SetUp(); | |
62 | |
63 // This function is called by SetUp(). It populates delta_file_ with the | |
64 // concatenated delta file header, delta window header, and delta window | |
65 // body, plus (if UseChecksum() is true) the corresponding checksum. | |
66 // It can be called again by a test that has modified the contents of | |
67 // delta_file_ and needs to restore them to their original state. | |
68 virtual void InitializeDeltaFile(); | |
69 | |
70 // This function adds an Adler32 checksum to the delta window header. | |
71 void AddChecksum(VCDChecksum checksum); | |
72 | |
73 // This function computes the Adler32 checksum for the expected target | |
74 // and adds it to the delta window header. | |
75 void ComputeAndAddChecksum(); | |
76 | |
77 // Write the maximum expressible positive 32-bit VarintBE | |
78 // (0x7FFFFFFF) at the given offset in the delta window. | |
79 void WriteMaxVarintAtOffset(int offset, int bytes_to_replace); | |
80 | |
81 // Write a negative 32-bit VarintBE (0x80000000) at the given offset | |
82 // in the delta window. | |
83 void WriteNegativeVarintAtOffset(int offset, int bytes_to_replace); | |
84 | |
85 // Write a VarintBE that has too many continuation bytes | |
86 // at the given offset in the delta window. | |
87 void WriteInvalidVarintAtOffset(int offset, int bytes_to_replace); | |
88 | |
89 // This function iterates through a list of fuzzers (bit masks used to corrupt | |
90 // bytes) and through positions in the delta file. Each time it is called, it | |
91 // attempts to corrupt a different byte in delta_file_ in a different way. If | |
92 // successful, it returns true. Once it exhausts the list of fuzzers and of | |
93 // byte positions in delta_file_, it returns false. | |
94 bool FuzzOneByteInDeltaFile(); | |
95 | |
96 // Assuming the length of the given string can be expressed as a VarintBE | |
97 // of length N, this function returns the byte at position which_byte, where | |
98 // 0 <= which_byte < N. | |
99 static char GetByteFromStringLength(const char* s, int which_byte) { | |
100 char varint_buf[VarintBE<int32_t>::kMaxBytes]; | |
101 VarintBE<int32_t>::Encode(static_cast<int32_t>(strlen(s)), varint_buf); | |
102 return varint_buf[which_byte]; | |
103 } | |
104 | |
105 // Assuming the length of the given string can be expressed as a one-byte | |
106 // VarintBE, this function returns that byte value. | |
107 static char StringLengthAsByte(const char* s) { | |
108 return GetByteFromStringLength(s, 0); | |
109 } | |
110 | |
111 // Assuming the length of the given string can be expressed as a two-byte | |
112 // VarintBE, this function returns the first byte of its representation. | |
113 static char FirstByteOfStringLength(const char* s) { | |
114 return GetByteFromStringLength(s, 0); | |
115 } | |
116 | |
117 // Assuming the length of the given string can be expressed as a two-byte | |
118 // VarintBE, this function returns the second byte of its representation. | |
119 static char SecondByteOfStringLength(const char* s) { | |
120 return GetByteFromStringLength(s, 1); | |
121 } | |
122 | |
123 VCDiffStreamingDecoder decoder_; | |
124 | |
125 // delta_file_ will be populated by InitializeDeltaFile() using the components | |
126 // delta_file_header_, delta_window_header_, and delta_window_body_. | |
127 string delta_file_; | |
128 | |
129 // This string is not populated during setup, but is used to receive the | |
130 // decoded target file in each test. | |
131 string output_; | |
132 | |
133 // Test fixtures that inherit from VCDiffDecoderTest can set these strings in | |
134 // their constructors to override their default values (which come from | |
135 // kDictionary, kExpectedTarget, etc.) | |
136 string dictionary_; | |
137 string expected_target_; | |
138 string expected_annotated_target_; | |
139 | |
140 // The components that will be used to construct delta_file_. | |
141 string delta_file_header_; | |
142 string delta_window_header_; | |
143 string delta_window_body_; | |
144 | |
145 private: | |
146 // These two counters are used by FuzzOneByteInDeltaFile() to iterate through | |
147 // different ways to corrupt the delta file. | |
148 size_t fuzzer_; | |
149 size_t fuzzed_byte_position_; | |
150 }; | |
151 | |
152 const char VCDiffDecoderTest::kStandardFileHeader[] = { | |
153 0xD6, // 'V' | 0x80 | |
154 0xC3, // 'C' | 0x80 | |
155 0xC4, // 'D' | 0x80 | |
156 0x00, // Draft standard version number | |
157 0x00 // Hdr_Indicator: no custom code table, no compression | |
158 }; | |
159 | |
160 const char VCDiffDecoderTest::kInterleavedFileHeader[] = { | |
161 0xD6, // 'V' | 0x80 | |
162 0xC3, // 'C' | 0x80 | |
163 0xC4, // 'D' | 0x80 | |
164 'S', // SDCH version code | |
165 0x00 // Hdr_Indicator: no custom code table, no compression | |
166 }; | |
167 | |
168 const char VCDiffDecoderTest::kDictionary[] = | |
169 "\"Just the place for a Snark!\" the Bellman cried,\n" | |
170 "As he landed his crew with care;\n" | |
171 "Supporting each man on the top of the tide\n" | |
172 "By a finger entwined in his hair.\n"; | |
173 | |
174 const char VCDiffDecoderTest::kExpectedTarget[] = | |
175 "\"Just the place for a Snark! I have said it twice:\n" | |
176 "That alone should encourage the crew.\n" | |
177 "Just the place for a Snark! I have said it thrice:\n" | |
178 "What I tell you three times is true.\"\n"; | |
179 | |
180 const char VCDiffDecoderTest::kExpectedAnnotatedTarget[] = | |
181 "<dmatch>\"Just the place for a Snark!</dmatch>" | |
182 "<literal> I have said it twice:\n" | |
183 "That alone should encourage the crew.\n</literal>" | |
184 "<bmatch>Just the place for a Snark! I have said it t</bmatch>" | |
185 "<literal>hr</literal>" | |
186 "<bmatch>ice:\n</bmatch>" | |
187 "<literal>What I te</literal>" | |
188 "<literal>ll</literal>" | |
189 "<literal> you three times is true.\"\n</literal>"; | |
190 | |
191 VCDiffDecoderTest::VCDiffDecoderTest() : fuzzer_(0), fuzzed_byte_position_(0) { | |
192 dictionary_ = kDictionary; | |
193 expected_target_ = kExpectedTarget; | |
194 expected_annotated_target_ = kExpectedAnnotatedTarget; | |
195 } | |
196 | |
197 void VCDiffDecoderTest::SetUp() { | |
198 InitializeDeltaFile(); | |
199 } | |
200 | |
201 void VCDiffDecoderTest::InitializeDeltaFile() { | |
202 delta_file_ = delta_file_header_ + delta_window_header_ + delta_window_body_; | |
203 } | |
204 | |
205 void VCDiffDecoderTest::AddChecksum(VCDChecksum checksum) { | |
206 int32_t checksum_as_int32 = static_cast<int32_t>(checksum); | |
207 delta_window_header_[0] |= VCD_CHECKSUM; | |
208 VarintBE<int32_t>::AppendToString(checksum_as_int32, &delta_window_header_); | |
209 // Adjust delta window size to include checksum. | |
210 // This method wouldn't work if adding to the length caused the VarintBE | |
211 // value to spill over into another byte. Luckily, this test data happens | |
212 // not to cause such an overflow. | |
213 delta_window_header_[4] += VarintBE<int32_t>::Length(checksum_as_int32); | |
214 } | |
215 | |
216 void VCDiffDecoderTest::ComputeAndAddChecksum() { | |
217 AddChecksum(ComputeAdler32(expected_target_.data(), | |
218 expected_target_.size())); | |
219 } | |
220 | |
221 // Write the maximum expressible positive 32-bit VarintBE | |
222 // (0x7FFFFFFF) at the given offset in the delta window. | |
223 void VCDiffDecoderTest::WriteMaxVarintAtOffset(int offset, | |
224 int bytes_to_replace) { | |
225 static const char kMaxVarint[] = { 0x87, 0xFF, 0xFF, 0xFF, 0x7F }; | |
226 delta_file_.replace(delta_file_header_.size() + offset, | |
227 bytes_to_replace, | |
228 kMaxVarint, | |
229 sizeof(kMaxVarint)); | |
230 } | |
231 | |
232 // Write a negative 32-bit VarintBE (0x80000000) at the given offset | |
233 // in the delta window. | |
234 void VCDiffDecoderTest::WriteNegativeVarintAtOffset(int offset, | |
235 int bytes_to_replace) { | |
236 static const char kNegativeVarint[] = { 0x88, 0x80, 0x80, 0x80, 0x00 }; | |
237 delta_file_.replace(delta_file_header_.size() + offset, | |
238 bytes_to_replace, | |
239 kNegativeVarint, | |
240 sizeof(kNegativeVarint)); | |
241 } | |
242 | |
243 // Write a VarintBE that has too many continuation bytes | |
244 // at the given offset in the delta window. | |
245 void VCDiffDecoderTest::WriteInvalidVarintAtOffset(int offset, | |
246 int bytes_to_replace) { | |
247 static const char kInvalidVarint[] = { 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }; | |
248 delta_file_.replace(delta_file_header_.size() + offset, | |
249 bytes_to_replace, | |
250 kInvalidVarint, | |
251 sizeof(kInvalidVarint)); | |
252 } | |
253 | |
254 bool VCDiffDecoderTest::FuzzOneByteInDeltaFile() { | |
255 static const struct Fuzzer { | |
256 char _and; | |
257 char _or; | |
258 char _xor; | |
259 } fuzzers[] = { | |
260 { 0xff, 0x80, 0x00 }, | |
261 { 0xff, 0xff, 0x00 }, | |
262 { 0xff, 0x00, 0x80 }, | |
263 { 0xff, 0x00, 0xff }, | |
264 { 0xff, 0x01, 0x00 }, | |
265 { 0x7f, 0x00, 0x00 }, | |
266 }; | |
267 | |
268 for (; fuzzer_ < (sizeof(fuzzers) / sizeof(fuzzers[0])); ++fuzzer_) { | |
269 for (; fuzzed_byte_position_ < delta_file_.size(); | |
270 ++fuzzed_byte_position_) { | |
271 char fuzzed_byte = (((delta_file_[fuzzed_byte_position_] | |
272 & fuzzers[fuzzer_]._and) | |
273 | fuzzers[fuzzer_]._or) | |
274 ^ fuzzers[fuzzer_]._xor); | |
275 if (fuzzed_byte != delta_file_[fuzzed_byte_position_]) { | |
276 delta_file_[fuzzed_byte_position_] = fuzzed_byte; | |
277 ++fuzzed_byte_position_; | |
278 return true; | |
279 } | |
280 } | |
281 fuzzed_byte_position_ = 0; | |
282 } | |
283 return false; | |
284 } | |
285 | |
286 // The "standard" decoder test, which decodes a delta file that uses the | |
287 // standard VCDIFF (RFC 3284) format with no extensions. | |
288 class VCDiffStandardDecoderTest : public VCDiffDecoderTest { | |
289 protected: | |
290 VCDiffStandardDecoderTest(); | |
291 virtual ~VCDiffStandardDecoderTest() {} | |
292 | |
293 private: | |
294 static const char kWindowHeader[]; | |
295 static const char kWindowBody[]; | |
296 }; | |
297 | |
298 const char VCDiffStandardDecoderTest::kWindowHeader[] = { | |
299 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
300 FirstByteOfStringLength(kDictionary), // Source segment size | |
301 SecondByteOfStringLength(kDictionary), | |
302 0x00, // Source segment position: start of dictionary | |
303 0x79, // Length of the delta encoding | |
304 FirstByteOfStringLength(kExpectedTarget), // Size of the target window | |
305 SecondByteOfStringLength(kExpectedTarget), | |
306 0x00, // Delta_indicator (no compression) | |
307 0x64, // length of data for ADDs and RUNs | |
308 0x0C, // length of instructions section | |
309 0x03 // length of addresses for COPYs | |
310 }; | |
311 | |
312 const char VCDiffStandardDecoderTest::kWindowBody[] = { | |
313 // Data for ADDs: 1st section (length 61) | |
314 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
315 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
316 'T', 'h', 'a', 't', ' ', | |
317 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
318 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
319 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
320 // Data for ADDs: 2nd section (length 2) | |
321 'h', 'r', | |
322 // Data for ADDs: 3rd section (length 9) | |
323 'W', 'h', 'a', 't', ' ', | |
324 'I', ' ', 't', 'e', | |
325 // Data for RUN: 4th section (length 1) | |
326 'l', | |
327 // Data for ADD: 4th section (length 27) | |
328 ' ', 'y', 'o', 'u', ' ', | |
329 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
330 't', 'r', 'u', 'e', '.', '\"', '\n', | |
331 // Instructions and sizes (length 13) | |
332 0x13, // VCD_COPY mode VCD_SELF, size 0 | |
333 0x1C, // Size of COPY (28) | |
334 0x01, // VCD_ADD size 0 | |
335 0x3D, // Size of ADD (61) | |
336 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
337 0x2C, // Size of COPY (44) | |
338 0xCB, // VCD_ADD size 2 + VCD_COPY mode NEAR(1), size 5 | |
339 0x0A, // VCD_ADD size 9 | |
340 0x00, // VCD_RUN size 0 | |
341 0x02, // Size of RUN (2) | |
342 0x01, // VCD_ADD size 0 | |
343 0x1B, // Size of ADD (27) | |
344 // Addresses for COPYs (length 3) | |
345 0x00, // Start of dictionary | |
346 0x58, // HERE mode address for 2nd copy (27+61 back from here_address) | |
347 0x2D // NEAR(1) mode address for 2nd copy (45 after prior address) | |
348 }; | |
349 | |
350 VCDiffStandardDecoderTest::VCDiffStandardDecoderTest() { | |
351 delta_file_header_.assign(kStandardFileHeader, sizeof(kStandardFileHeader)); | |
352 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
353 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
354 } | |
355 | |
356 TEST_F(VCDiffStandardDecoderTest, DecodeHeaderOnly) { | |
357 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
358 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), | |
359 delta_file_header_.size(), | |
360 &output_)); | |
361 EXPECT_TRUE(decoder_.FinishDecoding()); | |
362 EXPECT_EQ("", output_); | |
363 } | |
364 | |
365 TEST_F(VCDiffStandardDecoderTest, Decode) { | |
366 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
367 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
368 delta_file_.size(), | |
369 &output_)); | |
370 EXPECT_TRUE(decoder_.FinishDecoding()); | |
371 EXPECT_EQ(expected_target_, output_); | |
372 } | |
373 | |
374 // If we add a checksum to a standard-format delta file (without using format | |
375 // extensions), it will be interpreted as random bytes inserted into the middle | |
376 // of the file. The decode operation should fail, but where exactly it fails is | |
377 // not easy to predict. | |
378 TEST_F(VCDiffStandardDecoderTest, StandardFormatDoesNotSupportChecksum) { | |
379 ComputeAndAddChecksum(); | |
380 InitializeDeltaFile(); | |
381 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
382 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
383 delta_file_.size(), | |
384 &output_)); | |
385 EXPECT_EQ("", output_); | |
386 } | |
387 | |
388 // Remove one byte from the length of the chunk to process, and | |
389 // verify that an error is returned for FinishDecoding(). | |
390 TEST_F(VCDiffStandardDecoderTest, FinishAfterDecodingPartialWindow) { | |
391 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
392 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
393 delta_file_.size() - 1, | |
394 &output_)); | |
395 EXPECT_FALSE(decoder_.FinishDecoding()); | |
396 // The decoder should not create more target bytes than were expected. | |
397 EXPECT_GE(expected_target_.size(), output_.size()); | |
398 } | |
399 | |
400 TEST_F(VCDiffStandardDecoderTest, FinishAfterDecodingPartialWindowHeader) { | |
401 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
402 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
403 delta_file_header_.size() | |
404 + delta_window_header_.size() - 1, | |
405 &output_)); | |
406 EXPECT_FALSE(decoder_.FinishDecoding()); | |
407 EXPECT_EQ("", output_); | |
408 } | |
409 | |
410 // Fuzz bits to make sure decoder does not violently crash. | |
411 // This test has no expected behavior except that no crashes should occur. | |
412 // In some cases, changing bits will still decode to the correct target; | |
413 // for example, changing unused bits within a bitfield. | |
414 TEST_F(VCDiffStandardDecoderTest, FuzzBits) { | |
415 while (FuzzOneByteInDeltaFile()) { | |
416 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
417 if (decoder_.DecodeChunk(delta_file_.data(), | |
418 delta_file_.size(), | |
419 &output_)) { | |
420 decoder_.FinishDecoding(); | |
421 } | |
422 InitializeDeltaFile(); | |
423 output_.clear(); | |
424 } | |
425 } | |
426 | |
427 TEST_F(VCDiffStandardDecoderTest, CheckAnnotatedOutput) { | |
428 decoder_.EnableAnnotatedOutput(); | |
429 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
430 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
431 delta_file_.size(), | |
432 &output_)); | |
433 EXPECT_TRUE(decoder_.FinishDecoding()); | |
434 string annotated_output; | |
435 decoder_.GetAnnotatedOutput(&annotated_output); | |
436 EXPECT_EQ(expected_annotated_target_, annotated_output); | |
437 } | |
438 | |
439 // Change each element of the delta file window to an erroneous value | |
440 // and make sure it's caught as an error. | |
441 | |
442 TEST_F(VCDiffStandardDecoderTest, WinIndicatorHasBothSourceAndTarget) { | |
443 delta_file_[delta_file_header_.size()] = VCD_SOURCE + VCD_TARGET; | |
444 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
445 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
446 delta_file_.size(), | |
447 &output_)); | |
448 EXPECT_EQ("", output_); | |
449 } | |
450 | |
451 TEST_F(VCDiffStandardDecoderTest, OkayToSetUpperBitsOfWinIndicator) { | |
452 // It is not an error to set any of the other bits in Win_Indicator | |
453 // besides VCD_SOURCE and VCD_TARGET. | |
454 delta_file_[delta_file_header_.size()] = 0xFD; | |
455 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
456 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
457 delta_file_.size(), | |
458 &output_)); | |
459 EXPECT_TRUE(decoder_.FinishDecoding()); | |
460 EXPECT_EQ(expected_target_, output_); | |
461 } | |
462 | |
463 TEST_F(VCDiffStandardDecoderTest, CopyInstructionsShouldFailIfNoSourceSegment) { | |
464 // Replace the Win_Indicator and the source size and source offset with a | |
465 // single 0 byte (a Win_Indicator for a window with no source segment.) | |
466 delta_window_header_.replace(0, 4, "\0", 1); | |
467 InitializeDeltaFile(); | |
468 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
469 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
470 delta_file_.size(), | |
471 &output_)); | |
472 // The first COPY instruction should fail, so there should be no output | |
473 EXPECT_EQ("", output_); | |
474 } | |
475 | |
476 TEST_F(VCDiffStandardDecoderTest, SourceSegmentSizeExceedsDictionarySize) { | |
477 ++delta_file_[delta_file_header_.size() + 2]; // increment size | |
478 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
479 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
480 delta_file_.size(), | |
481 &output_)); | |
482 EXPECT_EQ("", output_); | |
483 } | |
484 | |
485 TEST_F(VCDiffStandardDecoderTest, SourceSegmentSizeMaxInt) { | |
486 WriteMaxVarintAtOffset(1, 2); | |
487 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
488 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
489 delta_file_.size(), | |
490 &output_)); | |
491 EXPECT_EQ("", output_); | |
492 } | |
493 | |
494 TEST_F(VCDiffStandardDecoderTest, SourceSegmentSizeNegative) { | |
495 WriteNegativeVarintAtOffset(1, 2); | |
496 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
497 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
498 delta_file_.size(), | |
499 &output_)); | |
500 EXPECT_EQ("", output_); | |
501 } | |
502 | |
503 TEST_F(VCDiffStandardDecoderTest, SourceSegmentSizeInvalid) { | |
504 WriteInvalidVarintAtOffset(1, 2); | |
505 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
506 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
507 delta_file_.size(), | |
508 &output_)); | |
509 EXPECT_EQ("", output_); | |
510 } | |
511 | |
512 TEST_F(VCDiffStandardDecoderTest, SourceSegmentEndExceedsDictionarySize) { | |
513 ++delta_file_[delta_file_header_.size() + 3]; // increment start pos | |
514 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
515 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
516 delta_file_.size(), | |
517 &output_)); | |
518 EXPECT_EQ("", output_); | |
519 } | |
520 | |
521 TEST_F(VCDiffStandardDecoderTest, SourceSegmentPosMaxInt) { | |
522 WriteMaxVarintAtOffset(3, 1); | |
523 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
524 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
525 delta_file_.size(), | |
526 &output_)); | |
527 EXPECT_EQ("", output_); | |
528 } | |
529 | |
530 TEST_F(VCDiffStandardDecoderTest, SourceSegmentPosNegative) { | |
531 WriteNegativeVarintAtOffset(3, 1); | |
532 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
533 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
534 delta_file_.size(), | |
535 &output_)); | |
536 EXPECT_EQ("", output_); | |
537 } | |
538 | |
539 TEST_F(VCDiffStandardDecoderTest, SourceSegmentPosInvalid) { | |
540 WriteInvalidVarintAtOffset(3, 1); | |
541 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
542 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
543 delta_file_.size(), | |
544 &output_)); | |
545 EXPECT_EQ("", output_); | |
546 } | |
547 | |
548 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthZero) { | |
549 delta_file_[delta_file_header_.size() + 4] = 0; | |
550 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
551 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
552 delta_file_.size(), | |
553 &output_)); | |
554 EXPECT_EQ("", output_); | |
555 } | |
556 | |
557 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthTooLargeByOne) { | |
558 ++delta_file_[delta_file_header_.size() + 4]; | |
559 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
560 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
561 delta_file_.size(), | |
562 &output_)); | |
563 EXPECT_EQ("", output_); | |
564 } | |
565 | |
566 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthTooSmallByOne) { | |
567 --delta_file_[delta_file_header_.size() + 4]; | |
568 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
569 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
570 delta_file_.size(), | |
571 &output_)); | |
572 EXPECT_EQ("", output_); | |
573 } | |
574 | |
575 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthMaxInt) { | |
576 WriteMaxVarintAtOffset(4, 1); | |
577 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
578 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
579 delta_file_.size(), | |
580 &output_)); | |
581 EXPECT_EQ("", output_); | |
582 } | |
583 | |
584 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthNegative) { | |
585 WriteNegativeVarintAtOffset(4, 1); | |
586 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
587 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
588 delta_file_.size(), | |
589 &output_)); | |
590 EXPECT_EQ("", output_); | |
591 } | |
592 | |
593 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthInvalid) { | |
594 WriteInvalidVarintAtOffset(4, 1); | |
595 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
596 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
597 delta_file_.size(), | |
598 &output_)); | |
599 EXPECT_EQ("", output_); | |
600 } | |
601 | |
602 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeZero) { | |
603 static const char zero_size[] = { 0x00 }; | |
604 delta_file_.replace(delta_file_header_.size() + 5, 2, zero_size, 1); | |
605 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
606 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
607 delta_file_.size(), | |
608 &output_)); | |
609 EXPECT_EQ("", output_); | |
610 } | |
611 | |
612 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeTooLargeByOne) { | |
613 ++delta_file_[delta_file_header_.size() + 6]; | |
614 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
615 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
616 delta_file_.size(), | |
617 &output_)); | |
618 EXPECT_EQ("", output_); | |
619 } | |
620 | |
621 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeTooSmallByOne) { | |
622 --delta_file_[delta_file_header_.size() + 6]; | |
623 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
624 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
625 delta_file_.size(), | |
626 &output_)); | |
627 EXPECT_EQ("", output_); | |
628 } | |
629 | |
630 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeMaxInt) { | |
631 WriteMaxVarintAtOffset(5, 2); | |
632 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
633 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
634 delta_file_.size(), | |
635 &output_)); | |
636 EXPECT_EQ("", output_); | |
637 } | |
638 | |
639 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeNegative) { | |
640 WriteNegativeVarintAtOffset(5, 2); | |
641 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
642 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
643 delta_file_.size(), | |
644 &output_)); | |
645 EXPECT_EQ("", output_); | |
646 } | |
647 | |
648 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeInvalid) { | |
649 WriteInvalidVarintAtOffset(5, 2); | |
650 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
651 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
652 delta_file_.size(), | |
653 &output_)); | |
654 EXPECT_EQ("", output_); | |
655 } | |
656 | |
657 TEST_F(VCDiffStandardDecoderTest, OkayToSetUpperBitsOfDeltaIndicator) { | |
658 delta_file_[delta_file_header_.size() + 7] = 0xF8; | |
659 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
660 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
661 delta_file_.size(), | |
662 &output_)); | |
663 EXPECT_TRUE(decoder_.FinishDecoding()); | |
664 EXPECT_EQ(expected_target_, output_); | |
665 } | |
666 | |
667 TEST_F(VCDiffStandardDecoderTest, DataCompressionNotSupported) { | |
668 delta_file_[delta_file_header_.size() + 7] = 0x01; | |
669 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
670 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
671 delta_file_.size(), | |
672 &output_)); | |
673 EXPECT_EQ("", output_); | |
674 } | |
675 | |
676 TEST_F(VCDiffStandardDecoderTest, InstructionCompressionNotSupported) { | |
677 delta_file_[delta_file_header_.size() + 7] = 0x02; | |
678 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
679 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
680 delta_file_.size(), | |
681 &output_)); | |
682 EXPECT_EQ("", output_); | |
683 } | |
684 | |
685 TEST_F(VCDiffStandardDecoderTest, AddressCompressionNotSupported) { | |
686 delta_file_[delta_file_header_.size() + 7] = 0x04; | |
687 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
688 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
689 delta_file_.size(), | |
690 &output_)); | |
691 EXPECT_EQ("", output_); | |
692 } | |
693 | |
694 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeZero) { | |
695 delta_file_[delta_file_header_.size() + 8] = 0; | |
696 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
697 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
698 delta_file_.size(), | |
699 &output_)); | |
700 EXPECT_EQ("", output_); | |
701 } | |
702 | |
703 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeTooLargeByOne) { | |
704 ++delta_file_[delta_file_header_.size() + 8]; | |
705 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
706 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
707 delta_file_.size(), | |
708 &output_)); | |
709 EXPECT_EQ("", output_); | |
710 } | |
711 | |
712 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeTooSmallByOne) { | |
713 --delta_file_[delta_file_header_.size() + 8]; | |
714 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
715 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
716 delta_file_.size(), | |
717 &output_)); | |
718 EXPECT_EQ("", output_); | |
719 } | |
720 | |
721 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeMaxInt) { | |
722 WriteMaxVarintAtOffset(8, 1); | |
723 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
724 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
725 delta_file_.size(), | |
726 &output_)); | |
727 EXPECT_EQ("", output_); | |
728 } | |
729 | |
730 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeNegative) { | |
731 WriteNegativeVarintAtOffset(8, 1); | |
732 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
733 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
734 delta_file_.size(), | |
735 &output_)); | |
736 EXPECT_EQ("", output_); | |
737 } | |
738 | |
739 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeInvalid) { | |
740 WriteInvalidVarintAtOffset(8, 1); | |
741 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
742 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
743 delta_file_.size(), | |
744 &output_)); | |
745 EXPECT_EQ("", output_); | |
746 } | |
747 | |
748 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeZero) { | |
749 delta_file_[delta_file_header_.size() + 9] = 0; | |
750 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
751 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
752 delta_file_.size(), | |
753 &output_)); | |
754 EXPECT_EQ("", output_); | |
755 } | |
756 | |
757 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeTooLargeByOne) { | |
758 ++delta_file_[delta_file_header_.size() + 9]; | |
759 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
760 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
761 delta_file_.size(), | |
762 &output_)); | |
763 EXPECT_EQ("", output_); | |
764 } | |
765 | |
766 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeTooSmallByOne) { | |
767 --delta_file_[delta_file_header_.size() + 9]; | |
768 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
769 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
770 delta_file_.size(), | |
771 &output_)); | |
772 EXPECT_EQ("", output_); | |
773 } | |
774 | |
775 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeMaxInt) { | |
776 WriteMaxVarintAtOffset(9, 1); | |
777 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
778 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
779 delta_file_.size(), | |
780 &output_)); | |
781 EXPECT_EQ("", output_); | |
782 } | |
783 | |
784 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeNegative) { | |
785 WriteNegativeVarintAtOffset(9, 1); | |
786 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
787 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
788 delta_file_.size(), | |
789 &output_)); | |
790 EXPECT_EQ("", output_); | |
791 } | |
792 | |
793 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeInvalid) { | |
794 WriteInvalidVarintAtOffset(9, 1); | |
795 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
796 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
797 delta_file_.size(), | |
798 &output_)); | |
799 EXPECT_EQ("", output_); | |
800 } | |
801 | |
802 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeZero) { | |
803 delta_file_[delta_file_header_.size() + 10] = 0; | |
804 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
805 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
806 delta_file_.size(), | |
807 &output_)); | |
808 EXPECT_EQ("", output_); | |
809 } | |
810 | |
811 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeTooLargeByOne) { | |
812 ++delta_file_[delta_file_header_.size() + 10]; | |
813 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
814 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
815 delta_file_.size(), | |
816 &output_)); | |
817 EXPECT_EQ("", output_); | |
818 } | |
819 | |
820 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeTooSmallByOne) { | |
821 --delta_file_[delta_file_header_.size() + 10]; | |
822 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
823 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
824 delta_file_.size(), | |
825 &output_)); | |
826 EXPECT_EQ("", output_); | |
827 } | |
828 | |
829 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeMaxInt) { | |
830 WriteMaxVarintAtOffset(10, 1); | |
831 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
832 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
833 delta_file_.size(), | |
834 &output_)); | |
835 EXPECT_EQ("", output_); | |
836 } | |
837 | |
838 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeNegative) { | |
839 WriteNegativeVarintAtOffset(10, 1); | |
840 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
841 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
842 delta_file_.size(), | |
843 &output_)); | |
844 EXPECT_EQ("", output_); | |
845 } | |
846 | |
847 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeInvalid) { | |
848 WriteInvalidVarintAtOffset(10, 1); | |
849 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
850 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
851 delta_file_.size(), | |
852 &output_)); | |
853 EXPECT_EQ("", output_); | |
854 } | |
855 | |
856 TEST_F(VCDiffStandardDecoderTest, InstructionsEndEarly) { | |
857 --delta_file_[delta_file_header_.size() + 9]; | |
858 ++delta_file_[delta_file_header_.size() + 10]; | |
859 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
860 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
861 delta_file_.size(), | |
862 &output_)); | |
863 EXPECT_EQ("", output_); | |
864 } | |
865 | |
866 // From this point on, the tests should also be run against the interleaved | |
867 // format. | |
868 | |
869 TEST_F(VCDiffStandardDecoderTest, CopyMoreThanExpectedTarget) { | |
870 delta_file_[delta_file_header_.size() + 0x70] = | |
871 FirstByteOfStringLength(kExpectedTarget); | |
872 delta_file_[delta_file_header_.size() + 0x71] = | |
873 SecondByteOfStringLength(kExpectedTarget) + 1; | |
874 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
875 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
876 delta_file_.size(), | |
877 &output_)); | |
878 EXPECT_EQ("", output_); | |
879 } | |
880 | |
881 TEST_F(VCDiffStandardDecoderTest, CopySizeZero) { | |
882 delta_file_[delta_file_header_.size() + 0x70] = 0; | |
883 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
884 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
885 delta_file_.size(), | |
886 &output_)); | |
887 EXPECT_EQ("", output_); | |
888 } | |
889 | |
890 TEST_F(VCDiffStandardDecoderTest, CopySizeTooLargeByOne) { | |
891 ++delta_file_[delta_file_header_.size() + 0x70]; | |
892 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
893 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
894 delta_file_.size(), | |
895 &output_)); | |
896 EXPECT_EQ("", output_); | |
897 } | |
898 | |
899 TEST_F(VCDiffStandardDecoderTest, CopySizeTooSmallByOne) { | |
900 --delta_file_[delta_file_header_.size() + 0x70]; | |
901 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
902 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
903 delta_file_.size(), | |
904 &output_)); | |
905 EXPECT_EQ("", output_); | |
906 } | |
907 | |
908 TEST_F(VCDiffStandardDecoderTest, CopySizeMaxInt) { | |
909 WriteMaxVarintAtOffset(0x70, 1); | |
910 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
911 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
912 delta_file_.size(), | |
913 &output_)); | |
914 EXPECT_EQ("", output_); | |
915 } | |
916 | |
917 TEST_F(VCDiffStandardDecoderTest, CopySizeNegative) { | |
918 WriteNegativeVarintAtOffset(0x70, 1); | |
919 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
920 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
921 delta_file_.size(), | |
922 &output_)); | |
923 EXPECT_EQ("", output_); | |
924 } | |
925 | |
926 TEST_F(VCDiffStandardDecoderTest, CopySizeInvalid) { | |
927 WriteInvalidVarintAtOffset(0x70, 1); | |
928 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
929 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
930 delta_file_.size(), | |
931 &output_)); | |
932 EXPECT_EQ("", output_); | |
933 } | |
934 | |
935 TEST_F(VCDiffStandardDecoderTest, CopyAddressBeyondHereAddress) { | |
936 delta_file_[delta_file_header_.size() + 0x7B] = | |
937 FirstByteOfStringLength(kDictionary); | |
938 delta_file_[delta_file_header_.size() + 0x7C] = | |
939 SecondByteOfStringLength(kDictionary); | |
940 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
941 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
942 delta_file_.size(), | |
943 &output_)); | |
944 EXPECT_EQ("", output_); | |
945 } | |
946 | |
947 TEST_F(VCDiffStandardDecoderTest, CopyAddressMaxInt) { | |
948 WriteMaxVarintAtOffset(0x7B, 1); | |
949 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
950 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
951 delta_file_.size(), | |
952 &output_)); | |
953 EXPECT_EQ("", output_); | |
954 } | |
955 | |
956 TEST_F(VCDiffStandardDecoderTest, CopyAddressNegative) { | |
957 WriteNegativeVarintAtOffset(0x70, 1); | |
958 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
959 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
960 delta_file_.size(), | |
961 &output_)); | |
962 EXPECT_EQ("", output_); | |
963 } | |
964 | |
965 TEST_F(VCDiffStandardDecoderTest, CopyAddressInvalid) { | |
966 WriteInvalidVarintAtOffset(0x70, 1); | |
967 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
968 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
969 delta_file_.size(), | |
970 &output_)); | |
971 EXPECT_EQ("", output_); | |
972 } | |
973 | |
974 TEST_F(VCDiffStandardDecoderTest, AddMoreThanExpectedTarget) { | |
975 delta_file_[delta_file_header_.size() + 0x72] = | |
976 FirstByteOfStringLength(kExpectedTarget); | |
977 delta_file_[delta_file_header_.size() + 0x73] = | |
978 SecondByteOfStringLength(kExpectedTarget) + 1; | |
979 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
980 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
981 delta_file_.size(), | |
982 &output_)); | |
983 EXPECT_EQ("", output_); | |
984 } | |
985 | |
986 TEST_F(VCDiffStandardDecoderTest, AddSizeZero) { | |
987 delta_file_[delta_file_header_.size() + 0x72] = 0; | |
988 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
989 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
990 delta_file_.size(), | |
991 &output_)); | |
992 EXPECT_EQ("", output_); | |
993 } | |
994 | |
995 TEST_F(VCDiffStandardDecoderTest, AddSizeTooLargeByOne) { | |
996 ++delta_file_[delta_file_header_.size() + 0x72]; | |
997 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
998 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
999 delta_file_.size(), | |
1000 &output_)); | |
1001 EXPECT_EQ("", output_); | |
1002 } | |
1003 | |
1004 TEST_F(VCDiffStandardDecoderTest, AddSizeTooSmallByOne) { | |
1005 --delta_file_[delta_file_header_.size() + 0x72]; | |
1006 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1007 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1008 delta_file_.size(), | |
1009 &output_)); | |
1010 EXPECT_EQ("", output_); | |
1011 } | |
1012 | |
1013 TEST_F(VCDiffStandardDecoderTest, AddSizeMaxInt) { | |
1014 WriteMaxVarintAtOffset(0x72, 1); | |
1015 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1016 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1017 delta_file_.size(), | |
1018 &output_)); | |
1019 EXPECT_EQ("", output_); | |
1020 } | |
1021 | |
1022 TEST_F(VCDiffStandardDecoderTest, AddSizeNegative) { | |
1023 WriteNegativeVarintAtOffset(0x72, 1); | |
1024 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1025 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1026 delta_file_.size(), | |
1027 &output_)); | |
1028 EXPECT_EQ("", output_); | |
1029 } | |
1030 | |
1031 TEST_F(VCDiffStandardDecoderTest, AddSizeInvalid) { | |
1032 WriteInvalidVarintAtOffset(0x72, 1); | |
1033 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1034 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1035 delta_file_.size(), | |
1036 &output_)); | |
1037 EXPECT_EQ("", output_); | |
1038 } | |
1039 | |
1040 TEST_F(VCDiffStandardDecoderTest, RunMoreThanExpectedTarget) { | |
1041 delta_file_[delta_file_header_.size() + 0x78] = | |
1042 FirstByteOfStringLength(kExpectedTarget); | |
1043 delta_file_[delta_file_header_.size() + 0x79] = | |
1044 SecondByteOfStringLength(kExpectedTarget) + 1; | |
1045 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1046 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1047 delta_file_.size(), | |
1048 &output_)); | |
1049 EXPECT_EQ("", output_); | |
1050 } | |
1051 | |
1052 TEST_F(VCDiffStandardDecoderTest, RunSizeZero) { | |
1053 delta_file_[delta_file_header_.size() + 0x78] = 0; | |
1054 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1055 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1056 delta_file_.size(), | |
1057 &output_)); | |
1058 EXPECT_EQ("", output_); | |
1059 } | |
1060 | |
1061 TEST_F(VCDiffStandardDecoderTest, RunSizeTooLargeByOne) { | |
1062 ++delta_file_[delta_file_header_.size() + 0x78]; | |
1063 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1064 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1065 delta_file_.size(), | |
1066 &output_)); | |
1067 EXPECT_EQ("", output_); | |
1068 } | |
1069 | |
1070 TEST_F(VCDiffStandardDecoderTest, RunSizeTooSmallByOne) { | |
1071 --delta_file_[delta_file_header_.size() + 0x78]; | |
1072 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1073 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1074 delta_file_.size(), | |
1075 &output_)); | |
1076 EXPECT_EQ("", output_); | |
1077 } | |
1078 | |
1079 TEST_F(VCDiffStandardDecoderTest, RunSizeMaxInt) { | |
1080 WriteMaxVarintAtOffset(0x78, 1); | |
1081 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1082 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1083 delta_file_.size(), | |
1084 &output_)); | |
1085 EXPECT_EQ("", output_); | |
1086 } | |
1087 | |
1088 TEST_F(VCDiffStandardDecoderTest, RunSizeNegative) { | |
1089 WriteNegativeVarintAtOffset(0x78, 1); | |
1090 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1091 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1092 delta_file_.size(), | |
1093 &output_)); | |
1094 EXPECT_EQ("", output_); | |
1095 } | |
1096 | |
1097 TEST_F(VCDiffStandardDecoderTest, RunSizeInvalid) { | |
1098 WriteInvalidVarintAtOffset(0x78, 1); | |
1099 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1100 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
1101 delta_file_.size(), | |
1102 &output_)); | |
1103 EXPECT_EQ("", output_); | |
1104 } | |
1105 | |
1106 // These are the same tests as for VCDiffStandardDecoderTest, with the added | |
1107 // complication that instead of calling DecodeChunk() once with the entire data | |
1108 // set, DecodeChunk() is called once for each byte of input. This is intended | |
1109 // to shake out any bugs with rewind and resume while parsing chunked data. | |
1110 | |
1111 typedef VCDiffStandardDecoderTest VCDiffStandardDecoderTestByteByByte; | |
1112 | |
1113 TEST_F(VCDiffStandardDecoderTestByteByByte, DecodeHeaderOnly) { | |
1114 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1115 for (size_t i = 0; i < delta_file_header_.size(); ++i) { | |
1116 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_header_[i], 1, &output_)); | |
1117 } | |
1118 EXPECT_TRUE(decoder_.FinishDecoding()); | |
1119 EXPECT_EQ("", output_); | |
1120 } | |
1121 | |
1122 TEST_F(VCDiffStandardDecoderTestByteByByte, Decode) { | |
1123 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1124 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1125 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
1126 } | |
1127 EXPECT_TRUE(decoder_.FinishDecoding()); | |
1128 EXPECT_EQ(expected_target_, output_); | |
1129 } | |
1130 | |
1131 // Remove one byte from the length of the chunk to process, and | |
1132 // verify that an error is returned for FinishDecoding(). | |
1133 TEST_F(VCDiffStandardDecoderTestByteByByte, FinishAfterDecodingPartialWindow) { | |
1134 delta_file_.resize(delta_file_.size() - 1); | |
1135 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1136 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1137 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
1138 } | |
1139 EXPECT_FALSE(decoder_.FinishDecoding()); | |
1140 // The decoder should not create more target bytes than were expected. | |
1141 EXPECT_GE(expected_target_.size(), output_.size()); | |
1142 } | |
1143 | |
1144 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
1145 FinishAfterDecodingPartialWindowHeader) { | |
1146 delta_file_.resize(delta_file_header_.size() | |
1147 + delta_window_header_.size() - 1); | |
1148 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1149 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1150 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
1151 } | |
1152 EXPECT_FALSE(decoder_.FinishDecoding()); | |
1153 EXPECT_EQ("", output_); | |
1154 } | |
1155 | |
1156 // If we add a checksum to a standard-format delta file (without using format | |
1157 // extensions), it will be interpreted as random bytes inserted into the middle | |
1158 // of the file. The decode operation should fail, but where exactly it fails is | |
1159 // undefined. | |
1160 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
1161 StandardFormatDoesNotSupportChecksum) { | |
1162 ComputeAndAddChecksum(); | |
1163 InitializeDeltaFile(); | |
1164 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1165 bool failed = false; | |
1166 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1167 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1168 failed = true; | |
1169 break; | |
1170 } | |
1171 } | |
1172 EXPECT_TRUE(failed); | |
1173 // The decoder should not create more target bytes than were expected. | |
1174 EXPECT_GE(expected_target_.size(), output_.size()); | |
1175 } | |
1176 | |
1177 // Fuzz bits to make sure decoder does not violently crash. | |
1178 // This test has no expected behavior except that no crashes should occur. | |
1179 // In some cases, changing bits will still decode to the correct target; | |
1180 // for example, changing unused bits within a bitfield. | |
1181 TEST_F(VCDiffStandardDecoderTestByteByByte, FuzzBits) { | |
1182 while (FuzzOneByteInDeltaFile()) { | |
1183 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1184 bool failed = false; | |
1185 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1186 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1187 failed = true; | |
1188 break; | |
1189 } | |
1190 } | |
1191 if (!failed) { | |
1192 decoder_.FinishDecoding(); | |
1193 } | |
1194 // The decoder should not create more target bytes than were expected. | |
1195 EXPECT_GE(expected_target_.size(), output_.size()); | |
1196 InitializeDeltaFile(); | |
1197 output_.clear(); | |
1198 } | |
1199 } | |
1200 | |
1201 TEST_F(VCDiffStandardDecoderTestByteByByte, CheckAnnotatedOutput) { | |
1202 decoder_.EnableAnnotatedOutput(); | |
1203 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1204 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1205 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
1206 } | |
1207 EXPECT_TRUE(decoder_.FinishDecoding()); | |
1208 string annotated_output; | |
1209 decoder_.GetAnnotatedOutput(&annotated_output); | |
1210 EXPECT_EQ(expected_annotated_target_, annotated_output); | |
1211 } | |
1212 | |
1213 // Change each element of the delta file window to an erroneous value | |
1214 // and make sure it's caught as an error. | |
1215 | |
1216 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
1217 WinIndicatorHasBothSourceAndTarget) { | |
1218 delta_file_[delta_file_header_.size()] = VCD_SOURCE + VCD_TARGET; | |
1219 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1220 bool failed = false; | |
1221 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1222 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1223 failed = true; | |
1224 // It should fail at the position that was altered | |
1225 EXPECT_EQ(delta_file_header_.size(), i); | |
1226 break; | |
1227 } | |
1228 } | |
1229 EXPECT_TRUE(failed); | |
1230 EXPECT_EQ("", output_); | |
1231 } | |
1232 | |
1233 TEST_F(VCDiffStandardDecoderTestByteByByte, OkayToSetUpperBitsOfWinIndicator) { | |
1234 // It is not an error to set any of the other bits in Win_Indicator | |
1235 // besides VCD_SOURCE and VCD_TARGET. | |
1236 delta_file_[delta_file_header_.size()] = 0xFD; | |
1237 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1238 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1239 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
1240 } | |
1241 EXPECT_TRUE(decoder_.FinishDecoding()); | |
1242 EXPECT_EQ(expected_target_, output_); | |
1243 } | |
1244 | |
1245 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
1246 CopyInstructionsShouldFailIfNoSourceSegment) { | |
1247 // Replace the Win_Indicator and the source size and source offset with a | |
1248 // single 0 byte (a Win_Indicator for a window with no source segment.) | |
1249 delta_window_header_.replace(0, 4, "\0", 1); | |
1250 InitializeDeltaFile(); | |
1251 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1252 bool failed = false; | |
1253 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1254 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1255 failed = true; | |
1256 // The first COPY instruction should fail. With the standard format, | |
1257 // it may need to see the whole delta window before knowing that it is | |
1258 // invalid. | |
1259 break; | |
1260 } | |
1261 } | |
1262 EXPECT_TRUE(failed); | |
1263 EXPECT_EQ("", output_); | |
1264 } | |
1265 | |
1266 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
1267 SourceSegmentSizeExceedsDictionarySize) { | |
1268 ++delta_file_[delta_file_header_.size() + 2]; // increment size | |
1269 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1270 bool failed = false; | |
1271 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1272 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1273 failed = true; | |
1274 // It should fail after decoding the source segment size | |
1275 EXPECT_EQ(delta_file_header_.size() + 2, i); | |
1276 break; | |
1277 } | |
1278 } | |
1279 EXPECT_TRUE(failed); | |
1280 EXPECT_EQ("", output_); | |
1281 } | |
1282 | |
1283 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentSizeMaxInt) { | |
1284 WriteMaxVarintAtOffset(1, 2); | |
1285 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1286 bool failed = false; | |
1287 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1288 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1289 failed = true; | |
1290 // It should fail after decoding the source segment size | |
1291 EXPECT_EQ(delta_file_header_.size() + 5, i); | |
1292 break; | |
1293 } | |
1294 } | |
1295 EXPECT_TRUE(failed); | |
1296 EXPECT_EQ("", output_); | |
1297 } | |
1298 | |
1299 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentSizeNegative) { | |
1300 WriteNegativeVarintAtOffset(1, 2); | |
1301 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1302 bool failed = false; | |
1303 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1304 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1305 failed = true; | |
1306 // It should fail after decoding the source segment size | |
1307 EXPECT_EQ(delta_file_header_.size() + 5, i); | |
1308 break; | |
1309 } | |
1310 } | |
1311 EXPECT_TRUE(failed); | |
1312 EXPECT_EQ("", output_); | |
1313 } | |
1314 | |
1315 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentSizeInvalid) { | |
1316 WriteInvalidVarintAtOffset(1, 2); | |
1317 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1318 bool failed = false; | |
1319 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1320 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1321 failed = true; | |
1322 // It should fail after decoding the source segment size | |
1323 EXPECT_GE(delta_file_header_.size() + 6, i); | |
1324 break; | |
1325 } | |
1326 } | |
1327 EXPECT_TRUE(failed); | |
1328 EXPECT_EQ("", output_); | |
1329 } | |
1330 | |
1331 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
1332 SourceSegmentEndExceedsDictionarySize) { | |
1333 ++delta_file_[delta_file_header_.size() + 3]; // increment start pos | |
1334 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1335 bool failed = false; | |
1336 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1337 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1338 failed = true; | |
1339 // It should fail after decoding the source segment end | |
1340 EXPECT_EQ(delta_file_header_.size() + 3, i); | |
1341 break; | |
1342 } | |
1343 } | |
1344 EXPECT_TRUE(failed); | |
1345 EXPECT_EQ("", output_); | |
1346 } | |
1347 | |
1348 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentPosMaxInt) { | |
1349 WriteMaxVarintAtOffset(3, 1); | |
1350 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1351 bool failed = false; | |
1352 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1353 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1354 failed = true; | |
1355 // It should fail after decoding the source segment pos | |
1356 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
1357 break; | |
1358 } | |
1359 } | |
1360 EXPECT_TRUE(failed); | |
1361 EXPECT_EQ("", output_); | |
1362 } | |
1363 | |
1364 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentPosNegative) { | |
1365 WriteNegativeVarintAtOffset(3, 1); | |
1366 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1367 bool failed = false; | |
1368 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1369 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1370 failed = true; | |
1371 // It should fail after decoding the source segment pos | |
1372 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
1373 break; | |
1374 } | |
1375 } | |
1376 EXPECT_TRUE(failed); | |
1377 EXPECT_EQ("", output_); | |
1378 } | |
1379 | |
1380 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentPosInvalid) { | |
1381 WriteInvalidVarintAtOffset(3, 1); | |
1382 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1383 bool failed = false; | |
1384 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1385 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1386 failed = true; | |
1387 // It should fail after decoding the source segment pos | |
1388 EXPECT_GE(delta_file_header_.size() + 8, i); | |
1389 break; | |
1390 } | |
1391 } | |
1392 EXPECT_TRUE(failed); | |
1393 EXPECT_EQ("", output_); | |
1394 } | |
1395 | |
1396 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthZero) { | |
1397 delta_file_[delta_file_header_.size() + 4] = 0; | |
1398 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1399 bool failed = false; | |
1400 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1401 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1402 failed = true; | |
1403 // It should fail after decoding the copy address segment size | |
1404 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1405 break; | |
1406 } | |
1407 } | |
1408 EXPECT_TRUE(failed); | |
1409 EXPECT_EQ("", output_); | |
1410 } | |
1411 | |
1412 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthTooLargeByOne) { | |
1413 ++delta_file_[delta_file_header_.size() + 4]; | |
1414 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1415 bool failed = false; | |
1416 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1417 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1418 failed = true; | |
1419 // It should fail after decoding the copy address segment size | |
1420 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1421 break; | |
1422 } | |
1423 } | |
1424 EXPECT_TRUE(failed); | |
1425 EXPECT_EQ("", output_); | |
1426 } | |
1427 | |
1428 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthTooSmallByOne) { | |
1429 --delta_file_[delta_file_header_.size() + 4]; | |
1430 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1431 bool failed = false; | |
1432 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1433 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1434 failed = true; | |
1435 // It should fail after decoding the copy address segment size | |
1436 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1437 break; | |
1438 } | |
1439 } | |
1440 EXPECT_TRUE(failed); | |
1441 EXPECT_EQ("", output_); | |
1442 } | |
1443 | |
1444 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthMaxInt) { | |
1445 WriteMaxVarintAtOffset(4, 1); | |
1446 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1447 bool failed = false; | |
1448 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1449 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1450 failed = true; | |
1451 // It should fail before finishing the window header | |
1452 EXPECT_GE(delta_file_header_.size() + delta_window_header_.size() + 4, | |
1453 i); | |
1454 break; | |
1455 } | |
1456 } | |
1457 EXPECT_TRUE(failed); | |
1458 EXPECT_EQ("", output_); | |
1459 } | |
1460 | |
1461 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthNegative) { | |
1462 WriteNegativeVarintAtOffset(4, 1); | |
1463 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1464 bool failed = false; | |
1465 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1466 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1467 failed = true; | |
1468 // It should fail after decoding the delta encoding length | |
1469 EXPECT_EQ(delta_file_header_.size() + 8, i); | |
1470 break; | |
1471 } | |
1472 } | |
1473 EXPECT_TRUE(failed); | |
1474 EXPECT_EQ("", output_); | |
1475 } | |
1476 | |
1477 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthInvalid) { | |
1478 WriteInvalidVarintAtOffset(4, 1); | |
1479 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1480 bool failed = false; | |
1481 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1482 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1483 failed = true; | |
1484 // It should fail after decoding the delta encoding length | |
1485 EXPECT_GE(delta_file_header_.size() + 9, i); | |
1486 break; | |
1487 } | |
1488 } | |
1489 EXPECT_TRUE(failed); | |
1490 EXPECT_EQ("", output_); | |
1491 } | |
1492 | |
1493 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeZero) { | |
1494 static const char zero_size[] = { 0x00 }; | |
1495 delta_file_.replace(delta_file_header_.size() + 5, 2, zero_size, 1); | |
1496 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1497 bool failed = false; | |
1498 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1499 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1500 failed = true; | |
1501 break; | |
1502 } | |
1503 } | |
1504 EXPECT_TRUE(failed); | |
1505 EXPECT_EQ("", output_); | |
1506 } | |
1507 | |
1508 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeTooLargeByOne) { | |
1509 ++delta_file_[delta_file_header_.size() + 6]; | |
1510 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1511 bool failed = false; | |
1512 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1513 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1514 failed = true; | |
1515 break; | |
1516 } | |
1517 } | |
1518 EXPECT_TRUE(failed); | |
1519 // The decoder should not create more target bytes than were expected. | |
1520 EXPECT_GE(expected_target_.size(), output_.size()); | |
1521 } | |
1522 | |
1523 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeTooSmallByOne) { | |
1524 --delta_file_[delta_file_header_.size() + 6]; | |
1525 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1526 bool failed = false; | |
1527 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1528 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1529 failed = true; | |
1530 break; | |
1531 } | |
1532 } | |
1533 EXPECT_TRUE(failed); | |
1534 // The decoder should not create more target bytes than were expected. | |
1535 EXPECT_GE(expected_target_.size(), output_.size()); | |
1536 } | |
1537 | |
1538 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeMaxInt) { | |
1539 WriteMaxVarintAtOffset(5, 2); | |
1540 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1541 bool failed = false; | |
1542 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1543 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1544 failed = true; | |
1545 // It should fail after decoding the target window size | |
1546 EXPECT_EQ(delta_file_header_.size() + 9, i); | |
1547 break; | |
1548 } | |
1549 } | |
1550 EXPECT_TRUE(failed); | |
1551 EXPECT_EQ("", output_); | |
1552 } | |
1553 | |
1554 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeNegative) { | |
1555 WriteNegativeVarintAtOffset(5, 2); | |
1556 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1557 bool failed = false; | |
1558 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1559 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1560 failed = true; | |
1561 // It should fail after decoding the target window size | |
1562 EXPECT_EQ(delta_file_header_.size() + 9, i); | |
1563 break; | |
1564 } | |
1565 } | |
1566 EXPECT_TRUE(failed); | |
1567 EXPECT_EQ("", output_); | |
1568 } | |
1569 | |
1570 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeInvalid) { | |
1571 WriteInvalidVarintAtOffset(5, 2); | |
1572 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1573 bool failed = false; | |
1574 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1575 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1576 failed = true; | |
1577 // It should fail after decoding the target window size | |
1578 EXPECT_GE(delta_file_header_.size() + 10, i); | |
1579 break; | |
1580 } | |
1581 } | |
1582 EXPECT_TRUE(failed); | |
1583 EXPECT_EQ("", output_); | |
1584 } | |
1585 | |
1586 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
1587 OkayToSetUpperBitsOfDeltaIndicator) { | |
1588 delta_file_[delta_file_header_.size() + 7] = 0xF8; | |
1589 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1590 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1591 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
1592 } | |
1593 EXPECT_TRUE(decoder_.FinishDecoding()); | |
1594 EXPECT_EQ(expected_target_, output_); | |
1595 } | |
1596 | |
1597 TEST_F(VCDiffStandardDecoderTestByteByByte, DataCompressionNotSupported) { | |
1598 delta_file_[delta_file_header_.size() + 7] = 0x01; | |
1599 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1600 bool failed = false; | |
1601 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1602 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1603 failed = true; | |
1604 // It should fail after decoding the delta indicator | |
1605 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
1606 break; | |
1607 } | |
1608 } | |
1609 EXPECT_TRUE(failed); | |
1610 EXPECT_EQ("", output_); | |
1611 } | |
1612 | |
1613 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
1614 InstructionCompressionNotSupported) { | |
1615 delta_file_[delta_file_header_.size() + 7] = 0x02; | |
1616 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1617 bool failed = false; | |
1618 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1619 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1620 failed = true; | |
1621 // It should fail after decoding the delta indicator | |
1622 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
1623 break; | |
1624 } | |
1625 } | |
1626 EXPECT_TRUE(failed); | |
1627 EXPECT_EQ("", output_); | |
1628 } | |
1629 | |
1630 TEST_F(VCDiffStandardDecoderTestByteByByte, AddressCompressionNotSupported) { | |
1631 delta_file_[delta_file_header_.size() + 7] = 0x04; | |
1632 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1633 bool failed = false; | |
1634 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1635 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1636 failed = true; | |
1637 // It should fail after decoding the delta indicator | |
1638 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
1639 break; | |
1640 } | |
1641 } | |
1642 EXPECT_TRUE(failed); | |
1643 EXPECT_EQ("", output_); | |
1644 } | |
1645 | |
1646 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeZero) { | |
1647 delta_file_[delta_file_header_.size() + 8] = 0; | |
1648 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1649 bool failed = false; | |
1650 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1651 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1652 failed = true; | |
1653 // It should fail after decoding the copy address segment size | |
1654 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1655 break; | |
1656 } | |
1657 } | |
1658 EXPECT_TRUE(failed); | |
1659 EXPECT_EQ("", output_); | |
1660 } | |
1661 | |
1662 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeTooLargeByOne) { | |
1663 ++delta_file_[delta_file_header_.size() + 8]; | |
1664 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1665 bool failed = false; | |
1666 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1667 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1668 failed = true; | |
1669 // It should fail after decoding the copy address segment size | |
1670 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1671 break; | |
1672 } | |
1673 } | |
1674 EXPECT_TRUE(failed); | |
1675 EXPECT_EQ("", output_); | |
1676 } | |
1677 | |
1678 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeTooSmallByOne) { | |
1679 --delta_file_[delta_file_header_.size() + 8]; | |
1680 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1681 bool failed = false; | |
1682 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1683 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1684 failed = true; | |
1685 // It should fail after decoding the copy address segment size | |
1686 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1687 break; | |
1688 } | |
1689 } | |
1690 EXPECT_TRUE(failed); | |
1691 EXPECT_EQ("", output_); | |
1692 } | |
1693 | |
1694 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeMaxInt) { | |
1695 WriteMaxVarintAtOffset(8, 1); | |
1696 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1697 bool failed = false; | |
1698 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1699 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1700 failed = true; | |
1701 // It should fail before finishing the window header | |
1702 EXPECT_GE(delta_file_header_.size() + delta_window_header_.size() + 4, | |
1703 i); | |
1704 break; | |
1705 } | |
1706 } | |
1707 EXPECT_TRUE(failed); | |
1708 EXPECT_EQ("", output_); | |
1709 } | |
1710 | |
1711 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeNegative) { | |
1712 WriteNegativeVarintAtOffset(8, 1); | |
1713 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1714 bool failed = false; | |
1715 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1716 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1717 failed = true; | |
1718 // It should fail after decoding the add/run data segment size | |
1719 EXPECT_EQ(delta_file_header_.size() + 12, i); | |
1720 break; | |
1721 } | |
1722 } | |
1723 EXPECT_TRUE(failed); | |
1724 EXPECT_EQ("", output_); | |
1725 } | |
1726 | |
1727 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeInvalid) { | |
1728 WriteInvalidVarintAtOffset(8, 1); | |
1729 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1730 bool failed = false; | |
1731 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1732 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1733 failed = true; | |
1734 // It should fail after decoding the add/run data segment size | |
1735 EXPECT_GE(delta_file_header_.size() + 13, i); | |
1736 break; | |
1737 } | |
1738 } | |
1739 EXPECT_TRUE(failed); | |
1740 EXPECT_EQ("", output_); | |
1741 } | |
1742 | |
1743 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeZero) { | |
1744 delta_file_[delta_file_header_.size() + 9] = 0; | |
1745 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1746 bool failed = false; | |
1747 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1748 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1749 failed = true; | |
1750 // It should fail after decoding the copy address segment size | |
1751 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1752 break; | |
1753 } | |
1754 } | |
1755 EXPECT_TRUE(failed); | |
1756 EXPECT_EQ("", output_); | |
1757 } | |
1758 | |
1759 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeTooLargeByOne) { | |
1760 ++delta_file_[delta_file_header_.size() + 9]; | |
1761 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1762 bool failed = false; | |
1763 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1764 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1765 failed = true; | |
1766 // It should fail after decoding the copy address segment size | |
1767 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1768 break; | |
1769 } | |
1770 } | |
1771 EXPECT_TRUE(failed); | |
1772 EXPECT_EQ("", output_); | |
1773 } | |
1774 | |
1775 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeTooSmallByOne) { | |
1776 --delta_file_[delta_file_header_.size() + 9]; | |
1777 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1778 bool failed = false; | |
1779 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1780 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1781 failed = true; | |
1782 // It should fail after decoding the copy address segment size | |
1783 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1784 break; | |
1785 } | |
1786 } | |
1787 EXPECT_TRUE(failed); | |
1788 EXPECT_EQ("", output_); | |
1789 } | |
1790 | |
1791 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeMaxInt) { | |
1792 WriteMaxVarintAtOffset(9, 1); | |
1793 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1794 bool failed = false; | |
1795 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1796 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1797 failed = true; | |
1798 // It should fail before finishing the window header | |
1799 EXPECT_GE(delta_file_header_.size() + delta_window_header_.size() + 4, | |
1800 i); | |
1801 break; | |
1802 } | |
1803 } | |
1804 EXPECT_TRUE(failed); | |
1805 EXPECT_EQ("", output_); | |
1806 } | |
1807 | |
1808 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeNegative) { | |
1809 WriteNegativeVarintAtOffset(9, 1); | |
1810 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1811 bool failed = false; | |
1812 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1813 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1814 failed = true; | |
1815 // It should fail after decoding the instructions segment size | |
1816 EXPECT_EQ(delta_file_header_.size() + 13, i); | |
1817 break; | |
1818 } | |
1819 } | |
1820 EXPECT_TRUE(failed); | |
1821 EXPECT_EQ("", output_); | |
1822 } | |
1823 | |
1824 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeInvalid) { | |
1825 WriteInvalidVarintAtOffset(9, 1); | |
1826 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1827 bool failed = false; | |
1828 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1829 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1830 failed = true; | |
1831 // It should fail after decoding the instructions segment size | |
1832 EXPECT_GE(delta_file_header_.size() + 14, i); | |
1833 break; | |
1834 } | |
1835 } | |
1836 EXPECT_TRUE(failed); | |
1837 EXPECT_EQ("", output_); | |
1838 } | |
1839 | |
1840 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeZero) { | |
1841 delta_file_[delta_file_header_.size() + 10] = 0; | |
1842 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1843 bool failed = false; | |
1844 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1845 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1846 failed = true; | |
1847 // It should fail after decoding the copy address segment size | |
1848 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1849 break; | |
1850 } | |
1851 } | |
1852 EXPECT_TRUE(failed); | |
1853 EXPECT_EQ("", output_); | |
1854 } | |
1855 | |
1856 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeTooLargeByOne) { | |
1857 ++delta_file_[delta_file_header_.size() + 10]; | |
1858 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1859 bool failed = false; | |
1860 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1861 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1862 failed = true; | |
1863 // It should fail after decoding the copy address segment size | |
1864 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1865 break; | |
1866 } | |
1867 } | |
1868 EXPECT_TRUE(failed); | |
1869 EXPECT_EQ("", output_); | |
1870 } | |
1871 | |
1872 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeTooSmallByOne) { | |
1873 --delta_file_[delta_file_header_.size() + 10]; | |
1874 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1875 bool failed = false; | |
1876 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1877 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1878 failed = true; | |
1879 // It should fail after decoding the copy address segment size | |
1880 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
1881 break; | |
1882 } | |
1883 } | |
1884 EXPECT_TRUE(failed); | |
1885 EXPECT_EQ("", output_); | |
1886 } | |
1887 | |
1888 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeMaxInt) { | |
1889 WriteMaxVarintAtOffset(10, 1); | |
1890 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1891 bool failed = false; | |
1892 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1893 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1894 failed = true; | |
1895 // It should fail after decoding the copy address segment size | |
1896 EXPECT_EQ(delta_file_header_.size() + 14, i); | |
1897 break; | |
1898 } | |
1899 } | |
1900 EXPECT_TRUE(failed); | |
1901 EXPECT_EQ("", output_); | |
1902 } | |
1903 | |
1904 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeNegative) { | |
1905 WriteNegativeVarintAtOffset(10, 1); | |
1906 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1907 bool failed = false; | |
1908 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1909 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1910 failed = true; | |
1911 // It should fail after decoding the copy address segment size | |
1912 EXPECT_EQ(delta_file_header_.size() + 14, i); | |
1913 break; | |
1914 } | |
1915 } | |
1916 EXPECT_TRUE(failed); | |
1917 EXPECT_EQ("", output_); | |
1918 } | |
1919 | |
1920 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeInvalid) { | |
1921 WriteInvalidVarintAtOffset(10, 1); | |
1922 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1923 bool failed = false; | |
1924 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1925 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1926 failed = true; | |
1927 // It should fail after decoding the copy address segment size | |
1928 EXPECT_GE(delta_file_header_.size() + 15, i); | |
1929 break; | |
1930 } | |
1931 } | |
1932 EXPECT_TRUE(failed); | |
1933 EXPECT_EQ("", output_); | |
1934 } | |
1935 | |
1936 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsEndEarly) { | |
1937 --delta_file_[delta_file_header_.size() + 9]; | |
1938 ++delta_file_[delta_file_header_.size() + 10]; | |
1939 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1940 bool failed = false; | |
1941 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1942 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1943 failed = true; | |
1944 break; | |
1945 } | |
1946 } | |
1947 EXPECT_TRUE(failed); | |
1948 // The decoder should not create more target bytes than were expected. | |
1949 EXPECT_GE(expected_target_.size(), output_.size()); | |
1950 } | |
1951 | |
1952 // From this point on, the tests should also be run against the interleaved | |
1953 // format. | |
1954 | |
1955 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyMoreThanExpectedTarget) { | |
1956 delta_file_[delta_file_header_.size() + 0x70] = | |
1957 FirstByteOfStringLength(kExpectedTarget); | |
1958 delta_file_[delta_file_header_.size() + 0x71] = | |
1959 SecondByteOfStringLength(kExpectedTarget) + 1; | |
1960 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1961 bool failed = false; | |
1962 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1963 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1964 failed = true; | |
1965 break; | |
1966 } | |
1967 } | |
1968 EXPECT_TRUE(failed); | |
1969 // The decoder should not create more target bytes than were expected. | |
1970 EXPECT_GE(expected_target_.size(), output_.size()); | |
1971 } | |
1972 | |
1973 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeZero) { | |
1974 delta_file_[delta_file_header_.size() + 0x70] = 0; | |
1975 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1976 bool failed = false; | |
1977 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1978 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1979 failed = true; | |
1980 break; | |
1981 } | |
1982 } | |
1983 EXPECT_TRUE(failed); | |
1984 // The decoder should not create more target bytes than were expected. | |
1985 EXPECT_GE(expected_target_.size(), output_.size()); | |
1986 } | |
1987 | |
1988 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeTooLargeByOne) { | |
1989 ++delta_file_[delta_file_header_.size() + 0x70]; | |
1990 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
1991 bool failed = false; | |
1992 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
1993 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
1994 failed = true; | |
1995 break; | |
1996 } | |
1997 } | |
1998 EXPECT_TRUE(failed); | |
1999 // The decoder should not create more target bytes than were expected. | |
2000 EXPECT_GE(expected_target_.size(), output_.size()); | |
2001 } | |
2002 | |
2003 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeTooSmallByOne) { | |
2004 --delta_file_[delta_file_header_.size() + 0x70]; | |
2005 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2006 bool failed = false; | |
2007 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2008 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2009 failed = true; | |
2010 break; | |
2011 } | |
2012 } | |
2013 EXPECT_TRUE(failed); | |
2014 // The decoder should not create more target bytes than were expected. | |
2015 EXPECT_GE(expected_target_.size(), output_.size()); | |
2016 } | |
2017 | |
2018 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeMaxInt) { | |
2019 WriteMaxVarintAtOffset(0x70, 1); | |
2020 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2021 bool failed = false; | |
2022 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2023 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2024 failed = true; | |
2025 break; | |
2026 } | |
2027 } | |
2028 EXPECT_TRUE(failed); | |
2029 // The decoder should not create more target bytes than were expected. | |
2030 EXPECT_GE(expected_target_.size(), output_.size()); | |
2031 } | |
2032 | |
2033 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeNegative) { | |
2034 WriteNegativeVarintAtOffset(0x70, 1); | |
2035 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2036 bool failed = false; | |
2037 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2038 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2039 failed = true; | |
2040 break; | |
2041 } | |
2042 } | |
2043 EXPECT_TRUE(failed); | |
2044 // The decoder should not create more target bytes than were expected. | |
2045 EXPECT_GE(expected_target_.size(), output_.size()); | |
2046 } | |
2047 | |
2048 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeInvalid) { | |
2049 WriteInvalidVarintAtOffset(0x70, 1); | |
2050 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2051 bool failed = false; | |
2052 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2053 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2054 failed = true; | |
2055 break; | |
2056 } | |
2057 } | |
2058 EXPECT_TRUE(failed); | |
2059 // The decoder should not create more target bytes than were expected. | |
2060 EXPECT_GE(expected_target_.size(), output_.size()); | |
2061 } | |
2062 | |
2063 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressBeyondHereAddress) { | |
2064 delta_file_[delta_file_header_.size() + 0x7B] = | |
2065 FirstByteOfStringLength(kDictionary); | |
2066 delta_file_[delta_file_header_.size() + 0x7C] = | |
2067 SecondByteOfStringLength(kDictionary); | |
2068 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2069 bool failed = false; | |
2070 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2071 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2072 failed = true; | |
2073 break; | |
2074 } | |
2075 } | |
2076 EXPECT_TRUE(failed); | |
2077 // The decoder should not create more target bytes than were expected. | |
2078 EXPECT_GE(expected_target_.size(), output_.size()); | |
2079 } | |
2080 | |
2081 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressMaxInt) { | |
2082 WriteMaxVarintAtOffset(0x7B, 1); | |
2083 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2084 bool failed = false; | |
2085 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2086 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2087 failed = true; | |
2088 break; | |
2089 } | |
2090 } | |
2091 EXPECT_TRUE(failed); | |
2092 // The decoder should not create more target bytes than were expected. | |
2093 EXPECT_GE(expected_target_.size(), output_.size()); | |
2094 } | |
2095 | |
2096 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressNegative) { | |
2097 WriteNegativeVarintAtOffset(0x70, 1); | |
2098 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2099 bool failed = false; | |
2100 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2101 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2102 failed = true; | |
2103 break; | |
2104 } | |
2105 } | |
2106 EXPECT_TRUE(failed); | |
2107 // The decoder should not create more target bytes than were expected. | |
2108 EXPECT_GE(expected_target_.size(), output_.size()); | |
2109 } | |
2110 | |
2111 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressInvalid) { | |
2112 WriteInvalidVarintAtOffset(0x70, 1); | |
2113 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2114 bool failed = false; | |
2115 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2116 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2117 failed = true; | |
2118 break; | |
2119 } | |
2120 } | |
2121 EXPECT_TRUE(failed); | |
2122 // The decoder should not create more target bytes than were expected. | |
2123 EXPECT_GE(expected_target_.size(), output_.size()); | |
2124 } | |
2125 | |
2126 TEST_F(VCDiffStandardDecoderTestByteByByte, AddMoreThanExpectedTarget) { | |
2127 delta_file_[delta_file_header_.size() + 0x72] = | |
2128 FirstByteOfStringLength(kExpectedTarget); | |
2129 delta_file_[delta_file_header_.size() + 0x73] = | |
2130 SecondByteOfStringLength(kExpectedTarget) + 1; | |
2131 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2132 bool failed = false; | |
2133 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2134 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2135 failed = true; | |
2136 break; | |
2137 } | |
2138 } | |
2139 EXPECT_TRUE(failed); | |
2140 // The decoder should not create more target bytes than were expected. | |
2141 EXPECT_GE(expected_target_.size(), output_.size()); | |
2142 } | |
2143 | |
2144 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeZero) { | |
2145 delta_file_[delta_file_header_.size() + 0x72] = 0; | |
2146 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2147 bool failed = false; | |
2148 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2149 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2150 failed = true; | |
2151 break; | |
2152 } | |
2153 } | |
2154 EXPECT_TRUE(failed); | |
2155 // The decoder should not create more target bytes than were expected. | |
2156 EXPECT_GE(expected_target_.size(), output_.size()); | |
2157 } | |
2158 | |
2159 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeTooLargeByOne) { | |
2160 ++delta_file_[delta_file_header_.size() + 0x72]; | |
2161 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2162 bool failed = false; | |
2163 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2164 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2165 failed = true; | |
2166 break; | |
2167 } | |
2168 } | |
2169 EXPECT_TRUE(failed); | |
2170 // The decoder should not create more target bytes than were expected. | |
2171 EXPECT_GE(expected_target_.size(), output_.size()); | |
2172 } | |
2173 | |
2174 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeTooSmallByOne) { | |
2175 --delta_file_[delta_file_header_.size() + 0x72]; | |
2176 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2177 bool failed = false; | |
2178 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2179 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2180 failed = true; | |
2181 break; | |
2182 } | |
2183 } | |
2184 EXPECT_TRUE(failed); | |
2185 // The decoder should not create more target bytes than were expected. | |
2186 EXPECT_GE(expected_target_.size(), output_.size()); | |
2187 } | |
2188 | |
2189 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeMaxInt) { | |
2190 WriteMaxVarintAtOffset(0x72, 1); | |
2191 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2192 bool failed = false; | |
2193 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2194 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2195 failed = true; | |
2196 break; | |
2197 } | |
2198 } | |
2199 EXPECT_TRUE(failed); | |
2200 // The decoder should not create more target bytes than were expected. | |
2201 EXPECT_GE(expected_target_.size(), output_.size()); | |
2202 } | |
2203 | |
2204 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeNegative) { | |
2205 WriteNegativeVarintAtOffset(0x72, 1); | |
2206 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2207 bool failed = false; | |
2208 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2209 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2210 failed = true; | |
2211 break; | |
2212 } | |
2213 } | |
2214 EXPECT_TRUE(failed); | |
2215 // The decoder should not create more target bytes than were expected. | |
2216 EXPECT_GE(expected_target_.size(), output_.size()); | |
2217 } | |
2218 | |
2219 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeInvalid) { | |
2220 WriteInvalidVarintAtOffset(0x72, 1); | |
2221 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2222 bool failed = false; | |
2223 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2224 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2225 failed = true; | |
2226 break; | |
2227 } | |
2228 } | |
2229 EXPECT_TRUE(failed); | |
2230 // The decoder should not create more target bytes than were expected. | |
2231 EXPECT_GE(expected_target_.size(), output_.size()); | |
2232 } | |
2233 | |
2234 TEST_F(VCDiffStandardDecoderTestByteByByte, RunMoreThanExpectedTarget) { | |
2235 delta_file_[delta_file_header_.size() + 0x78] = | |
2236 FirstByteOfStringLength(kExpectedTarget); | |
2237 delta_file_[delta_file_header_.size() + 0x79] = | |
2238 SecondByteOfStringLength(kExpectedTarget) + 1; | |
2239 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2240 bool failed = false; | |
2241 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2242 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2243 failed = true; | |
2244 break; | |
2245 } | |
2246 } | |
2247 EXPECT_TRUE(failed); | |
2248 // The decoder should not create more target bytes than were expected. | |
2249 EXPECT_GE(expected_target_.size(), output_.size()); | |
2250 } | |
2251 | |
2252 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeZero) { | |
2253 delta_file_[delta_file_header_.size() + 0x78] = 0; | |
2254 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2255 bool failed = false; | |
2256 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2257 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2258 failed = true; | |
2259 break; | |
2260 } | |
2261 } | |
2262 EXPECT_TRUE(failed); | |
2263 // The decoder should not create more target bytes than were expected. | |
2264 EXPECT_GE(expected_target_.size(), output_.size()); | |
2265 } | |
2266 | |
2267 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeTooLargeByOne) { | |
2268 ++delta_file_[delta_file_header_.size() + 0x78]; | |
2269 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2270 bool failed = false; | |
2271 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2272 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2273 failed = true; | |
2274 break; | |
2275 } | |
2276 } | |
2277 EXPECT_TRUE(failed); | |
2278 // The decoder should not create more target bytes than were expected. | |
2279 EXPECT_GE(expected_target_.size(), output_.size()); | |
2280 } | |
2281 | |
2282 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeTooSmallByOne) { | |
2283 --delta_file_[delta_file_header_.size() + 0x78]; | |
2284 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2285 bool failed = false; | |
2286 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2287 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2288 failed = true; | |
2289 break; | |
2290 } | |
2291 } | |
2292 EXPECT_TRUE(failed); | |
2293 // The decoder should not create more target bytes than were expected. | |
2294 EXPECT_GE(expected_target_.size(), output_.size()); | |
2295 } | |
2296 | |
2297 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeMaxInt) { | |
2298 WriteMaxVarintAtOffset(0x78, 1); | |
2299 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2300 bool failed = false; | |
2301 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2302 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2303 failed = true; | |
2304 break; | |
2305 } | |
2306 } | |
2307 EXPECT_TRUE(failed); | |
2308 // The decoder should not create more target bytes than were expected. | |
2309 EXPECT_GE(expected_target_.size(), output_.size()); | |
2310 } | |
2311 | |
2312 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeNegative) { | |
2313 WriteNegativeVarintAtOffset(0x78, 1); | |
2314 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2315 bool failed = false; | |
2316 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2317 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2318 failed = true; | |
2319 break; | |
2320 } | |
2321 } | |
2322 EXPECT_TRUE(failed); | |
2323 // The decoder should not create more target bytes than were expected. | |
2324 EXPECT_GE(expected_target_.size(), output_.size()); | |
2325 } | |
2326 | |
2327 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeInvalid) { | |
2328 WriteInvalidVarintAtOffset(0x78, 1); | |
2329 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2330 bool failed = false; | |
2331 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2332 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2333 failed = true; | |
2334 break; | |
2335 } | |
2336 } | |
2337 EXPECT_TRUE(failed); | |
2338 // The decoder should not create more target bytes than were expected. | |
2339 EXPECT_GE(expected_target_.size(), output_.size()); | |
2340 } | |
2341 | |
2342 // The "interleaved" decoder test, which decodes a delta file that uses the | |
2343 // SDCH extension of interleaving instructions, addresses, and literal data | |
2344 // instead of placing them in three separate sections. | |
2345 class VCDiffInterleavedDecoderTest : public VCDiffDecoderTest { | |
2346 protected: | |
2347 VCDiffInterleavedDecoderTest(); | |
2348 virtual ~VCDiffInterleavedDecoderTest() {} | |
2349 | |
2350 private: | |
2351 static const char kWindowHeader[]; | |
2352 static const char kWindowBody[]; | |
2353 }; | |
2354 | |
2355 const char VCDiffInterleavedDecoderTest::kWindowHeader[] = { | |
2356 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
2357 FirstByteOfStringLength(kDictionary), // Source segment size | |
2358 SecondByteOfStringLength(kDictionary), | |
2359 0x00, // Source segment position: start of dictionary | |
2360 0x79, // Length of the delta encoding | |
2361 FirstByteOfStringLength(kExpectedTarget), // Size of the target window | |
2362 SecondByteOfStringLength(kExpectedTarget), | |
2363 0x00, // Delta_indicator (no compression) | |
2364 0x00, // length of data for ADDs and RUNs (unused) | |
2365 0x73, // length of interleaved section | |
2366 0x00 // length of addresses for COPYs (unused) | |
2367 }; | |
2368 | |
2369 const char VCDiffInterleavedDecoderTest::kWindowBody[] = { | |
2370 0x13, // VCD_COPY mode VCD_SELF, size 0 | |
2371 0x1C, // Size of COPY (28) | |
2372 0x00, // Address of COPY: Start of dictionary | |
2373 0x01, // VCD_ADD size 0 | |
2374 0x3D, // Size of ADD (61) | |
2375 // Data for ADD (length 61) | |
2376 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
2377 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
2378 'T', 'h', 'a', 't', ' ', | |
2379 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
2380 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
2381 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
2382 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
2383 0x2C, // Size of COPY (44) | |
2384 0x58, // HERE mode address (27+61 back from here_address) | |
2385 0xCB, // VCD_ADD size 2 + VCD_COPY mode NEAR(1), size 5 | |
2386 // Data for ADDs: 2nd section (length 2) | |
2387 'h', 'r', | |
2388 0x2D, // NEAR(1) mode address (45 after prior address) | |
2389 0x0A, // VCD_ADD size 9 | |
2390 // Data for ADDs: 3rd section (length 9) | |
2391 'W', 'h', 'a', 't', ' ', | |
2392 'I', ' ', 't', 'e', | |
2393 0x00, // VCD_RUN size 0 | |
2394 0x02, // Size of RUN (2) | |
2395 // Data for RUN: 4th section (length 1) | |
2396 'l', | |
2397 0x01, // VCD_ADD size 0 | |
2398 0x1B, // Size of ADD (27) | |
2399 // Data for ADD: 4th section (length 27) | |
2400 ' ', 'y', 'o', 'u', ' ', | |
2401 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
2402 't', 'r', 'u', 'e', '.', '\"', '\n' | |
2403 }; | |
2404 | |
2405 VCDiffInterleavedDecoderTest::VCDiffInterleavedDecoderTest() { | |
2406 delta_file_header_.assign(kInterleavedFileHeader, | |
2407 sizeof(kInterleavedFileHeader)); | |
2408 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
2409 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
2410 } | |
2411 | |
2412 // Test headers, valid and invalid. | |
2413 | |
2414 TEST_F(VCDiffInterleavedDecoderTest, DecodeHeaderOnly) { | |
2415 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2416 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), | |
2417 delta_file_header_.size(), | |
2418 &output_)); | |
2419 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2420 EXPECT_EQ("", output_); | |
2421 } | |
2422 | |
2423 TEST_F(VCDiffInterleavedDecoderTest, PartialHeaderNotEnough) { | |
2424 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2425 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), | |
2426 delta_file_header_.size() - 2, | |
2427 &output_)); | |
2428 EXPECT_FALSE(decoder_.FinishDecoding()); | |
2429 EXPECT_EQ("", output_); | |
2430 } | |
2431 | |
2432 TEST_F(VCDiffInterleavedDecoderTest, BadMagicNumber) { | |
2433 delta_file_[1] = 'Q' | 0x80; | |
2434 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2435 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2436 delta_file_.size(), | |
2437 &output_)); | |
2438 EXPECT_EQ("", output_); | |
2439 } | |
2440 | |
2441 TEST_F(VCDiffInterleavedDecoderTest, BadVersionNumber) { | |
2442 delta_file_[3] = 0x01; | |
2443 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2444 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2445 delta_file_.size(), | |
2446 &output_)); | |
2447 EXPECT_EQ("", output_); | |
2448 } | |
2449 | |
2450 TEST_F(VCDiffInterleavedDecoderTest, SecondaryCompressionNotSupported) { | |
2451 delta_file_[4] = 0x01; | |
2452 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2453 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2454 delta_file_.size(), | |
2455 &output_)); | |
2456 EXPECT_EQ("", output_); | |
2457 } | |
2458 | |
2459 TEST_F(VCDiffInterleavedDecoderTest, Decode) { | |
2460 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2461 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
2462 delta_file_.size(), | |
2463 &output_)); | |
2464 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2465 EXPECT_EQ(expected_target_, output_); | |
2466 } | |
2467 | |
2468 TEST_F(VCDiffInterleavedDecoderTest, DecodeWithChecksum) { | |
2469 ComputeAndAddChecksum(); | |
2470 InitializeDeltaFile(); | |
2471 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2472 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
2473 delta_file_.size(), | |
2474 &output_)); | |
2475 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2476 EXPECT_EQ(expected_target_, output_); | |
2477 } | |
2478 | |
2479 TEST_F(VCDiffInterleavedDecoderTest, ChecksumDoesNotMatch) { | |
2480 AddChecksum(0xBADBAD); | |
2481 InitializeDeltaFile(); | |
2482 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2483 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2484 delta_file_.size(), | |
2485 &output_)); | |
2486 EXPECT_EQ("", output_); | |
2487 } | |
2488 | |
2489 // Remove one byte from the length of the chunk to process, and | |
2490 // verify that an error is returned for FinishDecoding(). | |
2491 TEST_F(VCDiffInterleavedDecoderTest, FinishAfterDecodingPartialWindow) { | |
2492 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2493 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
2494 delta_file_.size() - 1, | |
2495 &output_)); | |
2496 EXPECT_FALSE(decoder_.FinishDecoding()); | |
2497 // The decoder should not create more target bytes than were expected. | |
2498 EXPECT_GE(expected_target_.size(), output_.size()); | |
2499 } | |
2500 | |
2501 TEST_F(VCDiffInterleavedDecoderTest, FinishAfterDecodingPartialWindowHeader) { | |
2502 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2503 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
2504 delta_file_header_.size() | |
2505 + delta_window_header_.size() - 1, | |
2506 &output_)); | |
2507 EXPECT_FALSE(decoder_.FinishDecoding()); | |
2508 // The decoder should not create more target bytes than were expected. | |
2509 EXPECT_GE(expected_target_.size(), output_.size()); | |
2510 } | |
2511 | |
2512 // Fuzz bits to make sure decoder does not violently crash. | |
2513 // This test has no expected behavior except that no crashes should occur. | |
2514 // In some cases, changing bits will still decode to the correct target; | |
2515 // for example, changing unused bits within a bitfield. | |
2516 TEST_F(VCDiffInterleavedDecoderTest, FuzzBits) { | |
2517 while (FuzzOneByteInDeltaFile()) { | |
2518 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2519 if (decoder_.DecodeChunk(delta_file_.data(), | |
2520 delta_file_.size(), | |
2521 &output_)) { | |
2522 decoder_.FinishDecoding(); | |
2523 } | |
2524 InitializeDeltaFile(); | |
2525 output_.clear(); | |
2526 } | |
2527 } | |
2528 | |
2529 // If a checksum is present, then fuzzing any of the bits may produce an error, | |
2530 // but it should not result in an incorrect target being produced without | |
2531 // an error. | |
2532 TEST_F(VCDiffInterleavedDecoderTest, FuzzBitsWithChecksum) { | |
2533 ComputeAndAddChecksum(); | |
2534 InitializeDeltaFile(); | |
2535 while (FuzzOneByteInDeltaFile()) { | |
2536 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2537 if (decoder_.DecodeChunk(delta_file_.data(), | |
2538 delta_file_.size(), | |
2539 &output_)) { | |
2540 if (decoder_.FinishDecoding()) { | |
2541 // Decoding succeeded. Make sure the correct target was produced. | |
2542 EXPECT_EQ(expected_target_, output_); | |
2543 } | |
2544 } else { | |
2545 EXPECT_EQ("", output_); | |
2546 } | |
2547 InitializeDeltaFile(); | |
2548 output_.clear(); | |
2549 } | |
2550 } | |
2551 | |
2552 TEST_F(VCDiffInterleavedDecoderTest, CheckAnnotatedOutput) { | |
2553 decoder_.EnableAnnotatedOutput(); | |
2554 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2555 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
2556 delta_file_.size(), | |
2557 &output_)); | |
2558 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2559 string annotated_output; | |
2560 decoder_.GetAnnotatedOutput(&annotated_output); | |
2561 EXPECT_EQ(expected_annotated_target_, annotated_output); | |
2562 } | |
2563 | |
2564 TEST_F(VCDiffInterleavedDecoderTest, CopyMoreThanExpectedTarget) { | |
2565 delta_file_[delta_file_header_.size() + 0x0C] = | |
2566 FirstByteOfStringLength(kExpectedTarget); | |
2567 delta_file_[delta_file_header_.size() + 0x0D] = | |
2568 SecondByteOfStringLength(kExpectedTarget) + 1; | |
2569 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2570 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2571 delta_file_.size(), | |
2572 &output_)); | |
2573 EXPECT_EQ("", output_); | |
2574 } | |
2575 | |
2576 TEST_F(VCDiffInterleavedDecoderTest, CopySizeZero) { | |
2577 delta_file_[delta_file_header_.size() + 0x0C] = 0; | |
2578 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2579 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2580 delta_file_.size(), | |
2581 &output_)); | |
2582 EXPECT_EQ("", output_); | |
2583 } | |
2584 | |
2585 TEST_F(VCDiffInterleavedDecoderTest, CopySizeTooLargeByOne) { | |
2586 ++delta_file_[delta_file_header_.size() + 0x0C]; | |
2587 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2588 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2589 delta_file_.size(), | |
2590 &output_)); | |
2591 EXPECT_EQ("", output_); | |
2592 } | |
2593 | |
2594 TEST_F(VCDiffInterleavedDecoderTest, CopySizeTooSmallByOne) { | |
2595 --delta_file_[delta_file_header_.size() + 0x0C]; | |
2596 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2597 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2598 delta_file_.size(), | |
2599 &output_)); | |
2600 EXPECT_EQ("", output_); | |
2601 } | |
2602 | |
2603 TEST_F(VCDiffInterleavedDecoderTest, CopySizeMaxInt) { | |
2604 WriteMaxVarintAtOffset(0x0C, 1); | |
2605 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2606 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2607 delta_file_.size(), | |
2608 &output_)); | |
2609 EXPECT_EQ("", output_); | |
2610 } | |
2611 | |
2612 TEST_F(VCDiffInterleavedDecoderTest, CopySizeNegative) { | |
2613 WriteNegativeVarintAtOffset(0x0C, 1); | |
2614 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2615 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2616 delta_file_.size(), | |
2617 &output_)); | |
2618 EXPECT_EQ("", output_); | |
2619 } | |
2620 | |
2621 TEST_F(VCDiffInterleavedDecoderTest, CopySizeInvalid) { | |
2622 WriteInvalidVarintAtOffset(0x0C, 1); | |
2623 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2624 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2625 delta_file_.size(), | |
2626 &output_)); | |
2627 EXPECT_EQ("", output_); | |
2628 } | |
2629 | |
2630 TEST_F(VCDiffInterleavedDecoderTest, CopyAddressBeyondHereAddress) { | |
2631 delta_file_[delta_file_header_.size() + 0x0D] = | |
2632 FirstByteOfStringLength(kDictionary); | |
2633 delta_file_[delta_file_header_.size() + 0x0E] = | |
2634 SecondByteOfStringLength(kDictionary); | |
2635 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2636 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2637 delta_file_.size(), | |
2638 &output_)); | |
2639 EXPECT_EQ("", output_); | |
2640 } | |
2641 | |
2642 TEST_F(VCDiffInterleavedDecoderTest, CopyAddressMaxInt) { | |
2643 WriteMaxVarintAtOffset(0x0D, 1); | |
2644 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2645 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2646 delta_file_.size(), | |
2647 &output_)); | |
2648 EXPECT_EQ("", output_); | |
2649 } | |
2650 | |
2651 TEST_F(VCDiffInterleavedDecoderTest, CopyAddressNegative) { | |
2652 WriteNegativeVarintAtOffset(0x0D, 1); | |
2653 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2654 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2655 delta_file_.size(), | |
2656 &output_)); | |
2657 EXPECT_EQ("", output_); | |
2658 } | |
2659 | |
2660 TEST_F(VCDiffInterleavedDecoderTest, CopyAddressInvalid) { | |
2661 WriteInvalidVarintAtOffset(0x0D, 1); | |
2662 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2663 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2664 delta_file_.size(), | |
2665 &output_)); | |
2666 EXPECT_EQ("", output_); | |
2667 } | |
2668 | |
2669 TEST_F(VCDiffInterleavedDecoderTest, AddMoreThanExpectedTarget) { | |
2670 delta_file_[delta_file_header_.size() + 0x0F] = | |
2671 FirstByteOfStringLength(kExpectedTarget); | |
2672 delta_file_[delta_file_header_.size() + 0x10] = | |
2673 SecondByteOfStringLength(kExpectedTarget) + 1; | |
2674 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2675 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2676 delta_file_.size(), | |
2677 &output_)); | |
2678 EXPECT_EQ("", output_); | |
2679 } | |
2680 | |
2681 TEST_F(VCDiffInterleavedDecoderTest, AddSizeZero) { | |
2682 delta_file_[delta_file_header_.size() + 0x0F] = 0; | |
2683 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2684 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2685 delta_file_.size(), | |
2686 &output_)); | |
2687 EXPECT_EQ("", output_); | |
2688 } | |
2689 | |
2690 TEST_F(VCDiffInterleavedDecoderTest, AddSizeTooLargeByOne) { | |
2691 ++delta_file_[delta_file_header_.size() + 0x0F]; | |
2692 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2693 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2694 delta_file_.size(), | |
2695 &output_)); | |
2696 EXPECT_EQ("", output_); | |
2697 } | |
2698 | |
2699 TEST_F(VCDiffInterleavedDecoderTest, AddSizeTooSmallByOne) { | |
2700 --delta_file_[delta_file_header_.size() + 0x0F]; | |
2701 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2702 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2703 delta_file_.size(), | |
2704 &output_)); | |
2705 EXPECT_EQ("", output_); | |
2706 } | |
2707 | |
2708 TEST_F(VCDiffInterleavedDecoderTest, AddSizeMaxInt) { | |
2709 WriteMaxVarintAtOffset(0x0F, 1); | |
2710 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2711 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2712 delta_file_.size(), | |
2713 &output_)); | |
2714 EXPECT_EQ("", output_); | |
2715 } | |
2716 | |
2717 TEST_F(VCDiffInterleavedDecoderTest, AddSizeNegative) { | |
2718 WriteNegativeVarintAtOffset(0x0F, 1); | |
2719 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2720 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2721 delta_file_.size(), | |
2722 &output_)); | |
2723 EXPECT_EQ("", output_); | |
2724 } | |
2725 | |
2726 TEST_F(VCDiffInterleavedDecoderTest, AddSizeInvalid) { | |
2727 WriteInvalidVarintAtOffset(0x0F, 1); | |
2728 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2729 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2730 delta_file_.size(), | |
2731 &output_)); | |
2732 EXPECT_EQ("", output_); | |
2733 } | |
2734 | |
2735 TEST_F(VCDiffInterleavedDecoderTest, RunMoreThanExpectedTarget) { | |
2736 delta_file_[delta_file_header_.size() + 0x5F] = | |
2737 FirstByteOfStringLength(kExpectedTarget); | |
2738 delta_file_[delta_file_header_.size() + 0x60] = | |
2739 SecondByteOfStringLength(kExpectedTarget) + 1; | |
2740 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2741 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2742 delta_file_.size(), | |
2743 &output_)); | |
2744 EXPECT_EQ("", output_); | |
2745 } | |
2746 | |
2747 TEST_F(VCDiffInterleavedDecoderTest, RunSizeZero) { | |
2748 delta_file_[delta_file_header_.size() + 0x5F] = 0; | |
2749 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2750 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2751 delta_file_.size(), | |
2752 &output_)); | |
2753 EXPECT_EQ("", output_); | |
2754 } | |
2755 | |
2756 TEST_F(VCDiffInterleavedDecoderTest, RunSizeTooLargeByOne) { | |
2757 ++delta_file_[delta_file_header_.size() + 0x5F]; | |
2758 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2759 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2760 delta_file_.size(), | |
2761 &output_)); | |
2762 EXPECT_EQ("", output_); | |
2763 } | |
2764 | |
2765 TEST_F(VCDiffInterleavedDecoderTest, RunSizeTooSmallByOne) { | |
2766 --delta_file_[delta_file_header_.size() + 0x5F]; | |
2767 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2768 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2769 delta_file_.size(), | |
2770 &output_)); | |
2771 EXPECT_EQ("", output_); | |
2772 } | |
2773 | |
2774 TEST_F(VCDiffInterleavedDecoderTest, RunSizeMaxInt) { | |
2775 WriteMaxVarintAtOffset(0x5F, 1); | |
2776 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2777 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2778 delta_file_.size(), | |
2779 &output_)); | |
2780 EXPECT_EQ("", output_); | |
2781 } | |
2782 | |
2783 TEST_F(VCDiffInterleavedDecoderTest, RunSizeNegative) { | |
2784 WriteNegativeVarintAtOffset(0x5F, 1); | |
2785 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2786 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2787 delta_file_.size(), | |
2788 &output_)); | |
2789 EXPECT_EQ("", output_); | |
2790 } | |
2791 | |
2792 TEST_F(VCDiffInterleavedDecoderTest, RunSizeInvalid) { | |
2793 WriteInvalidVarintAtOffset(0x5F, 1); | |
2794 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2795 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
2796 delta_file_.size(), | |
2797 &output_)); | |
2798 EXPECT_EQ("", output_); | |
2799 } | |
2800 | |
2801 #if defined(HAVE_MPROTECT) && \ | |
2802 (defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN)) | |
2803 TEST_F(VCDiffInterleavedDecoderTest, ShouldNotReadPastEndOfBuffer) { | |
2804 // Allocate two memory pages. | |
2805 const int page_size = getpagesize(); | |
2806 void* two_pages = NULL; | |
2807 #ifdef HAVE_POSIX_MEMALIGN | |
2808 posix_memalign(&two_pages, page_size, 2 * page_size); | |
2809 #else // !HAVE_POSIX_MEMALIGN | |
2810 two_pages = memalign(page_size, 2 * page_size); | |
2811 #endif // HAVE_POSIX_MEMALIGN | |
2812 char* const first_page = reinterpret_cast<char*>(two_pages); | |
2813 char* const second_page = first_page + page_size; | |
2814 | |
2815 // Place the delta string at the end of the first page. | |
2816 char* delta_with_guard = second_page - delta_file_.size(); | |
2817 memcpy(delta_with_guard, delta_file_.data(), delta_file_.size()); | |
2818 | |
2819 // Make the second page unreadable. | |
2820 mprotect(second_page, page_size, PROT_NONE); | |
2821 | |
2822 // Now perform the decode operation, which will cause a segmentation fault | |
2823 // if it reads past the end of the buffer. | |
2824 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2825 EXPECT_TRUE(decoder_.DecodeChunk(delta_with_guard, | |
2826 delta_file_.size(), | |
2827 &output_)); | |
2828 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2829 EXPECT_EQ(expected_target_, output_); | |
2830 | |
2831 // Undo the mprotect. | |
2832 mprotect(second_page, page_size, PROT_READ|PROT_WRITE); | |
2833 free(two_pages); | |
2834 } | |
2835 | |
2836 TEST_F(VCDiffInterleavedDecoderTest, ShouldNotReadPastBeginningOfBuffer) { | |
2837 // Allocate two memory pages. | |
2838 const int page_size = getpagesize(); | |
2839 void* two_pages = NULL; | |
2840 #ifdef HAVE_POSIX_MEMALIGN | |
2841 posix_memalign(&two_pages, page_size, 2 * page_size); | |
2842 #else // !HAVE_POSIX_MEMALIGN | |
2843 two_pages = memalign(page_size, 2 * page_size); | |
2844 #endif // HAVE_POSIX_MEMALIGN | |
2845 char* const first_page = reinterpret_cast<char*>(two_pages); | |
2846 char* const second_page = first_page + page_size; | |
2847 | |
2848 // Make the first page unreadable. | |
2849 mprotect(first_page, page_size, PROT_NONE); | |
2850 | |
2851 // Place the delta string at the beginning of the second page. | |
2852 char* delta_with_guard = second_page; | |
2853 memcpy(delta_with_guard, delta_file_.data(), delta_file_.size()); | |
2854 | |
2855 // Now perform the decode operation, which will cause a segmentation fault | |
2856 // if it reads past the beginning of the buffer. | |
2857 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2858 EXPECT_TRUE(decoder_.DecodeChunk(delta_with_guard, | |
2859 delta_file_.size(), | |
2860 &output_)); | |
2861 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2862 EXPECT_EQ(expected_target_, output_); | |
2863 | |
2864 // Undo the mprotect. | |
2865 mprotect(first_page, page_size, PROT_READ|PROT_WRITE); | |
2866 free(two_pages); | |
2867 } | |
2868 #endif // HAVE_MPROTECT && (HAVE_MEMALIGN || HAVE_POSIX_MEMALIGN) | |
2869 | |
2870 // These are the same tests as for VCDiffInterleavedDecoderTest, with the added | |
2871 // complication that instead of calling DecodeChunk() once with the entire data | |
2872 // set, DecodeChunk() is called once for each byte of input. This is intended | |
2873 // to shake out any bugs with rewind and resume while parsing chunked data. | |
2874 | |
2875 typedef VCDiffInterleavedDecoderTest VCDiffInterleavedDecoderTestByteByByte; | |
2876 | |
2877 // Test headers, valid and invalid. | |
2878 | |
2879 TEST_F(VCDiffInterleavedDecoderTestByteByByte, DecodeHeaderOnly) { | |
2880 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2881 for (size_t i = 0; i < delta_file_header_.size(); ++i) { | |
2882 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_header_[i], 1, &output_)); | |
2883 } | |
2884 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2885 EXPECT_EQ("", output_); | |
2886 } | |
2887 | |
2888 TEST_F(VCDiffInterleavedDecoderTestByteByByte, PartialHeaderNotEnough) { | |
2889 delta_file_.resize(delta_file_header_.size() - 2); | |
2890 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2891 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2892 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
2893 } | |
2894 EXPECT_FALSE(decoder_.FinishDecoding()); | |
2895 EXPECT_EQ("", output_); | |
2896 } | |
2897 | |
2898 TEST_F(VCDiffInterleavedDecoderTestByteByByte, BadMagicNumber) { | |
2899 delta_file_[1] = 'Q' | 0x80; | |
2900 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2901 bool failed = false; | |
2902 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2903 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2904 // It should fail at the position that was altered | |
2905 EXPECT_EQ(1U, i); | |
2906 failed = true; | |
2907 break; | |
2908 } | |
2909 } | |
2910 EXPECT_TRUE(failed); | |
2911 EXPECT_EQ("", output_); | |
2912 } | |
2913 | |
2914 TEST_F(VCDiffInterleavedDecoderTestByteByByte, BadVersionNumber) { | |
2915 delta_file_[3] = 0x01; | |
2916 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2917 bool failed = false; | |
2918 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2919 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2920 failed = true; | |
2921 // It should fail at the position that was altered | |
2922 EXPECT_EQ(3U, i); | |
2923 break; | |
2924 } | |
2925 } | |
2926 EXPECT_TRUE(failed); | |
2927 EXPECT_EQ("", output_); | |
2928 } | |
2929 | |
2930 TEST_F(VCDiffInterleavedDecoderTestByteByByte, | |
2931 SecondaryCompressionNotSupported) { | |
2932 delta_file_[4] = 0x01; | |
2933 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2934 bool failed = false; | |
2935 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2936 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2937 failed = true; | |
2938 // It should fail at the position that was altered | |
2939 EXPECT_EQ(4U, i); | |
2940 break; | |
2941 } | |
2942 } | |
2943 EXPECT_TRUE(failed); | |
2944 EXPECT_EQ("", output_); | |
2945 } | |
2946 | |
2947 TEST_F(VCDiffInterleavedDecoderTestByteByByte, Decode) { | |
2948 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2949 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2950 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
2951 } | |
2952 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2953 EXPECT_EQ(expected_target_, output_); | |
2954 } | |
2955 | |
2956 TEST_F(VCDiffInterleavedDecoderTestByteByByte, DecodeWithChecksum) { | |
2957 ComputeAndAddChecksum(); | |
2958 InitializeDeltaFile(); | |
2959 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2960 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2961 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
2962 } | |
2963 EXPECT_TRUE(decoder_.FinishDecoding()); | |
2964 EXPECT_EQ(expected_target_, output_); | |
2965 } | |
2966 | |
2967 TEST_F(VCDiffInterleavedDecoderTestByteByByte, ChecksumDoesNotMatch) { | |
2968 AddChecksum(0xBADBAD); | |
2969 InitializeDeltaFile(); | |
2970 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2971 bool failed = false; | |
2972 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2973 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2974 failed = true; | |
2975 // It should fail after decoding the entire delta file | |
2976 EXPECT_EQ(delta_file_.size() - 1, i); | |
2977 break; | |
2978 } | |
2979 } | |
2980 EXPECT_TRUE(failed); | |
2981 // The decoder should not create more target bytes than were expected. | |
2982 EXPECT_GE(expected_target_.size(), output_.size()); | |
2983 } | |
2984 | |
2985 // Fuzz bits to make sure decoder does not violently crash. | |
2986 // This test has no expected behavior except that no crashes should occur. | |
2987 // In some cases, changing bits will still decode to the correct target; | |
2988 // for example, changing unused bits within a bitfield. | |
2989 TEST_F(VCDiffInterleavedDecoderTestByteByByte, FuzzBits) { | |
2990 while (FuzzOneByteInDeltaFile()) { | |
2991 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
2992 bool failed = false; | |
2993 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
2994 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
2995 failed = true; | |
2996 break; | |
2997 } | |
2998 } | |
2999 if (!failed) { | |
3000 decoder_.FinishDecoding(); | |
3001 } | |
3002 InitializeDeltaFile(); | |
3003 output_.clear(); | |
3004 } | |
3005 } | |
3006 | |
3007 // If a checksum is present, then fuzzing any of the bits may produce an error, | |
3008 // but it should not result in an incorrect target being produced without | |
3009 // an error. | |
3010 TEST_F(VCDiffInterleavedDecoderTestByteByByte, FuzzBitsWithChecksum) { | |
3011 ComputeAndAddChecksum(); | |
3012 InitializeDeltaFile(); | |
3013 while (FuzzOneByteInDeltaFile()) { | |
3014 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3015 bool failed = false; | |
3016 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3017 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3018 failed = true; | |
3019 break; | |
3020 } | |
3021 } | |
3022 if (!failed) { | |
3023 if (decoder_.FinishDecoding()) { | |
3024 // Decoding succeeded. Make sure the correct target was produced. | |
3025 EXPECT_EQ(expected_target_, output_); | |
3026 } | |
3027 } | |
3028 // The decoder should not create more target bytes than were expected. | |
3029 EXPECT_GE(expected_target_.size(), output_.size()); | |
3030 InitializeDeltaFile(); | |
3031 output_.clear(); | |
3032 } | |
3033 } | |
3034 | |
3035 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CheckAnnotatedOutput) { | |
3036 decoder_.EnableAnnotatedOutput(); | |
3037 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3038 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3039 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
3040 } | |
3041 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3042 string annotated_output; | |
3043 decoder_.GetAnnotatedOutput(&annotated_output); | |
3044 EXPECT_EQ(expected_annotated_target_, annotated_output); | |
3045 } | |
3046 | |
3047 TEST_F(VCDiffInterleavedDecoderTestByteByByte, | |
3048 CopyInstructionsShouldFailIfNoSourceSegment) { | |
3049 // Replace the Win_Indicator and the source size and source offset with a | |
3050 // single 0 byte (a Win_Indicator for a window with no source segment.) | |
3051 delta_window_header_.replace(0, 4, "\0", 1); | |
3052 InitializeDeltaFile(); | |
3053 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3054 bool failed = false; | |
3055 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3056 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3057 failed = true; | |
3058 // The first COPY instruction should fail. | |
3059 EXPECT_EQ(delta_file_header_.size() + delta_window_header_.size() + 2, i); | |
3060 break; | |
3061 } | |
3062 } | |
3063 EXPECT_TRUE(failed); | |
3064 EXPECT_EQ("", output_); | |
3065 } | |
3066 | |
3067 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyMoreThanExpectedTarget) { | |
3068 delta_file_[delta_file_header_.size() + 0x0C] = | |
3069 FirstByteOfStringLength(kExpectedTarget); | |
3070 delta_file_[delta_file_header_.size() + 0x0D] = | |
3071 SecondByteOfStringLength(kExpectedTarget) + 1; | |
3072 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3073 bool failed = false; | |
3074 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3075 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3076 failed = true; | |
3077 // It should fail at the position that was altered | |
3078 EXPECT_EQ(delta_file_header_.size() + 0x0D, i); | |
3079 break; | |
3080 } | |
3081 } | |
3082 EXPECT_TRUE(failed); | |
3083 // The decoder should not create more target bytes than were expected. | |
3084 EXPECT_GE(expected_target_.size(), output_.size()); | |
3085 } | |
3086 | |
3087 // A COPY instruction with an explicit size of 0 is not illegal according to the | |
3088 // standard, although it is inefficient and should not be generated by any | |
3089 // reasonable encoder. Changing the size of a COPY instruction to zero will | |
3090 // cause a failure because the generated target window size will not match the | |
3091 // expected target size. | |
3092 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeZero) { | |
3093 delta_file_[delta_file_header_.size() + 0x0C] = 0; | |
3094 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3095 bool failed = false; | |
3096 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3097 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3098 failed = true; | |
3099 break; | |
3100 } | |
3101 } | |
3102 EXPECT_TRUE(failed); | |
3103 // The decoder should not create more target bytes than were expected. | |
3104 EXPECT_GE(expected_target_.size(), output_.size()); | |
3105 } | |
3106 | |
3107 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeTooLargeByOne) { | |
3108 ++delta_file_[delta_file_header_.size() + 0x0C]; | |
3109 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3110 bool failed = false; | |
3111 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3112 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3113 failed = true; | |
3114 break; | |
3115 } | |
3116 } | |
3117 EXPECT_TRUE(failed); | |
3118 // The decoder should not create more target bytes than were expected. | |
3119 EXPECT_GE(expected_target_.size(), output_.size()); | |
3120 } | |
3121 | |
3122 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeTooSmallByOne) { | |
3123 --delta_file_[delta_file_header_.size() + 0x0C]; | |
3124 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3125 bool failed = false; | |
3126 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3127 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3128 failed = true; | |
3129 break; | |
3130 } | |
3131 } | |
3132 EXPECT_TRUE(failed); | |
3133 // The decoder should not create more target bytes than were expected. | |
3134 EXPECT_GE(expected_target_.size(), output_.size()); | |
3135 } | |
3136 | |
3137 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeMaxInt) { | |
3138 WriteMaxVarintAtOffset(0x0C, 1); | |
3139 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3140 bool failed = false; | |
3141 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3142 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3143 failed = true; | |
3144 // It should fail at the position that was altered | |
3145 EXPECT_EQ(delta_file_header_.size() + 0x10, i); | |
3146 break; | |
3147 } | |
3148 } | |
3149 EXPECT_TRUE(failed); | |
3150 // The decoder should not create more target bytes than were expected. | |
3151 EXPECT_GE(expected_target_.size(), output_.size()); | |
3152 } | |
3153 | |
3154 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeNegative) { | |
3155 WriteNegativeVarintAtOffset(0x0C, 1); | |
3156 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3157 bool failed = false; | |
3158 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3159 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3160 failed = true; | |
3161 // It should fail at the position that was altered | |
3162 EXPECT_EQ(delta_file_header_.size() + 0x10, i); | |
3163 break; | |
3164 } | |
3165 } | |
3166 EXPECT_TRUE(failed); | |
3167 // The decoder should not create more target bytes than were expected. | |
3168 EXPECT_GE(expected_target_.size(), output_.size()); | |
3169 } | |
3170 | |
3171 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeInvalid) { | |
3172 WriteInvalidVarintAtOffset(0x0C, 1); | |
3173 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3174 bool failed = false; | |
3175 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3176 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3177 failed = true; | |
3178 // It should fail at the position that was altered | |
3179 EXPECT_EQ(delta_file_header_.size() + 0x10, i); | |
3180 break; | |
3181 } | |
3182 } | |
3183 EXPECT_TRUE(failed); | |
3184 // The decoder should not create more target bytes than were expected. | |
3185 EXPECT_GE(expected_target_.size(), output_.size()); | |
3186 } | |
3187 | |
3188 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressBeyondHereAddress) { | |
3189 delta_file_[delta_file_header_.size() + 0x0D] = | |
3190 FirstByteOfStringLength(kDictionary); | |
3191 delta_file_[delta_file_header_.size() + 0x0E] = | |
3192 SecondByteOfStringLength(kDictionary); | |
3193 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3194 bool failed = false; | |
3195 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3196 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3197 failed = true; | |
3198 // It should fail at the position that was altered | |
3199 EXPECT_EQ(delta_file_header_.size() + 0x0E, i); | |
3200 break; | |
3201 } | |
3202 } | |
3203 EXPECT_TRUE(failed); | |
3204 // The decoder should not create more target bytes than were expected. | |
3205 EXPECT_GE(expected_target_.size(), output_.size()); | |
3206 } | |
3207 | |
3208 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressMaxInt) { | |
3209 WriteMaxVarintAtOffset(0x0D, 1); | |
3210 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3211 bool failed = false; | |
3212 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3213 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3214 failed = true; | |
3215 // It should fail at the position that was altered | |
3216 EXPECT_EQ(delta_file_header_.size() + 0x11, i); | |
3217 break; | |
3218 } | |
3219 } | |
3220 EXPECT_TRUE(failed); | |
3221 // The decoder should not create more target bytes than were expected. | |
3222 EXPECT_GE(expected_target_.size(), output_.size()); | |
3223 } | |
3224 | |
3225 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressNegative) { | |
3226 WriteNegativeVarintAtOffset(0x0D, 1); | |
3227 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3228 bool failed = false; | |
3229 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3230 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3231 failed = true; | |
3232 // It should fail at the position that was altered | |
3233 EXPECT_EQ(delta_file_header_.size() + 0x11, i); | |
3234 break; | |
3235 } | |
3236 } | |
3237 EXPECT_TRUE(failed); | |
3238 // The decoder should not create more target bytes than were expected. | |
3239 EXPECT_GE(expected_target_.size(), output_.size()); | |
3240 } | |
3241 | |
3242 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressInvalid) { | |
3243 WriteInvalidVarintAtOffset(0x0D, 1); | |
3244 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3245 bool failed = false; | |
3246 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3247 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3248 failed = true; | |
3249 // It should fail at the position that was altered | |
3250 EXPECT_EQ(delta_file_header_.size() + 0x11, i); | |
3251 break; | |
3252 } | |
3253 } | |
3254 EXPECT_TRUE(failed); | |
3255 // The decoder should not create more target bytes than were expected. | |
3256 EXPECT_GE(expected_target_.size(), output_.size()); | |
3257 } | |
3258 | |
3259 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddMoreThanExpectedTarget) { | |
3260 delta_file_[delta_file_header_.size() + 0x0F] = | |
3261 FirstByteOfStringLength(kExpectedTarget); | |
3262 delta_file_[delta_file_header_.size() + 0x10] = | |
3263 SecondByteOfStringLength(kExpectedTarget) + 1; | |
3264 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3265 bool failed = false; | |
3266 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3267 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3268 failed = true; | |
3269 // It should fail at the position that was altered | |
3270 EXPECT_EQ(delta_file_header_.size() + 0x10, i); | |
3271 break; | |
3272 } | |
3273 } | |
3274 EXPECT_TRUE(failed); | |
3275 // The decoder should not create more target bytes than were expected. | |
3276 EXPECT_GE(expected_target_.size(), output_.size()); | |
3277 } | |
3278 | |
3279 // An ADD instruction with an explicit size of 0 is not illegal according to the | |
3280 // standard, although it is inefficient and should not be generated by any | |
3281 // reasonable encoder. Changing the size of an ADD instruction to zero will | |
3282 // cause a failure because the generated target window size will not match the | |
3283 // expected target size. | |
3284 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeZero) { | |
3285 delta_file_[delta_file_header_.size() + 0x0F] = 0; | |
3286 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3287 bool failed = false; | |
3288 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3289 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3290 failed = true; | |
3291 break; | |
3292 } | |
3293 } | |
3294 EXPECT_TRUE(failed); | |
3295 // The decoder should not create more target bytes than were expected. | |
3296 EXPECT_GE(expected_target_.size(), output_.size()); | |
3297 } | |
3298 | |
3299 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeTooLargeByOne) { | |
3300 ++delta_file_[delta_file_header_.size() + 0x0F]; | |
3301 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3302 bool failed = false; | |
3303 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3304 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3305 failed = true; | |
3306 break; | |
3307 } | |
3308 } | |
3309 EXPECT_TRUE(failed); | |
3310 // The decoder should not create more target bytes than were expected. | |
3311 EXPECT_GE(expected_target_.size(), output_.size()); | |
3312 } | |
3313 | |
3314 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeTooSmallByOne) { | |
3315 --delta_file_[delta_file_header_.size() + 0x0F]; | |
3316 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3317 bool failed = false; | |
3318 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3319 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3320 failed = true; | |
3321 break; | |
3322 } | |
3323 } | |
3324 EXPECT_TRUE(failed); | |
3325 // The decoder should not create more target bytes than were expected. | |
3326 EXPECT_GE(expected_target_.size(), output_.size()); | |
3327 } | |
3328 | |
3329 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeMaxInt) { | |
3330 WriteMaxVarintAtOffset(0x0F, 1); | |
3331 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3332 bool failed = false; | |
3333 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3334 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3335 failed = true; | |
3336 // It should fail at the position that was altered | |
3337 EXPECT_EQ(delta_file_header_.size() + 0x13, i); | |
3338 break; | |
3339 } | |
3340 } | |
3341 EXPECT_TRUE(failed); | |
3342 // The decoder should not create more target bytes than were expected. | |
3343 EXPECT_GE(expected_target_.size(), output_.size()); | |
3344 } | |
3345 | |
3346 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeNegative) { | |
3347 WriteNegativeVarintAtOffset(0x0F, 1); | |
3348 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3349 bool failed = false; | |
3350 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3351 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3352 failed = true; | |
3353 // It should fail at the position that was altered | |
3354 EXPECT_EQ(delta_file_header_.size() + 0x13, i); | |
3355 break; | |
3356 } | |
3357 } | |
3358 EXPECT_TRUE(failed); | |
3359 // The decoder should not create more target bytes than were expected. | |
3360 EXPECT_GE(expected_target_.size(), output_.size()); | |
3361 } | |
3362 | |
3363 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeInvalid) { | |
3364 WriteInvalidVarintAtOffset(0x0F, 1); | |
3365 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3366 bool failed = false; | |
3367 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3368 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3369 failed = true; | |
3370 // It should fail at the position that was altered | |
3371 EXPECT_EQ(delta_file_header_.size() + 0x13, i); | |
3372 break; | |
3373 } | |
3374 } | |
3375 EXPECT_TRUE(failed); | |
3376 // The decoder should not create more target bytes than were expected. | |
3377 EXPECT_GE(expected_target_.size(), output_.size()); | |
3378 } | |
3379 | |
3380 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunMoreThanExpectedTarget) { | |
3381 delta_file_[delta_file_header_.size() + 0x5F] = | |
3382 FirstByteOfStringLength(kExpectedTarget); | |
3383 delta_file_[delta_file_header_.size() + 0x60] = | |
3384 SecondByteOfStringLength(kExpectedTarget) + 1; | |
3385 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3386 bool failed = false; | |
3387 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3388 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3389 failed = true; | |
3390 // It should fail at the position that was altered | |
3391 EXPECT_EQ(delta_file_header_.size() + 0x60, i); | |
3392 break; | |
3393 } | |
3394 } | |
3395 EXPECT_TRUE(failed); | |
3396 // The decoder should not create more target bytes than were expected. | |
3397 EXPECT_GE(expected_target_.size(), output_.size()); | |
3398 } | |
3399 | |
3400 // A RUN instruction with an explicit size of 0 is not illegal according to the | |
3401 // standard, although it is inefficient and should not be generated by any | |
3402 // reasonable encoder. Changing the size of a RUN instruction to zero will | |
3403 // cause a failure because the generated target window size will not match the | |
3404 // expected target size. | |
3405 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeZero) { | |
3406 delta_file_[delta_file_header_.size() + 0x5F] = 0; | |
3407 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3408 bool failed = false; | |
3409 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3410 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3411 failed = true; | |
3412 break; | |
3413 } | |
3414 } | |
3415 EXPECT_TRUE(failed); | |
3416 // The decoder should not create more target bytes than were expected. | |
3417 EXPECT_GE(expected_target_.size(), output_.size()); | |
3418 } | |
3419 | |
3420 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeTooLargeByOne) { | |
3421 ++delta_file_[delta_file_header_.size() + 0x5F]; | |
3422 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3423 bool failed = false; | |
3424 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3425 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3426 failed = true; | |
3427 break; | |
3428 } | |
3429 } | |
3430 EXPECT_TRUE(failed); | |
3431 // The decoder should not create more target bytes than were expected. | |
3432 EXPECT_GE(expected_target_.size(), output_.size()); | |
3433 } | |
3434 | |
3435 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeTooSmallByOne) { | |
3436 --delta_file_[delta_file_header_.size() + 0x5F]; | |
3437 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3438 bool failed = false; | |
3439 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3440 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3441 failed = true; | |
3442 break; | |
3443 } | |
3444 } | |
3445 EXPECT_TRUE(failed); | |
3446 // The decoder should not create more target bytes than were expected. | |
3447 EXPECT_GE(expected_target_.size(), output_.size()); | |
3448 } | |
3449 | |
3450 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeMaxInt) { | |
3451 WriteMaxVarintAtOffset(0x5F, 1); | |
3452 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3453 bool failed = false; | |
3454 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3455 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3456 failed = true; | |
3457 // It should fail at the position that was altered | |
3458 EXPECT_EQ(delta_file_header_.size() + 0x63, i); | |
3459 break; | |
3460 } | |
3461 } | |
3462 EXPECT_TRUE(failed); | |
3463 // The decoder should not create more target bytes than were expected. | |
3464 EXPECT_GE(expected_target_.size(), output_.size()); | |
3465 } | |
3466 | |
3467 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeNegative) { | |
3468 WriteNegativeVarintAtOffset(0x5F, 1); | |
3469 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3470 bool failed = false; | |
3471 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3472 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3473 failed = true; | |
3474 // It should fail at the position that was altered | |
3475 EXPECT_EQ(delta_file_header_.size() + 0x63, i); | |
3476 break; | |
3477 } | |
3478 } | |
3479 EXPECT_TRUE(failed); | |
3480 // The decoder should not create more target bytes than were expected. | |
3481 EXPECT_GE(expected_target_.size(), output_.size()); | |
3482 } | |
3483 | |
3484 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeInvalid) { | |
3485 WriteInvalidVarintAtOffset(0x5F, 1); | |
3486 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3487 bool failed = false; | |
3488 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3489 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3490 failed = true; | |
3491 // It should fail at the position that was altered | |
3492 EXPECT_EQ(delta_file_header_.size() + 0x63, i); | |
3493 break; | |
3494 } | |
3495 } | |
3496 EXPECT_TRUE(failed); | |
3497 // The decoder should not create more target bytes than were expected. | |
3498 EXPECT_GE(expected_target_.size(), output_.size()); | |
3499 } | |
3500 | |
3501 // Use the interleaved file header with the standard encoding. Should work. | |
3502 class VCDiffDecoderInterleavedAllowedButNotUsed | |
3503 : public VCDiffStandardDecoderTest { | |
3504 public: | |
3505 VCDiffDecoderInterleavedAllowedButNotUsed() { | |
3506 delta_file_header_.assign(kInterleavedFileHeader, | |
3507 sizeof(kInterleavedFileHeader)); | |
3508 } | |
3509 virtual ~VCDiffDecoderInterleavedAllowedButNotUsed() { } | |
3510 }; | |
3511 | |
3512 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, Decode) { | |
3513 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3514 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
3515 delta_file_.size(), | |
3516 &output_)); | |
3517 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3518 EXPECT_EQ(expected_target_, output_); | |
3519 } | |
3520 | |
3521 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, DecodeWithChecksum) { | |
3522 ComputeAndAddChecksum(); | |
3523 InitializeDeltaFile(); | |
3524 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3525 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
3526 delta_file_.size(), | |
3527 &output_)); | |
3528 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3529 EXPECT_EQ(expected_target_, output_); | |
3530 } | |
3531 | |
3532 typedef VCDiffDecoderInterleavedAllowedButNotUsed | |
3533 VCDiffDecoderInterleavedAllowedButNotUsedByteByByte; | |
3534 | |
3535 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte, Decode) { | |
3536 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3537 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3538 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
3539 } | |
3540 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3541 EXPECT_EQ(expected_target_, output_); | |
3542 } | |
3543 | |
3544 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte, | |
3545 DecodeWithChecksum) { | |
3546 ComputeAndAddChecksum(); | |
3547 InitializeDeltaFile(); | |
3548 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3549 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3550 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
3551 } | |
3552 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3553 EXPECT_EQ(expected_target_, output_); | |
3554 } | |
3555 | |
3556 // Use the standard file header with the interleaved encoding. Should fail. | |
3557 class VCDiffDecoderInterleavedUsedButNotSupported | |
3558 : public VCDiffInterleavedDecoderTest { | |
3559 public: | |
3560 VCDiffDecoderInterleavedUsedButNotSupported() { | |
3561 delta_file_header_.assign(kStandardFileHeader, sizeof(kStandardFileHeader)); | |
3562 } | |
3563 virtual ~VCDiffDecoderInterleavedUsedButNotSupported() { } | |
3564 }; | |
3565 | |
3566 TEST_F(VCDiffDecoderInterleavedUsedButNotSupported, DecodeShouldFail) { | |
3567 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3568 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
3569 delta_file_.size(), | |
3570 &output_)); | |
3571 EXPECT_EQ("", output_); | |
3572 } | |
3573 | |
3574 TEST_F(VCDiffDecoderInterleavedUsedButNotSupported, | |
3575 DecodeByteByByteShouldFail) { | |
3576 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3577 bool failed = false; | |
3578 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3579 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
3580 failed = true; | |
3581 break; | |
3582 } | |
3583 } | |
3584 EXPECT_TRUE(failed); | |
3585 // The decoder should not create more target bytes than were expected. | |
3586 EXPECT_GE(expected_target_.size(), output_.size()); | |
3587 } | |
3588 | |
3589 // Divides up the standard encoding into eight separate delta file windows. | |
3590 // Each delta instruction appears in its own window. | |
3591 class VCDiffStandardWindowDecoderTest : public VCDiffDecoderTest { | |
3592 protected: | |
3593 VCDiffStandardWindowDecoderTest(); | |
3594 virtual ~VCDiffStandardWindowDecoderTest() {} | |
3595 | |
3596 private: | |
3597 static const char kExpectedAnnotatedTarget[]; | |
3598 static const char kWindowBody[]; | |
3599 }; | |
3600 | |
3601 const char VCDiffStandardWindowDecoderTest::kWindowBody[] = { | |
3602 // Window 1: | |
3603 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
3604 FirstByteOfStringLength(kDictionary), // Source segment size | |
3605 SecondByteOfStringLength(kDictionary), | |
3606 0x00, // Source segment position: start of dictionary | |
3607 0x08, // Length of the delta encoding | |
3608 0x1C, // Size of the target window (28) | |
3609 0x00, // Delta_indicator (no compression) | |
3610 0x00, // length of data for ADDs and RUNs | |
3611 0x02, // length of instructions section | |
3612 0x01, // length of addresses for COPYs | |
3613 // No data for ADDs and RUNs | |
3614 // Instructions and sizes (length 2) | |
3615 0x13, // VCD_COPY mode VCD_SELF, size 0 | |
3616 0x1C, // Size of COPY (28) | |
3617 // Addresses for COPYs (length 1) | |
3618 0x00, // Start of dictionary | |
3619 // Window 2: | |
3620 0x00, // Win_Indicator: No source segment (ADD only) | |
3621 0x44, // Length of the delta encoding | |
3622 0x3D, // Size of the target window (61) | |
3623 0x00, // Delta_indicator (no compression) | |
3624 0x3D, // length of data for ADDs and RUNs | |
3625 0x02, // length of instructions section | |
3626 0x00, // length of addresses for COPYs | |
3627 // Data for ADD (length 61) | |
3628 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
3629 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
3630 'T', 'h', 'a', 't', ' ', | |
3631 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
3632 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
3633 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
3634 // Instructions and sizes (length 2) | |
3635 0x01, // VCD_ADD size 0 | |
3636 0x3D, // Size of ADD (61) | |
3637 // No addresses for COPYs | |
3638 // Window 3: | |
3639 VCD_TARGET, // Win_Indicator: take source from decoded data | |
3640 0x59, // Source segment size: length of data decoded so far | |
3641 0x00, // Source segment position: start of decoded data | |
3642 0x08, // Length of the delta encoding | |
3643 0x2C, // Size of the target window | |
3644 0x00, // Delta_indicator (no compression) | |
3645 0x00, // length of data for ADDs and RUNs | |
3646 0x02, // length of instructions section | |
3647 0x01, // length of addresses for COPYs | |
3648 // No data for ADDs and RUNs | |
3649 // Instructions and sizes (length 2) | |
3650 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
3651 0x2C, // Size of COPY (44) | |
3652 // Addresses for COPYs (length 1) | |
3653 0x58, // HERE mode address (27+61 back from here_address) | |
3654 // Window 4: | |
3655 VCD_TARGET, // Win_Indicator: take source from decoded data | |
3656 0x05, // Source segment size: only 5 bytes needed for this COPY | |
3657 0x2E, // Source segment position: offset for COPY | |
3658 0x09, // Length of the delta encoding | |
3659 0x07, // Size of the target window | |
3660 0x00, // Delta_indicator (no compression) | |
3661 0x02, // length of data for ADDs and RUNs | |
3662 0x01, // length of instructions section | |
3663 0x01, // length of addresses for COPYs | |
3664 // Data for ADD (length 2) | |
3665 'h', 'r', | |
3666 // Instructions and sizes (length 1) | |
3667 0xA7, // VCD_ADD size 2 + VCD_COPY mode SELF size 5 | |
3668 // Addresses for COPYs (length 1) | |
3669 0x00, // SELF mode address (start of source segment) | |
3670 // Window 5: | |
3671 0x00, // Win_Indicator: No source segment (ADD only) | |
3672 0x0F, // Length of the delta encoding | |
3673 0x09, // Size of the target window | |
3674 0x00, // Delta_indicator (no compression) | |
3675 0x09, // length of data for ADDs and RUNs | |
3676 0x01, // length of instructions section | |
3677 0x00, // length of addresses for COPYs | |
3678 // Data for ADD (length 9) | |
3679 'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e', | |
3680 // Instructions and sizes (length 1) | |
3681 0x0A, // VCD_ADD size 9 | |
3682 // No addresses for COPYs | |
3683 // Window 6: | |
3684 0x00, // Win_Indicator: No source segment (RUN only) | |
3685 0x08, // Length of the delta encoding | |
3686 0x02, // Size of the target window | |
3687 0x00, // Delta_indicator (no compression) | |
3688 0x01, // length of data for ADDs and RUNs | |
3689 0x02, // length of instructions section | |
3690 0x00, // length of addresses for COPYs | |
3691 // Data for RUN (length 1) | |
3692 'l', | |
3693 // Instructions and sizes (length 2) | |
3694 0x00, // VCD_RUN size 0 | |
3695 0x02, // Size of RUN (2) | |
3696 // No addresses for COPYs | |
3697 // Window 7: | |
3698 0x00, // Win_Indicator: No source segment (ADD only) | |
3699 0x22, // Length of the delta encoding | |
3700 0x1B, // Size of the target window | |
3701 0x00, // Delta_indicator (no compression) | |
3702 0x1B, // length of data for ADDs and RUNs | |
3703 0x02, // length of instructions section | |
3704 0x00, // length of addresses for COPYs | |
3705 // Data for ADD: 4th section (length 27) | |
3706 ' ', 'y', 'o', 'u', ' ', | |
3707 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
3708 't', 'r', 'u', 'e', '.', '\"', '\n', | |
3709 // Instructions and sizes (length 2) | |
3710 0x01, // VCD_ADD size 0 | |
3711 0x1B, // Size of ADD (27) | |
3712 // No addresses for COPYs | |
3713 }; | |
3714 | |
3715 // The window encoding should produce the same target file as the standard | |
3716 // encoding, but the annotated target will be different because some of the | |
3717 // <bmatch> tags (copying from the previously decoded data in the current target | |
3718 // window) are changed to <dmatch> (copying from the previously decoded data in | |
3719 // another target window, which is used as the source window for the current | |
3720 // delta window.) | |
3721 const char VCDiffStandardWindowDecoderTest::kExpectedAnnotatedTarget[] = | |
3722 "<dmatch>\"Just the place for a Snark!</dmatch>" | |
3723 "<literal> I have said it twice:\n" | |
3724 "That alone should encourage the crew.\n</literal>" | |
3725 "<dmatch>Just the place for a Snark! I have said it t</dmatch>" | |
3726 "<literal>hr</literal>" | |
3727 "<dmatch>ice:\n</dmatch>" | |
3728 "<literal>What I te</literal>" | |
3729 "<literal>ll</literal>" | |
3730 "<literal> you three times is true.\"\n</literal>"; | |
3731 | |
3732 VCDiffStandardWindowDecoderTest::VCDiffStandardWindowDecoderTest() { | |
3733 delta_file_header_.assign(kStandardFileHeader, sizeof(kStandardFileHeader)); | |
3734 expected_annotated_target_.assign(kExpectedAnnotatedTarget); | |
3735 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
3736 } | |
3737 | |
3738 TEST_F(VCDiffStandardWindowDecoderTest, Decode) { | |
3739 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3740 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
3741 delta_file_.size(), | |
3742 &output_)); | |
3743 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3744 EXPECT_EQ(expected_target_, output_); | |
3745 } | |
3746 | |
3747 // Bug 1287926: If DecodeChunk() stops in the middle of the window header, | |
3748 // and the expected size of the current target window is smaller than the | |
3749 // cumulative target bytes decoded so far, an underflow occurs and the decoder | |
3750 // tries to allocate ~MAX_INT bytes. | |
3751 TEST_F(VCDiffStandardWindowDecoderTest, DecodeBreakInFourthWindowHeader) { | |
3752 // Parse file header + first two windows. | |
3753 const int chunk_1_size = sizeof(kStandardFileHeader) + 83; | |
3754 // Parse third window, plus everything up to "Size of the target window" field | |
3755 // of fourth window, but do not parse complete header of fourth window. | |
3756 const int chunk_2_size = 12 + 5; | |
3757 CHECK_EQ(VCD_TARGET, static_cast<unsigned char>(delta_file_[chunk_1_size])); | |
3758 CHECK_EQ(0x00, static_cast<int>(delta_file_[chunk_1_size + chunk_2_size])); | |
3759 string output_chunk1, output_chunk2, output_chunk3; | |
3760 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3761 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
3762 chunk_1_size, | |
3763 &output_chunk1)); | |
3764 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size], | |
3765 chunk_2_size, | |
3766 &output_chunk2)); | |
3767 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size + chunk_2_size], | |
3768 delta_file_.size() | |
3769 - (chunk_1_size + chunk_2_size), | |
3770 &output_chunk3)); | |
3771 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3772 EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2 + output_chunk3); | |
3773 } | |
3774 | |
3775 TEST_F(VCDiffStandardWindowDecoderTest, DecodeInTwoParts) { | |
3776 const size_t delta_file_size = delta_file_.size(); | |
3777 for (size_t i = 1; i < delta_file_size; i++) { | |
3778 string output_chunk1, output_chunk2; | |
3779 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3780 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
3781 i, | |
3782 &output_chunk1)); | |
3783 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], | |
3784 delta_file_size - i, | |
3785 &output_chunk2)); | |
3786 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3787 EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2); | |
3788 } | |
3789 } | |
3790 | |
3791 TEST_F(VCDiffStandardWindowDecoderTest, DecodeInThreeParts) { | |
3792 const size_t delta_file_size = delta_file_.size(); | |
3793 for (size_t i = 1; i < delta_file_size - 1; i++) { | |
3794 for (size_t j = i + 1; j < delta_file_size; j++) { | |
3795 string output_chunk1, output_chunk2, output_chunk3; | |
3796 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3797 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
3798 i, | |
3799 &output_chunk1)); | |
3800 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], | |
3801 j - i, | |
3802 &output_chunk2)); | |
3803 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j], | |
3804 delta_file_size - j, | |
3805 &output_chunk3)); | |
3806 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3807 EXPECT_EQ(expected_target_, | |
3808 output_chunk1 + output_chunk2 + output_chunk3); | |
3809 } | |
3810 } | |
3811 } | |
3812 | |
3813 typedef VCDiffStandardWindowDecoderTest | |
3814 VCDiffStandardWindowDecoderTestByteByByte; | |
3815 TEST_F(VCDiffStandardWindowDecoderTestByteByByte, Decode) { | |
3816 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3817 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3818 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
3819 } | |
3820 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3821 EXPECT_EQ(expected_target_, output_); | |
3822 } | |
3823 | |
3824 // Divides up the interleaved encoding into eight separate delta file windows. | |
3825 class VCDiffInterleavedWindowDecoderTest | |
3826 : public VCDiffStandardWindowDecoderTest { | |
3827 protected: | |
3828 VCDiffInterleavedWindowDecoderTest(); | |
3829 virtual ~VCDiffInterleavedWindowDecoderTest() {} | |
3830 private: | |
3831 static const char kWindowBody[]; | |
3832 }; | |
3833 | |
3834 const char VCDiffInterleavedWindowDecoderTest::kWindowBody[] = { | |
3835 // Window 1: | |
3836 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
3837 FirstByteOfStringLength(kDictionary), // Source segment size | |
3838 SecondByteOfStringLength(kDictionary), | |
3839 0x00, // Source segment position: start of dictionary | |
3840 0x08, // Length of the delta encoding | |
3841 0x1C, // Size of the target window (28) | |
3842 0x00, // Delta_indicator (no compression) | |
3843 0x00, // length of data for ADDs and RUNs | |
3844 0x03, // length of instructions section | |
3845 0x00, // length of addresses for COPYs | |
3846 0x13, // VCD_COPY mode VCD_SELF, size 0 | |
3847 0x1C, // Size of COPY (28) | |
3848 0x00, // Start of dictionary | |
3849 // Window 2: | |
3850 0x00, // Win_Indicator: No source segment (ADD only) | |
3851 0x44, // Length of the delta encoding | |
3852 0x3D, // Size of the target window (61) | |
3853 0x00, // Delta_indicator (no compression) | |
3854 0x00, // length of data for ADDs and RUNs | |
3855 0x3F, // length of instructions section | |
3856 0x00, // length of addresses for COPYs | |
3857 0x01, // VCD_ADD size 0 | |
3858 0x3D, // Size of ADD (61) | |
3859 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
3860 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
3861 'T', 'h', 'a', 't', ' ', | |
3862 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
3863 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
3864 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
3865 // Window 3: | |
3866 VCD_TARGET, // Win_Indicator: take source from decoded data | |
3867 0x59, // Source segment size: length of data decoded so far | |
3868 0x00, // Source segment position: start of decoded data | |
3869 0x08, // Length of the delta encoding | |
3870 0x2C, // Size of the target window | |
3871 0x00, // Delta_indicator (no compression) | |
3872 0x00, // length of data for ADDs and RUNs | |
3873 0x03, // length of instructions section | |
3874 0x00, // length of addresses for COPYs | |
3875 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
3876 0x2C, // Size of COPY (44) | |
3877 0x58, // HERE mode address (27+61 back from here_address) | |
3878 // Window 4: | |
3879 VCD_TARGET, // Win_Indicator: take source from decoded data | |
3880 0x05, // Source segment size: only 5 bytes needed for this COPY | |
3881 0x2E, // Source segment position: offset for COPY | |
3882 0x09, // Length of the delta encoding | |
3883 0x07, // Size of the target window | |
3884 0x00, // Delta_indicator (no compression) | |
3885 0x00, // length of data for ADDs and RUNs | |
3886 0x04, // length of instructions section | |
3887 0x00, // length of addresses for COPYs | |
3888 0xA7, // VCD_ADD size 2 + VCD_COPY mode SELF, size 5 | |
3889 'h', 'r', | |
3890 0x00, // SELF mode address (start of source segment) | |
3891 // Window 5: | |
3892 0x00, // Win_Indicator: No source segment (ADD only) | |
3893 0x0F, // Length of the delta encoding | |
3894 0x09, // Size of the target window | |
3895 0x00, // Delta_indicator (no compression) | |
3896 0x00, // length of data for ADDs and RUNs | |
3897 0x0A, // length of instructions section | |
3898 0x00, // length of addresses for COPYs | |
3899 0x0A, // VCD_ADD size 9 | |
3900 'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e', | |
3901 // Window 6: | |
3902 0x00, // Win_Indicator: No source segment (RUN only) | |
3903 0x08, // Length of the delta encoding | |
3904 0x02, // Size of the target window | |
3905 0x00, // Delta_indicator (no compression) | |
3906 0x00, // length of data for ADDs and RUNs | |
3907 0x03, // length of instructions section | |
3908 0x00, // length of addresses for COPYs | |
3909 0x00, // VCD_RUN size 0 | |
3910 0x02, // Size of RUN (2) | |
3911 'l', | |
3912 // Window 7: | |
3913 0x00, // Win_Indicator: No source segment (ADD only) | |
3914 0x22, // Length of the delta encoding | |
3915 0x1B, // Size of the target window | |
3916 0x00, // Delta_indicator (no compression) | |
3917 0x00, // length of data for ADDs and RUNs | |
3918 0x1D, // length of instructions section | |
3919 0x00, // length of addresses for COPYs | |
3920 0x01, // VCD_ADD size 0 | |
3921 0x1B, // Size of ADD (27) | |
3922 ' ', 'y', 'o', 'u', ' ', | |
3923 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
3924 't', 'r', 'u', 'e', '.', '\"', '\n', | |
3925 }; | |
3926 | |
3927 VCDiffInterleavedWindowDecoderTest::VCDiffInterleavedWindowDecoderTest() { | |
3928 delta_file_header_.assign(kInterleavedFileHeader, | |
3929 sizeof(kInterleavedFileHeader)); | |
3930 // delta_window_header_ is left blank. All window headers and bodies are | |
3931 // lumped together in delta_window_body_. This means that AddChecksum() | |
3932 // cannot be used to test the checksum feature. | |
3933 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
3934 } | |
3935 | |
3936 TEST_F(VCDiffInterleavedWindowDecoderTest, Decode) { | |
3937 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3938 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
3939 delta_file_.size(), | |
3940 &output_)); | |
3941 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3942 EXPECT_EQ(expected_target_, output_); | |
3943 } | |
3944 | |
3945 TEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInTwoParts) { | |
3946 const size_t delta_file_size = delta_file_.size(); | |
3947 for (size_t i = 1; i < delta_file_size; i++) { | |
3948 string output_chunk1, output_chunk2; | |
3949 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3950 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
3951 i, | |
3952 &output_chunk1)); | |
3953 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], | |
3954 delta_file_size - i, | |
3955 &output_chunk2)); | |
3956 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3957 EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2); | |
3958 } | |
3959 } | |
3960 | |
3961 TEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInThreeParts) { | |
3962 const size_t delta_file_size = delta_file_.size(); | |
3963 for (size_t i = 1; i < delta_file_size - 1; i++) { | |
3964 for (size_t j = i + 1; j < delta_file_size; j++) { | |
3965 string output_chunk1, output_chunk2, output_chunk3; | |
3966 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3967 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
3968 i, | |
3969 &output_chunk1)); | |
3970 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], | |
3971 j - i, | |
3972 &output_chunk2)); | |
3973 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j], | |
3974 delta_file_size - j, | |
3975 &output_chunk3)); | |
3976 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3977 EXPECT_EQ(expected_target_, | |
3978 output_chunk1 + output_chunk2 + output_chunk3); | |
3979 } | |
3980 } | |
3981 } | |
3982 | |
3983 typedef VCDiffInterleavedWindowDecoderTest | |
3984 VCDiffInterleavedWindowDecoderTestByteByByte; | |
3985 | |
3986 TEST_F(VCDiffInterleavedWindowDecoderTestByteByByte, Decode) { | |
3987 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
3988 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
3989 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
3990 } | |
3991 EXPECT_TRUE(decoder_.FinishDecoding()); | |
3992 EXPECT_EQ(expected_target_, output_); | |
3993 } | |
3994 | |
3995 // The original version of VCDiffDecoder did not allow the caller to modify the | |
3996 // contents of output_string between calls to DecodeChunk(). That restriction | |
3997 // has been removed. Verify that the same result is still produced if the | |
3998 // output string is cleared after each call to DecodeChunk(). Use the window | |
3999 // encoding because it refers back to the previously decoded target data, which | |
4000 // is the feature that would fail if the restriction still applied. | |
4001 // | |
4002 TEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringCanBeModified) { | |
4003 string temp_output; | |
4004 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4005 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
4006 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &temp_output)); | |
4007 output_.append(temp_output); | |
4008 temp_output.clear(); | |
4009 } | |
4010 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4011 EXPECT_EQ(expected_target_, output_); | |
4012 } | |
4013 | |
4014 TEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringIsPreserved) { | |
4015 const string previous_data("Previous data"); | |
4016 output_ = previous_data; | |
4017 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4018 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
4019 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
4020 } | |
4021 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4022 EXPECT_EQ(previous_data + expected_target_, output_); | |
4023 } | |
4024 | |
4025 // A decode job that tests the ability to COPY across the boundary between | |
4026 // source data and target data. | |
4027 class VCDiffStandardCrossDecoderTest : public VCDiffDecoderTest { | |
4028 protected: | |
4029 static const char kExpectedTarget[]; | |
4030 static const char kExpectedAnnotatedTarget[]; | |
4031 static const char kWindowHeader[]; | |
4032 static const char kWindowBody[]; | |
4033 | |
4034 VCDiffStandardCrossDecoderTest(); | |
4035 virtual ~VCDiffStandardCrossDecoderTest() {} | |
4036 }; | |
4037 | |
4038 const char VCDiffStandardCrossDecoderTest::kWindowHeader[] = { | |
4039 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
4040 FirstByteOfStringLength(kDictionary), // Source segment size | |
4041 SecondByteOfStringLength(kDictionary), | |
4042 0x00, // Source segment position: start of dictionary | |
4043 0x15, // Length of the delta encoding | |
4044 StringLengthAsByte(kExpectedTarget), // Size of the target window | |
4045 0x00, // Delta_indicator (no compression) | |
4046 0x07, // length of data for ADDs and RUNs | |
4047 0x06, // length of instructions section | |
4048 0x03 // length of addresses for COPYs | |
4049 }; | |
4050 | |
4051 const char VCDiffStandardCrossDecoderTest::kWindowBody[] = { | |
4052 // Data for ADD (length 7) | |
4053 'S', 'p', 'i', 'd', 'e', 'r', 's', | |
4054 // Instructions and sizes (length 6) | |
4055 0x01, // VCD_ADD size 0 | |
4056 0x07, // Size of ADD (7) | |
4057 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
4058 0x19, // Size of COPY (25) | |
4059 0x14, // VCD_COPY mode VCD_SELF, size 4 | |
4060 0x25, // VCD_COPY mode VCD_HERE, size 5 | |
4061 // Addresses for COPYs (length 3) | |
4062 0x15, // HERE mode address for 1st copy (21 back from here_address) | |
4063 0x06, // SELF mode address for 2nd copy | |
4064 0x14 // HERE mode address for 3rd copy | |
4065 }; | |
4066 | |
4067 const char VCDiffStandardCrossDecoderTest::kExpectedTarget[] = | |
4068 "Spiders in his hair.\n" | |
4069 "Spiders in the air.\n"; | |
4070 | |
4071 const char VCDiffStandardCrossDecoderTest::kExpectedAnnotatedTarget[] = | |
4072 "<literal>Spiders</literal>" | |
4073 "<dmatch> in his hair.\n</dmatch>" // crosses source-target boundary | |
4074 "<bmatch>Spiders in </bmatch>" | |
4075 "<dmatch>the </dmatch>" | |
4076 "<bmatch>air.\n</bmatch>"; | |
4077 | |
4078 VCDiffStandardCrossDecoderTest::VCDiffStandardCrossDecoderTest() { | |
4079 delta_file_header_.assign(kStandardFileHeader, sizeof(kStandardFileHeader)); | |
4080 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
4081 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
4082 expected_target_.assign(kExpectedTarget); | |
4083 expected_annotated_target_.assign(kExpectedAnnotatedTarget); | |
4084 } | |
4085 | |
4086 TEST_F(VCDiffStandardCrossDecoderTest, Decode) { | |
4087 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4088 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
4089 delta_file_.size(), | |
4090 &output_)); | |
4091 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4092 EXPECT_EQ(expected_target_, output_); | |
4093 } | |
4094 | |
4095 typedef VCDiffStandardCrossDecoderTest VCDiffStandardCrossDecoderTestByteByByte; | |
4096 | |
4097 TEST_F(VCDiffStandardCrossDecoderTestByteByByte, Decode) { | |
4098 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4099 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
4100 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
4101 } | |
4102 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4103 EXPECT_EQ(expected_target_, output_); | |
4104 } | |
4105 | |
4106 // The same decode job that tests the ability to COPY across the boundary | |
4107 // between source data and target data, but using the interleaved format rather | |
4108 // than the standard format. | |
4109 class VCDiffInterleavedCrossDecoderTest | |
4110 : public VCDiffStandardCrossDecoderTest { | |
4111 protected: | |
4112 VCDiffInterleavedCrossDecoderTest(); | |
4113 virtual ~VCDiffInterleavedCrossDecoderTest() {} | |
4114 | |
4115 private: | |
4116 static const char kWindowHeader[]; | |
4117 static const char kWindowBody[]; | |
4118 }; | |
4119 | |
4120 const char VCDiffInterleavedCrossDecoderTest::kWindowHeader[] = { | |
4121 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
4122 FirstByteOfStringLength(kDictionary), // Source segment size | |
4123 SecondByteOfStringLength(kDictionary), | |
4124 0x00, // Source segment position: start of dictionary | |
4125 0x15, // Length of the delta encoding | |
4126 StringLengthAsByte(kExpectedTarget), // Size of the target window | |
4127 0x00, // Delta_indicator (no compression) | |
4128 0x00, // length of data for ADDs and RUNs | |
4129 0x10, // length of instructions section | |
4130 0x00, // length of addresses for COPYs | |
4131 }; | |
4132 | |
4133 const char VCDiffInterleavedCrossDecoderTest::kWindowBody[] = { | |
4134 0x01, // VCD_ADD size 0 | |
4135 0x07, // Size of ADD (7) | |
4136 // Data for ADD (length 7) | |
4137 'S', 'p', 'i', 'd', 'e', 'r', 's', | |
4138 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
4139 0x19, // Size of COPY (25) | |
4140 0x15, // HERE mode address for 1st copy (21 back from here_address) | |
4141 0x14, // VCD_COPY mode VCD_SELF, size 4 | |
4142 0x06, // SELF mode address for 2nd copy | |
4143 0x25, // VCD_COPY mode VCD_HERE, size 5 | |
4144 0x14 // HERE mode address for 3rd copy | |
4145 }; | |
4146 | |
4147 VCDiffInterleavedCrossDecoderTest::VCDiffInterleavedCrossDecoderTest() { | |
4148 delta_file_header_.assign(kInterleavedFileHeader, | |
4149 sizeof(kInterleavedFileHeader)); | |
4150 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
4151 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
4152 } | |
4153 | |
4154 TEST_F(VCDiffInterleavedCrossDecoderTest, Decode) { | |
4155 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4156 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
4157 delta_file_.size(), | |
4158 &output_)); | |
4159 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4160 EXPECT_EQ(expected_target_, output_); | |
4161 } | |
4162 | |
4163 TEST_F(VCDiffInterleavedCrossDecoderTest, DecodeWithChecksum) { | |
4164 ComputeAndAddChecksum(); | |
4165 InitializeDeltaFile(); | |
4166 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4167 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
4168 delta_file_.size(), | |
4169 &output_)); | |
4170 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4171 EXPECT_EQ(expected_target_, output_); | |
4172 } | |
4173 | |
4174 typedef VCDiffInterleavedCrossDecoderTest | |
4175 VCDiffInterleavedCrossDecoderTestByteByByte; | |
4176 | |
4177 TEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, Decode) { | |
4178 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4179 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
4180 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
4181 } | |
4182 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4183 EXPECT_EQ(expected_target_, output_); | |
4184 } | |
4185 | |
4186 TEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, DecodeWithChecksum) { | |
4187 ComputeAndAddChecksum(); | |
4188 InitializeDeltaFile(); | |
4189 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4190 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
4191 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
4192 } | |
4193 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4194 EXPECT_EQ(expected_target_, output_); | |
4195 } | |
4196 | |
4197 // Test using a custom code table and custom cache sizes with interleaved | |
4198 // format. | |
4199 class VCDiffCustomCodeTableDecoderTest : public VCDiffInterleavedDecoderTest { | |
4200 protected: | |
4201 static const char kFileHeader[]; | |
4202 static const char kWindowHeader[]; | |
4203 static const char kWindowBody[]; | |
4204 static const char kEncodedCustomCodeTable[]; | |
4205 | |
4206 VCDiffCustomCodeTableDecoderTest(); | |
4207 virtual ~VCDiffCustomCodeTableDecoderTest() {} | |
4208 }; | |
4209 | |
4210 const char VCDiffCustomCodeTableDecoderTest::kFileHeader[] = { | |
4211 0xD6, // 'V' | 0x80 | |
4212 0xC3, // 'C' | 0x80 | |
4213 0xC4, // 'D' | 0x80 | |
4214 'S', // SDCH version code | |
4215 0x02 // Hdr_Indicator: Use custom code table | |
4216 }; | |
4217 | |
4218 // Make a custom code table that includes exactly the instructions we need | |
4219 // to encode the first test's data without using any explicit length values. | |
4220 // Be careful not to replace any existing opcodes that have size 0, | |
4221 // to ensure that the custom code table is valid (can express all possible | |
4222 // values of inst (also known as instruction type) and mode with size 0.) | |
4223 // This encoding uses interleaved format, which is easier to read. | |
4224 // | |
4225 // Here are the changes to the standard code table: | |
4226 // ADD size 2 (opcode 3) => RUN size 2 (inst1[3] = VCD_RUN) | |
4227 // ADD size 16 (opcode 17) => ADD size 27 (size1[17] = 27) | |
4228 // ADD size 17 (opcode 18) => ADD size 61 (size1[18] = 61) | |
4229 // COPY mode 0 size 18 (opcode 34) => COPY mode 0 size 28 (size1[34] = 28) | |
4230 // COPY mode 1 size 18 (opcode 50) => COPY mode 1 size 44 (size1[50] = 44) | |
4231 // | |
4232 const char VCDiffCustomCodeTableDecoderTest::kEncodedCustomCodeTable[] = { | |
4233 0xD6, // 'V' | 0x80 | |
4234 0xC3, // 'C' | 0x80 | |
4235 0xC4, // 'D' | 0x80 | |
4236 'S', // SDCH version code | |
4237 0x00, // Hdr_Indicator: no custom code table, no compression | |
4238 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
4239 (sizeof(VCDiffCodeTableData) >> 7) | 0x80, // First byte of table length | |
4240 sizeof(VCDiffCodeTableData) & 0x7F, // Second byte of table length | |
4241 0x00, // Source segment position: start of default code table | |
4242 0x1F, // Length of the delta encoding | |
4243 (sizeof(VCDiffCodeTableData) >> 7) | 0x80, // First byte of table length | |
4244 sizeof(VCDiffCodeTableData) & 0x7F, // Second byte of table length | |
4245 0x00, // Delta_indicator (no compression) | |
4246 0x00, // length of data for ADDs and RUNs (unused) | |
4247 0x19, // length of interleaved section | |
4248 0x00, // length of addresses for COPYs (unused) | |
4249 0x05, // VCD_ADD size 4 | |
4250 // Data for ADD (length 4) | |
4251 VCD_RUN, VCD_ADD, VCD_ADD, VCD_RUN, | |
4252 0x13, // VCD_COPY mode VCD_SELF size 0 | |
4253 0x84, // Size of copy: upper bits (512 - 4 + 17 = 525) | |
4254 0x0D, // Size of copy: lower bits | |
4255 0x04, // Address of COPY | |
4256 0x03, // VCD_ADD size 2 | |
4257 // Data for ADD (length 2) | |
4258 0x1B, 0x3D, | |
4259 0x3F, // VCD_COPY mode VCD_NEAR(0) size 15 | |
4260 0x84, // Address of copy: upper bits (525 + 2 = 527) | |
4261 0x0F, // Address of copy: lower bits | |
4262 0x02, // VCD_ADD size 1 | |
4263 // Data for ADD (length 1) | |
4264 0x1C, | |
4265 0x4F, // VCD_COPY mode VCD_NEAR(1) size 15 | |
4266 0x10, // Address of copy | |
4267 0x02, // VCD_ADD size 1 | |
4268 // Data for ADD (length 1) | |
4269 0x2C, | |
4270 0x53, // VCD_COPY mode VCD_NEAR(2) size 0 | |
4271 0x87, // Size of copy: upper bits (256 * 4 - 51 = 973) | |
4272 0x4D, // Size of copy: lower bits | |
4273 0x10 // Address of copy | |
4274 }; | |
4275 | |
4276 // This is similar to VCDiffInterleavedDecoderTest, but uses the custom code | |
4277 // table to eliminate the need to explicitly encode instruction sizes. | |
4278 // Notice that NEAR(0) mode is used here where NEAR(1) mode was used in | |
4279 // VCDiffInterleavedDecoderTest. This is because the custom code table | |
4280 // has the size of the NEAR cache set to 1; only the most recent | |
4281 // COPY instruction is available. This will also be a test of | |
4282 // custom cache sizes. | |
4283 const char VCDiffCustomCodeTableDecoderTest::kWindowHeader[] = { | |
4284 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
4285 FirstByteOfStringLength(kDictionary), // Source segment size | |
4286 SecondByteOfStringLength(kDictionary), | |
4287 0x00, // Source segment position: start of dictionary | |
4288 0x74, // Length of the delta encoding | |
4289 FirstByteOfStringLength(kExpectedTarget), // Size of the target window | |
4290 SecondByteOfStringLength(kExpectedTarget), | |
4291 0x00, // Delta_indicator (no compression) | |
4292 0x00, // length of data for ADDs and RUNs (unused) | |
4293 0x6E, // length of interleaved section | |
4294 0x00 // length of addresses for COPYs (unused) | |
4295 }; | |
4296 | |
4297 const char VCDiffCustomCodeTableDecoderTest::kWindowBody[] = { | |
4298 0x22, // VCD_COPY mode VCD_SELF, size 28 | |
4299 0x00, // Address of COPY: Start of dictionary | |
4300 0x12, // VCD_ADD size 61 | |
4301 // Data for ADD (length 61) | |
4302 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
4303 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
4304 'T', 'h', 'a', 't', ' ', | |
4305 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
4306 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
4307 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
4308 0x32, // VCD_COPY mode VCD_HERE, size 44 | |
4309 0x58, // HERE mode address (27+61 back from here_address) | |
4310 0xBF, // VCD_ADD size 2 + VCD_COPY mode NEAR(0), size 5 | |
4311 // Data for ADDs: 2nd section (length 2) | |
4312 'h', 'r', | |
4313 0x2D, // NEAR(0) mode address (45 after prior address) | |
4314 0x0A, // VCD_ADD size 9 | |
4315 // Data for ADDs: 3rd section (length 9) | |
4316 'W', 'h', 'a', 't', ' ', | |
4317 'I', ' ', 't', 'e', | |
4318 0x03, // VCD_RUN size 2 | |
4319 // Data for RUN: 4th section (length 1) | |
4320 'l', | |
4321 0x11, // VCD_ADD size 27 | |
4322 // Data for ADD: 4th section (length 27) | |
4323 ' ', 'y', 'o', 'u', ' ', | |
4324 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
4325 't', 'r', 'u', 'e', '.', '\"', '\n' | |
4326 }; | |
4327 | |
4328 VCDiffCustomCodeTableDecoderTest::VCDiffCustomCodeTableDecoderTest() { | |
4329 delta_file_header_.assign(kFileHeader, sizeof(kFileHeader)); | |
4330 delta_file_header_.push_back(0x01); // NEAR cache size (custom) | |
4331 delta_file_header_.push_back(0x06); // SAME cache size (custom) | |
4332 delta_file_header_.append(kEncodedCustomCodeTable, | |
4333 sizeof(kEncodedCustomCodeTable)); | |
4334 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
4335 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
4336 } | |
4337 | |
4338 TEST_F(VCDiffCustomCodeTableDecoderTest, CustomCodeTableEncodingMatches) { | |
4339 VCDiffCodeTableData custom_code_table( | |
4340 VCDiffCodeTableData::kDefaultCodeTableData); | |
4341 custom_code_table.inst1[3] = VCD_RUN; | |
4342 custom_code_table.size1[17] = 27; | |
4343 custom_code_table.size1[18] = 61; | |
4344 custom_code_table.size1[34] = 28; | |
4345 custom_code_table.size1[50] = 44; | |
4346 | |
4347 decoder_.StartDecoding( | |
4348 reinterpret_cast<const char*>( | |
4349 &VCDiffCodeTableData::kDefaultCodeTableData), | |
4350 sizeof(VCDiffCodeTableData::kDefaultCodeTableData)); | |
4351 EXPECT_TRUE(decoder_.DecodeChunk(kEncodedCustomCodeTable, | |
4352 sizeof(kEncodedCustomCodeTable), | |
4353 &output_)); | |
4354 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4355 EXPECT_EQ(sizeof(custom_code_table), output_.size()); | |
4356 const VCDiffCodeTableData* decoded_table = | |
4357 reinterpret_cast<const VCDiffCodeTableData*>(output_.data()); | |
4358 EXPECT_EQ(VCD_RUN, decoded_table->inst1[0]); | |
4359 EXPECT_EQ(VCD_RUN, decoded_table->inst1[3]); | |
4360 EXPECT_EQ(27, decoded_table->size1[17]); | |
4361 EXPECT_EQ(61, decoded_table->size1[18]); | |
4362 EXPECT_EQ(28, decoded_table->size1[34]); | |
4363 EXPECT_EQ(44, decoded_table->size1[50]); | |
4364 for (int i = 0; i < VCDiffCodeTableData::kCodeTableSize; ++i) { | |
4365 EXPECT_EQ(custom_code_table.inst1[i], decoded_table->inst1[i]); | |
4366 EXPECT_EQ(custom_code_table.inst2[i], decoded_table->inst2[i]); | |
4367 EXPECT_EQ(custom_code_table.size1[i], decoded_table->size1[i]); | |
4368 EXPECT_EQ(custom_code_table.size2[i], decoded_table->size2[i]); | |
4369 EXPECT_EQ(custom_code_table.mode1[i], decoded_table->mode1[i]); | |
4370 EXPECT_EQ(custom_code_table.mode2[i], decoded_table->mode2[i]); | |
4371 } | |
4372 } | |
4373 | |
4374 TEST_F(VCDiffCustomCodeTableDecoderTest, DecodeUsingCustomCodeTable) { | |
4375 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4376 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
4377 delta_file_.size(), | |
4378 &output_)); | |
4379 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4380 EXPECT_EQ(expected_target_, output_); | |
4381 } | |
4382 | |
4383 TEST_F(VCDiffCustomCodeTableDecoderTest, IncompleteCustomCodeTable) { | |
4384 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4385 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), | |
4386 delta_file_header_.size() - 1, | |
4387 &output_)); | |
4388 EXPECT_FALSE(decoder_.FinishDecoding()); | |
4389 EXPECT_EQ("", output_); | |
4390 } | |
4391 | |
4392 typedef VCDiffCustomCodeTableDecoderTest | |
4393 VCDiffCustomCodeTableDecoderTestByteByByte; | |
4394 | |
4395 TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, DecodeUsingCustomCodeTable) { | |
4396 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4397 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
4398 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
4399 } | |
4400 EXPECT_TRUE(decoder_.FinishDecoding()); | |
4401 EXPECT_EQ(expected_target_, output_); | |
4402 } | |
4403 | |
4404 TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, IncompleteCustomCodeTable) { | |
4405 delta_file_.resize(delta_file_header_.size() - 1); | |
4406 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4407 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
4408 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
4409 } | |
4410 EXPECT_FALSE(decoder_.FinishDecoding()); | |
4411 EXPECT_EQ("", output_); | |
4412 } | |
4413 | |
4414 #ifdef GTEST_HAS_DEATH_TEST | |
4415 typedef VCDiffCustomCodeTableDecoderTest VCDiffCustomCodeTableDecoderDeathTest; | |
4416 | |
4417 TEST_F(VCDiffCustomCodeTableDecoderDeathTest, BadCustomCacheSizes) { | |
4418 delta_file_header_.assign(kFileHeader, sizeof(kFileHeader)); | |
4419 delta_file_header_.push_back(0x81); // NEAR cache size (top bit) | |
4420 delta_file_header_.push_back(0x10); // NEAR cache size (custom value 0x90) | |
4421 delta_file_header_.push_back(0x81); // SAME cache size (top bit) | |
4422 delta_file_header_.push_back(0x10); // SAME cache size (custom value 0x90) | |
4423 delta_file_header_.append(kEncodedCustomCodeTable, | |
4424 sizeof(kEncodedCustomCodeTable)); | |
4425 InitializeDeltaFile(); | |
4426 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
4427 EXPECT_DEBUG_DEATH(EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
4428 delta_file_.size(), | |
4429 &output_)), | |
4430 "cache"); | |
4431 EXPECT_EQ("", output_); | |
4432 } | |
4433 #endif // GTEST_HAS_DEATH_TEST | |
4434 | |
4435 } // namespace open_vcdiff | |
4436 } // unnamed namespace | |
OLD | NEW |