diff options
Diffstat (limited to 'xdelta3/testing')
-rw-r--r-- | xdelta3/testing/Makefile | 3 | ||||
-rw-r--r-- | xdelta3/testing/file.h | 13 | ||||
-rw-r--r-- | xdelta3/testing/modify.h | 2 | ||||
-rw-r--r-- | xdelta3/testing/regtest.cc | 322 | ||||
-rw-r--r-- | xdelta3/testing/sizes.h | 19 |
5 files changed, 290 insertions, 69 deletions
diff --git a/xdelta3/testing/Makefile b/xdelta3/testing/Makefile index 77cc11d..f859f94 100644 --- a/xdelta3/testing/Makefile +++ b/xdelta3/testing/Makefile | |||
@@ -1,2 +1,5 @@ | |||
1 | all: | 1 | all: |
2 | (cd .. && make all) | 2 | (cd .. && make all) |
3 | |||
4 | xdelta3regtest: | ||
5 | (cd .. && make xdelta3regtest) | ||
diff --git a/xdelta3/testing/file.h b/xdelta3/testing/file.h index a204d74..67309ac 100644 --- a/xdelta3/testing/file.h +++ b/xdelta3/testing/file.h | |||
@@ -82,16 +82,21 @@ public: | |||
82 | } | 82 | } |
83 | 83 | ||
84 | void SetSize(size_t size) { | 84 | void SetSize(size_t size) { |
85 | size_ = size; | 85 | uint8_t *t = NULL; |
86 | |||
87 | if (data_size_ < size) { | 86 | if (data_size_ < size) { |
88 | if (data_) { | 87 | if (data_) { |
89 | delete [] data_; | 88 | t = data_; |
90 | } | 89 | } |
91 | data_ = new uint8_t[size]; | 90 | data_ = new uint8_t[size]; |
92 | data_size_ = size; | 91 | data_size_ = size; |
93 | } | 92 | } |
93 | if (t && size < size_) { | ||
94 | memcpy(data_, t, size); | ||
95 | } | ||
96 | delete [] t; | ||
97 | size_ = size; | ||
94 | } | 98 | } |
99 | |||
95 | private: | 100 | private: |
96 | friend class BlockIterator; | 101 | friend class BlockIterator; |
97 | 102 | ||
@@ -268,6 +273,7 @@ public: | |||
268 | } | 273 | } |
269 | 274 | ||
270 | void SetBlock(xoff_t blkno) { | 275 | void SetBlock(xoff_t blkno) { |
276 | CHECK_LE(blkno, Blocks()); | ||
271 | blkno_ = blkno; | 277 | blkno_ = blkno; |
272 | } | 278 | } |
273 | 279 | ||
@@ -373,4 +379,3 @@ public: | |||
373 | private: | 379 | private: |
374 | mutable main_file file_; | 380 | mutable main_file file_; |
375 | }; | 381 | }; |
376 | |||
diff --git a/xdelta3/testing/modify.h b/xdelta3/testing/modify.h index 5c2e316..023e6ce 100644 --- a/xdelta3/testing/modify.h +++ b/xdelta3/testing/modify.h | |||
@@ -15,7 +15,7 @@ public: | |||
15 | DELETE = 3, // Delete a specified range of data | 15 | DELETE = 3, // Delete a specified range of data |
16 | COPY = 4, // Copy from one region, inserting elsewhere | 16 | COPY = 4, // Copy from one region, inserting elsewhere |
17 | MOVE = 5, // Copy then delete copied-from range | 17 | MOVE = 5, // Copy then delete copied-from range |
18 | COPYOVER = 6 // Copy then delete copied-to range | 18 | COPYOVER = 6 // Copy then delete copied-to range |
19 | 19 | ||
20 | // ADD, DELETE, and COPY change the file size | 20 | // ADD, DELETE, and COPY change the file size |
21 | // MODIFY, MOVE, COPYOVER preserve the file size | 21 | // MODIFY, MOVE, COPYOVER preserve the file size |
diff --git a/xdelta3/testing/regtest.cc b/xdelta3/testing/regtest.cc index 12b712e..7f9ba52 100644 --- a/xdelta3/testing/regtest.cc +++ b/xdelta3/testing/regtest.cc | |||
@@ -9,12 +9,18 @@ public: | |||
9 | typedef typename Constants::Sizes Sizes; | 9 | typedef typename Constants::Sizes Sizes; |
10 | 10 | ||
11 | struct Options { | 11 | struct Options { |
12 | Options() : encode_srcwin_maxsz(1<<20), | 12 | Options() |
13 | block_size(Constants::BLOCK_SIZE), | 13 | : encode_srcwin_maxsz(1<<20), |
14 | size_known(false) { } | 14 | block_size(Constants::BLOCK_SIZE), |
15 | size_known(false), | ||
16 | iopt_size(XD3_DEFAULT_IOPT_SIZE), | ||
17 | smatch_cfg(XD3_SMATCH_DEFAULT) { } | ||
18 | |||
15 | size_t encode_srcwin_maxsz; | 19 | size_t encode_srcwin_maxsz; |
16 | size_t block_size; | 20 | size_t block_size; |
17 | bool size_known; | 21 | bool size_known; |
22 | usize_t iopt_size; | ||
23 | xd3_smatch_cfg smatch_cfg; | ||
18 | }; | 24 | }; |
19 | 25 | ||
20 | #include "segment.h" | 26 | #include "segment.h" |
@@ -26,7 +32,7 @@ public: | |||
26 | void InMemoryEncodeDecode(const FileSpec &source_file, | 32 | void InMemoryEncodeDecode(const FileSpec &source_file, |
27 | const FileSpec &target_file, | 33 | const FileSpec &target_file, |
28 | Block *coded_data, | 34 | Block *coded_data, |
29 | const Options &options = Options()) { | 35 | const Options &options) { |
30 | xd3_stream encode_stream; | 36 | xd3_stream encode_stream; |
31 | xd3_config encode_config; | 37 | xd3_config encode_config; |
32 | xd3_source encode_source; | 38 | xd3_source encode_source; |
@@ -51,16 +57,8 @@ public: | |||
51 | xd3_init_config(&decode_config, XD3_ADLER32); | 57 | xd3_init_config(&decode_config, XD3_ADLER32); |
52 | 58 | ||
53 | encode_config.winsize = Constants::WINDOW_SIZE; | 59 | encode_config.winsize = Constants::WINDOW_SIZE; |
54 | 60 | encode_config.iopt_size = options.iopt_size; | |
55 | // TODO! the smatcher setup isn't working, | 61 | encode_config.smatch_cfg = options.smatch_cfg; |
56 | // if (options.large_cksum_step) { | ||
57 | // encode_config.smatch_cfg = XD3_SMATCH_SOFT; | ||
58 | // encode_config.smatcher_soft.large_step = options.large_cksum_step; | ||
59 | // } | ||
60 | // if (options.large_cksum_size) { | ||
61 | // encode_config.smatch_cfg = XD3_SMATCH_SOFT; | ||
62 | // encode_config.smatcher_soft.large_look = options.large_cksum_size; | ||
63 | // } | ||
64 | 62 | ||
65 | CHECK_EQ(0, xd3_config_stream (&encode_stream, &encode_config)); | 63 | CHECK_EQ(0, xd3_config_stream (&encode_stream, &encode_config)); |
66 | CHECK_EQ(0, xd3_config_stream (&decode_stream, &decode_config)); | 64 | CHECK_EQ(0, xd3_config_stream (&decode_stream, &decode_config)); |
@@ -71,30 +69,30 @@ public: | |||
71 | encode_source.max_winsize = options.encode_srcwin_maxsz; | 69 | encode_source.max_winsize = options.encode_srcwin_maxsz; |
72 | decode_source.max_winsize = options.encode_srcwin_maxsz; | 70 | decode_source.max_winsize = options.encode_srcwin_maxsz; |
73 | 71 | ||
74 | if (!options.size_known) | 72 | if (!options.size_known) |
75 | { | 73 | { |
76 | xd3_set_source (&encode_stream, &encode_source); | 74 | xd3_set_source (&encode_stream, &encode_source); |
77 | xd3_set_source (&decode_stream, &decode_source); | 75 | xd3_set_source (&decode_stream, &decode_source); |
78 | } | 76 | } |
79 | else | 77 | else |
80 | { | 78 | { |
81 | xd3_set_source_and_size (&encode_stream, &encode_source, | 79 | xd3_set_source_and_size (&encode_stream, &encode_source, |
82 | source_file.Size()); | 80 | source_file.Size()); |
83 | xd3_set_source_and_size (&decode_stream, &decode_source, | 81 | xd3_set_source_and_size (&decode_stream, &decode_source, |
84 | source_file.Size()); | 82 | source_file.Size()); |
85 | } | 83 | } |
86 | 84 | ||
87 | BlockIterator source_iterator(source_file, options.block_size); | 85 | BlockIterator source_iterator(source_file, options.block_size); |
88 | BlockIterator target_iterator(target_file, Constants::READ_SIZE); | 86 | BlockIterator target_iterator(target_file, Constants::WINDOW_SIZE); |
89 | Block encode_source_block, decode_source_block; | 87 | Block encode_source_block, decode_source_block; |
90 | Block decoded_block, target_block; | 88 | Block decoded_block, target_block; |
91 | bool encoding = true; | 89 | bool encoding = true; |
92 | bool done = false; | 90 | bool done = false; |
93 | bool done_after_input = false; | 91 | bool done_after_input = false; |
94 | 92 | ||
95 | IF_DEBUG1 (XPR(NTR "source %"Q"u[%"Q"u] target %"Q"u[%lu] winsize %lu\n", | 93 | IF_DEBUG1 (XPR(NTR "source %"Q"u[%"Q"u] target %"Q"u winsize %lu\n", |
96 | source_file.Size(), options.block_size, | 94 | source_file.Size(), options.block_size, |
97 | target_file.Size(), Constants::READ_SIZE, | 95 | target_file.Size(), |
98 | Constants::WINDOW_SIZE)); | 96 | Constants::WINDOW_SIZE)); |
99 | 97 | ||
100 | while (!done) { | 98 | while (!done) { |
@@ -102,7 +100,8 @@ public: | |||
102 | 100 | ||
103 | xoff_t blks = target_iterator.Blocks(); | 101 | xoff_t blks = target_iterator.Blocks(); |
104 | 102 | ||
105 | IF_DEBUG2(XPR(NTR "target in %s: %llu..%llu %"Q"u(%"Q"u) verified %"Q"u\n", | 103 | IF_DEBUG2(XPR(NTR "target in %s: %"Q"u..%"Q"u %"Q"u(%"Q"u) " |
104 | "verified %"Q"u\n", | ||
106 | encoding ? "encoding" : "decoding", | 105 | encoding ? "encoding" : "decoding", |
107 | target_iterator.Offset(), | 106 | target_iterator.Offset(), |
108 | target_iterator.Offset() + target_block.Size(), | 107 | target_iterator.Offset() + target_block.Size(), |
@@ -229,10 +228,10 @@ public: | |||
229 | ExtFile *coded_data, | 228 | ExtFile *coded_data, |
230 | const Options &options) { | 229 | const Options &options) { |
231 | vector<const char*> ecmd; | 230 | vector<const char*> ecmd; |
232 | char buf[16]; | 231 | char wbuf[16]; |
233 | snprintf(buf, sizeof(buf), "-B%"Q"u", options.encode_srcwin_maxsz); | 232 | snprintf(wbuf, sizeof(wbuf), "-B%"Q"u", options.encode_srcwin_maxsz); |
234 | ecmd.push_back("xdelta3"); | 233 | ecmd.push_back("xdelta3"); |
235 | ecmd.push_back(buf); | 234 | ecmd.push_back(wbuf); |
236 | ecmd.push_back("-s"); | 235 | ecmd.push_back("-s"); |
237 | ecmd.push_back(source_file.Name()); | 236 | ecmd.push_back(source_file.Name()); |
238 | ecmd.push_back(target_file.Name()); | 237 | ecmd.push_back(target_file.Name()); |
@@ -245,7 +244,7 @@ public: | |||
245 | vector<const char*> dcmd; | 244 | vector<const char*> dcmd; |
246 | ExtFile recon_file; | 245 | ExtFile recon_file; |
247 | dcmd.push_back("xdelta3"); | 246 | dcmd.push_back("xdelta3"); |
248 | ecmd.push_back(buf); | 247 | ecmd.push_back(wbuf); |
249 | dcmd.push_back("-d"); | 248 | dcmd.push_back("-d"); |
250 | dcmd.push_back("-s"); | 249 | dcmd.push_back("-s"); |
251 | dcmd.push_back(source_file.Name()); | 250 | dcmd.push_back(source_file.Name()); |
@@ -256,10 +255,115 @@ public: | |||
256 | CHECK_EQ(0, xd3_main_cmdline(dcmd.size() - 1, | 255 | CHECK_EQ(0, xd3_main_cmdline(dcmd.size() - 1, |
257 | const_cast<char**>(&dcmd[0]))); | 256 | const_cast<char**>(&dcmd[0]))); |
258 | 257 | ||
259 | CHECK_EQ(0, test_compare_files(recon_file.Name(), | 258 | CHECK_EQ(0, test_compare_files(recon_file.Name(), |
260 | target_file.Name())); | 259 | target_file.Name())); |
261 | } | 260 | } |
262 | 261 | ||
262 | // Similar to xd3_process_memory, with support for test Options. | ||
263 | // Exercises xd3_process_stream. | ||
264 | int TestProcessMemory (int is_encode, | ||
265 | int (*func) (xd3_stream *), | ||
266 | const uint8_t *input, | ||
267 | usize_t input_size, | ||
268 | const uint8_t *source, | ||
269 | usize_t source_size, | ||
270 | uint8_t *output, | ||
271 | usize_t *output_size, | ||
272 | usize_t output_size_max, | ||
273 | const Options &options) { | ||
274 | xd3_stream stream; | ||
275 | xd3_config config; | ||
276 | xd3_source src; | ||
277 | int ret; | ||
278 | |||
279 | memset (& stream, 0, sizeof (stream)); | ||
280 | memset (& config, 0, sizeof (config)); | ||
281 | |||
282 | if (is_encode) | ||
283 | { | ||
284 | config.winsize = input_size; | ||
285 | config.iopt_size = options.iopt_size; | ||
286 | config.sprevsz = xd3_pow2_roundup (config.winsize); | ||
287 | } | ||
288 | |||
289 | if ((ret = xd3_config_stream (&stream, &config)) != 0) | ||
290 | { | ||
291 | goto exit; | ||
292 | } | ||
293 | |||
294 | if (source != NULL) | ||
295 | { | ||
296 | memset (& src, 0, sizeof (src)); | ||
297 | |||
298 | src.blksize = source_size; | ||
299 | src.onblk = source_size; | ||
300 | src.curblk = source; | ||
301 | src.curblkno = 0; | ||
302 | src.max_winsize = source_size; | ||
303 | |||
304 | if ((ret = xd3_set_source_and_size (&stream, &src, source_size)) != 0) | ||
305 | { | ||
306 | goto exit; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | if ((ret = xd3_process_stream (is_encode, | ||
311 | & stream, | ||
312 | func, 1, | ||
313 | input, input_size, | ||
314 | output, | ||
315 | output_size, | ||
316 | output_size_max)) != 0) | ||
317 | { | ||
318 | goto exit; | ||
319 | } | ||
320 | |||
321 | exit: | ||
322 | if (ret != 0) | ||
323 | { | ||
324 | IF_DEBUG2 (DP(RINT "test_process_memory: %d: %s\n", ret, stream.msg)); | ||
325 | } | ||
326 | xd3_free_stream(&stream); | ||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | void EncodeDecodeAPI(const FileSpec &spec0, const FileSpec &spec1, | ||
331 | Block *delta, const Options &options) { | ||
332 | Block from; | ||
333 | Block to; | ||
334 | spec0.Get(&from, 0, spec0.Size()); | ||
335 | spec1.Get(&to, 0, spec1.Size()); | ||
336 | |||
337 | delta->SetSize(to.Size() * 1.5); | ||
338 | usize_t out_size; | ||
339 | int enc_ret = TestProcessMemory(true, | ||
340 | &xd3_encode_input, | ||
341 | to.Data(), | ||
342 | to.Size(), | ||
343 | from.Data(), | ||
344 | from.Size(), | ||
345 | delta->Data(), | ||
346 | &out_size, | ||
347 | delta->Size(), | ||
348 | options); | ||
349 | CHECK_EQ(0, enc_ret); | ||
350 | delta->SetSize(out_size); | ||
351 | |||
352 | Block recon; | ||
353 | recon.SetSize(to.Size()); | ||
354 | usize_t recon_size; | ||
355 | int dec_ret = xd3_decode_memory(delta->Data(), | ||
356 | delta->Size(), | ||
357 | from.Data(), | ||
358 | from.Size(), | ||
359 | recon.Data(), | ||
360 | &recon_size, | ||
361 | recon.Size(), | ||
362 | 0); | ||
363 | CHECK_EQ(0, dec_ret); | ||
364 | CHECK_EQ(0, CmpDifferentBlockBytes(to, recon)); | ||
365 | } | ||
366 | |||
263 | ////////////////////////////////////////////////////////////////////// | 367 | ////////////////////////////////////////////////////////////////////// |
264 | 368 | ||
265 | void TestRandomNumbers() { | 369 | void TestRandomNumbers() { |
@@ -370,7 +474,7 @@ void TestFirstByte() { | |||
370 | } | 474 | } |
371 | spec0.GenerateFixedSize(size); | 475 | spec0.GenerateFixedSize(size); |
372 | spec0.ModifyTo(Modify1stByte(), &spec1); | 476 | spec0.ModifyTo(Modify1stByte(), &spec1); |
373 | InMemoryEncodeDecode(spec0, spec1, NULL); | 477 | InMemoryEncodeDecode(spec0, spec1, NULL, Options()); |
374 | } | 478 | } |
375 | } | 479 | } |
376 | 480 | ||
@@ -406,7 +510,7 @@ void TestModifyMutator() { | |||
406 | // pass. | 510 | // pass. |
407 | CHECK_GE(diff, test_cases[i].size - (2 * test_cases[i].size / 256)); | 511 | CHECK_GE(diff, test_cases[i].size - (2 * test_cases[i].size / 256)); |
408 | 512 | ||
409 | InMemoryEncodeDecode(spec0, spec1, NULL); | 513 | InMemoryEncodeDecode(spec0, spec1, NULL, Options()); |
410 | } | 514 | } |
411 | } | 515 | } |
412 | 516 | ||
@@ -439,7 +543,7 @@ void TestAddMutator() { | |||
439 | CHECK_EQ(spec0.Size() + test_cases[i].size, spec1.Size()); | 543 | CHECK_EQ(spec0.Size() + test_cases[i].size, spec1.Size()); |
440 | 544 | ||
441 | Block coded; | 545 | Block coded; |
442 | InMemoryEncodeDecode(spec0, spec1, &coded); | 546 | InMemoryEncodeDecode(spec0, spec1, &coded, Options()); |
443 | 547 | ||
444 | Delta delta(coded); | 548 | Delta delta(coded); |
445 | CHECK_EQ(test_cases[i].expected_adds, | 549 | CHECK_EQ(test_cases[i].expected_adds, |
@@ -476,7 +580,7 @@ void TestDeleteMutator() { | |||
476 | CHECK_EQ(spec0.Size() - test_cases[i].size, spec1.Size()); | 580 | CHECK_EQ(spec0.Size() - test_cases[i].size, spec1.Size()); |
477 | 581 | ||
478 | Block coded; | 582 | Block coded; |
479 | InMemoryEncodeDecode(spec0, spec1, &coded); | 583 | InMemoryEncodeDecode(spec0, spec1, &coded, Options()); |
480 | 584 | ||
481 | Delta delta(coded); | 585 | Delta delta(coded); |
482 | CHECK_EQ(0, delta.AddedBytes()); | 586 | CHECK_EQ(0, delta.AddedBytes()); |
@@ -511,7 +615,7 @@ void TestCopyMutator() { | |||
511 | CHECK_EQ(spec0.Size() + test_cases[i].size, spec1.Size()); | 615 | CHECK_EQ(spec0.Size() + test_cases[i].size, spec1.Size()); |
512 | 616 | ||
513 | Block coded; | 617 | Block coded; |
514 | InMemoryEncodeDecode(spec0, spec1, &coded); | 618 | InMemoryEncodeDecode(spec0, spec1, &coded, Options()); |
515 | 619 | ||
516 | Delta delta(coded); | 620 | Delta delta(coded); |
517 | CHECK_EQ(0, delta.AddedBytes()); | 621 | CHECK_EQ(0, delta.AddedBytes()); |
@@ -553,7 +657,7 @@ void TestMoveMutator() { | |||
553 | CHECK_EQ(spec0.Size(), spec1.Size()); | 657 | CHECK_EQ(spec0.Size(), spec1.Size()); |
554 | 658 | ||
555 | Block coded; | 659 | Block coded; |
556 | InMemoryEncodeDecode(spec0, spec1, &coded); | 660 | InMemoryEncodeDecode(spec0, spec1, &coded, Options()); |
557 | 661 | ||
558 | Delta delta(coded); | 662 | Delta delta(coded); |
559 | CHECK_EQ(0, delta.AddedBytes()); | 663 | CHECK_EQ(0, delta.AddedBytes()); |
@@ -596,7 +700,7 @@ void TestOverwriteMutator() { | |||
596 | 700 | ||
597 | // Note: this test is written to expose a problem, but the problem was | 701 | // Note: this test is written to expose a problem, but the problem was |
598 | // only exposed with BLOCK_SIZE = 128. | 702 | // only exposed with BLOCK_SIZE = 128. |
599 | void TestNonBlockingProgress() { | 703 | void TestNonBlocking() { |
600 | MTRandom rand; | 704 | MTRandom rand; |
601 | FileSpec spec0(&rand); | 705 | FileSpec spec0(&rand); |
602 | FileSpec spec1(&rand); | 706 | FileSpec spec1(&rand); |
@@ -635,7 +739,7 @@ void TestNonBlockingProgress() { | |||
635 | 739 | ||
636 | spec0.ModifyTo(ChangeListMutator(ctl), &spec2); | 740 | spec0.ModifyTo(ChangeListMutator(ctl), &spec2); |
637 | 741 | ||
638 | InMemoryEncodeDecode(spec1, spec2, NULL); | 742 | InMemoryEncodeDecode(spec1, spec2, NULL, Options()); |
639 | } | 743 | } |
640 | 744 | ||
641 | void TestEmptyInMemory() { | 745 | void TestEmptyInMemory() { |
@@ -647,7 +751,7 @@ void TestEmptyInMemory() { | |||
647 | spec0.GenerateFixedSize(0); | 751 | spec0.GenerateFixedSize(0); |
648 | spec1.GenerateFixedSize(0); | 752 | spec1.GenerateFixedSize(0); |
649 | 753 | ||
650 | InMemoryEncodeDecode(spec0, spec1, &block); | 754 | InMemoryEncodeDecode(spec0, spec1, &block, Options()); |
651 | 755 | ||
652 | Delta delta(block); | 756 | Delta delta(block); |
653 | CHECK_LT(0, block.Size()); | 757 | CHECK_LT(0, block.Size()); |
@@ -663,12 +767,138 @@ void TestBlockInMemory() { | |||
663 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE); | 767 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE); |
664 | spec1.GenerateFixedSize(Constants::BLOCK_SIZE); | 768 | spec1.GenerateFixedSize(Constants::BLOCK_SIZE); |
665 | 769 | ||
666 | InMemoryEncodeDecode(spec0, spec1, &block); | 770 | InMemoryEncodeDecode(spec0, spec1, &block, Options()); |
667 | 771 | ||
668 | Delta delta(block); | 772 | Delta delta(block); |
669 | CHECK_EQ(spec1.Blocks(Constants::WINDOW_SIZE), delta.Windows()); | 773 | CHECK_EQ(spec1.Blocks(Constants::WINDOW_SIZE), delta.Windows()); |
670 | } | 774 | } |
671 | 775 | ||
776 | void TestSmallStride() { | ||
777 | MTRandom rand; | ||
778 | FileSpec spec0(&rand); | ||
779 | usize_t size = Constants::BLOCK_SIZE * 4; | ||
780 | spec0.GenerateFixedSize(size); | ||
781 | |||
782 | /* TODO Need to study the actual causes of missed adds for tests | ||
783 | * less than 30 bytes. */ | ||
784 | const int s = 30; | ||
785 | usize_t adds = 0; | ||
786 | ChangeList cl; | ||
787 | for (usize_t j = s; j < size; j += s, ++adds) | ||
788 | { | ||
789 | cl.push_back(Change(Change::MODIFY, 1, j)); | ||
790 | } | ||
791 | |||
792 | FileSpec spec1(&rand); | ||
793 | spec0.ModifyTo(ChangeListMutator(cl), &spec1); | ||
794 | |||
795 | Options options; | ||
796 | options.encode_srcwin_maxsz = size; | ||
797 | options.iopt_size = 128; | ||
798 | options.smatch_cfg = XD3_SMATCH_SLOW; | ||
799 | options.size_known = false; | ||
800 | |||
801 | Block block; | ||
802 | InMemoryEncodeDecode(spec0, spec1, &block, options); | ||
803 | Delta delta(block); | ||
804 | |||
805 | // Allow an additional two byte of add per window | ||
806 | usize_t allowance = 2 * size / Constants::WINDOW_SIZE; | ||
807 | CHECK_GE(adds + allowance, delta.AddedBytes()); | ||
808 | } | ||
809 | |||
810 | void TestCopyWindow() { | ||
811 | // Construct an input that has many copies, to fill the IOPT buffer | ||
812 | // and force a source window decision. "srclen" may be set to a | ||
813 | // value that goes beyond the end-of-source. | ||
814 | const int clen = 16; | ||
815 | const int size = 4096; | ||
816 | const int nmov = size / clen; | ||
817 | MTRandom rand; | ||
818 | FileSpec spec0(&rand); | ||
819 | ChangeList cl; | ||
820 | |||
821 | spec0.GenerateFixedSize(size); | ||
822 | |||
823 | for (int j = 0; j < nmov; j += 2) | ||
824 | { | ||
825 | cl.push_back(Change(Change::MOVE, | ||
826 | clen, (j + 1) * clen, j * clen)); | ||
827 | } | ||
828 | |||
829 | FileSpec spec1(&rand); | ||
830 | spec0.ModifyTo(ChangeListMutator(cl), &spec1); | ||
831 | |||
832 | Options options; | ||
833 | options.encode_srcwin_maxsz = size; | ||
834 | options.iopt_size = 128; | ||
835 | options.smatch_cfg = XD3_SMATCH_SLOW; | ||
836 | options.size_known = false; | ||
837 | |||
838 | Block block1; | ||
839 | InMemoryEncodeDecode(spec0, spec1, &block1, options); | ||
840 | Delta delta1(block1); | ||
841 | CHECK_EQ(0, delta1.AddedBytes()); | ||
842 | |||
843 | Block block2; | ||
844 | InMemoryEncodeDecode(spec1, spec0, &block2, options); | ||
845 | Delta delta2(block2); | ||
846 | CHECK_EQ(0, delta2.AddedBytes()); | ||
847 | |||
848 | Block block3; | ||
849 | Block block4; | ||
850 | EncodeDecodeAPI(spec0, spec1, &block3, options); | ||
851 | EncodeDecodeAPI(spec1, spec0, &block4, options); | ||
852 | } | ||
853 | |||
854 | void TestCopyFromEnd() { | ||
855 | // Copies from the end of the source buffer, which reach a block | ||
856 | // boundary end-of-file. | ||
857 | const int size = 4096; | ||
858 | const int clen = 16; | ||
859 | const int nmov = (size / 2) / clen; | ||
860 | MTRandom rand; | ||
861 | FileSpec spec0(&rand); | ||
862 | ChangeList cl; | ||
863 | |||
864 | spec0.GenerateFixedSize(size); | ||
865 | |||
866 | cl.push_back(Change(Change::MODIFY, 2012, 2048)); | ||
867 | |||
868 | for (int j = 0; j < nmov; j += 2) | ||
869 | { | ||
870 | cl.push_back(Change(Change::MOVE, | ||
871 | clen, (j + 1) * clen, j * clen)); | ||
872 | } | ||
873 | |||
874 | cl.push_back(Change(Change::COPYOVER, 28, 4068, 3000)); | ||
875 | cl.push_back(Change(Change::COPYOVER, 30, 4066, 3100)); | ||
876 | cl.push_back(Change(Change::COPYOVER, 32, 4064, 3200)); | ||
877 | |||
878 | FileSpec spec1(&rand); | ||
879 | spec0.ModifyTo(ChangeListMutator(cl), &spec1); | ||
880 | |||
881 | Options options; | ||
882 | options.encode_srcwin_maxsz = size; | ||
883 | options.iopt_size = 128; | ||
884 | options.smatch_cfg = XD3_SMATCH_SLOW; | ||
885 | |||
886 | Block block1; | ||
887 | InMemoryEncodeDecode(spec0, spec1, &block1, options); | ||
888 | Delta delta1(block1); | ||
889 | CHECK_GE(2000, delta1.AddedBytes()); | ||
890 | |||
891 | Block block2; | ||
892 | InMemoryEncodeDecode(spec1, spec0, &block2, options); | ||
893 | Delta delta2(block2); | ||
894 | CHECK_LE(2000, delta2.AddedBytes()); | ||
895 | |||
896 | Block block3; | ||
897 | Block block4; | ||
898 | EncodeDecodeAPI(spec0, spec1, &block3, options); | ||
899 | EncodeDecodeAPI(spec1, spec0, &block4, options); | ||
900 | } | ||
901 | |||
672 | void TestHalfBlockCopy() { | 902 | void TestHalfBlockCopy() { |
673 | MTRandom rand; | 903 | MTRandom rand; |
674 | FileSpec spec0(&rand); | 904 | FileSpec spec0(&rand); |
@@ -694,11 +924,11 @@ void TestHalfBlockCopy() { | |||
694 | Constants::BLOCK_SIZE)); | 924 | Constants::BLOCK_SIZE)); |
695 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | 925 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); |
696 | 926 | ||
697 | const int onecopy_adds = | 927 | const int onecopy_adds = |
698 | 4 * Constants::BLOCK_SIZE - Constants::BLOCK_SIZE / 2; | 928 | 4 * Constants::BLOCK_SIZE - Constants::BLOCK_SIZE / 2; |
699 | const int nocopy_adds = 4 * Constants::BLOCK_SIZE; | 929 | const int nocopy_adds = 4 * Constants::BLOCK_SIZE; |
700 | 930 | ||
701 | // Note the case b=4 is contrived: the caller should use a single block | 931 | // Note the case b=4 is contrived: the caller should use a single block |
702 | // containing the entire source, if possible. | 932 | // containing the entire source, if possible. |
703 | for (int b = 1; b <= 4; b++) | 933 | for (int b = 1; b <= 4; b++) |
704 | { | 934 | { |
@@ -721,7 +951,7 @@ void TestHalfBlockCopy() { | |||
721 | { | 951 | { |
722 | // For small-block inputs, the entire file is read into one | 952 | // For small-block inputs, the entire file is read into one |
723 | // block (the min source window size is 16kB). | 953 | // block (the min source window size is 16kB). |
724 | // | 954 | // |
725 | // For large blocks, at least 3 blocks of source window are | 955 | // For large blocks, at least 3 blocks of source window are |
726 | // needed. | 956 | // needed. |
727 | CHECK_EQ(onecopy_adds, delta1.AddedBytes()); | 957 | CHECK_EQ(onecopy_adds, delta1.AddedBytes()); |
@@ -760,7 +990,7 @@ void FourWayMergeTest(const FileSpec &spec0, | |||
760 | TmpFile f0, f1, f2, f3; | 990 | TmpFile f0, f1, f2, f3; |
761 | ExtFile d01, d12, d23; | 991 | ExtFile d01, d12, d23; |
762 | Options options; | 992 | Options options; |
763 | options.encode_srcwin_maxsz = | 993 | options.encode_srcwin_maxsz = |
764 | std::max(spec0.Size(), options.encode_srcwin_maxsz); | 994 | std::max(spec0.Size(), options.encode_srcwin_maxsz); |
765 | 995 | ||
766 | spec0.WriteTmpFile(&f0); | 996 | spec0.WriteTmpFile(&f0); |
@@ -975,12 +1205,15 @@ void UnitTest() { | |||
975 | // These are Xdelta tests. | 1205 | // These are Xdelta tests. |
976 | template <class T> | 1206 | template <class T> |
977 | void MainTest() { | 1207 | void MainTest() { |
978 | XPR(NT "Blocksize %"Q"u readsize %"Q"u windowsize %"Q"u\n", | 1208 | XPR(NT "Blocksize %"Q"u windowsize %"Q"u\n", |
979 | T::BLOCK_SIZE, T::READ_SIZE, T::WINDOW_SIZE); | 1209 | T::BLOCK_SIZE, T::WINDOW_SIZE); |
980 | Regtest<T> regtest; | 1210 | Regtest<T> regtest; |
981 | TEST(TestEmptyInMemory); | 1211 | TEST(TestEmptyInMemory); |
982 | TEST(TestBlockInMemory); | 1212 | TEST(TestBlockInMemory); |
983 | TEST(TestNonBlockingProgress); | 1213 | TEST(TestSmallStride); |
1214 | TEST(TestCopyWindow); | ||
1215 | TEST(TestCopyFromEnd); | ||
1216 | TEST(TestNonBlocking); | ||
984 | TEST(TestHalfBlockCopy); | 1217 | TEST(TestHalfBlockCopy); |
985 | TEST(TestMergeCommand1); | 1218 | TEST(TestMergeCommand1); |
986 | TEST(TestMergeCommand2); | 1219 | TEST(TestMergeCommand2); |
@@ -988,7 +1221,7 @@ void MainTest() { | |||
988 | 1221 | ||
989 | #undef TEST | 1222 | #undef TEST |
990 | 1223 | ||
991 | int main(int argc, char **argv) | 1224 | int main(int argc, char **argv) |
992 | { | 1225 | { |
993 | vector<const char*> mcmd; | 1226 | vector<const char*> mcmd; |
994 | string pn; | 1227 | string pn; |
@@ -1004,7 +1237,6 @@ int main(int argc, char **argv) | |||
1004 | UnitTest<SmallBlock>(); | 1237 | UnitTest<SmallBlock>(); |
1005 | MainTest<SmallBlock>(); | 1238 | MainTest<SmallBlock>(); |
1006 | MainTest<MixedBlock>(); | 1239 | MainTest<MixedBlock>(); |
1007 | MainTest<PrimeBlock>(); | ||
1008 | MainTest<OversizeBlock>(); | 1240 | MainTest<OversizeBlock>(); |
1009 | MainTest<LargeBlock>(); | 1241 | MainTest<LargeBlock>(); |
1010 | 1242 | ||
diff --git a/xdelta3/testing/sizes.h b/xdelta3/testing/sizes.h index 18f46e9..223d359 100644 --- a/xdelta3/testing/sizes.h +++ b/xdelta3/testing/sizes.h | |||
@@ -77,54 +77,35 @@ const size_t BaseConstants::TEST_ROUNDS = 10; | |||
77 | struct SmallBlock : public BaseConstants { | 77 | struct SmallBlock : public BaseConstants { |
78 | static const xoff_t BLOCK_SIZE; | 78 | static const xoff_t BLOCK_SIZE; |
79 | static const size_t WINDOW_SIZE; | 79 | static const size_t WINDOW_SIZE; |
80 | static const size_t READ_SIZE; | ||
81 | typedef SmallSizes Sizes; | 80 | typedef SmallSizes Sizes; |
82 | }; | 81 | }; |
83 | 82 | ||
84 | const size_t SmallBlock::READ_SIZE = 1<<7; | ||
85 | const xoff_t SmallBlock::BLOCK_SIZE = 1<<7; | 83 | const xoff_t SmallBlock::BLOCK_SIZE = 1<<7; |
86 | const size_t SmallBlock::WINDOW_SIZE = 1<<7; | 84 | const size_t SmallBlock::WINDOW_SIZE = 1<<7; |
87 | 85 | ||
88 | struct LargeBlock : public BaseConstants { | 86 | struct LargeBlock : public BaseConstants { |
89 | static const xoff_t BLOCK_SIZE; | 87 | static const xoff_t BLOCK_SIZE; |
90 | static const size_t WINDOW_SIZE; | 88 | static const size_t WINDOW_SIZE; |
91 | static const size_t READ_SIZE; | ||
92 | typedef LargeSizes Sizes; | 89 | typedef LargeSizes Sizes; |
93 | }; | 90 | }; |
94 | 91 | ||
95 | const size_t LargeBlock::READ_SIZE = (1 << 13); | ||
96 | const xoff_t LargeBlock::BLOCK_SIZE = (1 << 13); | 92 | const xoff_t LargeBlock::BLOCK_SIZE = (1 << 13); |
97 | const size_t LargeBlock::WINDOW_SIZE = (1 << 13); | 93 | const size_t LargeBlock::WINDOW_SIZE = (1 << 13); |
98 | 94 | ||
99 | struct MixedBlock : public BaseConstants { | 95 | struct MixedBlock : public BaseConstants { |
100 | static const xoff_t BLOCK_SIZE; | 96 | static const xoff_t BLOCK_SIZE; |
101 | static const size_t WINDOW_SIZE; | 97 | static const size_t WINDOW_SIZE; |
102 | static const size_t READ_SIZE; | ||
103 | typedef SmallSizes Sizes; | 98 | typedef SmallSizes Sizes; |
104 | }; | 99 | }; |
105 | 100 | ||
106 | const size_t MixedBlock::READ_SIZE = 1<<6; | ||
107 | const xoff_t MixedBlock::BLOCK_SIZE = 1<<7; | 101 | const xoff_t MixedBlock::BLOCK_SIZE = 1<<7; |
108 | const size_t MixedBlock::WINDOW_SIZE = 1<<8; | 102 | const size_t MixedBlock::WINDOW_SIZE = 1<<8; |
109 | 103 | ||
110 | struct OversizeBlock : public BaseConstants { | 104 | struct OversizeBlock : public BaseConstants { |
111 | static const xoff_t BLOCK_SIZE; | 105 | static const xoff_t BLOCK_SIZE; |
112 | static const size_t WINDOW_SIZE; | 106 | static const size_t WINDOW_SIZE; |
113 | static const size_t READ_SIZE; | ||
114 | typedef SmallSizes Sizes; | 107 | typedef SmallSizes Sizes; |
115 | }; | 108 | }; |
116 | 109 | ||
117 | const size_t OversizeBlock::READ_SIZE = (1<<6) + (1<<7); | ||
118 | const xoff_t OversizeBlock::BLOCK_SIZE = 1<<8; | 110 | const xoff_t OversizeBlock::BLOCK_SIZE = 1<<8; |
119 | const size_t OversizeBlock::WINDOW_SIZE = 1<<7; | 111 | const size_t OversizeBlock::WINDOW_SIZE = 1<<7; |
120 | |||
121 | struct PrimeBlock : public BaseConstants { | ||
122 | static const xoff_t BLOCK_SIZE; | ||
123 | static const size_t WINDOW_SIZE; | ||
124 | static const size_t READ_SIZE; | ||
125 | typedef SmallSizes Sizes; | ||
126 | }; | ||
127 | |||
128 | const size_t PrimeBlock::READ_SIZE = 71; | ||
129 | const xoff_t PrimeBlock::BLOCK_SIZE = 512; // Must be a power-of-2 | ||
130 | const size_t PrimeBlock::WINDOW_SIZE = 73; | ||