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/checksum_test.cc756
-rw-r--r--xdelta3/testing/checksum_test_c.c174
-rw-r--r--xdelta3/testing/delta.h38
-rw-r--r--xdelta3/testing/file.h30
-rw-r--r--xdelta3/testing/regtest.cc37
-rwxr-xr-xxdelta3/testing/run_release.sh2
-rw-r--r--xdelta3/testing/test.h6
8 files changed, 993 insertions, 53 deletions
diff --git a/xdelta3/testing/Makefile b/xdelta3/testing/Makefile
index f859f94..d0b9c9e 100644
--- a/xdelta3/testing/Makefile
+++ b/xdelta3/testing/Makefile
@@ -3,3 +3,6 @@ all:
3 3
4xdelta3regtest: 4xdelta3regtest:
5 (cd .. && make xdelta3regtest) 5 (cd .. && make xdelta3regtest)
6
7xdelta3checksum:
8 (cd .. && make xdelta3checksum)
diff --git a/xdelta3/testing/checksum_test.cc b/xdelta3/testing/checksum_test.cc
new file mode 100644
index 0000000..9418d24
--- /dev/null
+++ b/xdelta3/testing/checksum_test.cc
@@ -0,0 +1,756 @@
1/* Copyright (C) 2007 Josh MacDonald */
2
3#include "test.h"
4#include <assert.h>
5#include <list>
6#include <vector>
7#include <algorithm>
8
9#include "../cpp-btree/btree_map.h"
10
11extern "C" {
12uint32_t xd3_large32_cksum_old (xd3_hash_cfg *cfg, const uint8_t *base, const usize_t look);
13uint32_t xd3_large32_cksum_update_old (xd3_hash_cfg *cfg, uint32_t cksum,
14 const uint8_t *base, const usize_t look);
15
16uint64_t xd3_large64_cksum_old (xd3_hash_cfg *cfg, const uint8_t *base, const usize_t look);
17uint64_t xd3_large64_cksum_update_old (xd3_hash_cfg *cfg, uint64_t cksum,
18 const uint8_t *base, const usize_t look);
19}
20
21using btree::btree_map;
22using std::list;
23using std::vector;
24
25// MLCG parameters
26// a, a*
27uint32_t good_32bit_values[] = {
28 1597334677U, // ...
29 741103597U, 887987685U,
30};
31
32// a, a*
33uint64_t good_64bit_values[] = {
34 1181783497276652981ULL, 4292484099903637661ULL,
35 7664345821815920749ULL, // ...
36};
37
38void print_header() {
39 static int hdr_cnt = 0;
40 if (hdr_cnt++ % 20 == 0) {
41 printf("%-32sConf\t\tCount\tUniq\tFull\tCover\tColls"
42 "\tMB/s\tIters\t#Colls\n", "Name");
43 }
44}
45
46struct true_type { };
47struct false_type { };
48
49template <typename Word>
50usize_t bitsof();
51
52template<>
53usize_t bitsof<unsigned int>() {
54 return sizeof(unsigned int) * 8;
55}
56
57template<>
58usize_t bitsof<unsigned long>() {
59 return sizeof(unsigned long) * 8;
60}
61
62template<>
63usize_t bitsof<unsigned long long>() {
64 return sizeof(unsigned long long) * 8;
65}
66
67template <typename Word>
68struct hhash { // shift "s" bits leaving the high bits as a hash value for
69 // this checksum, which are the most "distant" in terms of the
70 // spectral test for the rabin_karp MLCG. For short windows,
71 // the high bits aren't enough, XOR "mask" worth of these in.
72 Word operator()(const Word t, const Word s, const Word mask) {
73 return (t >> s) ^ (t & mask);
74 }
75};
76
77template <typename Word>
78Word good_word();
79
80template<>
81uint32_t good_word<uint32_t>() {
82 return good_32bit_values[0];
83}
84
85template<>
86uint64_t good_word<uint64_t>() {
87 return good_64bit_values[0];
88}
89
90// CLASSES
91
92#define SELF Word, CksumSize, CksumSkip, Hash, Compaction
93#define MEMBER template <typename Word, \
94 int CksumSize, \
95 int CksumSkip, \
96 typename Hash, \
97 int Compaction>
98
99MEMBER
100struct cksum_params {
101 typedef Word word_type;
102 typedef Hash hash_type;
103
104 static const int cksum_size = CksumSize;
105 static const int cksum_skip = CksumSkip;
106 static const int compaction = Compaction;
107};
108
109MEMBER
110struct rabin_karp : public cksum_params<SELF> {
111 // (a^cksum_size-1 c_0) + (a^cksum_size-2 c_1) ...
112 rabin_karp()
113 : powers(make_powers()),
114 product(powers[0] * good_word<Word>()),
115 incr_state(0) { }
116
117 static Word* make_powers() {
118 Word *p = new Word[CksumSize];
119 p[CksumSize - 1] = 1;
120 for (int i = CksumSize - 2; i >= 0; i--) {
121 p[i] = p[i + 1] * good_word<Word>();
122 }
123 return p;
124 }
125
126 ~rabin_karp() {
127 delete [] powers;
128 }
129
130 Word step(const uint8_t *ptr) {
131 Word h = 0;
132 for (int i = 0; i < CksumSize; i++) {
133 h += (ptr[i]) * powers[i];
134 }
135 return h;
136 }
137
138 Word state0(const uint8_t *ptr) {
139 incr_state = step(ptr);
140 return incr_state;
141 }
142
143 Word incr(const uint8_t *ptr) {
144 incr_state = good_word<Word>() * incr_state -
145 product * (ptr[-1]) + (ptr[CksumSize - 1]);
146 return incr_state;
147 }
148
149 const Word *const powers;
150 const Word product;
151 Word incr_state;
152};
153
154MEMBER
155struct with_stream : public cksum_params<SELF> {
156 xd3_stream stream;
157
158 with_stream()
159 {
160 xd3_config cfg;
161 memset (&stream, 0, sizeof (stream));
162 xd3_init_config (&cfg, 0);
163 cfg.smatch_cfg = XD3_SMATCH_SOFT;
164 cfg.smatcher_soft.large_look = CksumSize;
165 cfg.smatcher_soft.large_step = CksumSkip;
166 cfg.smatcher_soft.small_look = 4;
167 cfg.smatcher_soft.small_chain = 4;
168 cfg.smatcher_soft.small_lchain = 4;
169 cfg.smatcher_soft.max_lazy = 4;
170 cfg.smatcher_soft.long_enough = 4;
171 CHECK_EQ(0, xd3_config_stream (&stream, &cfg));
172
173 CHECK_EQ(0, xd3_size_hashtable (&stream,
174 1<<10 /* ignored */,
175 stream.smatcher.large_look,
176 & stream.large_hash));
177 }
178 ~with_stream()
179 {
180 xd3_free_stream (&stream);
181 }
182};
183
184MEMBER
185struct large_cksum : public with_stream<SELF> {
186 Word step(const uint8_t *ptr) {
187 return xd3_large_cksum (&this->stream.large_hash, ptr, CksumSize);
188 }
189
190 Word state0(const uint8_t *ptr) {
191 incr_state = step(ptr);
192 return incr_state;
193 }
194
195 Word incr(const uint8_t *ptr) {
196 incr_state = xd3_large_cksum_update (&this->stream.large_hash,
197 incr_state, ptr - 1, CksumSize);
198 return incr_state;
199 }
200
201 Word incr_state;
202};
203
204#if SIZEOF_USIZE_T == 4
205#define xd3_large_cksum_old xd3_large32_cksum_old
206#define xd3_large_cksum_update_old xd3_large32_cksum_update_old
207#elif SIZEOF_USIZE_T == 8
208#define xd3_large_cksum_old xd3_large64_cksum_old
209#define xd3_large_cksum_update_old xd3_large64_cksum_update_old
210#endif
211
212MEMBER
213struct large_cksum_old : public with_stream<SELF> {
214 Word step(const uint8_t *ptr) {
215 return xd3_large_cksum_old (&this->stream.large_hash, ptr, CksumSize);
216 }
217
218 Word state0(const uint8_t *ptr) {
219 incr_state = step(ptr);
220 return incr_state;
221 }
222
223 Word incr(const uint8_t *ptr) {
224 incr_state = xd3_large_cksum_update_old (&this->stream.large_hash,
225 incr_state, ptr - 1, CksumSize);
226 return incr_state;
227 }
228
229 Word incr_state;
230};
231
232// TESTS
233
234template <typename Word>
235struct file_stats {
236 typedef const uint8_t* ptr_type;
237 typedef Word word_type;
238 typedef btree::btree_multimap<word_type, ptr_type> table_type;
239 typedef typename table_type::iterator table_iterator;
240
241 usize_t cksum_size;
242 usize_t cksum_skip;
243 usize_t unique;
244 usize_t unique_values;
245 usize_t count;
246 table_type table;
247
248 file_stats(usize_t size, usize_t skip)
249 : cksum_size(size),
250 cksum_skip(skip),
251 unique(0),
252 unique_values(0),
253 count(0) {
254 }
255
256 void reset() {
257 unique = 0;
258 unique_values = 0;
259 count = 0;
260 table.clear();
261 }
262
263 void update(word_type word, ptr_type ptr) {
264 table_iterator t_i = table.find(word);
265
266 count++;
267 if (t_i != table.end()) {
268 int collisions = 0;
269 for (table_iterator p_i = t_i;
270 p_i != table.end() && p_i->first == word;
271 ++p_i) {
272 if (memcmp(p_i->second, ptr, cksum_size) == 0) {
273 return;
274 }
275 collisions++;
276 }
277 if (collisions >= 1000) {
278 fprintf(stderr, "Something is not right, lots of collisions=%d\n",
279 collisions);
280 abort();
281 }
282 } else {
283 unique_values++;
284 }
285 unique++;
286 table.insert(std::make_pair(word, ptr));
287 return;
288 }
289
290 void freeze() {
291 table.clear();
292 }
293};
294
295struct test_result_base;
296
297static vector<test_result_base*> all_tests;
298
299struct test_result_base {
300 virtual ~test_result_base() {
301 }
302 virtual void reset() = 0;
303 virtual void print() = 0;
304 virtual void get(const uint8_t* buf, const size_t buf_size,
305 usize_t iters) = 0;
306 virtual void stat() = 0;
307 virtual usize_t count() = 0;
308 virtual usize_t dups() = 0;
309 virtual double uniqueness() = 0;
310 virtual double fullness() = 0;
311 virtual double collisions() = 0;
312 virtual double coverage() = 0;
313 virtual double compression() = 0;
314 virtual double time() = 0;
315 virtual double total_time() = 0;
316 virtual usize_t total_count() = 0;
317 virtual usize_t total_dups() = 0;
318};
319
320template <typename Checksum>
321struct test_result : public test_result_base {
322 Checksum cksum;
323 const char *test_name;
324 file_stats<typename Checksum::word_type> fstats;
325 usize_t test_size;
326 usize_t n_steps;
327 usize_t n_incrs;
328 typename Checksum::word_type s_bits;
329 typename Checksum::word_type s_mask;
330 usize_t t_entries;
331 usize_t h_bits;
332 usize_t h_buckets_full;
333 char *hash_table;
334 long accum_millis;
335 usize_t accum_iters;
336
337 // These are not reset
338 double accum_time;
339 usize_t accum_count;
340 usize_t accum_dups;
341 usize_t accum_colls;
342 size_t accum_size;
343
344 test_result(const char *name)
345 : test_name(name),
346 fstats(Checksum::cksum_size, Checksum::cksum_skip),
347 hash_table(NULL),
348 accum_millis(0),
349 accum_iters(0),
350 accum_time(0.0),
351 accum_count(0),
352 accum_dups(0),
353 accum_colls(0),
354 accum_size(0) {
355 all_tests.push_back(this);
356 }
357
358 ~test_result() {
359 reset();
360 }
361
362 void reset() {
363 // size of file
364 test_size = 0;
365
366 // count
367 n_steps = 0;
368 n_incrs = 0;
369
370 // four values used by new_table()/summarize_table()
371 s_bits = 0;
372 s_mask = 0;
373 t_entries = 0;
374 h_bits = 0;
375 h_buckets_full = 0;
376
377 accum_millis = 0;
378 accum_iters = 0;
379
380 fstats.reset();
381
382 // temporary
383 if (hash_table) {
384 delete(hash_table);
385 hash_table = NULL;
386 }
387 }
388
389 usize_t count() {
390 if (Checksum::cksum_skip == 1) {
391 return n_incrs;
392 } else {
393 return n_steps;
394 }
395 }
396
397 usize_t dups() {
398 return fstats.count - fstats.unique;
399 }
400
401 /* Fraction of distinct strings of length cksum_size which are not
402 * represented in the hash table. */
403 double collisions() {
404 return (fstats.unique - fstats.unique_values) / (double) fstats.unique;
405 }
406 usize_t colls() {
407 return (fstats.unique - fstats.unique_values);
408 }
409
410 double uniqueness() {
411 return 1.0 - (double) dups() / count();
412 }
413
414 double fullness() {
415 return (double) h_buckets_full / (1 << h_bits);
416 }
417
418 double coverage() {
419 return (double) h_buckets_full / uniqueness() / count();
420 }
421
422 double compression() {
423 return 1.0 - coverage();
424 }
425
426 double time() {
427 return (double) accum_millis / accum_iters;
428 }
429
430 double total_time() {
431 return accum_time;
432 }
433
434 usize_t total_count() {
435 return accum_count;
436 }
437
438 usize_t total_dups() {
439 return accum_dups;
440 }
441
442 usize_t total_colls() {
443 return accum_dups;
444 }
445
446 void stat() {
447 accum_time += time();
448 accum_count += count();
449 accum_dups += dups();
450 accum_colls += colls();
451 accum_size += test_size;
452 }
453
454 void print() {
455 if (fstats.count != count()) {
456 fprintf(stderr, "internal error: %" W "d != %" W "d\n", fstats.count, count());
457 abort();
458 }
459 print_header();
460 printf("%-32s%d/%d 2^%" W "u\t%" W "u\t%0.4f\t%.4f\t%.4f\t%.1e\t%.2f\t"
461 "%" W "u\t%" W "u\n",
462 test_name,
463 Checksum::cksum_size,
464 Checksum::cksum_skip,
465 h_bits,
466 count(),
467 uniqueness(),
468 fullness(),
469 coverage(),
470 collisions(),
471 0.001 * accum_iters * test_size / accum_millis,
472 accum_iters,
473 colls());
474 }
475
476 usize_t size_log2 (usize_t slots) {
477 usize_t bits = bitsof<typename Checksum::word_type>() - 1;
478 usize_t i;
479
480 for (i = 3; i <= bits; i += 1) {
481 if (slots <= (1U << i)) {
482 return i - Checksum::compaction;
483 }
484 }
485
486 return bits;
487 }
488
489 void new_table(usize_t entries) {
490 t_entries = entries;
491 h_bits = size_log2(entries);
492
493 usize_t n = 1 << h_bits;
494
495 s_bits = bitsof<typename Checksum::word_type>() - h_bits;
496 s_mask = n - 1U;
497
498 hash_table = new char[n / 8];
499 memset(hash_table, 0, n / 8);
500 }
501
502 int get_table_bit(usize_t i) {
503 return hash_table[i/8] & (1 << i%8);
504 }
505
506 int set_table_bit(usize_t i) {
507 return hash_table[i/8] |= (1 << i%8);
508 }
509
510 void summarize_table() {
511 usize_t n = 1 << h_bits;
512 usize_t f = 0;
513 for (usize_t i = 0; i < n; i++) {
514 if (get_table_bit(i)) {
515 f++;
516 }
517 }
518 h_buckets_full = f;
519 }
520
521 void get(const uint8_t* buf, const size_t buf_size, usize_t test_iters) {
522 typename Checksum::hash_type hash;
523 const uint8_t *ptr;
524 const uint8_t *end;
525 usize_t periods;
526 int64_t last_offset;
527 int64_t stop;
528
529 test_size = buf_size;
530 last_offset = buf_size - Checksum::cksum_size;
531
532 if (last_offset < 0) {
533 periods = 0;
534 n_steps = 0;
535 n_incrs = 0;
536 stop = -Checksum::cksum_size;
537 } else {
538 periods = last_offset / Checksum::cksum_skip;
539 n_steps = periods + 1;
540 n_incrs = last_offset + 1;
541 stop = last_offset - (periods + 1) * Checksum::cksum_skip;
542 }
543
544 // Compute file stats once.
545 if (fstats.unique_values == 0) {
546 if (Checksum::cksum_skip == 1) {
547 for (size_t i = 0; i <= buf_size - Checksum::cksum_size; i++) {
548 fstats.update(hash(cksum.step(buf + i), s_bits, s_mask), buf + i);
549 }
550 } else {
551 ptr = buf + last_offset;
552 end = buf + stop;
553
554 for (; ptr != end; ptr -= Checksum::cksum_skip) {
555 fstats.update(hash(cksum.step(ptr), s_bits, s_mask), ptr);
556 }
557 }
558 fstats.freeze();
559 }
560
561 long start_test = get_millisecs_now();
562
563 if (Checksum::cksum_skip != 1) {
564 new_table(n_steps);
565
566 for (usize_t i = 0; i < test_iters; i++) {
567 ptr = buf + last_offset;
568 end = buf + stop;
569
570 for (; ptr != end; ptr -= Checksum::cksum_skip) {
571 set_table_bit(hash(cksum.step(ptr), s_bits, s_mask));
572 }
573 }
574
575 summarize_table();
576 }
577
578 stop = buf_size - Checksum::cksum_size + 1;
579 if (stop < 0) {
580 stop = 0;
581 }
582
583 if (Checksum::cksum_skip == 1) {
584 new_table(n_incrs);
585
586 for (usize_t i = 0; i < test_iters; i++) {
587 ptr = buf;
588 end = buf + stop;
589
590 if (ptr != end) {
591 set_table_bit(hash(cksum.state0(ptr++), s_bits, s_mask));
592 }
593
594 for (; ptr != end; ptr++) {
595 typename Checksum::word_type w = cksum.incr(ptr);
596 CHECK_EQ(w, cksum.step(ptr));
597 set_table_bit(hash(w, s_bits, s_mask));
598 }
599 }
600
601 summarize_table();
602 }
603
604 accum_iters += test_iters;
605 accum_millis += get_millisecs_now() - start_test;
606 }
607};
608
609static int read_whole_file(const char *name,
610 uint8_t **buf_ptr,
611 size_t *buf_len) {
612 main_file file;
613 int ret;
614 xoff_t len;
615 size_t nread;
616 main_file_init(&file);
617 file.filename = name;
618 ret = main_file_open(&file, name, XO_READ);
619 if (ret != 0) {
620 fprintf(stderr, "open failed\n");
621 goto exit;
622 }
623 ret = main_file_stat(&file, &len);
624 if (ret != 0) {
625 fprintf(stderr, "stat failed\n");
626 goto exit;
627 }
628
629 (*buf_len) = (size_t)len;
630 (*buf_ptr) = (uint8_t*) main_malloc(*buf_len);
631 ret = main_file_read(&file, *buf_ptr, *buf_len, &nread,
632 "read failed");
633 if (ret == 0 && *buf_len == nread) {
634 ret = 0;
635 } else {
636 fprintf(stderr, "invalid read\n");
637 ret = XD3_INTERNAL;
638 }
639 exit:
640 main_file_cleanup(&file);
641 return ret;
642}
643
644int main(int argc, char** argv) {
645 int i;
646 uint8_t *buf = NULL;
647 size_t buf_len = 0;
648 int ret;
649
650 if (argc <= 1) {
651 fprintf(stderr, "usage: %s file ...\n", argv[0]);
652 return 1;
653 }
654
655// TODO: The xdelta3-hash.h code is identical now; add sameness test.
656// using rabin_karp<> template.
657#define TEST(T,Z,S,C) \
658 test_result<large_cksum<T,Z,S,hhash<T>,C>> \
659 _xck_ ## T ## _ ## Z ## _ ## S ## _ ## C \
660 ("xck_" #T "_" #Z "_" #S "_" #C); \
661 test_result<large_cksum_old<T,Z,S,hhash<T>,C>> \
662 _old_ ## T ## _ ## Z ## _ ## S ## _ ## C \
663 ("old_" #T "_" #Z "_" #S "_" #C)
664
665#define TESTS(SIZE, SKIP) \
666 TEST(usize_t, SIZE, SKIP, 1); \
667 TEST(usize_t, SIZE, SKIP, 2)
668
669 TESTS(5, 1);
670 TESTS(6, 1);
671 TESTS(7, 1);
672 TESTS(8, 1);
673 TESTS(9, 1);
674 TESTS(10, 1);
675 TESTS(11, 1);
676 TESTS(12, 1);
677 TESTS(13, 1);
678 TESTS(14, 1);
679 TESTS(15, 1);
680 TESTS(16, 1);
681 TESTS(17, 1);
682 TESTS(18, 1);
683 TESTS(19, 1);
684 TESTS(20, 1);
685 TESTS(21, 1);
686 TESTS(22, 1);
687 TESTS(23, 1);
688 TESTS(24, 1);
689 TESTS(25, 1);
690 TESTS(26, 1);
691 TESTS(27, 1);
692 TESTS(28, 1);
693 TESTS(29, 1);
694 TESTS(30, 1);
695 TESTS(31, 1);
696 TESTS(32, 1);
697 TESTS(33, 1);
698 TESTS(34, 1);
699 TESTS(35, 1);
700 TESTS(36, 1);
701 TESTS(37, 1);
702 TESTS(38, 1);
703 TESTS(39, 1);
704
705
706 for (i = 1; i < argc; i++) {
707 if ((ret = read_whole_file(argv[i],
708 & buf,
709 & buf_len))) {
710 return 1;
711 }
712
713 fprintf(stderr, "file %s is %zu bytes\n",
714 argv[i], buf_len);
715
716 double min_time = -1.0;
717 double min_compression = 0.0;
718
719 for (vector<test_result_base*>::iterator iter = all_tests.begin();
720 iter != all_tests.end(); ++iter) {
721 test_result_base *test = *iter;
722 test->reset();
723
724 usize_t iters = 1;
725 long start_test = get_millisecs_now();
726
727 do {
728 test->get(buf, buf_len, iters);
729 iters *= 3;
730 iters /= 2;
731 } while (get_millisecs_now() - start_test < 2000);
732
733 test->stat();
734
735 if (min_time < 0.0) {
736 min_compression = test->compression();
737 min_time = test->time();
738 }
739
740 if (min_time > test->time()) {
741 min_time = test->time();
742 }
743
744 if (min_compression > test->compression()) {
745 min_compression = test->compression();
746 }
747
748 test->print();
749 }
750
751 main_free(buf);
752 buf = NULL;
753 }
754
755 return 0;
756}
diff --git a/xdelta3/testing/checksum_test_c.c b/xdelta3/testing/checksum_test_c.c
new file mode 100644
index 0000000..8f0507a
--- /dev/null
+++ b/xdelta3/testing/checksum_test_c.c
@@ -0,0 +1,174 @@
1#include "../xdelta3.c"
2
3// OLD CHECKSUM CODE
4
5#define PERMUTE32(x) (__single_hash32[x])
6#define PERMUTE64(x) (__single_hash64[x])
7
8const uint16_t __single_hash32[256] =
9{
10 /* This hashes the input alphabet (Scheme SLIB pseudo-random). */
11 0xbcd1, 0xbb65, 0x42c2, 0xdffe, 0x9666, 0x431b, 0x8504, 0xeb46,
12 0x6379, 0xd460, 0xcf14, 0x53cf, 0xdb51, 0xdb08, 0x12c8, 0xf602,
13 0xe766, 0x2394, 0x250d, 0xdcbb, 0xa678, 0x02af, 0xa5c6, 0x7ea6,
14 0xb645, 0xcb4d, 0xc44b, 0xe5dc, 0x9fe6, 0x5b5c, 0x35f5, 0x701a,
15 0x220f, 0x6c38, 0x1a56, 0x4ca3, 0xffc6, 0xb152, 0x8d61, 0x7a58,
16 0x9025, 0x8b3d, 0xbf0f, 0x95a3, 0xe5f4, 0xc127, 0x3bed, 0x320b,
17 0xb7f3, 0x6054, 0x333c, 0xd383, 0x8154, 0x5242, 0x4e0d, 0x0a94,
18 0x7028, 0x8689, 0x3a22, 0x0980, 0x1847, 0xb0f1, 0x9b5c, 0x4176,
19 0xb858, 0xd542, 0x1f6c, 0x2497, 0x6a5a, 0x9fa9, 0x8c5a, 0x7743,
20 0xa8a9, 0x9a02, 0x4918, 0x438c, 0xc388, 0x9e2b, 0x4cad, 0x01b6,
21 0xab19, 0xf777, 0x365f, 0x1eb2, 0x091e, 0x7bf8, 0x7a8e, 0x5227,
22 0xeab1, 0x2074, 0x4523, 0xe781, 0x01a3, 0x163d, 0x3b2e, 0x287d,
23 0x5e7f, 0xa063, 0xb134, 0x8fae, 0x5e8e, 0xb7b7, 0x4548, 0x1f5a,
24 0xfa56, 0x7a24, 0x900f, 0x42dc, 0xcc69, 0x02a0, 0x0b22, 0xdb31,
25 0x71fe, 0x0c7d, 0x1732, 0x1159, 0xcb09, 0xe1d2, 0x1351, 0x52e9,
26 0xf536, 0x5a4f, 0xc316, 0x6bf9, 0x8994, 0xb774, 0x5f3e, 0xf6d6,
27 0x3a61, 0xf82c, 0xcc22, 0x9d06, 0x299c, 0x09e5, 0x1eec, 0x514f,
28 0x8d53, 0xa650, 0x5c6e, 0xc577, 0x7958, 0x71ac, 0x8916, 0x9b4f,
29 0x2c09, 0x5211, 0xf6d8, 0xcaaa, 0xf7ef, 0x287f, 0x7a94, 0xab49,
30 0xfa2c, 0x7222, 0xe457, 0xd71a, 0x00c3, 0x1a76, 0xe98c, 0xc037,
31 0x8208, 0x5c2d, 0xdfda, 0xe5f5, 0x0b45, 0x15ce, 0x8a7e, 0xfcad,
32 0xaa2d, 0x4b5c, 0xd42e, 0xb251, 0x907e, 0x9a47, 0xc9a6, 0xd93f,
33 0x085e, 0x35ce, 0xa153, 0x7e7b, 0x9f0b, 0x25aa, 0x5d9f, 0xc04d,
34 0x8a0e, 0x2875, 0x4a1c, 0x295f, 0x1393, 0xf760, 0x9178, 0x0f5b,
35 0xfa7d, 0x83b4, 0x2082, 0x721d, 0x6462, 0x0368, 0x67e2, 0x8624,
36 0x194d, 0x22f6, 0x78fb, 0x6791, 0xb238, 0xb332, 0x7276, 0xf272,
37 0x47ec, 0x4504, 0xa961, 0x9fc8, 0x3fdc, 0xb413, 0x007a, 0x0806,
38 0x7458, 0x95c6, 0xccaa, 0x18d6, 0xe2ae, 0x1b06, 0xf3f6, 0x5050,
39 0xc8e8, 0xf4ac, 0xc04c, 0xf41c, 0x992f, 0xae44, 0x5f1b, 0x1113,
40 0x1738, 0xd9a8, 0x19ea, 0x2d33, 0x9698, 0x2fe9, 0x323f, 0xcde2,
41 0x6d71, 0xe37d, 0xb697, 0x2c4f, 0x4373, 0x9102, 0x075d, 0x8e25,
42 0x1672, 0xec28, 0x6acb, 0x86cc, 0x186e, 0x9414, 0xd674, 0xd1a5
43};
44
45const uint32_t __single_hash64[256] =
46{
47 /* http://random.org 2014.10.24 */
48 0xd25e9f0a, 0xb1af9d5e, 0xb753dfa2, 0x157050f7, /* 0 */
49 0xc84b072c, 0xdd14fe7c, 0xf92208c3, 0xdf08a0c0,
50 0x63a5c118, 0x76f5d90f, 0xa2f8b93e, 0xb6c12d22,
51 0xaf074957, 0x966fb7d9, 0x62f7b785, 0xb40e8a09,
52 0x0a811d5d, 0x323a6daa, 0xb62f7c5b, 0xfdcb9a53,
53 0xf25a9067, 0x4506bc7a, 0xff58a74b, 0x5ae62817,
54 0x74097675, 0x722c0fd9, 0x116a2a66, 0x65f76728,
55 0x72c79651, 0xe043cf9d, 0x64b867c7, 0x6604834f,
56 0xcdca58a6, 0x0f164e2d, 0x24515f05, 0x632cdbf8,
57 0x18091d4a, 0x3eff4128, 0x673d1c33, 0xd8e10c71,
58 0x1a3edf11, 0xba52892f, 0xa56949e0, 0xf3e1dd77, /* 10 */
59 0x86fcbe3e, 0x138d66d0, 0x4fc98359, 0xc22e5dd6,
60 0xc59f2267, 0x6c6dd739, 0xe03da190, 0x07e8469c,
61 0xadcfb02c, 0x00d3b0d9, 0xa1f44918, 0x8bd84d87,
62 0x08ec9ec1, 0xbbcd156f, 0xb57718e3, 0x3177e752,
63 0xf52a4d70, 0xde7aaad9, 0x075f1da0, 0x21ba00c6,
64 0xb9469a5c, 0xcf08d5ba, 0x91ac9edc, 0xc6167b63,
65 0xc1974919, 0xc8c8d195, 0x4b1996dd, 0xeff8991c,
66 0xf7f66c6b, 0x25b012e2, 0x59d12a98, 0xea40d3cc,
67 0x41f9970b, 0xec48101a, 0xa3bdcf90, 0x99f16905,
68 0x27af6c97, 0xc849af37, 0x49cad89b, 0xf48c2278, /* 20 */
69 0x5529c3d8, 0x9e7d6dce, 0x16feb52d, 0xf1b0aca1,
70 0xaf28fccb, 0x48e4ce3c, 0xc4436617, 0x64524e3e,
71 0x61806681, 0x6384f2d7, 0x1172880f, 0x34a5ef5f,
72 0xcc8cc0a8, 0x66e8f100, 0x2866085f, 0xba9b1b2d,
73 0x51285949, 0x2be4b574, 0x889b1ef5, 0x3dbe920d,
74 0x9277a62f, 0x0584a9f6, 0x085d8fc4, 0x4b5d403d,
75 0x4e46ca78, 0x3294c2f9, 0x29313e70, 0xe4f09b24,
76 0xe73b331c, 0x072f5552, 0x2e390b78, 0xea0021ca,
77 0xd8f40320, 0xed0e16fd, 0x7de9cf7a, 0xf17e3d6c,
78 0x8df1bd85, 0x052cae67, 0x3486e512, 0x3a1c09b8, /* 30 */
79 0x6c2a7b4e, 0x83455753, 0xbc0353ac, 0x0ffe20b6,
80 0x5fdcef85, 0x010f506c, 0x595ce972, 0xe28680d0,
81 0xa7e216b2, 0xa392ee0f, 0x25b73faa, 0x2b1f4983,
82 0xeeaefe98, 0x1d3d9cbc, 0x6aebe97b, 0x8b7b3584,
83 0x9e6a9a07, 0xd37f1e99, 0x4ac2a441, 0x8ae9a213,
84 0x7d0e27d7, 0x5de54b9a, 0x8621de1f, 0xf0f2f866,
85 0xcb08d275, 0x49c3f87e, 0xd5ee68c1, 0x9802fc77,
86 0x68be6c5e, 0x65aa8c27, 0xf423d5f7, 0x10ec5502,
87 0x9909bce1, 0x509cdf1b, 0x338fea72, 0x2733e9bf,
88 0xf92f4fd7, 0x87738ea2, 0x931a8bbc, 0x0a5c9155, /* 40 */
89 0xbe5edd9b, 0xadbf5838, 0x0338f8d2, 0x290da210,
90 0x390c37d8, 0xe7cffae8, 0x20617ebe, 0x464322dd,
91 0x7b3c4e78, 0xac142dcb, 0x2d5cef76, 0xd8fe49fc,
92 0x60f4e9a9, 0x7473816f, 0x0dc35f39, 0x5eed80c1,
93 0x0cb55ab6, 0x1d3ac541, 0x13c7f529, 0x7bffdf4a,
94 0xe334785b, 0x85263ec1, 0xd132ae56, 0x7c868b9e,
95 0x47f60638, 0x1012b979, 0x81c31dd3, 0x1af868c8,
96 0x0c5d0742, 0xd1b3e1a2, 0x5873200a, 0xf848465c,
97 0x0fc4d596, 0x609c18af, 0xc9f5a480, 0xd1a94a84,
98 0xa1431a3f, 0x7de8bb1a, 0x25f1256b, 0x1dcc732c, /* 50 */
99 0x6aa1549a, 0xa2367281, 0x32f2a77e, 0x82e62a0f,
100 0x045cbb56, 0x74b2027c, 0xd71a32d9, 0x022e7cb5,
101 0xe99be177, 0x60222fdf, 0xd69681ca, 0x9008ee2c,
102 0x32923db4, 0xcf82bf97, 0x38960a5b, 0xb3503d5b,
103 0x9bd4c7f2, 0x33c029c8, 0x1ef504a3, 0xdb249d3b,
104 0x91e89676, 0x4ca43b36, 0x9191433c, 0x465d5dc4,
105 0xf4dcb118, 0x9d11dd00, 0xb592f058, 0xdbe5ce30,
106 0x74790d92, 0x779850a8, 0x7180d25b, 0xfa951d99,
107 0x5990935a, 0x921cb022, 0x3b7c39bc, 0x6a38a7c7,
108 0xdc22703b, 0x142bab3b, 0x4e3d9479, 0x44bb8482, /* 60 */
109 0x8043abce, 0xfebe832a, 0x8e6a2f98, 0x4d43c4fe,
110 0xd192a70a, 0x802f3c3a, 0x5d11bbab, 0x2665d241,
111 0xb3f3a680, 0x3a8d223f, 0xcf82cdb4, 0x4ed28743,
112};
113
114uint64_t
115xd3_large64_cksum_old (xd3_hash_cfg *ignore, const uint8_t *base, const usize_t look)
116{
117 static const uint64_t kBits = 32;
118 static const uint64_t kMask = 0xffffffff;
119 usize_t i = 0;
120 uint64_t low = 0;
121 uint64_t high = 0;
122
123 for (; i < look; i += 1)
124 {
125 low += PERMUTE64(*base++);
126 high += low;
127 }
128
129 return ((high & kMask) << kBits) | (low & kMask);
130}
131
132uint64_t
133xd3_large64_cksum_update_old (xd3_hash_cfg *ignore, const uint64_t cksum,
134 const uint8_t *base, const usize_t look)
135{
136 static const uint64_t kBits = 32;
137 static const uint64_t kMask = 0xffffffff;
138 uint64_t old_c = PERMUTE64(base[0]);
139 uint64_t new_c = PERMUTE64(base[look]);
140 uint64_t low = ((cksum & kMask) - old_c + new_c) & kMask;
141 uint64_t high = ((cksum >> kBits) - (old_c * look) + low) & kMask;
142 return (high << kBits) | low;
143}
144
145uint32_t
146xd3_large32_cksum_old (xd3_hash_cfg *ignore, const uint8_t *base, const usize_t look)
147{
148 static const uint32_t kBits = 16;
149 static const uint32_t kMask = 0xffff;
150 usize_t i = 0;
151 uint32_t low = 0;
152 uint32_t high = 0;
153
154 for (; i < look; i += 1)
155 {
156 low += PERMUTE32(*base++);
157 high += low;
158 }
159
160 return ((high & kMask) << kBits) | (low & kMask);
161}
162
163uint32_t
164xd3_large32_cksum_update_old (xd3_hash_cfg *ignore, const uint32_t cksum,
165 const uint8_t *base, const usize_t look)
166{
167 static const uint32_t kBits = 16;
168 static const uint32_t kMask = 0xffff;
169 uint32_t old_c = PERMUTE32(base[0]);
170 uint32_t new_c = PERMUTE32(base[look]);
171 uint32_t low = ((cksum & kMask) - old_c + new_c) & kMask;
172 uint32_t high = ((cksum >> kBits) - (old_c * look) + low) & kMask;
173 return (high << kBits) | low;
174}
diff --git a/xdelta3/testing/delta.h b/xdelta3/testing/delta.h
index b0cca7c..deac217 100644
--- a/xdelta3/testing/delta.h
+++ b/xdelta3/testing/delta.h
@@ -30,7 +30,7 @@ public:
30 case XD3_WINFINISH: 30 case XD3_WINFINISH:
31 break; 31 break;
32 default: 32 default:
33 DP(RINT "error code %s\n", xd3_strerror (ret)); 33 cerr << "decode: " << done;
34 abort(); 34 abort();
35 } 35 }
36 } 36 }
@@ -48,23 +48,25 @@ public:
48 return stream_.whole_target.wininfolen; 48 return stream_.whole_target.wininfolen;
49 } 49 }
50 50
51 void Print() const { 51// Note: This does not benefit from -Wformat= checking, due to the
52 for (size_t i = 0; i < stream_.whole_target.instlen; i++) { 52// enclosing template. Further, it was not used.
53 xd3_winst &winst = stream_.whole_target.inst[i]; 53// void Print() const {
54 switch (winst.type) { 54// for (size_t i = 0; i < stream_.whole_target.instlen; i++) {
55 case XD3_RUN: 55// xd3_winst &winst = stream_.whole_target.inst[i];
56 DP(RINT "%"Q"u run %u\n", winst.position, winst.size); 56// switch (winst.type) {
57 break; 57// case XD3_RUN:
58 case XD3_ADD: 58// DP(RINT, "%" Q "u run %" W "u\n", winst.position, winst.size);
59 DP(RINT "%"Q"u add %u\n", winst.position, winst.size); 59// break;
60 break; 60// case XD3_ADD:
61 default: 61// DP(RINT "%" Q "u add %" W "u\n", winst.position, winst.size);
62 DP(RINT "%"Q"u copy %u @ %"Q"u (mode %u)\n", 62// break;
63 winst.position, winst.size, winst.addr, winst.mode); 63// default:
64 break; 64// DP(RINT "%" Q "u copy %" W "u @ %" Q "u (mode %u)\n",
65 } 65// winst.position, winst.size, winst.addr, winst.mode);
66 } 66// break;
67 } 67// }
68// }
69// }
68 70
69private: 71private:
70 xd3_stream stream_; 72 xd3_stream stream_;
diff --git a/xdelta3/testing/file.h b/xdelta3/testing/file.h
index 55b0eb8..2188f7a 100644
--- a/xdelta3/testing/file.h
+++ b/xdelta3/testing/file.h
@@ -62,20 +62,22 @@ public:
62 size_ = 0; 62 size_ = 0;
63 } 63 }
64 64
65 void Print() const { 65 // Note: This does not benefit from -Wformat= checking, due to the
66 xoff_t pos = 0; 66 // enclosing template. Further, it was not used.
67 for (size_t i = 0; i < Size(); i++) { 67 // void Print() const {
68 if (pos % 16 == 0) { 68 // xoff_t pos = 0;
69 DP(RINT "%5"Q"x: ", pos); 69 // for (size_t i = 0; i < Size(); i++) {
70 } 70 // if (pos % 16 == 0) {
71 DP(RINT "%02x ", (*this)[i]); 71 // DP(RINT "%5" Q "x: ", pos);
72 if (pos % 16 == 15) { 72 // }
73 DP(RINT "\n"); 73 // DP(RINT "%02x ", (*this)[i]);
74 } 74 // if (pos % 16 == 15) {
75 pos++; 75 // DP(RINT "\n");
76 } 76 // }
77 DP(RINT "\n"); 77 // pos++;
78 } 78 // }
79 // DP(RINT "\n");
80 // }
79 81
80 void WriteTmpFile(TmpFile *f) const { 82 void WriteTmpFile(TmpFile *f) const {
81 f->Append(this); 83 f->Append(this);
diff --git a/xdelta3/testing/regtest.cc b/xdelta3/testing/regtest.cc
index b2cdaa5..dd2ab8d 100644
--- a/xdelta3/testing/regtest.cc
+++ b/xdelta3/testing/regtest.cc
@@ -92,22 +92,24 @@ public:
92 bool done = false; 92 bool done = false;
93 bool done_after_input = false; 93 bool done_after_input = false;
94 94
95 IF_DEBUG1 (XPR(NTR "source %"Q"u[%"Q"u] target %"Q"u winsize %"Z"u\n", 95 IF_DEBUG1 (XPR(NTR "source %" Q "u[%" Z "u] target %" Q "u winsize %" Z "u\n",
96 source_file.Size(), options.block_size, 96 source_file.Size(), options.block_size,
97 target_file.Size(), 97 target_file.Size(),
98 Constants::WINDOW_SIZE)); 98 Constants::WINDOW_SIZE));
99 99
100 while (!done) { 100 while (!done) {
101 target_iterator.Get(&target_block); 101 target_iterator.Get(&target_block);
102 102
103 xoff_t blks = target_iterator.Blocks(); 103 xoff_t blks = target_iterator.Blocks();
104 104
105 IF_DEBUG2(XPR(NTR "target in %s: %"Q"u..%"Q"u %"Q"u(%"Q"u) " 105 IF_DEBUG2(XPR(NTR "target in %s: %" Q "u[%" Z "u] %" Q "u(%" Q "u) "
106 "verified %"Q"u\n", 106 "verified %" Q "u\n",
107 encoding ? "encoding" : "decoding", 107 encoding ? "encoding" : "decoding",
108 target_iterator.Offset(), 108 target_iterator.Offset(),
109 target_iterator.Offset() + target_block.Size(), 109 target_block.Size(),
110 target_iterator.Blkno(), blks, verified_bytes)); 110 target_iterator.Blkno(),
111 blks,
112 verified_bytes));
111 113
112 if (blks == 0 || target_iterator.Blkno() == (blks - 1)) { 114 if (blks == 0 || target_iterator.Blkno() == (blks - 1)) {
113 xd3_set_flags(&encode_stream, XD3_FLUSH | encode_stream.flags); 115 xd3_set_flags(&encode_stream, XD3_FLUSH | encode_stream.flags);
@@ -153,8 +155,8 @@ public:
153 xd3_source *src = (encoding ? &encode_source : &decode_source); 155 xd3_source *src = (encoding ? &encode_source : &decode_source);
154 Block *block = (encoding ? &encode_source_block : &decode_source_block); 156 Block *block = (encoding ? &encode_source_block : &decode_source_block);
155 if (encoding) { 157 if (encoding) {
156 IF_DEBUG2(XPR(NTR "[srcblock] %"Q"u last srcpos %"Q"u " 158 IF_DEBUG2(XPR(NTR "[srcblock] %" Q "u last srcpos %" Q "u "
157 "encodepos %"Q"u\n", 159 "encodepos %" Q "u\n",
158 encode_source.getblkno, 160 encode_source.getblkno,
159 encode_stream.match_last_srcpos, 161 encode_stream.match_last_srcpos,
160 encode_stream.input_position + encode_stream.total_in)); 162 encode_stream.input_position + encode_stream.total_in));
@@ -231,7 +233,7 @@ public:
231 const Options &options) { 233 const Options &options) {
232 vector<const char*> ecmd; 234 vector<const char*> ecmd;
233 char bbuf[16]; 235 char bbuf[16];
234 snprintf(bbuf, sizeof(bbuf), "-B%"Q"u", options.encode_srcwin_maxsz); 236 snprintf(bbuf, sizeof(bbuf), "-B%" Q "u", options.encode_srcwin_maxsz);
235 ecmd.push_back("xdelta3"); 237 ecmd.push_back("xdelta3");
236 ecmd.push_back(bbuf); 238 ecmd.push_back(bbuf);
237 ecmd.push_back("-s"); 239 ecmd.push_back("-s");
@@ -371,7 +373,7 @@ public:
371void TestPrintf() { 373void TestPrintf() {
372 char buf[64]; 374 char buf[64];
373 xoff_t x = XOFF_T_MAX; 375 xoff_t x = XOFF_T_MAX;
374 snprintf_func (buf, sizeof(buf), "%"Q"u", x); 376 snprintf_func (buf, sizeof(buf), "%" Q "u", x);
375 const char *expect = XD3_USE_LARGEFILE64 ? 377 const char *expect = XD3_USE_LARGEFILE64 ?
376 "18446744073709551615" : "4294967295"; 378 "18446744073709551615" : "4294967295";
377 XD3_ASSERT(strcmp (buf, expect) == 0); 379 XD3_ASSERT(strcmp (buf, expect) == 0);
@@ -696,8 +698,9 @@ void TestOverwriteMutator() {
696 CHECK(memcmp(b0.Data() + 30, b1.Data() + 30, 698 CHECK(memcmp(b0.Data() + 30, b1.Data() + 30,
697 Constants::BLOCK_SIZE - 30) == 0); 699 Constants::BLOCK_SIZE - 30) == 0);
698 700
701 xoff_t zero = 0;
699 cl1.clear(); 702 cl1.clear();
700 cl1.push_back(Change(Change::COPYOVER, 10, 20, (xoff_t)0)); 703 cl1.push_back(Change(Change::COPYOVER, 10, 20, zero));
701 spec0.ModifyTo(ChangeListMutator(cl1), &spec1); 704 spec0.ModifyTo(ChangeListMutator(cl1), &spec1);
702 CHECK_EQ(spec0.Size(), spec1.Size()); 705 CHECK_EQ(spec0.Size(), spec1.Size());
703 706
@@ -813,7 +816,7 @@ void TestSmallStride() {
813 InMemoryEncodeDecode(spec0, spec1, &block, options); 816 InMemoryEncodeDecode(spec0, spec1, &block, options);
814 Delta delta(block); 817 Delta delta(block);
815 818
816 IF_DEBUG1(DP(RINT "[stride=%d] changes=%u adds=%"Q"u\n", 819 IF_DEBUG1(DP(RINT "[stride=%d] changes=%" W "u adds=%" Q "u\n",
817 s, changes, delta.AddedBytes())); 820 s, changes, delta.AddedBytes()));
818 double allowance = Constants::BLOCK_SIZE < 8192 || s < 30 ? 3.0 : 1.1; 821 double allowance = Constants::BLOCK_SIZE < 8192 || s < 30 ? 3.0 : 1.1;
819 CHECK_GE(allowance * changes, (double)delta.AddedBytes()); 822 CHECK_GE(allowance * changes, (double)delta.AddedBytes());
@@ -1259,7 +1262,7 @@ void UnitTest() {
1259// These are Xdelta tests. 1262// These are Xdelta tests.
1260template <class T> 1263template <class T>
1261void MainTest() { 1264void MainTest() {
1262 XPR(NT "Blocksize %"Q"u windowsize %"Z"u\n", 1265 XPR(NT "Blocksize %" Q "u windowsize %" Z "u\n",
1263 T::BLOCK_SIZE, T::WINDOW_SIZE); 1266 T::BLOCK_SIZE, T::WINDOW_SIZE);
1264 Regtest<T> regtest; 1267 Regtest<T> regtest;
1265 TEST(TestEmptyInMemory); 1268 TEST(TestEmptyInMemory);
diff --git a/xdelta3/testing/run_release.sh b/xdelta3/testing/run_release.sh
new file mode 100755
index 0000000..85ed1f7
--- /dev/null
+++ b/xdelta3/testing/run_release.sh
@@ -0,0 +1,2 @@
1#!/bin/sh
2(cd .. && ./run_release.sh)
diff --git a/xdelta3/testing/test.h b/xdelta3/testing/test.h
index 1eabcbd..7de24fb 100644
--- a/xdelta3/testing/test.h
+++ b/xdelta3/testing/test.h
@@ -18,8 +18,8 @@ extern "C" {
18 18
19#define CHECK_OP(x,y,OP) \ 19#define CHECK_OP(x,y,OP) \
20 do { \ 20 do { \
21 typeof(x) _x(x); \ 21 __typeof__(x) _x(x); \
22 typeof(x) _y(y); \ 22 __typeof__(x) _y(y); \
23 if (!(_x OP _y)) { \ 23 if (!(_x OP _y)) { \
24 cerr << __FILE__ << ":" << __LINE__ << " Check failed: " << #x " " #OP " " #y << endl; \ 24 cerr << __FILE__ << ":" << __LINE__ << " Check failed: " << #x " " #OP " " #y << endl; \
25 cerr << __FILE__ << ":" << __LINE__ << " {0} " << _x << endl; \ 25 cerr << __FILE__ << ":" << __LINE__ << " {0} " << _x << endl; \
@@ -68,5 +68,3 @@ pair<T, U> make_pair(const T& t, const U& u) {
68 68
69using std::min; 69using std::min;
70using std::max; 70using std::max;
71
72