blob: 01a79469bbb7e6fb620fe69abf739a8703f3b520 [file] [log] [blame]
openvcdiff311c7142008-08-26 19:29:25 +00001// 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"
openvcdiff28db8072008-10-10 23:29:11 +000018#include <stdlib.h> // free, posix_memalign
19#include <string.h> // memcpy
openvcdiff311c7142008-08-26 19:29:25 +000020#include <string>
21#include "testing.h"
22#include "varint_bigendian.h"
23#include "vcdecoder_test.h"
24#include "vcdiff_defs.h" // VCD_SOURCE
25
26#ifdef HAVE_MALLOC_H
27#include <malloc.h>
28#endif // HAVE_MALLOC_H
29
30#ifdef HAVE_SYS_MMAN_H
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +000031#if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
32#undef _XOPEN_SOURCE
openvcdiff311c7142008-08-26 19:29:25 +000033#define _XOPEN_SOURCE 600 // posix_memalign
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +000034#endif
openvcdiff311c7142008-08-26 19:29:25 +000035#include <sys/mman.h> // mprotect
36#endif // HAVE_SYS_MMAN_H
37
38#ifdef HAVE_UNISTD_H
39#include <unistd.h> // getpagesize
40#endif // HAVE_UNISTD_H
41
42namespace open_vcdiff {
43
openvcdiff311c7142008-08-26 19:29:25 +000044// Test headers, valid and invalid.
45
46TEST_F(VCDiffInterleavedDecoderTest, DecodeHeaderOnly) {
47 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
48 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(),
49 delta_file_header_.size(),
50 &output_));
51 EXPECT_TRUE(decoder_.FinishDecoding());
52 EXPECT_EQ("", output_);
53}
54
55TEST_F(VCDiffInterleavedDecoderTest, PartialHeaderNotEnough) {
56 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
57 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(),
58 delta_file_header_.size() - 2,
59 &output_));
60 EXPECT_FALSE(decoder_.FinishDecoding());
61 EXPECT_EQ("", output_);
62}
63
64TEST_F(VCDiffInterleavedDecoderTest, BadMagicNumber) {
65 delta_file_[1] = 'Q' | 0x80;
66 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
67 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
68 delta_file_.size(),
69 &output_));
70 EXPECT_EQ("", output_);
71}
72
73TEST_F(VCDiffInterleavedDecoderTest, BadVersionNumber) {
74 delta_file_[3] = 0x01;
75 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
76 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
77 delta_file_.size(),
78 &output_));
79 EXPECT_EQ("", output_);
80}
81
82TEST_F(VCDiffInterleavedDecoderTest, SecondaryCompressionNotSupported) {
83 delta_file_[4] = 0x01;
84 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
85 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
86 delta_file_.size(),
87 &output_));
88 EXPECT_EQ("", output_);
89}
90
91TEST_F(VCDiffInterleavedDecoderTest, Decode) {
92 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
93 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
94 delta_file_.size(),
95 &output_));
96 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +000097 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff311c7142008-08-26 19:29:25 +000098}
99
100TEST_F(VCDiffInterleavedDecoderTest, DecodeWithChecksum) {
101 ComputeAndAddChecksum();
102 InitializeDeltaFile();
103 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
104 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
105 delta_file_.size(),
106 &output_));
107 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000108 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff311c7142008-08-26 19:29:25 +0000109}
110
111TEST_F(VCDiffInterleavedDecoderTest, ChecksumDoesNotMatch) {
112 AddChecksum(0xBADBAD);
113 InitializeDeltaFile();
114 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
115 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
116 delta_file_.size(),
117 &output_));
118 EXPECT_EQ("", output_);
119}
120
121TEST_F(VCDiffInterleavedDecoderTest, ChecksumIsInvalid64BitVarint) {
122 static const char kInvalidVarint[] = { 0x81, 0x80, 0x80, 0x80, 0x80, 0x80,
123 0x80, 0x80, 0x80, 0x00 };
124 delta_window_header_[0] |= VCD_CHECKSUM;
125 delta_window_header_.append(kInvalidVarint, sizeof(kInvalidVarint));
126 // Adjust delta window size to include size of invalid Varint.
127 string size_of_invalid_varint;
128 VarintBE<int32_t>::AppendToString(
129 static_cast<int32_t>(delta_window_header_[4] + sizeof(kInvalidVarint)),
130 &size_of_invalid_varint);
131 delta_window_header_.replace(4, 1, size_of_invalid_varint);
132 InitializeDeltaFile();
133 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
134 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
135 delta_file_.size(),
136 &output_));
137 EXPECT_EQ("", output_);
138}
139
140// Remove one byte from the length of the chunk to process, and
141// verify that an error is returned for FinishDecoding().
142TEST_F(VCDiffInterleavedDecoderTest, FinishAfterDecodingPartialWindow) {
143 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
144 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
145 delta_file_.size() - 1,
146 &output_));
147 EXPECT_FALSE(decoder_.FinishDecoding());
148 // The decoder should not create more target bytes than were expected.
149 EXPECT_GE(expected_target_.size(), output_.size());
150}
151
152TEST_F(VCDiffInterleavedDecoderTest, FinishAfterDecodingPartialWindowHeader) {
153 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
154 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
155 delta_file_header_.size()
156 + delta_window_header_.size() - 1,
157 &output_));
158 EXPECT_FALSE(decoder_.FinishDecoding());
159 // The decoder should not create more target bytes than were expected.
160 EXPECT_GE(expected_target_.size(), output_.size());
161}
162
openvcdiff28db8072008-10-10 23:29:11 +0000163TEST_F(VCDiffInterleavedDecoderTest, TargetMatchesWindowSizeLimit) {
164 decoder_.SetMaximumTargetWindowSize(expected_target_.size());
165 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
166 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
167 delta_file_.size(),
168 &output_));
169 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000170 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff28db8072008-10-10 23:29:11 +0000171}
172
173TEST_F(VCDiffInterleavedDecoderTest, TargetMatchesFileSizeLimit) {
174 decoder_.SetMaximumTargetFileSize(expected_target_.size());
175 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
176 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
177 delta_file_.size(),
178 &output_));
179 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000180 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff28db8072008-10-10 23:29:11 +0000181}
182
183TEST_F(VCDiffInterleavedDecoderTest, TargetExceedsWindowSizeLimit) {
184 decoder_.SetMaximumTargetWindowSize(expected_target_.size() - 1);
185 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
186 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
187 delta_file_.size(),
188 &output_));
189 EXPECT_EQ("", output_);
190}
191
192TEST_F(VCDiffInterleavedDecoderTest, TargetExceedsFileSizeLimit) {
193 decoder_.SetMaximumTargetFileSize(expected_target_.size() - 1);
194 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
195 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
196 delta_file_.size(),
197 &output_));
198 EXPECT_EQ("", output_);
199}
200
openvcdiff311c7142008-08-26 19:29:25 +0000201// Fuzz bits to make sure decoder does not violently crash.
202// This test has no expected behavior except that no crashes should occur.
203// In some cases, changing bits will still decode to the correct target;
204// for example, changing unused bits within a bitfield.
205TEST_F(VCDiffInterleavedDecoderTest, FuzzBits) {
206 while (FuzzOneByteInDeltaFile()) {
207 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
208 if (decoder_.DecodeChunk(delta_file_.data(),
209 delta_file_.size(),
210 &output_)) {
211 decoder_.FinishDecoding();
212 }
213 InitializeDeltaFile();
214 output_.clear();
215 }
216}
217
218// If a checksum is present, then fuzzing any of the bits may produce an error,
219// but it should not result in an incorrect target being produced without
220// an error.
221TEST_F(VCDiffInterleavedDecoderTest, FuzzBitsWithChecksum) {
222 ComputeAndAddChecksum();
223 InitializeDeltaFile();
224 while (FuzzOneByteInDeltaFile()) {
225 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
226 if (decoder_.DecodeChunk(delta_file_.data(),
227 delta_file_.size(),
228 &output_)) {
229 if (decoder_.FinishDecoding()) {
230 // Decoding succeeded. Make sure the correct target was produced.
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000231 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff311c7142008-08-26 19:29:25 +0000232 }
233 } else {
234 EXPECT_EQ("", output_);
235 }
236 InitializeDeltaFile();
237 output_.clear();
238 }
239}
240
openvcdiff311c7142008-08-26 19:29:25 +0000241TEST_F(VCDiffInterleavedDecoderTest, CopyMoreThanExpectedTarget) {
242 delta_file_[delta_file_header_.size() + 0x0C] =
243 FirstByteOfStringLength(kExpectedTarget);
244 delta_file_[delta_file_header_.size() + 0x0D] =
245 SecondByteOfStringLength(kExpectedTarget) + 1;
246 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
247 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
248 delta_file_.size(),
249 &output_));
250 EXPECT_EQ("", output_);
251}
252
253TEST_F(VCDiffInterleavedDecoderTest, CopySizeZero) {
254 delta_file_[delta_file_header_.size() + 0x0C] = 0;
255 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
256 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
257 delta_file_.size(),
258 &output_));
259 EXPECT_EQ("", output_);
260}
261
262TEST_F(VCDiffInterleavedDecoderTest, CopySizeTooLargeByOne) {
263 ++delta_file_[delta_file_header_.size() + 0x0C];
264 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
265 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
266 delta_file_.size(),
267 &output_));
268 EXPECT_EQ("", output_);
269}
270
271TEST_F(VCDiffInterleavedDecoderTest, CopySizeTooSmallByOne) {
272 --delta_file_[delta_file_header_.size() + 0x0C];
273 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
274 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
275 delta_file_.size(),
276 &output_));
277 EXPECT_EQ("", output_);
278}
279
280TEST_F(VCDiffInterleavedDecoderTest, CopySizeMaxInt) {
281 WriteMaxVarintAtOffset(0x0C, 1);
282 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
283 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
284 delta_file_.size(),
285 &output_));
286 EXPECT_EQ("", output_);
287}
288
289TEST_F(VCDiffInterleavedDecoderTest, CopySizeNegative) {
290 WriteNegativeVarintAtOffset(0x0C, 1);
291 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
292 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
293 delta_file_.size(),
294 &output_));
295 EXPECT_EQ("", output_);
296}
297
298TEST_F(VCDiffInterleavedDecoderTest, CopySizeInvalid) {
299 WriteInvalidVarintAtOffset(0x0C, 1);
300 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
301 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
302 delta_file_.size(),
303 &output_));
304 EXPECT_EQ("", output_);
305}
306
307TEST_F(VCDiffInterleavedDecoderTest, CopyAddressBeyondHereAddress) {
308 delta_file_[delta_file_header_.size() + 0x0D] =
309 FirstByteOfStringLength(kDictionary);
310 delta_file_[delta_file_header_.size() + 0x0E] =
311 SecondByteOfStringLength(kDictionary);
312 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
313 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
314 delta_file_.size(),
315 &output_));
316 EXPECT_EQ("", output_);
317}
318
319TEST_F(VCDiffInterleavedDecoderTest, CopyAddressMaxInt) {
320 WriteMaxVarintAtOffset(0x0D, 1);
321 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
322 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
323 delta_file_.size(),
324 &output_));
325 EXPECT_EQ("", output_);
326}
327
328TEST_F(VCDiffInterleavedDecoderTest, CopyAddressNegative) {
329 WriteNegativeVarintAtOffset(0x0D, 1);
330 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
331 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
332 delta_file_.size(),
333 &output_));
334 EXPECT_EQ("", output_);
335}
336
337TEST_F(VCDiffInterleavedDecoderTest, CopyAddressInvalid) {
338 WriteInvalidVarintAtOffset(0x0D, 1);
339 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
340 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
341 delta_file_.size(),
342 &output_));
343 EXPECT_EQ("", output_);
344}
345
346TEST_F(VCDiffInterleavedDecoderTest, AddMoreThanExpectedTarget) {
347 delta_file_[delta_file_header_.size() + 0x0F] =
348 FirstByteOfStringLength(kExpectedTarget);
349 delta_file_[delta_file_header_.size() + 0x10] =
350 SecondByteOfStringLength(kExpectedTarget) + 1;
351 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
352 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
353 delta_file_.size(),
354 &output_));
355 EXPECT_EQ("", output_);
356}
357
358TEST_F(VCDiffInterleavedDecoderTest, AddSizeZero) {
359 delta_file_[delta_file_header_.size() + 0x0F] = 0;
360 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
361 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
362 delta_file_.size(),
363 &output_));
364 EXPECT_EQ("", output_);
365}
366
367TEST_F(VCDiffInterleavedDecoderTest, AddSizeTooLargeByOne) {
368 ++delta_file_[delta_file_header_.size() + 0x0F];
369 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
370 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
371 delta_file_.size(),
372 &output_));
373 EXPECT_EQ("", output_);
374}
375
376TEST_F(VCDiffInterleavedDecoderTest, AddSizeTooSmallByOne) {
377 --delta_file_[delta_file_header_.size() + 0x0F];
378 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
379 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
380 delta_file_.size(),
381 &output_));
382 EXPECT_EQ("", output_);
383}
384
385TEST_F(VCDiffInterleavedDecoderTest, AddSizeMaxInt) {
386 WriteMaxVarintAtOffset(0x0F, 1);
387 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
388 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
389 delta_file_.size(),
390 &output_));
391 EXPECT_EQ("", output_);
392}
393
394TEST_F(VCDiffInterleavedDecoderTest, AddSizeNegative) {
395 WriteNegativeVarintAtOffset(0x0F, 1);
396 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
397 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
398 delta_file_.size(),
399 &output_));
400 EXPECT_EQ("", output_);
401}
402
403TEST_F(VCDiffInterleavedDecoderTest, AddSizeInvalid) {
404 WriteInvalidVarintAtOffset(0x0F, 1);
405 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
406 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
407 delta_file_.size(),
408 &output_));
409 EXPECT_EQ("", output_);
410}
411
412TEST_F(VCDiffInterleavedDecoderTest, RunMoreThanExpectedTarget) {
413 delta_file_[delta_file_header_.size() + 0x5F] =
414 FirstByteOfStringLength(kExpectedTarget);
415 delta_file_[delta_file_header_.size() + 0x60] =
416 SecondByteOfStringLength(kExpectedTarget) + 1;
417 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
418 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
419 delta_file_.size(),
420 &output_));
421 EXPECT_EQ("", output_);
422}
423
424TEST_F(VCDiffInterleavedDecoderTest, RunSizeZero) {
425 delta_file_[delta_file_header_.size() + 0x5F] = 0;
426 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
427 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
428 delta_file_.size(),
429 &output_));
430 EXPECT_EQ("", output_);
431}
432
433TEST_F(VCDiffInterleavedDecoderTest, RunSizeTooLargeByOne) {
434 ++delta_file_[delta_file_header_.size() + 0x5F];
435 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
436 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
437 delta_file_.size(),
438 &output_));
439 EXPECT_EQ("", output_);
440}
441
442TEST_F(VCDiffInterleavedDecoderTest, RunSizeTooSmallByOne) {
443 --delta_file_[delta_file_header_.size() + 0x5F];
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
451TEST_F(VCDiffInterleavedDecoderTest, RunSizeMaxInt) {
452 WriteMaxVarintAtOffset(0x5F, 1);
453 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
454 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
455 delta_file_.size(),
456 &output_));
457 EXPECT_EQ("", output_);
458}
459
460TEST_F(VCDiffInterleavedDecoderTest, RunSizeNegative) {
461 WriteNegativeVarintAtOffset(0x5F, 1);
462 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
463 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
464 delta_file_.size(),
465 &output_));
466 EXPECT_EQ("", output_);
467}
468
469TEST_F(VCDiffInterleavedDecoderTest, RunSizeInvalid) {
470 WriteInvalidVarintAtOffset(0x5F, 1);
471 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
472 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
473 delta_file_.size(),
474 &output_));
475 EXPECT_EQ("", output_);
476}
477
478#if defined(HAVE_MPROTECT) && \
479 (defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN))
480TEST_F(VCDiffInterleavedDecoderTest, ShouldNotReadPastEndOfBuffer) {
481 // Allocate two memory pages.
482 const int page_size = getpagesize();
483 void* two_pages = NULL;
484#ifdef HAVE_POSIX_MEMALIGN
485 posix_memalign(&two_pages, page_size, 2 * page_size);
486#else // !HAVE_POSIX_MEMALIGN
487 two_pages = memalign(page_size, 2 * page_size);
488#endif // HAVE_POSIX_MEMALIGN
489 char* const first_page = reinterpret_cast<char*>(two_pages);
490 char* const second_page = first_page + page_size;
491
492 // Place the delta string at the end of the first page.
493 char* delta_with_guard = second_page - delta_file_.size();
494 memcpy(delta_with_guard, delta_file_.data(), delta_file_.size());
495
496 // Make the second page unreadable.
497 mprotect(second_page, page_size, PROT_NONE);
498
499 // Now perform the decode operation, which will cause a segmentation fault
500 // if it reads past the end of the buffer.
501 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
502 EXPECT_TRUE(decoder_.DecodeChunk(delta_with_guard,
503 delta_file_.size(),
504 &output_));
505 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000506 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff311c7142008-08-26 19:29:25 +0000507
508 // Undo the mprotect.
509 mprotect(second_page, page_size, PROT_READ|PROT_WRITE);
510 free(two_pages);
511}
512
513TEST_F(VCDiffInterleavedDecoderTest, ShouldNotReadPastBeginningOfBuffer) {
514 // Allocate two memory pages.
515 const int page_size = getpagesize();
516 void* two_pages = NULL;
517#ifdef HAVE_POSIX_MEMALIGN
518 posix_memalign(&two_pages, page_size, 2 * page_size);
519#else // !HAVE_POSIX_MEMALIGN
520 two_pages = memalign(page_size, 2 * page_size);
521#endif // HAVE_POSIX_MEMALIGN
522 char* const first_page = reinterpret_cast<char*>(two_pages);
523 char* const second_page = first_page + page_size;
524
525 // Make the first page unreadable.
526 mprotect(first_page, page_size, PROT_NONE);
527
528 // Place the delta string at the beginning of the second page.
529 char* delta_with_guard = second_page;
530 memcpy(delta_with_guard, delta_file_.data(), delta_file_.size());
531
532 // Now perform the decode operation, which will cause a segmentation fault
533 // if it reads past the beginning of the buffer.
534 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
535 EXPECT_TRUE(decoder_.DecodeChunk(delta_with_guard,
536 delta_file_.size(),
537 &output_));
538 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000539 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff311c7142008-08-26 19:29:25 +0000540
541 // Undo the mprotect.
542 mprotect(first_page, page_size, PROT_READ|PROT_WRITE);
543 free(two_pages);
544}
545#endif // HAVE_MPROTECT && (HAVE_MEMALIGN || HAVE_POSIX_MEMALIGN)
546
547// These are the same tests as for VCDiffInterleavedDecoderTest, with the added
548// complication that instead of calling DecodeChunk() once with the entire data
549// set, DecodeChunk() is called once for each byte of input. This is intended
550// to shake out any bugs with rewind and resume while parsing chunked data.
551
552typedef VCDiffInterleavedDecoderTest VCDiffInterleavedDecoderTestByteByByte;
553
554// Test headers, valid and invalid.
555
556TEST_F(VCDiffInterleavedDecoderTestByteByByte, DecodeHeaderOnly) {
557 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
558 for (size_t i = 0; i < delta_file_header_.size(); ++i) {
559 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_header_[i], 1, &output_));
560 }
561 EXPECT_TRUE(decoder_.FinishDecoding());
562 EXPECT_EQ("", output_);
563}
564
565TEST_F(VCDiffInterleavedDecoderTestByteByByte, PartialHeaderNotEnough) {
566 delta_file_.resize(delta_file_header_.size() - 2);
567 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
568 for (size_t i = 0; i < delta_file_.size(); ++i) {
569 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
570 }
571 EXPECT_FALSE(decoder_.FinishDecoding());
572 EXPECT_EQ("", output_);
573}
574
575TEST_F(VCDiffInterleavedDecoderTestByteByByte, BadMagicNumber) {
576 delta_file_[1] = 'Q' | 0x80;
577 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
578 bool failed = false;
579 for (size_t i = 0; i < delta_file_.size(); ++i) {
580 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
581 // It should fail at the position that was altered
582 EXPECT_EQ(1U, i);
583 failed = true;
584 break;
585 }
586 }
587 EXPECT_TRUE(failed);
588 EXPECT_EQ("", output_);
589}
590
591TEST_F(VCDiffInterleavedDecoderTestByteByByte, BadVersionNumber) {
592 delta_file_[3] = 0x01;
593 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
594 bool failed = false;
595 for (size_t i = 0; i < delta_file_.size(); ++i) {
596 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
597 failed = true;
598 // It should fail at the position that was altered
599 EXPECT_EQ(3U, i);
600 break;
601 }
602 }
603 EXPECT_TRUE(failed);
604 EXPECT_EQ("", output_);
605}
606
607TEST_F(VCDiffInterleavedDecoderTestByteByByte,
608 SecondaryCompressionNotSupported) {
609 delta_file_[4] = 0x01;
610 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
611 bool failed = false;
612 for (size_t i = 0; i < delta_file_.size(); ++i) {
613 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
614 failed = true;
615 // It should fail at the position that was altered
616 EXPECT_EQ(4U, i);
617 break;
618 }
619 }
620 EXPECT_TRUE(failed);
621 EXPECT_EQ("", output_);
622}
623
624TEST_F(VCDiffInterleavedDecoderTestByteByByte, Decode) {
625 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
626 for (size_t i = 0; i < delta_file_.size(); ++i) {
627 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
628 }
629 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000630 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff311c7142008-08-26 19:29:25 +0000631}
632
633TEST_F(VCDiffInterleavedDecoderTestByteByByte, DecodeWithChecksum) {
634 ComputeAndAddChecksum();
635 InitializeDeltaFile();
636 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
637 for (size_t i = 0; i < delta_file_.size(); ++i) {
638 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
639 }
640 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000641 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff311c7142008-08-26 19:29:25 +0000642}
643
644TEST_F(VCDiffInterleavedDecoderTestByteByByte, ChecksumDoesNotMatch) {
645 AddChecksum(0xBADBAD);
646 InitializeDeltaFile();
647 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
648 bool failed = false;
649 for (size_t i = 0; i < delta_file_.size(); ++i) {
650 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
651 failed = true;
652 // It should fail after decoding the entire delta file
653 EXPECT_EQ(delta_file_.size() - 1, i);
654 break;
655 }
656 }
657 EXPECT_TRUE(failed);
658 // The decoder should not create more target bytes than were expected.
659 EXPECT_GE(expected_target_.size(), output_.size());
660}
661
662TEST_F(VCDiffInterleavedDecoderTestByteByByte, ChecksumIsInvalid64BitVarint) {
663 static const char kInvalidVarint[] = { 0x81, 0x80, 0x80, 0x80, 0x80, 0x80,
664 0x80, 0x80, 0x80, 0x00 };
665 delta_window_header_[0] |= VCD_CHECKSUM;
666 delta_window_header_.append(kInvalidVarint, sizeof(kInvalidVarint));
667 // Adjust delta window size to include size of invalid Varint.
668 string size_of_invalid_varint;
669 VarintBE<int32_t>::AppendToString(
670 static_cast<int32_t>(delta_window_header_[4] + sizeof(kInvalidVarint)),
671 &size_of_invalid_varint);
672 delta_window_header_.replace(4, 1, size_of_invalid_varint);
673 InitializeDeltaFile();
674 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
675 bool failed = false;
676 for (size_t i = 0; i < delta_file_.size(); ++i) {
677 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
678 failed = true;
679 // It should fail while trying to interpret the checksum.
680 EXPECT_EQ(delta_file_header_.size() + delta_window_header_.size() - 2, i);
681 break;
682 }
683 }
684 EXPECT_TRUE(failed);
685 // The decoder should not create more target bytes than were expected.
686 EXPECT_GE(expected_target_.size(), output_.size());
687}
688
openvcdiff28db8072008-10-10 23:29:11 +0000689TEST_F(VCDiffInterleavedDecoderTestByteByByte, TargetMatchesWindowSizeLimit) {
690 decoder_.SetMaximumTargetWindowSize(expected_target_.size());
691 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
692 for (size_t i = 0; i < delta_file_.size(); ++i) {
693 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
694 }
695 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000696 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff28db8072008-10-10 23:29:11 +0000697}
698
699TEST_F(VCDiffInterleavedDecoderTestByteByByte, TargetMatchesFileSizeLimit) {
700 decoder_.SetMaximumTargetFileSize(expected_target_.size());
701 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
702 for (size_t i = 0; i < delta_file_.size(); ++i) {
703 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
704 }
705 EXPECT_TRUE(decoder_.FinishDecoding());
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000706 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff28db8072008-10-10 23:29:11 +0000707}
708
709TEST_F(VCDiffInterleavedDecoderTestByteByByte, TargetExceedsWindowSizeLimit) {
710 decoder_.SetMaximumTargetWindowSize(expected_target_.size() - 1);
711 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
712 bool failed = false;
713 for (size_t i = 0; i < delta_file_.size(); ++i) {
714 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
715 failed = true;
716 break;
717 }
718 }
719 EXPECT_TRUE(failed);
720 EXPECT_EQ("", output_);
721}
722
723TEST_F(VCDiffInterleavedDecoderTestByteByByte, TargetExceedsFileSizeLimit) {
724 decoder_.SetMaximumTargetFileSize(expected_target_.size() - 1);
725 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
726 bool failed = false;
727 for (size_t i = 0; i < delta_file_.size(); ++i) {
728 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
729 failed = true;
730 break;
731 }
732 }
733 EXPECT_TRUE(failed);
734 EXPECT_EQ("", output_);
735}
736
openvcdiff311c7142008-08-26 19:29:25 +0000737// Fuzz bits to make sure decoder does not violently crash.
738// This test has no expected behavior except that no crashes should occur.
739// In some cases, changing bits will still decode to the correct target;
740// for example, changing unused bits within a bitfield.
741TEST_F(VCDiffInterleavedDecoderTestByteByByte, FuzzBits) {
742 while (FuzzOneByteInDeltaFile()) {
743 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
744 bool failed = false;
745 for (size_t i = 0; i < delta_file_.size(); ++i) {
746 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
747 failed = true;
748 break;
749 }
750 }
751 if (!failed) {
752 decoder_.FinishDecoding();
753 }
754 InitializeDeltaFile();
755 output_.clear();
756 }
757}
758
759// If a checksum is present, then fuzzing any of the bits may produce an error,
760// but it should not result in an incorrect target being produced without
761// an error.
762TEST_F(VCDiffInterleavedDecoderTestByteByByte, FuzzBitsWithChecksum) {
763 ComputeAndAddChecksum();
764 InitializeDeltaFile();
765 while (FuzzOneByteInDeltaFile()) {
766 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
767 bool failed = false;
768 for (size_t i = 0; i < delta_file_.size(); ++i) {
769 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
770 failed = true;
771 break;
772 }
773 }
774 if (!failed) {
775 if (decoder_.FinishDecoding()) {
776 // Decoding succeeded. Make sure the correct target was produced.
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000777 EXPECT_EQ(expected_target_.c_str(), output_);
openvcdiff311c7142008-08-26 19:29:25 +0000778 }
779 }
780 // The decoder should not create more target bytes than were expected.
781 EXPECT_GE(expected_target_.size(), output_.size());
782 InitializeDeltaFile();
783 output_.clear();
784 }
785}
786
openvcdiff311c7142008-08-26 19:29:25 +0000787TEST_F(VCDiffInterleavedDecoderTestByteByByte,
788 CopyInstructionsShouldFailIfNoSourceSegment) {
789 // Replace the Win_Indicator and the source size and source offset with a
790 // single 0 byte (a Win_Indicator for a window with no source segment.)
791 delta_window_header_.replace(0, 4, "\0", 1);
792 InitializeDeltaFile();
793 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
794 bool failed = false;
795 for (size_t i = 0; i < delta_file_.size(); ++i) {
796 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
797 failed = true;
798 // The first COPY instruction should fail.
799 EXPECT_EQ(delta_file_header_.size() + delta_window_header_.size() + 2, i);
800 break;
801 }
802 }
803 EXPECT_TRUE(failed);
804 EXPECT_EQ("", output_);
805}
806
807TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyMoreThanExpectedTarget) {
808 delta_file_[delta_file_header_.size() + 0x0C] =
809 FirstByteOfStringLength(kExpectedTarget);
810 delta_file_[delta_file_header_.size() + 0x0D] =
811 SecondByteOfStringLength(kExpectedTarget) + 1;
812 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
813 bool failed = false;
814 for (size_t i = 0; i < delta_file_.size(); ++i) {
815 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
816 failed = true;
817 // It should fail at the position that was altered
818 EXPECT_EQ(delta_file_header_.size() + 0x0D, i);
819 break;
820 }
821 }
822 EXPECT_TRUE(failed);
823 // The decoder should not create more target bytes than were expected.
824 EXPECT_GE(expected_target_.size(), output_.size());
825}
826
827// A COPY instruction with an explicit size of 0 is not illegal according to the
828// standard, although it is inefficient and should not be generated by any
829// reasonable encoder. Changing the size of a COPY instruction to zero will
830// cause a failure because the generated target window size will not match the
831// expected target size.
832TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeZero) {
833 delta_file_[delta_file_header_.size() + 0x0C] = 0;
834 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
835 bool failed = false;
836 for (size_t i = 0; i < delta_file_.size(); ++i) {
837 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
838 failed = true;
839 break;
840 }
841 }
842 EXPECT_TRUE(failed);
843 // The decoder should not create more target bytes than were expected.
844 EXPECT_GE(expected_target_.size(), output_.size());
845}
846
847TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeTooLargeByOne) {
848 ++delta_file_[delta_file_header_.size() + 0x0C];
849 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
850 bool failed = false;
851 for (size_t i = 0; i < delta_file_.size(); ++i) {
852 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
853 failed = true;
854 break;
855 }
856 }
857 EXPECT_TRUE(failed);
858 // The decoder should not create more target bytes than were expected.
859 EXPECT_GE(expected_target_.size(), output_.size());
860}
861
862TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeTooSmallByOne) {
863 --delta_file_[delta_file_header_.size() + 0x0C];
864 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
865 bool failed = false;
866 for (size_t i = 0; i < delta_file_.size(); ++i) {
867 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
868 failed = true;
869 break;
870 }
871 }
872 EXPECT_TRUE(failed);
873 // The decoder should not create more target bytes than were expected.
874 EXPECT_GE(expected_target_.size(), output_.size());
875}
876
877TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeMaxInt) {
878 WriteMaxVarintAtOffset(0x0C, 1);
879 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
880 bool failed = false;
881 for (size_t i = 0; i < delta_file_.size(); ++i) {
882 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
883 failed = true;
884 // It should fail at the position that was altered
885 EXPECT_EQ(delta_file_header_.size() + 0x10, i);
886 break;
887 }
888 }
889 EXPECT_TRUE(failed);
890 // The decoder should not create more target bytes than were expected.
891 EXPECT_GE(expected_target_.size(), output_.size());
892}
893
894TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeNegative) {
895 WriteNegativeVarintAtOffset(0x0C, 1);
896 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
897 bool failed = false;
898 for (size_t i = 0; i < delta_file_.size(); ++i) {
899 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
900 failed = true;
901 // It should fail at the position that was altered
openvcdiff@gmail.comf1dd9332009-10-09 22:40:32 +0000902 EXPECT_EQ(delta_file_header_.size() + 0x0F, i);
openvcdiff311c7142008-08-26 19:29:25 +0000903 break;
904 }
905 }
906 EXPECT_TRUE(failed);
907 // The decoder should not create more target bytes than were expected.
908 EXPECT_GE(expected_target_.size(), output_.size());
909}
910
911TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeInvalid) {
912 WriteInvalidVarintAtOffset(0x0C, 1);
913 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
914 bool failed = false;
915 for (size_t i = 0; i < delta_file_.size(); ++i) {
916 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
917 failed = true;
918 // It should fail at the position that was altered
919 EXPECT_EQ(delta_file_header_.size() + 0x10, i);
920 break;
921 }
922 }
923 EXPECT_TRUE(failed);
924 // The decoder should not create more target bytes than were expected.
925 EXPECT_GE(expected_target_.size(), output_.size());
926}
927
928TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressBeyondHereAddress) {
929 delta_file_[delta_file_header_.size() + 0x0D] =
930 FirstByteOfStringLength(kDictionary);
931 delta_file_[delta_file_header_.size() + 0x0E] =
932 SecondByteOfStringLength(kDictionary);
933 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
934 bool failed = false;
935 for (size_t i = 0; i < delta_file_.size(); ++i) {
936 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
937 failed = true;
938 // It should fail at the position that was altered
939 EXPECT_EQ(delta_file_header_.size() + 0x0E, i);
940 break;
941 }
942 }
943 EXPECT_TRUE(failed);
944 // The decoder should not create more target bytes than were expected.
945 EXPECT_GE(expected_target_.size(), output_.size());
946}
947
948TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressMaxInt) {
949 WriteMaxVarintAtOffset(0x0D, 1);
950 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
951 bool failed = false;
952 for (size_t i = 0; i < delta_file_.size(); ++i) {
953 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
954 failed = true;
955 // It should fail at the position that was altered
956 EXPECT_EQ(delta_file_header_.size() + 0x11, i);
957 break;
958 }
959 }
960 EXPECT_TRUE(failed);
961 // The decoder should not create more target bytes than were expected.
962 EXPECT_GE(expected_target_.size(), output_.size());
963}
964
965TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressNegative) {
966 WriteNegativeVarintAtOffset(0x0D, 1);
967 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
968 bool failed = false;
969 for (size_t i = 0; i < delta_file_.size(); ++i) {
970 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
971 failed = true;
972 // It should fail at the position that was altered
openvcdiff@gmail.comf1dd9332009-10-09 22:40:32 +0000973 EXPECT_EQ(delta_file_header_.size() + 0x10, i);
openvcdiff311c7142008-08-26 19:29:25 +0000974 break;
975 }
976 }
977 EXPECT_TRUE(failed);
978 // The decoder should not create more target bytes than were expected.
979 EXPECT_GE(expected_target_.size(), output_.size());
980}
981
982TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressInvalid) {
983 WriteInvalidVarintAtOffset(0x0D, 1);
984 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
985 bool failed = false;
986 for (size_t i = 0; i < delta_file_.size(); ++i) {
987 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
988 failed = true;
989 // It should fail at the position that was altered
990 EXPECT_EQ(delta_file_header_.size() + 0x11, i);
991 break;
992 }
993 }
994 EXPECT_TRUE(failed);
995 // The decoder should not create more target bytes than were expected.
996 EXPECT_GE(expected_target_.size(), output_.size());
997}
998
999TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddMoreThanExpectedTarget) {
1000 delta_file_[delta_file_header_.size() + 0x0F] =
1001 FirstByteOfStringLength(kExpectedTarget);
1002 delta_file_[delta_file_header_.size() + 0x10] =
1003 SecondByteOfStringLength(kExpectedTarget) + 1;
1004 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1005 bool failed = false;
1006 for (size_t i = 0; i < delta_file_.size(); ++i) {
1007 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1008 failed = true;
1009 // It should fail at the position that was altered
1010 EXPECT_EQ(delta_file_header_.size() + 0x10, i);
1011 break;
1012 }
1013 }
1014 EXPECT_TRUE(failed);
1015 // The decoder should not create more target bytes than were expected.
1016 EXPECT_GE(expected_target_.size(), output_.size());
1017}
1018
1019// An ADD instruction with an explicit size of 0 is not illegal according to the
1020// standard, although it is inefficient and should not be generated by any
1021// reasonable encoder. Changing the size of an ADD instruction to zero will
1022// cause a failure because the generated target window size will not match the
1023// expected target size.
1024TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeZero) {
1025 delta_file_[delta_file_header_.size() + 0x0F] = 0;
1026 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1027 bool failed = false;
1028 for (size_t i = 0; i < delta_file_.size(); ++i) {
1029 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1030 failed = true;
1031 break;
1032 }
1033 }
1034 EXPECT_TRUE(failed);
1035 // The decoder should not create more target bytes than were expected.
1036 EXPECT_GE(expected_target_.size(), output_.size());
1037}
1038
1039TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeTooLargeByOne) {
1040 ++delta_file_[delta_file_header_.size() + 0x0F];
1041 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1042 bool failed = false;
1043 for (size_t i = 0; i < delta_file_.size(); ++i) {
1044 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1045 failed = true;
1046 break;
1047 }
1048 }
1049 EXPECT_TRUE(failed);
1050 // The decoder should not create more target bytes than were expected.
1051 EXPECT_GE(expected_target_.size(), output_.size());
1052}
1053
1054TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeTooSmallByOne) {
1055 --delta_file_[delta_file_header_.size() + 0x0F];
1056 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1057 bool failed = false;
1058 for (size_t i = 0; i < delta_file_.size(); ++i) {
1059 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1060 failed = true;
1061 break;
1062 }
1063 }
1064 EXPECT_TRUE(failed);
1065 // The decoder should not create more target bytes than were expected.
1066 EXPECT_GE(expected_target_.size(), output_.size());
1067}
1068
1069TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeMaxInt) {
1070 WriteMaxVarintAtOffset(0x0F, 1);
1071 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1072 bool failed = false;
1073 for (size_t i = 0; i < delta_file_.size(); ++i) {
1074 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1075 failed = true;
1076 // It should fail at the position that was altered
1077 EXPECT_EQ(delta_file_header_.size() + 0x13, i);
1078 break;
1079 }
1080 }
1081 EXPECT_TRUE(failed);
1082 // The decoder should not create more target bytes than were expected.
1083 EXPECT_GE(expected_target_.size(), output_.size());
1084}
1085
1086TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeNegative) {
1087 WriteNegativeVarintAtOffset(0x0F, 1);
1088 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1089 bool failed = false;
1090 for (size_t i = 0; i < delta_file_.size(); ++i) {
1091 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1092 failed = true;
1093 // It should fail at the position that was altered
openvcdiff@gmail.comf1dd9332009-10-09 22:40:32 +00001094 EXPECT_EQ(delta_file_header_.size() + 0x12, i);
openvcdiff311c7142008-08-26 19:29:25 +00001095 break;
1096 }
1097 }
1098 EXPECT_TRUE(failed);
1099 // The decoder should not create more target bytes than were expected.
1100 EXPECT_GE(expected_target_.size(), output_.size());
1101}
1102
1103TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeInvalid) {
1104 WriteInvalidVarintAtOffset(0x0F, 1);
1105 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1106 bool failed = false;
1107 for (size_t i = 0; i < delta_file_.size(); ++i) {
1108 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1109 failed = true;
1110 // It should fail at the position that was altered
1111 EXPECT_EQ(delta_file_header_.size() + 0x13, i);
1112 break;
1113 }
1114 }
1115 EXPECT_TRUE(failed);
1116 // The decoder should not create more target bytes than were expected.
1117 EXPECT_GE(expected_target_.size(), output_.size());
1118}
1119
1120TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunMoreThanExpectedTarget) {
1121 delta_file_[delta_file_header_.size() + 0x5F] =
1122 FirstByteOfStringLength(kExpectedTarget);
1123 delta_file_[delta_file_header_.size() + 0x60] =
1124 SecondByteOfStringLength(kExpectedTarget) + 1;
1125 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1126 bool failed = false;
1127 for (size_t i = 0; i < delta_file_.size(); ++i) {
1128 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1129 failed = true;
1130 // It should fail at the position that was altered
1131 EXPECT_EQ(delta_file_header_.size() + 0x60, i);
1132 break;
1133 }
1134 }
1135 EXPECT_TRUE(failed);
1136 // The decoder should not create more target bytes than were expected.
1137 EXPECT_GE(expected_target_.size(), output_.size());
1138}
1139
1140// A RUN instruction with an explicit size of 0 is not illegal according to the
1141// standard, although it is inefficient and should not be generated by any
1142// reasonable encoder. Changing the size of a RUN instruction to zero will
1143// cause a failure because the generated target window size will not match the
1144// expected target size.
1145TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeZero) {
1146 delta_file_[delta_file_header_.size() + 0x5F] = 0;
1147 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1148 bool failed = false;
1149 for (size_t i = 0; i < delta_file_.size(); ++i) {
1150 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1151 failed = true;
1152 break;
1153 }
1154 }
1155 EXPECT_TRUE(failed);
1156 // The decoder should not create more target bytes than were expected.
1157 EXPECT_GE(expected_target_.size(), output_.size());
1158}
1159
1160TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeTooLargeByOne) {
1161 ++delta_file_[delta_file_header_.size() + 0x5F];
1162 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1163 bool failed = false;
1164 for (size_t i = 0; i < delta_file_.size(); ++i) {
1165 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1166 failed = true;
1167 break;
1168 }
1169 }
1170 EXPECT_TRUE(failed);
1171 // The decoder should not create more target bytes than were expected.
1172 EXPECT_GE(expected_target_.size(), output_.size());
1173}
1174
1175TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeTooSmallByOne) {
1176 --delta_file_[delta_file_header_.size() + 0x5F];
1177 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1178 bool failed = false;
1179 for (size_t i = 0; i < delta_file_.size(); ++i) {
1180 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1181 failed = true;
1182 break;
1183 }
1184 }
1185 EXPECT_TRUE(failed);
1186 // The decoder should not create more target bytes than were expected.
1187 EXPECT_GE(expected_target_.size(), output_.size());
1188}
1189
1190TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeMaxInt) {
1191 WriteMaxVarintAtOffset(0x5F, 1);
1192 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1193 bool failed = false;
1194 for (size_t i = 0; i < delta_file_.size(); ++i) {
1195 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1196 failed = true;
1197 // It should fail at the position that was altered
1198 EXPECT_EQ(delta_file_header_.size() + 0x63, i);
1199 break;
1200 }
1201 }
1202 EXPECT_TRUE(failed);
1203 // The decoder should not create more target bytes than were expected.
1204 EXPECT_GE(expected_target_.size(), output_.size());
1205}
1206
1207TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeNegative) {
1208 WriteNegativeVarintAtOffset(0x5F, 1);
1209 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1210 bool failed = false;
1211 for (size_t i = 0; i < delta_file_.size(); ++i) {
1212 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1213 failed = true;
1214 // It should fail at the position that was altered
openvcdiff@gmail.comf1dd9332009-10-09 22:40:32 +00001215 EXPECT_EQ(delta_file_header_.size() + 0x62, i);
openvcdiff311c7142008-08-26 19:29:25 +00001216 break;
1217 }
1218 }
1219 EXPECT_TRUE(failed);
1220 // The decoder should not create more target bytes than were expected.
1221 EXPECT_GE(expected_target_.size(), output_.size());
1222}
1223
1224TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeInvalid) {
1225 WriteInvalidVarintAtOffset(0x5F, 1);
1226 decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1227 bool failed = false;
1228 for (size_t i = 0; i < delta_file_.size(); ++i) {
1229 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1230 failed = true;
1231 // It should fail at the position that was altered
1232 EXPECT_EQ(delta_file_header_.size() + 0x63, i);
1233 break;
1234 }
1235 }
1236 EXPECT_TRUE(failed);
1237 // The decoder should not create more target bytes than were expected.
1238 EXPECT_GE(expected_target_.size(), output_.size());
1239}
1240
1241} // namespace open_vcdiff