diff options
-rw-r--r-- | xdelta3/testing/Makefile | 2 | ||||
-rw-r--r-- | xdelta3/testing/file.h | 6 | ||||
-rw-r--r-- | xdelta3/testing/modify.h | 12 | ||||
-rw-r--r-- | xdelta3/testing/regtest.cc | 568 | ||||
-rw-r--r-- | xdelta3/xdelta3-internal.h | 1 | ||||
-rw-r--r-- | xdelta3/xdelta3-test.h | 22 | ||||
-rw-r--r-- | xdelta3/xdelta3.c | 13 |
7 files changed, 382 insertions, 242 deletions
diff --git a/xdelta3/testing/Makefile b/xdelta3/testing/Makefile new file mode 100644 index 0000000..77cc11d --- /dev/null +++ b/xdelta3/testing/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | all: | ||
2 | (cd .. && make all) | ||
diff --git a/xdelta3/testing/file.h b/xdelta3/testing/file.h index a204d74..2c13f63 100644 --- a/xdelta3/testing/file.h +++ b/xdelta3/testing/file.h | |||
@@ -342,6 +342,12 @@ public: | |||
342 | return true; | 342 | return true; |
343 | } | 343 | } |
344 | 344 | ||
345 | // Check whether a real file matches another | ||
346 | bool EqualsSpec(const ExtFile &other) const { | ||
347 | int ret = compare_files(Name(), other.Name()); | ||
348 | return true; | ||
349 | } | ||
350 | |||
345 | protected: | 351 | protected: |
346 | string filename_; | 352 | string filename_; |
347 | }; | 353 | }; |
diff --git a/xdelta3/testing/modify.h b/xdelta3/testing/modify.h index d4698e3..5c2e316 100644 --- a/xdelta3/testing/modify.h +++ b/xdelta3/testing/modify.h | |||
@@ -15,10 +15,10 @@ 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 | OVERWRITE = 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, OVERWRITE preserve the file size | 21 | // MODIFY, MOVE, COPYOVER preserve the file size |
22 | }; | 22 | }; |
23 | 23 | ||
24 | // Constructor for modify, add, delete. | 24 | // Constructor for modify, add, delete. |
@@ -28,7 +28,7 @@ public: | |||
28 | addr1(addr1_0), | 28 | addr1(addr1_0), |
29 | addr2(0), | 29 | addr2(0), |
30 | insert(NULL) { | 30 | insert(NULL) { |
31 | CHECK(kind != MOVE && kind != COPY && kind != OVERWRITE); | 31 | CHECK(kind != MOVE && kind != COPY && kind != COPYOVER); |
32 | } | 32 | } |
33 | 33 | ||
34 | // Constructor for modify, add w/ provided data. | 34 | // Constructor for modify, add w/ provided data. |
@@ -38,7 +38,7 @@ public: | |||
38 | addr1(addr1_0), | 38 | addr1(addr1_0), |
39 | addr2(0), | 39 | addr2(0), |
40 | insert(insert0) { | 40 | insert(insert0) { |
41 | CHECK(kind != MOVE && kind != COPY && kind != OVERWRITE); | 41 | CHECK(kind != MOVE && kind != COPY && kind != COPYOVER); |
42 | } | 42 | } |
43 | 43 | ||
44 | // Constructor for move, copy, overwrite | 44 | // Constructor for move, copy, overwrite |
@@ -48,7 +48,7 @@ public: | |||
48 | addr1(addr1_0), | 48 | addr1(addr1_0), |
49 | addr2(addr2_0), | 49 | addr2(addr2_0), |
50 | insert(NULL) { | 50 | insert(NULL) { |
51 | CHECK(kind == MOVE || kind == COPY || kind == OVERWRITE); | 51 | CHECK(kind == MOVE || kind == COPY || kind == COPYOVER); |
52 | } | 52 | } |
53 | 53 | ||
54 | Kind kind; | 54 | Kind kind; |
@@ -106,7 +106,7 @@ public: | |||
106 | case Change::MOVE: | 106 | case Change::MOVE: |
107 | MoveChange(ch, table, source_table, rand); | 107 | MoveChange(ch, table, source_table, rand); |
108 | break; | 108 | break; |
109 | case Change::OVERWRITE: | 109 | case Change::COPYOVER: |
110 | OverwriteChange(ch, table, source_table, rand); | 110 | OverwriteChange(ch, table, source_table, rand); |
111 | break; | 111 | break; |
112 | } | 112 | } |
diff --git a/xdelta3/testing/regtest.cc b/xdelta3/testing/regtest.cc index d5864d6..12b712e 100644 --- a/xdelta3/testing/regtest.cc +++ b/xdelta3/testing/regtest.cc | |||
@@ -9,7 +9,12 @@ 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), | ||
13 | block_size(Constants::BLOCK_SIZE), | ||
14 | size_known(false) { } | ||
12 | size_t encode_srcwin_maxsz; | 15 | size_t encode_srcwin_maxsz; |
16 | size_t block_size; | ||
17 | bool size_known; | ||
13 | }; | 18 | }; |
14 | 19 | ||
15 | #include "segment.h" | 20 | #include "segment.h" |
@@ -18,218 +23,265 @@ public: | |||
18 | #include "cmp.h" | 23 | #include "cmp.h" |
19 | #include "delta.h" | 24 | #include "delta.h" |
20 | 25 | ||
21 | void InMemoryEncodeDecode(const FileSpec &source_file, | 26 | void InMemoryEncodeDecode(const FileSpec &source_file, |
22 | const FileSpec &target_file, | 27 | const FileSpec &target_file, |
23 | Block *coded_data, | 28 | Block *coded_data, |
24 | const Options &options = Options()) { | 29 | const Options &options = Options()) { |
25 | xd3_stream encode_stream; | 30 | xd3_stream encode_stream; |
26 | xd3_config encode_config; | 31 | xd3_config encode_config; |
27 | xd3_source encode_source; | 32 | xd3_source encode_source; |
28 | 33 | ||
29 | xd3_stream decode_stream; | 34 | xd3_stream decode_stream; |
30 | xd3_config decode_config; | 35 | xd3_config decode_config; |
31 | xd3_source decode_source; | 36 | xd3_source decode_source; |
32 | xoff_t verified_bytes = 0; | 37 | xoff_t verified_bytes = 0; |
33 | xoff_t encoded_bytes = 0; | 38 | xoff_t encoded_bytes = 0; |
34 | 39 | ||
35 | if (coded_data) { | 40 | if (coded_data) { |
36 | coded_data->Reset(); | 41 | coded_data->Reset(); |
37 | } | 42 | } |
38 | 43 | ||
39 | memset(&encode_stream, 0, sizeof (encode_stream)); | 44 | memset(&encode_stream, 0, sizeof (encode_stream)); |
40 | memset(&encode_source, 0, sizeof (encode_source)); | 45 | memset(&encode_source, 0, sizeof (encode_source)); |
41 | 46 | ||
42 | memset(&decode_stream, 0, sizeof (decode_stream)); | 47 | memset(&decode_stream, 0, sizeof (decode_stream)); |
43 | memset(&decode_source, 0, sizeof (decode_source)); | 48 | memset(&decode_source, 0, sizeof (decode_source)); |
44 | 49 | ||
45 | xd3_init_config(&encode_config, XD3_ADLER32); | 50 | xd3_init_config(&encode_config, XD3_ADLER32); |
46 | xd3_init_config(&decode_config, XD3_ADLER32); | 51 | xd3_init_config(&decode_config, XD3_ADLER32); |
47 | 52 | ||
48 | encode_config.winsize = Constants::WINDOW_SIZE; | 53 | encode_config.winsize = Constants::WINDOW_SIZE; |
49 | 54 | ||
50 | // TODO! the smatcher setup isn't working, | 55 | // TODO! the smatcher setup isn't working, |
51 | // if (options.large_cksum_step) { | 56 | // if (options.large_cksum_step) { |
52 | // encode_config.smatch_cfg = XD3_SMATCH_SOFT; | 57 | // encode_config.smatch_cfg = XD3_SMATCH_SOFT; |
53 | // encode_config.smatcher_soft.large_step = options.large_cksum_step; | 58 | // encode_config.smatcher_soft.large_step = options.large_cksum_step; |
54 | // } | 59 | // } |
55 | // if (options.large_cksum_size) { | 60 | // if (options.large_cksum_size) { |
56 | // encode_config.smatch_cfg = XD3_SMATCH_SOFT; | 61 | // encode_config.smatch_cfg = XD3_SMATCH_SOFT; |
57 | // encode_config.smatcher_soft.large_look = options.large_cksum_size; | 62 | // encode_config.smatcher_soft.large_look = options.large_cksum_size; |
58 | // } | 63 | // } |
59 | 64 | ||
60 | CHECK_EQ(0, xd3_config_stream (&encode_stream, &encode_config)); | 65 | CHECK_EQ(0, xd3_config_stream (&encode_stream, &encode_config)); |
61 | CHECK_EQ(0, xd3_config_stream (&decode_stream, &decode_config)); | 66 | CHECK_EQ(0, xd3_config_stream (&decode_stream, &decode_config)); |
62 | 67 | ||
63 | encode_source.blksize = Constants::BLOCK_SIZE; | 68 | encode_source.blksize = options.block_size; |
64 | decode_source.blksize = Constants::BLOCK_SIZE; | 69 | decode_source.blksize = options.block_size; |
65 | 70 | ||
66 | encode_source.max_winsize = options.encode_srcwin_maxsz; | 71 | encode_source.max_winsize = options.encode_srcwin_maxsz; |
72 | decode_source.max_winsize = options.encode_srcwin_maxsz; | ||
67 | 73 | ||
68 | xd3_set_source (&encode_stream, &encode_source); | 74 | if (!options.size_known) |
69 | xd3_set_source (&decode_stream, &decode_source); | 75 | { |
76 | xd3_set_source (&encode_stream, &encode_source); | ||
77 | xd3_set_source (&decode_stream, &decode_source); | ||
78 | } | ||
79 | else | ||
80 | { | ||
81 | xd3_set_source_and_size (&encode_stream, &encode_source, | ||
82 | source_file.Size()); | ||
83 | xd3_set_source_and_size (&decode_stream, &decode_source, | ||
84 | source_file.Size()); | ||
85 | } | ||
70 | 86 | ||
71 | BlockIterator source_iterator(source_file, Constants::BLOCK_SIZE); | 87 | BlockIterator source_iterator(source_file, options.block_size); |
72 | BlockIterator target_iterator(target_file, Constants::READ_SIZE); | 88 | BlockIterator target_iterator(target_file, Constants::READ_SIZE); |
73 | Block encode_source_block, decode_source_block; | 89 | Block encode_source_block, decode_source_block; |
74 | Block decoded_block, target_block; | 90 | Block decoded_block, target_block; |
75 | bool encoding = true; | 91 | bool encoding = true; |
76 | bool done = false; | 92 | bool done = false; |
77 | bool done_after_input = false; | 93 | bool done_after_input = false; |
78 | 94 | ||
79 | IF_DEBUG1 (XPR(NTR "source %"Q"u[%"Q"u] target %"Q"u[%lu] winsize %lu\n", | 95 | IF_DEBUG1 (XPR(NTR "source %"Q"u[%"Q"u] target %"Q"u[%lu] winsize %lu\n", |
80 | source_file.Size(), Constants::BLOCK_SIZE, | 96 | source_file.Size(), options.block_size, |
81 | target_file.Size(), Constants::READ_SIZE, | 97 | target_file.Size(), Constants::READ_SIZE, |
82 | Constants::WINDOW_SIZE)); | 98 | Constants::WINDOW_SIZE)); |
83 | 99 | ||
84 | while (!done) { | 100 | while (!done) { |
85 | target_iterator.Get(&target_block); | 101 | target_iterator.Get(&target_block); |
86 | 102 | ||
87 | xoff_t blks = target_iterator.Blocks(); | 103 | xoff_t blks = target_iterator.Blocks(); |
88 | 104 | ||
89 | IF_DEBUG2(XPR(NTR "target in %s: %llu..%llu %"Q"u(%"Q"u) verified %"Q"u\n", | 105 | IF_DEBUG2(XPR(NTR "target in %s: %llu..%llu %"Q"u(%"Q"u) verified %"Q"u\n", |
90 | encoding ? "encoding" : "decoding", | 106 | encoding ? "encoding" : "decoding", |
91 | target_iterator.Offset(), | 107 | target_iterator.Offset(), |
92 | target_iterator.Offset() + target_block.Size(), | 108 | target_iterator.Offset() + target_block.Size(), |
93 | target_iterator.Blkno(), blks, verified_bytes)); | 109 | target_iterator.Blkno(), blks, verified_bytes)); |
94 | 110 | ||
95 | if (blks == 0 || target_iterator.Blkno() == (blks - 1)) { | 111 | if (blks == 0 || target_iterator.Blkno() == (blks - 1)) { |
96 | xd3_set_flags(&encode_stream, XD3_FLUSH | encode_stream.flags); | 112 | xd3_set_flags(&encode_stream, XD3_FLUSH | encode_stream.flags); |
97 | } | 113 | } |
98 | 114 | ||
99 | xd3_avail_input(&encode_stream, target_block.Data(), target_block.Size()); | 115 | xd3_avail_input(&encode_stream, target_block.Data(), target_block.Size()); |
100 | encoded_bytes += target_block.Size(); | 116 | encoded_bytes += target_block.Size(); |
101 | |||
102 | process: | ||
103 | int ret; | ||
104 | const char *msg; | ||
105 | if (encoding) { | ||
106 | ret = xd3_encode_input(&encode_stream); | ||
107 | msg = encode_stream.msg; | ||
108 | } else { | ||
109 | ret = xd3_decode_input(&decode_stream); | ||
110 | msg = decode_stream.msg; | ||
111 | } | ||
112 | (void) msg; | ||
113 | 117 | ||
114 | switch (ret) { | 118 | process: |
115 | case XD3_OUTPUT: | 119 | int ret; |
120 | const char *msg; | ||
116 | if (encoding) { | 121 | if (encoding) { |
117 | if (coded_data != NULL) { | 122 | ret = xd3_encode_input(&encode_stream); |
118 | // Optional encoded-output to the caller | 123 | msg = encode_stream.msg; |
119 | coded_data->Append(encode_stream.next_out, | ||
120 | encode_stream.avail_out); | ||
121 | } | ||
122 | // Feed this data to the decoder. | ||
123 | xd3_avail_input(&decode_stream, | ||
124 | encode_stream.next_out, | ||
125 | encode_stream.avail_out); | ||
126 | xd3_consume_output(&encode_stream); | ||
127 | encoding = false; | ||
128 | } else { | 124 | } else { |
129 | decoded_block.Append(decode_stream.next_out, | 125 | ret = xd3_decode_input(&decode_stream); |
130 | decode_stream.avail_out); | 126 | msg = decode_stream.msg; |
131 | xd3_consume_output(&decode_stream); | ||
132 | } | ||
133 | goto process; | ||
134 | |||
135 | case XD3_GETSRCBLK: { | ||
136 | xd3_source *src = (encoding ? &encode_source : &decode_source); | ||
137 | Block *block = (encoding ? &encode_source_block : &decode_source_block); | ||
138 | if (encoding) { | ||
139 | IF_DEBUG1(XPR(NTR "[srcblock] %"Q"u last srcpos %"Q"u " | ||
140 | "encodepos %"Q"u\n", | ||
141 | encode_source.getblkno, | ||
142 | encode_stream.match_last_srcpos, | ||
143 | encode_stream.input_position + encode_stream.total_in)); | ||
144 | } | 127 | } |
145 | 128 | (void) msg; | |
146 | source_iterator.SetBlock(src->getblkno); | 129 | |
147 | source_iterator.Get(block); | 130 | switch (ret) { |
148 | src->curblkno = src->getblkno; | 131 | case XD3_OUTPUT: |
149 | src->onblk = block->Size(); | 132 | if (encoding) { |
150 | src->curblk = block->Data(); | 133 | if (coded_data != NULL) { |
151 | 134 | // Optional encoded-output to the caller | |
152 | goto process; | 135 | coded_data->Append(encode_stream.next_out, |
153 | } | 136 | encode_stream.avail_out); |
154 | 137 | } | |
155 | case XD3_INPUT: | 138 | // Feed this data to the decoder. |
156 | if (!encoding) { | 139 | xd3_avail_input(&decode_stream, |
157 | encoding = true; | 140 | encode_stream.next_out, |
158 | goto process; | 141 | encode_stream.avail_out); |
159 | } else { | 142 | xd3_consume_output(&encode_stream); |
160 | if (done_after_input) { | ||
161 | done = true; | ||
162 | continue; | ||
163 | } | ||
164 | |||
165 | if (target_block.Size() < target_iterator.BlockSize()) { | ||
166 | encoding = false; | 143 | encoding = false; |
167 | } else { | 144 | } else { |
168 | target_iterator.Next(); | 145 | decoded_block.Append(decode_stream.next_out, |
146 | decode_stream.avail_out); | ||
147 | xd3_consume_output(&decode_stream); | ||
169 | } | 148 | } |
170 | continue; | 149 | goto process; |
171 | } | ||
172 | 150 | ||
173 | case XD3_WINFINISH: | 151 | case XD3_GETSRCBLK: { |
174 | if (encoding) { | 152 | xd3_source *src = (encoding ? &encode_source : &decode_source); |
175 | if (encode_stream.flags & XD3_FLUSH) { | 153 | Block *block = (encoding ? &encode_source_block : &decode_source_block); |
176 | done_after_input = true; | 154 | if (encoding) { |
155 | IF_DEBUG1(XPR(NTR "[srcblock] %"Q"u last srcpos %"Q"u " | ||
156 | "encodepos %"Q"u\n", | ||
157 | encode_source.getblkno, | ||
158 | encode_stream.match_last_srcpos, | ||
159 | encode_stream.input_position + encode_stream.total_in)); | ||
177 | } | 160 | } |
178 | encoding = false; | 161 | |
179 | } else { | 162 | source_iterator.SetBlock(src->getblkno); |
180 | CHECK_EQ(0, CmpDifferentBlockBytesAtOffset(decoded_block, | 163 | source_iterator.Get(block); |
181 | target_file, | 164 | src->curblkno = src->getblkno; |
182 | verified_bytes)); | 165 | src->onblk = block->Size(); |
183 | verified_bytes += decoded_block.Size(); | 166 | src->curblk = block->Data(); |
184 | decoded_block.Reset(); | 167 | |
185 | encoding = true; | 168 | goto process; |
186 | } | 169 | } |
187 | goto process; | ||
188 | 170 | ||
189 | case XD3_WINSTART: | 171 | case XD3_INPUT: |
190 | case XD3_GOTHEADER: | 172 | if (!encoding) { |
191 | goto process; | 173 | encoding = true; |
174 | goto process; | ||
175 | } else { | ||
176 | if (done_after_input) { | ||
177 | done = true; | ||
178 | continue; | ||
179 | } | ||
192 | 180 | ||
193 | default: | 181 | if (target_block.Size() < target_iterator.BlockSize()) { |
194 | XPR(NTR "%s = %s %s\n", encoding ? "E " : " D", | 182 | encoding = false; |
195 | xd3_strerror(ret), | 183 | } else { |
196 | msg == NULL ? "" : msg); | 184 | target_iterator.Next(); |
185 | } | ||
186 | continue; | ||
187 | } | ||
197 | 188 | ||
198 | CHECK_EQ(0, ret); | 189 | case XD3_WINFINISH: |
199 | CHECK_EQ(-1, ret); | 190 | if (encoding) { |
200 | } | 191 | if (encode_stream.flags & XD3_FLUSH) { |
192 | done_after_input = true; | ||
193 | } | ||
194 | encoding = false; | ||
195 | } else { | ||
196 | CHECK_EQ(0, CmpDifferentBlockBytesAtOffset(decoded_block, | ||
197 | target_file, | ||
198 | verified_bytes)); | ||
199 | verified_bytes += decoded_block.Size(); | ||
200 | decoded_block.Reset(); | ||
201 | encoding = true; | ||
202 | } | ||
203 | goto process; | ||
204 | |||
205 | case XD3_WINSTART: | ||
206 | case XD3_GOTHEADER: | ||
207 | goto process; | ||
208 | |||
209 | default: | ||
210 | XPR(NTR "%s = %s %s\n", encoding ? "E " : " D", | ||
211 | xd3_strerror(ret), | ||
212 | msg == NULL ? "" : msg); | ||
213 | |||
214 | CHECK_EQ(0, ret); | ||
215 | CHECK_EQ(-1, ret); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | CHECK_EQ(target_file.Size(), encoded_bytes); | ||
220 | CHECK_EQ(target_file.Size(), verified_bytes); | ||
221 | CHECK_EQ(0, xd3_close_stream(&decode_stream)); | ||
222 | CHECK_EQ(0, xd3_close_stream(&encode_stream)); | ||
223 | xd3_free_stream(&encode_stream); | ||
224 | xd3_free_stream(&decode_stream); | ||
225 | } | ||
226 | |||
227 | void MainEncodeDecode(const TmpFile &source_file, | ||
228 | const TmpFile &target_file, | ||
229 | ExtFile *coded_data, | ||
230 | const Options &options) { | ||
231 | vector<const char*> ecmd; | ||
232 | char buf[16]; | ||
233 | snprintf(buf, sizeof(buf), "-B%"Q"u", options.encode_srcwin_maxsz); | ||
234 | ecmd.push_back("xdelta3"); | ||
235 | ecmd.push_back(buf); | ||
236 | ecmd.push_back("-s"); | ||
237 | ecmd.push_back(source_file.Name()); | ||
238 | ecmd.push_back(target_file.Name()); | ||
239 | ecmd.push_back(coded_data->Name()); | ||
240 | ecmd.push_back(NULL); | ||
241 | |||
242 | CHECK_EQ(0, xd3_main_cmdline(ecmd.size() - 1, | ||
243 | const_cast<char**>(&ecmd[0]))); | ||
244 | |||
245 | vector<const char*> dcmd; | ||
246 | ExtFile recon_file; | ||
247 | dcmd.push_back("xdelta3"); | ||
248 | ecmd.push_back(buf); | ||
249 | dcmd.push_back("-d"); | ||
250 | dcmd.push_back("-s"); | ||
251 | dcmd.push_back(source_file.Name()); | ||
252 | dcmd.push_back(coded_data->Name()); | ||
253 | dcmd.push_back(recon_file.Name()); | ||
254 | dcmd.push_back(NULL); | ||
255 | |||
256 | CHECK_EQ(0, xd3_main_cmdline(dcmd.size() - 1, | ||
257 | const_cast<char**>(&dcmd[0]))); | ||
258 | |||
259 | CHECK_EQ(0, test_compare_files(recon_file.Name(), | ||
260 | target_file.Name())); | ||
201 | } | 261 | } |
202 | 262 | ||
203 | CHECK_EQ(target_file.Size(), encoded_bytes); | 263 | ////////////////////////////////////////////////////////////////////// |
204 | CHECK_EQ(target_file.Size(), verified_bytes); | ||
205 | CHECK_EQ(0, xd3_close_stream(&decode_stream)); | ||
206 | CHECK_EQ(0, xd3_close_stream(&encode_stream)); | ||
207 | xd3_free_stream(&encode_stream); | ||
208 | xd3_free_stream(&decode_stream); | ||
209 | } | ||
210 | |||
211 | ////////////////////////////////////////////////////////////////////// | ||
212 | 264 | ||
213 | void TestRandomNumbers() { | 265 | void TestRandomNumbers() { |
214 | MTRandom rand; | 266 | MTRandom rand; |
215 | int rounds = 1<<20; | 267 | int rounds = 1<<20; |
216 | uint64_t usum = 0; | 268 | uint64_t usum = 0; |
217 | uint64_t esum = 0; | 269 | uint64_t esum = 0; |
218 | 270 | ||
219 | for (int i = 0; i < rounds; i++) { | 271 | for (int i = 0; i < rounds; i++) { |
220 | usum += rand.Rand32(); | 272 | usum += rand.Rand32(); |
221 | esum += rand.ExpRand32(1024); | 273 | esum += rand.ExpRand32(1024); |
222 | } | 274 | } |
223 | 275 | ||
224 | double allowed_error = 0.01; | 276 | double allowed_error = 0.01; |
225 | 277 | ||
226 | uint32_t umean = usum / rounds; | 278 | uint32_t umean = usum / rounds; |
227 | uint32_t emean = esum / rounds; | 279 | uint32_t emean = esum / rounds; |
228 | 280 | ||
229 | uint32_t uexpect = UINT32_MAX / 2; | 281 | uint32_t uexpect = UINT32_MAX / 2; |
230 | uint32_t eexpect = 1024; | 282 | uint32_t eexpect = 1024; |
231 | 283 | ||
232 | if (umean < uexpect * (1.0 - allowed_error) || | 284 | if (umean < uexpect * (1.0 - allowed_error) || |
233 | umean > uexpect * (1.0 + allowed_error)) { | 285 | umean > uexpect * (1.0 + allowed_error)) { |
234 | XPR(NT "uniform mean error: %u != %u\n", umean, uexpect); | 286 | XPR(NT "uniform mean error: %u != %u\n", umean, uexpect); |
235 | abort(); | 287 | abort(); |
@@ -516,7 +568,7 @@ void TestOverwriteMutator() { | |||
516 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE); | 568 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE); |
517 | 569 | ||
518 | ChangeList cl1; | 570 | ChangeList cl1; |
519 | cl1.push_back(Change(Change::OVERWRITE, 10, 0, 20)); | 571 | cl1.push_back(Change(Change::COPYOVER, 10, 0, 20)); |
520 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | 572 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); |
521 | CHECK_EQ(spec0.Size(), spec1.Size()); | 573 | CHECK_EQ(spec0.Size(), spec1.Size()); |
522 | 574 | ||
@@ -530,7 +582,7 @@ void TestOverwriteMutator() { | |||
530 | Constants::BLOCK_SIZE - 30) == 0); | 582 | Constants::BLOCK_SIZE - 30) == 0); |
531 | 583 | ||
532 | cl1.clear(); | 584 | cl1.clear(); |
533 | cl1.push_back(Change(Change::OVERWRITE, 10, 20, (xoff_t)0)); | 585 | cl1.push_back(Change(Change::COPYOVER, 10, 20, (xoff_t)0)); |
534 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | 586 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); |
535 | CHECK_EQ(spec0.Size(), spec1.Size()); | 587 | CHECK_EQ(spec0.Size(), spec1.Size()); |
536 | 588 | ||
@@ -553,13 +605,13 @@ void TestNonBlockingProgress() { | |||
553 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 3); | 605 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 3); |
554 | 606 | ||
555 | // This is a lazy target match | 607 | // This is a lazy target match |
556 | Change ct(Change::OVERWRITE, 22, | 608 | Change ct(Change::COPYOVER, 22, |
557 | Constants::BLOCK_SIZE + 50, | 609 | Constants::BLOCK_SIZE + 50, |
558 | Constants::BLOCK_SIZE + 20); | 610 | Constants::BLOCK_SIZE + 20); |
559 | 611 | ||
560 | // This is a source match just after the block boundary, shorter | 612 | // This is a source match just after the block boundary, shorter |
561 | // than the lazy target match. | 613 | // than the lazy target match. |
562 | Change cs1(Change::OVERWRITE, 16, | 614 | Change cs1(Change::COPYOVER, 16, |
563 | Constants::BLOCK_SIZE + 51, | 615 | Constants::BLOCK_SIZE + 51, |
564 | Constants::BLOCK_SIZE - 1); | 616 | Constants::BLOCK_SIZE - 1); |
565 | 617 | ||
@@ -617,64 +669,108 @@ void TestBlockInMemory() { | |||
617 | CHECK_EQ(spec1.Blocks(Constants::WINDOW_SIZE), delta.Windows()); | 669 | CHECK_EQ(spec1.Blocks(Constants::WINDOW_SIZE), delta.Windows()); |
618 | } | 670 | } |
619 | 671 | ||
620 | void TestFifoCopyDiscipline() { | 672 | void TestHalfBlockCopy() { |
621 | MTRandom rand; | 673 | MTRandom rand; |
622 | FileSpec spec0(&rand); | 674 | FileSpec spec0(&rand); |
623 | FileSpec spec1(&rand); | 675 | FileSpec spec1(&rand); |
624 | 676 | ||
625 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 4); | 677 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 4); |
626 | 678 | ||
627 | // Create a half-block copy, 2.5 blocks apart. With 64-byte blocks, | 679 | // Create a half-block copy, 2.5 blocks apart, from the second half |
628 | // the file in spec0 copies @ 384 from spec1 @ 64. | 680 | // of the source version to the first half of the target version. |
681 | // 0 1 2 3 | ||
682 | // spec0 [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb][ccccc][bbbbb] | ||
683 | // spec1 [aaaaa][ccccc][aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] | ||
629 | ChangeList cl1; | 684 | ChangeList cl1; |
630 | cl1.push_back(Change(Change::MODIFY, | 685 | cl1.push_back(Change(Change::MODIFY, |
631 | Constants::BLOCK_SIZE / 2, | 686 | Constants::BLOCK_SIZE / 2, // size |
632 | 0)); | 687 | 0)); |
633 | cl1.push_back(Change(Change::OVERWRITE, | 688 | cl1.push_back(Change(Change::COPYOVER, |
634 | Constants::BLOCK_SIZE / 2, | 689 | Constants::BLOCK_SIZE / 2, // size |
635 | Constants::BLOCK_SIZE * 3, | 690 | Constants::BLOCK_SIZE * 3, // offset |
636 | Constants::BLOCK_SIZE / 2)); | 691 | Constants::BLOCK_SIZE / 2)); |
637 | cl1.push_back(Change(Change::MODIFY, | 692 | cl1.push_back(Change(Change::MODIFY, |
638 | Constants::BLOCK_SIZE * 3, | 693 | Constants::BLOCK_SIZE * 3, |
639 | Constants::BLOCK_SIZE)); | 694 | Constants::BLOCK_SIZE)); |
640 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | 695 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); |
641 | 696 | ||
642 | Options options1; | 697 | const int onecopy_adds = |
643 | options1.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 4; | 698 | 4 * Constants::BLOCK_SIZE - Constants::BLOCK_SIZE / 2; |
699 | const int nocopy_adds = 4 * Constants::BLOCK_SIZE; | ||
700 | |||
701 | // Note the case b=4 is contrived: the caller should use a single block | ||
702 | // containing the entire source, if possible. | ||
703 | for (int b = 1; b <= 4; b++) | ||
704 | { | ||
705 | Options options; | ||
706 | options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * b; | ||
707 | |||
708 | Block block0; | ||
709 | Block block1; | ||
710 | InMemoryEncodeDecode(spec0, spec1, &block0, options); | ||
711 | InMemoryEncodeDecode(spec1, spec0, &block1, options); | ||
712 | Delta delta0(block0); | ||
713 | Delta delta1(block1); | ||
714 | |||
715 | // The first block never copies from the last source block, by | ||
716 | // design, because if the last source block is available when | ||
717 | // the first target block is ready, the caller is expected to | ||
718 | // use a single block. | ||
719 | CHECK_EQ(nocopy_adds, delta0.AddedBytes()); | ||
720 | if (Constants::BLOCK_SIZE < 8192 || b > 2) | ||
721 | { | ||
722 | // For small-block inputs, the entire file is read into one | ||
723 | // block (the min source window size is 16kB). | ||
724 | // | ||
725 | // For large blocks, at least 3 blocks of source window are | ||
726 | // needed. | ||
727 | CHECK_EQ(onecopy_adds, delta1.AddedBytes()); | ||
728 | } | ||
729 | else | ||
730 | { | ||
731 | // When there are fewer than 3 source blocks. | ||
732 | CHECK_EQ(nocopy_adds, delta1.AddedBytes()); | ||
733 | } | ||
734 | // XPR(NT "0=%zu 1=%zu\n", delta0.AddedBytes(), delta1.AddedBytes()); | ||
735 | } | ||
736 | |||
737 | Options options; | ||
738 | options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 4; | ||
739 | options.block_size = Constants::BLOCK_SIZE * 4; | ||
740 | |||
741 | // Test the whole-buffer case. | ||
742 | Block block0; | ||
644 | Block block1; | 743 | Block block1; |
645 | InMemoryEncodeDecode(spec1, spec0, &block1, options1); | 744 | InMemoryEncodeDecode(spec0, spec1, &block0, options); |
745 | InMemoryEncodeDecode(spec1, spec0, &block1, options); | ||
746 | Delta delta0(block0); | ||
646 | Delta delta1(block1); | 747 | Delta delta1(block1); |
647 | CHECK_EQ(4 * Constants::BLOCK_SIZE - | 748 | // This <= >= are only for blocksize = 512, which has irregular readsize. |
648 | Constants::BLOCK_SIZE / 2, delta1.AddedBytes()); | 749 | CHECK_LE(onecopy_adds, delta0.AddedBytes()); |
649 | 750 | CHECK_GE(onecopy_adds + 1, delta0.AddedBytes()); | |
650 | Options options2; | 751 | |
651 | options2.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 3; | 752 | CHECK_EQ(onecopy_adds, delta1.AddedBytes()); |
652 | Block block2; | 753 | // XPR(NT "0=%zu 1=%zu\n", delta0.AddedBytes(), delta1.AddedBytes()); |
653 | InMemoryEncodeDecode(spec1, spec0, &block2, options2); | ||
654 | Delta delta2(block2); | ||
655 | CHECK_EQ(4 * Constants::BLOCK_SIZE, delta2.AddedBytes()); | ||
656 | } | 754 | } |
657 | 755 | ||
658 | void FourWayMergeTest(const FileSpec &spec0, | 756 | void FourWayMergeTest(const FileSpec &spec0, |
659 | const FileSpec &spec1, | 757 | const FileSpec &spec1, |
660 | const FileSpec &spec2, | 758 | const FileSpec &spec2, |
661 | const FileSpec &spec3) { | 759 | const FileSpec &spec3) { |
662 | Block delta01, delta12, delta23; | 760 | TmpFile f0, f1, f2, f3; |
663 | 761 | ExtFile d01, d12, d23; | |
664 | InMemoryEncodeDecode(spec0, spec1, &delta01); | 762 | Options options; |
665 | InMemoryEncodeDecode(spec1, spec2, &delta12); | 763 | options.encode_srcwin_maxsz = |
666 | InMemoryEncodeDecode(spec2, spec3, &delta23); | 764 | std::max(spec0.Size(), options.encode_srcwin_maxsz); |
667 | |||
668 | TmpFile f0, f1, f2, f3, d01, d12, d23; | ||
669 | 765 | ||
670 | spec0.WriteTmpFile(&f0); | 766 | spec0.WriteTmpFile(&f0); |
671 | spec1.WriteTmpFile(&f1); | 767 | spec1.WriteTmpFile(&f1); |
672 | spec2.WriteTmpFile(&f2); | 768 | spec2.WriteTmpFile(&f2); |
673 | spec2.WriteTmpFile(&f3); | 769 | spec3.WriteTmpFile(&f3); |
674 | 770 | ||
675 | delta01.WriteTmpFile(&d01); | 771 | MainEncodeDecode(f0, f1, &d01, options); |
676 | delta12.WriteTmpFile(&d12); | 772 | MainEncodeDecode(f1, f2, &d12, options); |
677 | delta23.WriteTmpFile(&d23); | 773 | MainEncodeDecode(f2, f3, &d23, options); |
678 | 774 | ||
679 | // Merge 2 | 775 | // Merge 2 |
680 | ExtFile out; | 776 | ExtFile out; |
@@ -687,7 +783,7 @@ void FourWayMergeTest(const FileSpec &spec0, | |||
687 | mcmd.push_back(out.Name()); | 783 | mcmd.push_back(out.Name()); |
688 | mcmd.push_back(NULL); | 784 | mcmd.push_back(NULL); |
689 | 785 | ||
690 | //XPR(NTR "Running one merge: %s\n", CommandToString(mcmd).c_str()); | 786 | // XPR(NTR "Running one merge: %s\n", CommandToString(mcmd).c_str()); |
691 | CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, | 787 | CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, |
692 | const_cast<char**>(&mcmd[0]))); | 788 | const_cast<char**>(&mcmd[0]))); |
693 | 789 | ||
@@ -701,14 +797,46 @@ void FourWayMergeTest(const FileSpec &spec0, | |||
701 | tcmd.push_back(recon.Name()); | 797 | tcmd.push_back(recon.Name()); |
702 | tcmd.push_back(NULL); | 798 | tcmd.push_back(NULL); |
703 | 799 | ||
704 | //XPR(NTR "Running one recon! %s\n", CommandToString(tcmd).c_str()); | 800 | // XPR(NTR "Running one recon! %s\n", CommandToString(tcmd).c_str()); |
705 | CHECK_EQ(0, xd3_main_cmdline(tcmd.size() - 1, | 801 | CHECK_EQ(0, xd3_main_cmdline(tcmd.size() - 1, |
706 | const_cast<char**>(&tcmd[0]))); | 802 | const_cast<char**>(&tcmd[0]))); |
707 | //XPR(NTR "Should equal! %s\n", f2.Name()); | 803 | // XPR(NTR "Should equal! %s\n", f2.Name()); |
708 | 804 | ||
709 | CHECK(recon.EqualsSpec(spec2)); | 805 | CHECK(recon.EqualsSpec(spec2)); |
710 | 806 | ||
711 | /* TODO: we've only done 3-way merges, try 4-way. */ | 807 | // Merge 3 |
808 | ExtFile out3; | ||
809 | vector<const char*> mcmd3; | ||
810 | mcmd3.push_back("xdelta3"); | ||
811 | mcmd3.push_back("merge"); | ||
812 | mcmd3.push_back("-m"); | ||
813 | mcmd3.push_back(d01.Name()); | ||
814 | mcmd3.push_back("-m"); | ||
815 | mcmd3.push_back(d12.Name()); | ||
816 | mcmd3.push_back(d23.Name()); | ||
817 | mcmd3.push_back(out3.Name()); | ||
818 | mcmd3.push_back(NULL); | ||
819 | |||
820 | // XPR(NTR "Running one 3-merge: %s\n", CommandToString(mcmd3).c_str()); | ||
821 | CHECK_EQ(0, xd3_main_cmdline(mcmd3.size() - 1, | ||
822 | const_cast<char**>(&mcmd3[0]))); | ||
823 | |||
824 | ExtFile recon3; | ||
825 | vector<const char*> tcmd3; | ||
826 | tcmd3.push_back("xdelta3"); | ||
827 | tcmd3.push_back("-d"); | ||
828 | tcmd3.push_back("-s"); | ||
829 | tcmd3.push_back(f0.Name()); | ||
830 | tcmd3.push_back(out3.Name()); | ||
831 | tcmd3.push_back(recon3.Name()); | ||
832 | tcmd3.push_back(NULL); | ||
833 | |||
834 | // XPR(NTR "Running one 3-recon %s\n", CommandToString(tcmd3).c_str()); | ||
835 | CHECK_EQ(0, xd3_main_cmdline(tcmd3.size() - 1, | ||
836 | const_cast<char**>(&tcmd3[0]))); | ||
837 | // XPR(NTR "Should equal %s\n", f3.Name()); | ||
838 | |||
839 | CHECK(recon3.EqualsSpec(spec3)); | ||
712 | } | 840 | } |
713 | 841 | ||
714 | void TestMergeCommand1() { | 842 | void TestMergeCommand1() { |
@@ -735,6 +863,7 @@ void TestMergeCommand1() { | |||
735 | 863 | ||
736 | // XPR(NTR "S0 = %lu\n", size0); | 864 | // XPR(NTR "S0 = %lu\n", size0); |
737 | // XPR(NTR "C1 = %lu\n", change1); | 865 | // XPR(NTR "C1 = %lu\n", change1); |
866 | // XPR(NTR "."); | ||
738 | 867 | ||
739 | size_t add1_pos = size0 ? rand.Rand32() % size0 : 0; | 868 | size_t add1_pos = size0 ? rand.Rand32() % size0 : 0; |
740 | size_t del2_pos = size0 ? rand.Rand32() % size0 : 0; | 869 | size_t del2_pos = size0 ? rand.Rand32() % size0 : 0; |
@@ -802,6 +931,7 @@ void TestMergeCommand2() { | |||
802 | // XPR(NTR "S1 = %lu\n", size1); | 931 | // XPR(NTR "S1 = %lu\n", size1); |
803 | // XPR(NTR "S2 = %lu\n", size2); | 932 | // XPR(NTR "S2 = %lu\n", size2); |
804 | // XPR(NTR "S3 = %lu\n", size3); | 933 | // XPR(NTR "S3 = %lu\n", size3); |
934 | // XPR(NTR "."); | ||
805 | 935 | ||
806 | spec0.GenerateFixedSize(size0); | 936 | spec0.GenerateFixedSize(size0); |
807 | 937 | ||
@@ -845,12 +975,13 @@ void UnitTest() { | |||
845 | // These are Xdelta tests. | 975 | // These are Xdelta tests. |
846 | template <class T> | 976 | template <class T> |
847 | void MainTest() { | 977 | void MainTest() { |
848 | XPR(NT "Blocksize: %"Q"u\n", T::BLOCK_SIZE); | 978 | XPR(NT "Blocksize %"Q"u readsize %"Q"u windowsize %"Q"u\n", |
979 | T::BLOCK_SIZE, T::READ_SIZE, T::WINDOW_SIZE); | ||
849 | Regtest<T> regtest; | 980 | Regtest<T> regtest; |
850 | TEST(TestEmptyInMemory); | 981 | TEST(TestEmptyInMemory); |
851 | TEST(TestBlockInMemory); | 982 | TEST(TestBlockInMemory); |
852 | TEST(TestNonBlockingProgress); | 983 | TEST(TestNonBlockingProgress); |
853 | TEST(TestFifoCopyDiscipline); | 984 | TEST(TestHalfBlockCopy); |
854 | TEST(TestMergeCommand1); | 985 | TEST(TestMergeCommand1); |
855 | TEST(TestMergeCommand2); | 986 | TEST(TestMergeCommand2); |
856 | } | 987 | } |
@@ -870,14 +1001,15 @@ int main(int argc, char **argv) | |||
870 | mcmd.push_back("test"); | 1001 | mcmd.push_back("test"); |
871 | mcmd.push_back(NULL); | 1002 | mcmd.push_back(NULL); |
872 | 1003 | ||
873 | CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, | ||
874 | const_cast<char**>(&mcmd[0]))); | ||
875 | |||
876 | UnitTest<SmallBlock>(); | 1004 | UnitTest<SmallBlock>(); |
877 | MainTest<SmallBlock>(); | 1005 | MainTest<SmallBlock>(); |
878 | MainTest<MixedBlock>(); | 1006 | MainTest<MixedBlock>(); |
879 | MainTest<PrimeBlock>(); | 1007 | MainTest<PrimeBlock>(); |
880 | MainTest<OversizeBlock>(); | 1008 | MainTest<OversizeBlock>(); |
881 | MainTest<LargeBlock>(); | 1009 | MainTest<LargeBlock>(); |
1010 | |||
1011 | CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, | ||
1012 | const_cast<char**>(&mcmd[0]))); | ||
1013 | |||
882 | return 0; | 1014 | return 0; |
883 | } | 1015 | } |
diff --git a/xdelta3/xdelta3-internal.h b/xdelta3/xdelta3-internal.h index 13f4a34..8e9e25b 100644 --- a/xdelta3/xdelta3-internal.h +++ b/xdelta3/xdelta3-internal.h | |||
@@ -40,6 +40,7 @@ int main_file_read (main_file *ifile, | |||
40 | const char *msg); | 40 | const char *msg); |
41 | int main_file_write (main_file *ofile, uint8_t *buf, | 41 | int main_file_write (main_file *ofile, uint8_t *buf, |
42 | usize_t size, const char *msg); | 42 | usize_t size, const char *msg); |
43 | int test_compare_files (const char* f0, const char* f1); | ||
43 | usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno); | 44 | usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno); |
44 | xoff_t xd3_source_eof(const xd3_source *src); | 45 | xoff_t xd3_source_eof(const xd3_source *src); |
45 | uint32_t xd3_large_cksum_update (uint32_t cksum, | 46 | uint32_t xd3_large_cksum_update (uint32_t cksum, |
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h index a2ba64f..e9848b6 100644 --- a/xdelta3/xdelta3-test.h +++ b/xdelta3/xdelta3-test.h | |||
@@ -39,7 +39,7 @@ struct mtrand { | |||
39 | uint32_t mt_buffer_[MT_LEN]; | 39 | uint32_t mt_buffer_[MT_LEN]; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | int compare_files (const char* tgt, const char *rec); | 42 | int test_compare_files (const char* tgt, const char *rec); |
43 | void mt_init(mtrand *mt, uint32_t seed); | 43 | void mt_init(mtrand *mt, uint32_t seed); |
44 | uint32_t mt_random (mtrand *mt); | 44 | uint32_t mt_random (mtrand *mt); |
45 | int test_setup (void); | 45 | int test_setup (void); |
@@ -369,7 +369,7 @@ test_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out) | |||
369 | } | 369 | } |
370 | 370 | ||
371 | int | 371 | int |
372 | compare_files (const char* tgt, const char *rec) | 372 | test_compare_files (const char* tgt, const char *rec) |
373 | { | 373 | { |
374 | FILE *orig, *recons; | 374 | FILE *orig, *recons; |
375 | static uint8_t obuf[TESTBUFSIZE], rbuf[TESTBUFSIZE]; | 375 | static uint8_t obuf[TESTBUFSIZE], rbuf[TESTBUFSIZE]; |
@@ -1771,7 +1771,7 @@ test_command_line_arguments (xd3_stream *stream, int ignore) | |||
1771 | } | 1771 | } |
1772 | 1772 | ||
1773 | /* Compare the target file. */ | 1773 | /* Compare the target file. */ |
1774 | if ((ret = compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) | 1774 | if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) |
1775 | { | 1775 | { |
1776 | return ret; | 1776 | return ret; |
1777 | } | 1777 | } |
@@ -1802,12 +1802,12 @@ test_command_line_arguments (xd3_stream *stream, int ignore) | |||
1802 | return XD3_INTERNAL; | 1802 | return XD3_INTERNAL; |
1803 | } | 1803 | } |
1804 | 1804 | ||
1805 | /* Also check that compare_files works. The delta and original should | 1805 | /* Also check that test_compare_files works. The delta and original should |
1806 | * not be identical. */ | 1806 | * not be identical. */ |
1807 | if ((ret = compare_files (TEST_DELTA_FILE, | 1807 | if ((ret = test_compare_files (TEST_DELTA_FILE, |
1808 | TEST_TARGET_FILE)) == 0) | 1808 | TEST_TARGET_FILE)) == 0) |
1809 | { | 1809 | { |
1810 | stream->msg = "broken compare_files"; | 1810 | stream->msg = "broken test_compare_files"; |
1811 | return XD3_INTERNAL; | 1811 | return XD3_INTERNAL; |
1812 | } | 1812 | } |
1813 | 1813 | ||
@@ -2004,7 +2004,7 @@ test_recode_command2 (xd3_stream *stream, int has_source, | |||
2004 | } | 2004 | } |
2005 | 2005 | ||
2006 | /* Now compare. */ | 2006 | /* Now compare. */ |
2007 | if ((ret = compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) | 2007 | if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) |
2008 | { | 2008 | { |
2009 | return ret; | 2009 | return ret; |
2010 | } | 2010 | } |
@@ -2089,7 +2089,7 @@ test_compressed_pipe (xd3_stream *stream, main_extcomp *ext, char* buf, | |||
2089 | return XD3_INTERNAL; | 2089 | return XD3_INTERNAL; |
2090 | } | 2090 | } |
2091 | 2091 | ||
2092 | if ((ret = compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) | 2092 | if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) |
2093 | { | 2093 | { |
2094 | return XD3_INTERNAL; | 2094 | return XD3_INTERNAL; |
2095 | } | 2095 | } |
@@ -2219,7 +2219,7 @@ test_source_decompression (xd3_stream *stream, int ignore) | |||
2219 | snprintf_func (buf, TESTBUFSIZE, "%s -v -dq -R -s%s %s %s", program_name, | 2219 | snprintf_func (buf, TESTBUFSIZE, "%s -v -dq -R -s%s %s %s", program_name, |
2220 | TEST_SOURCE_FILE, TEST_DELTA_FILE, TEST_RECON_FILE); | 2220 | TEST_SOURCE_FILE, TEST_DELTA_FILE, TEST_RECON_FILE); |
2221 | if ((ret = do_cmd (stream, buf))) { return ret; } | 2221 | if ((ret = do_cmd (stream, buf))) { return ret; } |
2222 | if ((ret = compare_files (TEST_COPY_FILE, | 2222 | if ((ret = test_compare_files (TEST_COPY_FILE, |
2223 | TEST_RECON_FILE))) { return ret; } | 2223 | TEST_RECON_FILE))) { return ret; } |
2224 | 2224 | ||
2225 | /* Decode the delta file with recompression, should get a compressed file | 2225 | /* Decode the delta file with recompression, should get a compressed file |
@@ -2230,7 +2230,7 @@ test_source_decompression (xd3_stream *stream, int ignore) | |||
2230 | snprintf_func (buf, TESTBUFSIZE, "%s %s < %s > %s", ext->decomp_cmdname, ext->decomp_options, | 2230 | snprintf_func (buf, TESTBUFSIZE, "%s %s < %s > %s", ext->decomp_cmdname, ext->decomp_options, |
2231 | TEST_RECON_FILE, TEST_RECON2_FILE); | 2231 | TEST_RECON_FILE, TEST_RECON2_FILE); |
2232 | if ((ret = do_cmd (stream, buf))) { return ret; } | 2232 | if ((ret = do_cmd (stream, buf))) { return ret; } |
2233 | if ((ret = compare_files (TEST_COPY_FILE, | 2233 | if ((ret = test_compare_files (TEST_COPY_FILE, |
2234 | TEST_RECON2_FILE))) { return ret; } | 2234 | TEST_RECON2_FILE))) { return ret; } |
2235 | 2235 | ||
2236 | /* Encode with decompression disabled */ | 2236 | /* Encode with decompression disabled */ |
@@ -2243,7 +2243,7 @@ test_source_decompression (xd3_stream *stream, int ignore) | |||
2243 | snprintf_func (buf, TESTBUFSIZE, "%s -d -D -vfq -s%s %s %s", program_name, | 2243 | snprintf_func (buf, TESTBUFSIZE, "%s -d -D -vfq -s%s %s %s", program_name, |
2244 | TEST_SOURCE_FILE, TEST_DELTA_FILE, TEST_RECON_FILE); | 2244 | TEST_SOURCE_FILE, TEST_DELTA_FILE, TEST_RECON_FILE); |
2245 | if ((ret = do_cmd (stream, buf))) { return ret; } | 2245 | if ((ret = do_cmd (stream, buf))) { return ret; } |
2246 | if ((ret = compare_files (TEST_TARGET_FILE, | 2246 | if ((ret = test_compare_files (TEST_TARGET_FILE, |
2247 | TEST_RECON_FILE))) { return ret; } | 2247 | TEST_RECON_FILE))) { return ret; } |
2248 | 2248 | ||
2249 | test_cleanup(); | 2249 | test_cleanup(); |
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c index 608622a..3e1bc14 100644 --- a/xdelta3/xdelta3.c +++ b/xdelta3/xdelta3.c | |||
@@ -1127,7 +1127,8 @@ xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_ri | |||
1127 | * it cannot be an add. This check is more clear. */ | 1127 | * it cannot be an add. This check is more clear. */ |
1128 | if (prev_mode >= 0 && inst->size <= desc->copyadd_add_max) | 1128 | if (prev_mode >= 0 && inst->size <= desc->copyadd_add_max) |
1129 | { | 1129 | { |
1130 | const xd3_code_table_sizes *sizes = & desc->copyadd_max_sizes[prev_mode]; | 1130 | const xd3_code_table_sizes *sizes = |
1131 | & desc->copyadd_max_sizes[prev_mode]; | ||
1131 | 1132 | ||
1132 | /* This check and the inst->size-<= above are == in | 1133 | /* This check and the inst->size-<= above are == in |
1133 | the default table. */ | 1134 | the default table. */ |
@@ -5079,12 +5080,10 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point) | |||
5079 | * small inputs, especially when the content may have moved anywhere | 5080 | * small inputs, especially when the content may have moved anywhere |
5080 | * in the file (e.g., tar files). | 5081 | * in the file (e.g., tar files). |
5081 | * | 5082 | * |
5082 | * if (src->size > src->max_winsize), index at least one block (which | 5083 | * if (src->size > src->max_winsize), index at least one block ahead |
5083 | * the command-line sets to 1/32 of src->max_winsize) ahead of the | 5084 | * of the logical position. This is good for different reasons: |
5084 | * logical position. This is good for different reasons: when a | 5085 | * when a long match spanning several source blocks is encountered, |
5085 | * long match spanning several source blocks is encountered, this | 5086 | * this avoids computing checksums for those blocks. |
5086 | * avoids computing checksums for those blocks. If the data can | ||
5087 | * move anywhere, this is bad. | ||
5088 | */ | 5087 | */ |
5089 | logical_input_cksum_pos += stream->src->blksize; | 5088 | logical_input_cksum_pos += stream->src->blksize; |
5090 | 5089 | ||