diff options
-rw-r--r-- | xdelta3/testing/regtest.cc | 32 | ||||
-rw-r--r-- | xdelta3/testing/sizes.h | 55 | ||||
-rw-r--r-- | xdelta3/testing/test.h | 4 | ||||
-rw-r--r-- | xdelta3/xdelta3-test.h | 46 | ||||
-rw-r--r-- | xdelta3/xdelta3.c | 1 | ||||
-rw-r--r-- | xdelta3/xdelta3.h | 2 |
6 files changed, 96 insertions, 44 deletions
diff --git a/xdelta3/testing/regtest.cc b/xdelta3/testing/regtest.cc index f64111e..3b4d4c6 100644 --- a/xdelta3/testing/regtest.cc +++ b/xdelta3/testing/regtest.cc | |||
@@ -68,8 +68,8 @@ void InMemoryEncodeDecode(FileSpec &source_file, FileSpec &target_file) { | |||
68 | ret = xd3_decode_input(&decode_stream); | 68 | ret = xd3_decode_input(&decode_stream); |
69 | } | 69 | } |
70 | 70 | ||
71 | DP(RINT "%s = %s\n", encoding ? "encoding" : "decoding", | 71 | //DP(RINT "%s = %s\n", encoding ? "encoding" : "decoding", |
72 | xd3_strerror(ret)); | 72 | // xd3_strerror(ret)); |
73 | 73 | ||
74 | switch (ret) { | 74 | switch (ret) { |
75 | case XD3_OUTPUT: | 75 | case XD3_OUTPUT: |
@@ -117,7 +117,7 @@ void InMemoryEncodeDecode(FileSpec &source_file, FileSpec &target_file) { | |||
117 | encoding = false; | 117 | encoding = false; |
118 | } else { | 118 | } else { |
119 | CHECK_EQ(0, CmpDifferentBlockBytes(decoded_block, target_block)); | 119 | CHECK_EQ(0, CmpDifferentBlockBytes(decoded_block, target_block)); |
120 | DP(RINT "verified block %"Q"u\n", target_iterator.Blkno()); | 120 | //DP(RINT "verified block %"Q"u\n", target_iterator.Blkno()); |
121 | decoded_block.Reset(); | 121 | decoded_block.Reset(); |
122 | encoding = true; | 122 | encoding = true; |
123 | } | 123 | } |
@@ -236,23 +236,18 @@ void TestFirstByte() { | |||
236 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE + 1); | 236 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE + 1); |
237 | spec0.ModifyTo<Modify1stByte>(&spec1); | 237 | spec0.ModifyTo<Modify1stByte>(&spec1); |
238 | CHECK_EQ(1, CmpDifferentBytes(spec0, spec1)); | 238 | CHECK_EQ(1, CmpDifferentBytes(spec0, spec1)); |
239 | } | ||
240 | |||
241 | void TestBasicEncodeDecode() { | ||
242 | MTRandom rand; | ||
243 | FileSpec spec0(&rand); | ||
244 | FileSpec spec1(&rand); | ||
245 | spec0.GenerateFixedSize(1024); | ||
246 | spec0.ModifyTo<Modify1stByte>(&spec1); | ||
247 | InMemoryEncodeDecode(spec0, spec1); | ||
248 | 239 | ||
249 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE); | 240 | SizeIterator<size_t, SmallSizes> si(&rand, 20); |
250 | spec0.ModifyTo<Modify1stByte>(&spec1); | ||
251 | InMemoryEncodeDecode(spec0, spec1); | ||
252 | 241 | ||
253 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 2); | 242 | for (; !si.Done(); si.Next()) { |
254 | spec0.ModifyTo<Modify1stByte>(&spec1); | 243 | size_t size = si.Get(); |
255 | InMemoryEncodeDecode(spec0, spec1); | 244 | if (size == 0) { |
245 | continue; | ||
246 | } | ||
247 | spec0.GenerateFixedSize(size); | ||
248 | spec0.ModifyTo<Modify1stByte>(&spec1); | ||
249 | InMemoryEncodeDecode(spec0, spec1); | ||
250 | } | ||
256 | } | 251 | } |
257 | 252 | ||
258 | int main(int argc, char **argv) { | 253 | int main(int argc, char **argv) { |
@@ -260,7 +255,6 @@ int main(int argc, char **argv) { | |||
260 | TEST(TestRandomNumbers); | 255 | TEST(TestRandomNumbers); |
261 | TEST(TestRandomFile); | 256 | TEST(TestRandomFile); |
262 | TEST(TestFirstByte); | 257 | TEST(TestFirstByte); |
263 | TEST(TestBasicEncodeDecode); | ||
264 | return 0; | 258 | return 0; |
265 | } | 259 | } |
266 | 260 | ||
diff --git a/xdelta3/testing/sizes.h b/xdelta3/testing/sizes.h new file mode 100644 index 0000000..8913baa --- /dev/null +++ b/xdelta3/testing/sizes.h | |||
@@ -0,0 +1,55 @@ | |||
1 | // -*- Mode: C++ -*- | ||
2 | namespace regtest { | ||
3 | |||
4 | template <typename T, typename U> | ||
5 | class SizeIterator { | ||
6 | public: | ||
7 | SizeIterator(MTRandom *rand, size_t howmany) | ||
8 | : rand_(rand), | ||
9 | count_(0), | ||
10 | fixed_(U::sizes), | ||
11 | fixed_size_(SIZEOF_ARRAY(U::sizes)), | ||
12 | howmany_(howmany) { } | ||
13 | |||
14 | T Get() { | ||
15 | if (count_ < fixed_size_) { | ||
16 | return fixed_[count_]; | ||
17 | } | ||
18 | return rand_->Rand<T>() % U::max_value; | ||
19 | } | ||
20 | |||
21 | bool Done() { | ||
22 | return count_ >= howmany_; | ||
23 | } | ||
24 | |||
25 | void Next() { | ||
26 | count_++; | ||
27 | } | ||
28 | |||
29 | private: | ||
30 | MTRandom *rand_; | ||
31 | size_t count_; | ||
32 | T* fixed_; | ||
33 | size_t fixed_size_; | ||
34 | size_t howmany_; | ||
35 | }; | ||
36 | |||
37 | class SmallSizes { | ||
38 | public: | ||
39 | static size_t sizes[]; | ||
40 | static size_t max_value; | ||
41 | }; | ||
42 | |||
43 | size_t SmallSizes::sizes[] = { | ||
44 | 0, 1, 1024, 3333, | ||
45 | Constants::BLOCK_SIZE - 3333, | ||
46 | Constants::BLOCK_SIZE, | ||
47 | Constants::BLOCK_SIZE + 3333, | ||
48 | 2 * Constants::BLOCK_SIZE - 3333, | ||
49 | 2 * Constants::BLOCK_SIZE, | ||
50 | 2 * Constants::BLOCK_SIZE + 3333, | ||
51 | }; | ||
52 | |||
53 | size_t SmallSizes::max_value = Constants::BLOCK_SIZE * 3; | ||
54 | |||
55 | } // namespace regtest | ||
diff --git a/xdelta3/testing/test.h b/xdelta3/testing/test.h index 74767fd..4d2dc8a 100644 --- a/xdelta3/testing/test.h +++ b/xdelta3/testing/test.h | |||
@@ -59,3 +59,7 @@ using regtest::Modify1stByte; | |||
59 | 59 | ||
60 | #include "cmp.h" | 60 | #include "cmp.h" |
61 | using regtest::CmpDifferentBytes; | 61 | using regtest::CmpDifferentBytes; |
62 | |||
63 | #include "sizes.h" | ||
64 | using regtest::SizeIterator; | ||
65 | using regtest::SmallSizes; | ||
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h index 02c440a..c34aa3f 100644 --- a/xdelta3/xdelta3-test.h +++ b/xdelta3/xdelta3-test.h | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | struct mtrand_ { | 32 | struct mtrand_ { |
33 | int mt_index; | 33 | int mt_index; |
34 | usize_t mt_buffer[MT_LEN]; | 34 | uint32_t mt_buffer[MT_LEN]; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | typedef struct mtrand_ mtrand; | 37 | typedef struct mtrand_ mtrand; |
@@ -46,13 +46,13 @@ static void mt_init (mtrand *mt, int seed) { | |||
46 | mt->mt_index = 0; | 46 | mt->mt_index = 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | static usize_t mt_random (mtrand *mt) { | 49 | static uint32_t mt_random (mtrand *mt) { |
50 | usize_t * b = mt->mt_buffer; | 50 | uint32_t * b = mt->mt_buffer; |
51 | int idx = mt->mt_index; | 51 | int idx = mt->mt_index; |
52 | usize_t s; | 52 | uint32_t s; |
53 | int i; | 53 | int i; |
54 | 54 | ||
55 | if (idx == MT_LEN*sizeof(usize_t)) | 55 | if (idx == MT_LEN*sizeof(uint32_t)) |
56 | { | 56 | { |
57 | idx = 0; | 57 | idx = 0; |
58 | i = 0; | 58 | i = 0; |
@@ -68,14 +68,25 @@ static usize_t mt_random (mtrand *mt) { | |||
68 | s = TWIST(b, MT_LEN-1, 0); | 68 | s = TWIST(b, MT_LEN-1, 0); |
69 | b[MT_LEN-1] = b[MT_IA-1] ^ (s >> 1) ^ MAGIC(s); | 69 | b[MT_LEN-1] = b[MT_IA-1] ^ (s >> 1) ^ MAGIC(s); |
70 | } | 70 | } |
71 | mt->mt_index = idx + sizeof(usize_t); | 71 | mt->mt_index = idx + sizeof(uint32_t); |
72 | return *(usize_t *)((unsigned char *)b + idx); | 72 | return *(uint32_t *)((unsigned char *)b + idx); |
73 | } | 73 | } |
74 | 74 | ||
75 | static mtrand static_mtrand; | 75 | static mtrand static_mtrand; |
76 | 76 | ||
77 | #include <math.h> | 77 | #include <math.h> |
78 | 78 | ||
79 | static uint32_t | ||
80 | mt_exp_rand (uint32_t mean, uint32_t max_value) | ||
81 | { | ||
82 | double mean_d = mean; | ||
83 | double erand = log (1.0 / (mt_random (&static_mtrand) / | ||
84 | (double)UINT32_MAX)); | ||
85 | uint32_t x = (uint32_t) (mean_d * erand + 0.5); | ||
86 | |||
87 | return min (x, max_value); | ||
88 | } | ||
89 | |||
79 | #ifndef WIN32 | 90 | #ifndef WIN32 |
80 | #include <sys/wait.h> | 91 | #include <sys/wait.h> |
81 | #endif | 92 | #endif |
@@ -103,8 +114,6 @@ static char TEST_RECON2_FILE[TESTFILESIZE]; | |||
103 | static char TEST_COPY_FILE[TESTFILESIZE]; | 114 | static char TEST_COPY_FILE[TESTFILESIZE]; |
104 | static char TEST_NOPERM_FILE[TESTFILESIZE]; | 115 | static char TEST_NOPERM_FILE[TESTFILESIZE]; |
105 | 116 | ||
106 | static int test_exponential_dist (usize_t mean, usize_t max); | ||
107 | |||
108 | #define CHECK(cond) if (!(cond)) { DP(RINT "check failure: " #cond); abort(); } | 117 | #define CHECK(cond) if (!(cond)) { DP(RINT "check failure: " #cond); abort(); } |
109 | 118 | ||
110 | /* Use a fixed soft config so that test values are fixed. See also | 119 | /* Use a fixed soft config so that test values are fixed. See also |
@@ -149,17 +158,6 @@ static int do_fail (xd3_stream *stream, const char *buf) | |||
149 | return 0; | 158 | return 0; |
150 | } | 159 | } |
151 | 160 | ||
152 | static int | ||
153 | test_exponential_dist (usize_t mean, usize_t max_value) | ||
154 | { | ||
155 | double mean_d = mean; | ||
156 | double erand = log (1.0 / (mt_random (&static_mtrand) / | ||
157 | (double)USIZE_T_MAX)); | ||
158 | usize_t x = (usize_t) (mean_d * erand + 0.5); | ||
159 | |||
160 | return min (x, max_value); | ||
161 | } | ||
162 | |||
163 | /* Test that the exponential distribution actually produces its mean. */ | 161 | /* Test that the exponential distribution actually produces its mean. */ |
164 | static int | 162 | static int |
165 | test_random_numbers (xd3_stream *stream, int ignore) | 163 | test_random_numbers (xd3_stream *stream, int ignore) |
@@ -175,7 +173,7 @@ test_random_numbers (xd3_stream *stream, int ignore) | |||
175 | 173 | ||
176 | for (i = 0; i < n_rounds; i += 1) | 174 | for (i = 0; i < n_rounds; i += 1) |
177 | { | 175 | { |
178 | sum += test_exponential_dist (mean, USIZE_T_MAX); | 176 | sum += mt_exp_rand (mean, USIZE_T_MAX); |
179 | } | 177 | } |
180 | 178 | ||
181 | average = (double) sum / (double) n_rounds; | 179 | average = (double) sum / (double) n_rounds; |
@@ -272,7 +270,7 @@ test_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out) | |||
272 | for (i = 0; i < ts; ) | 270 | for (i = 0; i < ts; ) |
273 | { | 271 | { |
274 | size_t left = ts - i; | 272 | size_t left = ts - i; |
275 | size_t next = test_exponential_dist (TEST_ADD_MEAN, TEST_ADD_MAX); | 273 | size_t next = mt_exp_rand (TEST_ADD_MEAN, TEST_ADD_MAX); |
276 | size_t add_left = sadd_max - sadd; | 274 | size_t add_left = sadd_max - sadd; |
277 | double add_prob = (left == 0) ? 0 : (add_left / (double) left); | 275 | double add_prob = (left == 0) ? 0 : (add_left / (double) left); |
278 | int do_copy; | 276 | int do_copy; |
@@ -1120,7 +1118,7 @@ sec_dist_func4 (xd3_stream *stream, xd3_output *data) | |||
1120 | int i, ret, x; | 1118 | int i, ret, x; |
1121 | for (i = 0; i < ALPHABET_SIZE*20; i += 1) | 1119 | for (i = 0; i < ALPHABET_SIZE*20; i += 1) |
1122 | { | 1120 | { |
1123 | x = test_exponential_dist (10, ALPHABET_SIZE/2); | 1121 | x = mt_exp_rand (10, ALPHABET_SIZE/2); |
1124 | if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } | 1122 | if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } |
1125 | } | 1123 | } |
1126 | return 0; | 1124 | return 0; |
@@ -1133,7 +1131,7 @@ sec_dist_func5 (xd3_stream *stream, xd3_output *data) | |||
1133 | int i, ret, x; | 1131 | int i, ret, x; |
1134 | for (i = 0; i < ALPHABET_SIZE*20; i += 1) | 1132 | for (i = 0; i < ALPHABET_SIZE*20; i += 1) |
1135 | { | 1133 | { |
1136 | x = test_exponential_dist (10, ALPHABET_SIZE-1); | 1134 | x = mt_exp_rand (10, ALPHABET_SIZE-1); |
1137 | if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } | 1135 | if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } |
1138 | } | 1136 | } |
1139 | return 0; | 1137 | return 0; |
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c index 60a348d..77fc534 100644 --- a/xdelta3/xdelta3.c +++ b/xdelta3/xdelta3.c | |||
@@ -3801,6 +3801,7 @@ xd3_encode_input (xd3_stream *stream) | |||
3801 | else | 3801 | else |
3802 | { | 3802 | { |
3803 | stream->match_state = MATCH_SEARCHING; | 3803 | stream->match_state = MATCH_SEARCHING; |
3804 | stream->match_fwd = 0; | ||
3804 | } | 3805 | } |
3805 | XD3_ASSERT (stream->match_fwd == 0); | 3806 | XD3_ASSERT (stream->match_fwd == 0); |
3806 | 3807 | ||
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h index f5b75d1..fa5b332 100644 --- a/xdelta3/xdelta3.h +++ b/xdelta3/xdelta3.h | |||
@@ -1207,7 +1207,7 @@ void xd3_avail_input (xd3_stream *stream, | |||
1207 | * xd3_avail_input it will return XD3_INPUT right away without | 1207 | * xd3_avail_input it will return XD3_INPUT right away without |
1208 | * allocating a stream->winsize buffer. This is to avoid an | 1208 | * allocating a stream->winsize buffer. This is to avoid an |
1209 | * unwanted allocation. */ | 1209 | * unwanted allocation. */ |
1210 | XD3_ASSERT (idata != NULL); | 1210 | XD3_ASSERT (idata != NULL || isize == 0); |
1211 | 1211 | ||
1212 | stream->next_in = idata; | 1212 | stream->next_in = idata; |
1213 | stream->avail_in = isize; | 1213 | stream->avail_in = isize; |