summaryrefslogtreecommitdiff
path: root/xdelta3/testing
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta3/testing')
-rw-r--r--xdelta3/testing/Makefile3
-rw-r--r--xdelta3/testing/file.h13
-rw-r--r--xdelta3/testing/modify.h2
-rw-r--r--xdelta3/testing/regtest.cc322
-rw-r--r--xdelta3/testing/sizes.h19
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 @@
1all: 1all:
2 (cd .. && make all) 2 (cd .. && make all)
3
4xdelta3regtest:
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
95private: 100private:
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:
373private: 379private:
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.
599void TestNonBlockingProgress() { 703void 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
641void TestEmptyInMemory() { 745void 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
776void 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
810void 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
854void 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
672void TestHalfBlockCopy() { 902void 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.
976template <class T> 1206template <class T>
977void MainTest() { 1207void 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
991int main(int argc, char **argv) 1224int 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;
77struct SmallBlock : public BaseConstants { 77struct 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
84const size_t SmallBlock::READ_SIZE = 1<<7;
85const xoff_t SmallBlock::BLOCK_SIZE = 1<<7; 83const xoff_t SmallBlock::BLOCK_SIZE = 1<<7;
86const size_t SmallBlock::WINDOW_SIZE = 1<<7; 84const size_t SmallBlock::WINDOW_SIZE = 1<<7;
87 85
88struct LargeBlock : public BaseConstants { 86struct 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
95const size_t LargeBlock::READ_SIZE = (1 << 13);
96const xoff_t LargeBlock::BLOCK_SIZE = (1 << 13); 92const xoff_t LargeBlock::BLOCK_SIZE = (1 << 13);
97const size_t LargeBlock::WINDOW_SIZE = (1 << 13); 93const size_t LargeBlock::WINDOW_SIZE = (1 << 13);
98 94
99struct MixedBlock : public BaseConstants { 95struct 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
106const size_t MixedBlock::READ_SIZE = 1<<6;
107const xoff_t MixedBlock::BLOCK_SIZE = 1<<7; 101const xoff_t MixedBlock::BLOCK_SIZE = 1<<7;
108const size_t MixedBlock::WINDOW_SIZE = 1<<8; 102const size_t MixedBlock::WINDOW_SIZE = 1<<8;
109 103
110struct OversizeBlock : public BaseConstants { 104struct 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
117const size_t OversizeBlock::READ_SIZE = (1<<6) + (1<<7);
118const xoff_t OversizeBlock::BLOCK_SIZE = 1<<8; 110const xoff_t OversizeBlock::BLOCK_SIZE = 1<<8;
119const size_t OversizeBlock::WINDOW_SIZE = 1<<7; 111const size_t OversizeBlock::WINDOW_SIZE = 1<<7;
120
121struct 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
128const size_t PrimeBlock::READ_SIZE = 71;
129const xoff_t PrimeBlock::BLOCK_SIZE = 512; // Must be a power-of-2
130const size_t PrimeBlock::WINDOW_SIZE = 73;