1 ///////////////////////////////////////////////////////////////////////////////
4 /// \brief Tests functions handling the lzma_index structure
6 // Author: Lasse Collin
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
11 ///////////////////////////////////////////////////////////////////////////////
15 #define MEMLIMIT (LZMA_VLI_C(1) << 20)
18 #define BIG_COUNT 5555
24 lzma_index
*i
= lzma_index_init(NULL
);
33 lzma_index
*i
= lzma_index_init(NULL
);
35 expect(lzma_index_append(i
, NULL
, 101, 555) == LZMA_OK
);
36 expect(lzma_index_append(i
, NULL
, 602, 777) == LZMA_OK
);
37 expect(lzma_index_append(i
, NULL
, 804, 999) == LZMA_OK
);
45 lzma_index
*i
= lzma_index_init(NULL
);
48 lzma_vli total_size
= 0;
49 lzma_vli uncompressed_size
= 0;
51 // Add pseudo-random sizes (but always the same size values).
53 for (size_t j
= 0; j
< BIG_COUNT
; ++j
) {
55 const uint32_t t
= n
* 3011;
56 expect(lzma_index_append(i
, NULL
, t
, n
) == LZMA_OK
);
57 total_size
+= (t
+ 3) & ~LZMA_VLI_C(3);
58 uncompressed_size
+= n
;
61 expect(lzma_index_block_count(i
) == BIG_COUNT
);
62 expect(lzma_index_total_size(i
) == total_size
);
63 expect(lzma_index_uncompressed_size(i
) == uncompressed_size
);
64 expect(lzma_index_total_size(i
) + lzma_index_size(i
)
65 + 2 * LZMA_STREAM_HEADER_SIZE
66 == lzma_index_stream_size(i
));
73 is_equal(const lzma_index
*a
, const lzma_index
*b
)
75 // Compare only the Stream and Block sizes and offsets.
76 lzma_index_iter ra
, rb
;
77 lzma_index_iter_init(&ra
, a
);
78 lzma_index_iter_init(&rb
, b
);
81 bool reta
= lzma_index_iter_next(&ra
, LZMA_INDEX_ITER_ANY
);
82 bool retb
= lzma_index_iter_next(&rb
, LZMA_INDEX_ITER_ANY
);
84 return !(reta
^ retb
);
86 if (ra
.stream
.number
!= rb
.stream
.number
87 || ra
.stream
.block_count
88 != rb
.stream
.block_count
89 || ra
.stream
.compressed_offset
90 != rb
.stream
.compressed_offset
91 || ra
.stream
.uncompressed_offset
92 != rb
.stream
.uncompressed_offset
93 || ra
.stream
.compressed_size
94 != rb
.stream
.compressed_size
95 || ra
.stream
.uncompressed_size
96 != rb
.stream
.uncompressed_size
101 if (ra
.stream
.block_count
== 0)
104 if (ra
.block
.number_in_file
!= rb
.block
.number_in_file
105 || ra
.block
.compressed_file_offset
106 != rb
.block
.compressed_file_offset
107 || ra
.block
.uncompressed_file_offset
108 != rb
.block
.uncompressed_file_offset
109 || ra
.block
.number_in_stream
110 != rb
.block
.number_in_stream
111 || ra
.block
.compressed_stream_offset
112 != rb
.block
.compressed_stream_offset
113 || ra
.block
.uncompressed_stream_offset
114 != rb
.block
.uncompressed_stream_offset
115 || ra
.block
.uncompressed_size
116 != rb
.block
.uncompressed_size
117 || ra
.block
.unpadded_size
118 != rb
.block
.unpadded_size
119 || ra
.block
.total_size
120 != rb
.block
.total_size
)
129 lzma_index
*a
= create_empty();
130 lzma_index
*b
= create_small();
131 lzma_index
*c
= create_big();
134 expect(is_equal(a
, a
));
135 expect(is_equal(b
, b
));
136 expect(is_equal(c
, c
));
138 expect(!is_equal(a
, b
));
139 expect(!is_equal(a
, c
));
140 expect(!is_equal(b
, c
));
142 lzma_index_end(a
, NULL
);
143 lzma_index_end(b
, NULL
);
144 lzma_index_end(c
, NULL
);
151 // Integer overflow tests
152 lzma_index
*i
= create_empty();
154 expect(lzma_index_append(i
, NULL
, LZMA_VLI_MAX
- 5, 1234)
159 lzma_index_end(i
, NULL
);
164 test_copy(const lzma_index
*i
)
166 lzma_index
*d
= lzma_index_dup(i
, NULL
);
168 expect(is_equal(i
, d
));
169 lzma_index_end(d
, NULL
);
174 test_read(lzma_index
*i
)
177 lzma_index_iter_init(&r
, i
);
179 // Try twice so we see that rewinding works.
180 for (size_t j
= 0; j
< 2; ++j
) {
181 lzma_vli total_size
= 0;
182 lzma_vli uncompressed_size
= 0;
183 lzma_vli stream_offset
= LZMA_STREAM_HEADER_SIZE
;
184 lzma_vli uncompressed_offset
= 0;
187 while (!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
)) {
190 total_size
+= r
.block
.total_size
;
191 uncompressed_size
+= r
.block
.uncompressed_size
;
193 expect(r
.block
.compressed_file_offset
195 expect(r
.block
.uncompressed_file_offset
196 == uncompressed_offset
);
198 stream_offset
+= r
.block
.total_size
;
199 uncompressed_offset
+= r
.block
.uncompressed_size
;
202 expect(lzma_index_total_size(i
) == total_size
);
203 expect(lzma_index_uncompressed_size(i
) == uncompressed_size
);
204 expect(lzma_index_block_count(i
) == count
);
206 lzma_index_iter_rewind(&r
);
212 test_code(lzma_index
*i
)
214 const size_t alloc_size
= 128 * 1024;
215 uint8_t *buf
= malloc(alloc_size
);
219 lzma_stream strm
= LZMA_STREAM_INIT
;
220 expect(lzma_index_encoder(&strm
, i
) == LZMA_OK
);
221 const lzma_vli index_size
= lzma_index_size(i
);
222 succeed(coder_loop(&strm
, NULL
, 0, buf
, index_size
,
223 LZMA_STREAM_END
, LZMA_RUN
));
227 expect(lzma_index_decoder(&strm
, &d
, MEMLIMIT
) == LZMA_OK
);
229 succeed(decoder_loop(&strm
, buf
, index_size
));
231 expect(is_equal(i
, d
));
233 lzma_index_end(d
, NULL
);
236 // Decode with hashing
237 lzma_index_hash
*h
= lzma_index_hash_init(NULL
, NULL
);
240 lzma_index_iter_init(&r
, i
);
241 while (!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
))
242 expect(lzma_index_hash_append(h
, r
.block
.unpadded_size
,
243 r
.block
.uncompressed_size
) == LZMA_OK
);
245 while (pos
< index_size
- 1)
246 expect(lzma_index_hash_decode(h
, buf
, &pos
, pos
+ 1)
248 expect(lzma_index_hash_decode(h
, buf
, &pos
, pos
+ 1)
251 lzma_index_hash_end(h
, NULL
);
255 expect(lzma_index_buffer_encode(i
, buf
, &buf_pos
, index_size
)
257 expect(buf_pos
== 1);
259 succeed(lzma_index_buffer_encode(i
, buf
, &buf_pos
, index_size
+ 1));
260 expect(buf_pos
== index_size
+ 1);
264 uint64_t memlimit
= MEMLIMIT
;
265 expect(lzma_index_buffer_decode(&d
, &memlimit
, NULL
, buf
, &buf_pos
,
266 index_size
) == LZMA_DATA_ERROR
);
267 expect(buf_pos
== 1);
270 succeed(lzma_index_buffer_decode(&d
, &memlimit
, NULL
, buf
, &buf_pos
,
272 expect(buf_pos
== index_size
+ 1);
273 expect(is_equal(i
, d
));
275 lzma_index_end(d
, NULL
);
282 test_many(lzma_index
*i
)
293 lzma_index
*a
, *b
, *c
;
299 expect(lzma_index_cat(a
, b
, NULL
) == LZMA_OK
);
300 expect(lzma_index_block_count(a
) == 0);
301 expect(lzma_index_stream_size(a
) == 2 * LZMA_STREAM_HEADER_SIZE
+ 8);
302 expect(lzma_index_file_size(a
)
303 == 2 * (2 * LZMA_STREAM_HEADER_SIZE
+ 8));
304 lzma_index_iter_init(&r
, a
);
305 expect(lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
));
308 expect(lzma_index_cat(a
, b
, NULL
) == LZMA_OK
);
309 expect(lzma_index_block_count(a
) == 0);
310 expect(lzma_index_stream_size(a
) == 2 * LZMA_STREAM_HEADER_SIZE
+ 8);
311 expect(lzma_index_file_size(a
)
312 == 3 * (2 * LZMA_STREAM_HEADER_SIZE
+ 8));
316 expect(lzma_index_stream_padding(b
, 4) == LZMA_OK
);
317 expect(lzma_index_cat(b
, c
, NULL
) == LZMA_OK
);
318 expect(lzma_index_block_count(b
) == 0);
319 expect(lzma_index_stream_size(b
) == 2 * LZMA_STREAM_HEADER_SIZE
+ 8);
320 expect(lzma_index_file_size(b
)
321 == 2 * (2 * LZMA_STREAM_HEADER_SIZE
+ 8) + 4);
323 expect(lzma_index_stream_padding(a
, 8) == LZMA_OK
);
324 expect(lzma_index_cat(a
, b
, NULL
) == LZMA_OK
);
325 expect(lzma_index_block_count(a
) == 0);
326 expect(lzma_index_stream_size(a
) == 2 * LZMA_STREAM_HEADER_SIZE
+ 8);
327 expect(lzma_index_file_size(a
)
328 == 5 * (2 * LZMA_STREAM_HEADER_SIZE
+ 8) + 4 + 8);
330 expect(lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
));
331 lzma_index_iter_rewind(&r
);
332 expect(lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
));
333 lzma_index_end(a
, NULL
);
337 lzma_vli stream_size
= lzma_index_stream_size(a
);
338 lzma_index_iter_init(&r
, a
);
339 for (int i
= SMALL_COUNT
; i
>= 0; --i
)
340 expect(!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
)
344 expect(lzma_index_stream_padding(a
, 4) == LZMA_OK
);
345 expect(lzma_index_cat(a
, b
, NULL
) == LZMA_OK
);
346 expect(lzma_index_file_size(a
) == stream_size
* 2 + 4);
347 expect(lzma_index_stream_size(a
) > stream_size
);
348 expect(lzma_index_stream_size(a
) < stream_size
* 2);
349 for (int i
= SMALL_COUNT
; i
>= 0; --i
)
350 expect(!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
)
353 lzma_index_iter_rewind(&r
);
354 for (int i
= SMALL_COUNT
* 2; i
>= 0; --i
)
355 expect(!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
)
360 expect(lzma_index_stream_padding(b
, 8) == LZMA_OK
);
361 expect(lzma_index_cat(b
, c
, NULL
) == LZMA_OK
);
362 expect(lzma_index_stream_padding(a
, 12) == LZMA_OK
);
363 expect(lzma_index_cat(a
, b
, NULL
) == LZMA_OK
);
364 expect(lzma_index_file_size(a
) == stream_size
* 4 + 4 + 8 + 12);
366 expect(lzma_index_block_count(a
) == SMALL_COUNT
* 4);
367 for (int i
= SMALL_COUNT
* 2; i
>= 0; --i
)
368 expect(!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
)
371 lzma_index_iter_rewind(&r
);
372 for (int i
= SMALL_COUNT
* 4; i
>= 0; --i
)
373 expect(!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
)
376 lzma_index_end(a
, NULL
);
378 // Mix of empty and small
381 expect(lzma_index_stream_padding(a
, 4) == LZMA_OK
);
382 expect(lzma_index_cat(a
, b
, NULL
) == LZMA_OK
);
383 lzma_index_iter_init(&r
, a
);
384 for (int i
= SMALL_COUNT
; i
>= 0; --i
)
385 expect(!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
)
388 lzma_index_end(a
, NULL
);
392 stream_size
= lzma_index_stream_size(a
);
394 expect(lzma_index_stream_padding(a
, 4) == LZMA_OK
);
395 expect(lzma_index_cat(a
, b
, NULL
) == LZMA_OK
);
396 expect(lzma_index_file_size(a
) == stream_size
* 2 + 4);
397 expect(lzma_index_stream_size(a
) > stream_size
);
398 expect(lzma_index_stream_size(a
) < stream_size
* 2);
402 expect(lzma_index_stream_padding(b
, 8) == LZMA_OK
);
403 expect(lzma_index_cat(b
, c
, NULL
) == LZMA_OK
);
404 expect(lzma_index_stream_padding(a
, 12) == LZMA_OK
);
405 expect(lzma_index_cat(a
, b
, NULL
) == LZMA_OK
);
406 expect(lzma_index_file_size(a
) == stream_size
* 4 + 4 + 8 + 12);
408 lzma_index_iter_init(&r
, a
);
409 for (int i
= BIG_COUNT
* 4; i
>= 0; --i
)
410 expect(!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
)
413 lzma_index_end(a
, NULL
);
420 lzma_index
*i
= lzma_index_init(NULL
);
423 lzma_index_iter_init(&r
, i
);
425 // Cannot locate anything from an empty Index.
426 expect(lzma_index_iter_locate(&r
, 0));
427 expect(lzma_index_iter_locate(&r
, 555));
429 // One empty Record: nothing is found since there's no uncompressed
431 expect(lzma_index_append(i
, NULL
, 16, 0) == LZMA_OK
);
432 expect(lzma_index_iter_locate(&r
, 0));
434 // Non-empty Record and we can find something.
435 expect(lzma_index_append(i
, NULL
, 32, 5) == LZMA_OK
);
436 expect(!lzma_index_iter_locate(&r
, 0));
437 expect(r
.block
.total_size
== 32);
438 expect(r
.block
.uncompressed_size
== 5);
439 expect(r
.block
.compressed_file_offset
440 == LZMA_STREAM_HEADER_SIZE
+ 16);
441 expect(r
.block
.uncompressed_file_offset
== 0);
443 // Still cannot find anything past the end.
444 expect(lzma_index_iter_locate(&r
, 5));
446 // Add the third Record.
447 expect(lzma_index_append(i
, NULL
, 40, 11) == LZMA_OK
);
449 expect(!lzma_index_iter_locate(&r
, 0));
450 expect(r
.block
.total_size
== 32);
451 expect(r
.block
.uncompressed_size
== 5);
452 expect(r
.block
.compressed_file_offset
453 == LZMA_STREAM_HEADER_SIZE
+ 16);
454 expect(r
.block
.uncompressed_file_offset
== 0);
456 expect(!lzma_index_iter_next(&r
, LZMA_INDEX_ITER_BLOCK
));
457 expect(r
.block
.total_size
== 40);
458 expect(r
.block
.uncompressed_size
== 11);
459 expect(r
.block
.compressed_file_offset
460 == LZMA_STREAM_HEADER_SIZE
+ 16 + 32);
461 expect(r
.block
.uncompressed_file_offset
== 5);
463 expect(!lzma_index_iter_locate(&r
, 2));
464 expect(r
.block
.total_size
== 32);
465 expect(r
.block
.uncompressed_size
== 5);
466 expect(r
.block
.compressed_file_offset
467 == LZMA_STREAM_HEADER_SIZE
+ 16);
468 expect(r
.block
.uncompressed_file_offset
== 0);
470 expect(!lzma_index_iter_locate(&r
, 5));
471 expect(r
.block
.total_size
== 40);
472 expect(r
.block
.uncompressed_size
== 11);
473 expect(r
.block
.compressed_file_offset
474 == LZMA_STREAM_HEADER_SIZE
+ 16 + 32);
475 expect(r
.block
.uncompressed_file_offset
== 5);
477 expect(!lzma_index_iter_locate(&r
, 5 + 11 - 1));
478 expect(r
.block
.total_size
== 40);
479 expect(r
.block
.uncompressed_size
== 11);
480 expect(r
.block
.compressed_file_offset
481 == LZMA_STREAM_HEADER_SIZE
+ 16 + 32);
482 expect(r
.block
.uncompressed_file_offset
== 5);
484 expect(lzma_index_iter_locate(&r
, 5 + 11));
485 expect(lzma_index_iter_locate(&r
, 5 + 15));
488 lzma_index_end(i
, NULL
);
489 i
= lzma_index_init(NULL
);
491 lzma_index_iter_init(&r
, i
);
493 for (size_t n
= 4; n
<= 4 * 5555; n
+= 4)
494 expect(lzma_index_append(i
, NULL
, n
+ 8, n
) == LZMA_OK
);
496 expect(lzma_index_block_count(i
) == 5555);
499 expect(!lzma_index_iter_locate(&r
, 0));
500 expect(r
.block
.total_size
== 4 + 8);
501 expect(r
.block
.uncompressed_size
== 4);
502 expect(r
.block
.compressed_file_offset
== LZMA_STREAM_HEADER_SIZE
);
503 expect(r
.block
.uncompressed_file_offset
== 0);
505 expect(!lzma_index_iter_locate(&r
, 3));
506 expect(r
.block
.total_size
== 4 + 8);
507 expect(r
.block
.uncompressed_size
== 4);
508 expect(r
.block
.compressed_file_offset
== LZMA_STREAM_HEADER_SIZE
);
509 expect(r
.block
.uncompressed_file_offset
== 0);
512 expect(!lzma_index_iter_locate(&r
, 4));
513 expect(r
.block
.total_size
== 2 * 4 + 8);
514 expect(r
.block
.uncompressed_size
== 2 * 4);
515 expect(r
.block
.compressed_file_offset
516 == LZMA_STREAM_HEADER_SIZE
+ 4 + 8);
517 expect(r
.block
.uncompressed_file_offset
== 4);
520 expect(!lzma_index_iter_locate(
521 &r
, lzma_index_uncompressed_size(i
) - 1));
522 expect(r
.block
.total_size
== 4 * 5555 + 8);
523 expect(r
.block
.uncompressed_size
== 4 * 5555);
524 expect(r
.block
.compressed_file_offset
== lzma_index_total_size(i
)
525 + LZMA_STREAM_HEADER_SIZE
- 4 * 5555 - 8);
526 expect(r
.block
.uncompressed_file_offset
527 == lzma_index_uncompressed_size(i
) - 4 * 5555);
529 // Allocation chunk boundaries. See INDEX_GROUP_SIZE in
530 // liblzma/common/index.c.
531 const size_t group_multiple
= 256 * 4;
532 const size_t radius
= 8;
533 const size_t start
= group_multiple
- radius
;
537 for (n
= 1; n
< start
; ++n
) {
542 while (n
< start
+ 2 * radius
) {
543 expect(!lzma_index_iter_locate(&r
, ubase
+ n
* 4));
545 expect(r
.block
.compressed_file_offset
== tbase
+ n
* 4 + 8
546 + LZMA_STREAM_HEADER_SIZE
);
547 expect(r
.block
.uncompressed_file_offset
== ubase
+ n
* 4);
553 expect(r
.block
.total_size
== n
* 4 + 8);
554 expect(r
.block
.uncompressed_size
== n
* 4);
557 // Do it also backwards.
559 expect(!lzma_index_iter_locate(&r
, ubase
+ (n
- 1) * 4));
561 expect(r
.block
.total_size
== n
* 4 + 8);
562 expect(r
.block
.uncompressed_size
== n
* 4);
568 expect(r
.block
.compressed_file_offset
== tbase
+ n
* 4 + 8
569 + LZMA_STREAM_HEADER_SIZE
);
570 expect(r
.block
.uncompressed_file_offset
== ubase
+ n
* 4);
573 // Test locating in concatenated Index.
574 lzma_index_end(i
, NULL
);
575 i
= lzma_index_init(NULL
);
577 lzma_index_iter_init(&r
, i
);
578 for (n
= 0; n
< group_multiple
; ++n
)
579 expect(lzma_index_append(i
, NULL
, 8, 0) == LZMA_OK
);
580 expect(lzma_index_append(i
, NULL
, 16, 1) == LZMA_OK
);
581 expect(!lzma_index_iter_locate(&r
, 0));
582 expect(r
.block
.total_size
== 16);
583 expect(r
.block
.uncompressed_size
== 1);
584 expect(r
.block
.compressed_file_offset
585 == LZMA_STREAM_HEADER_SIZE
+ group_multiple
* 8);
586 expect(r
.block
.uncompressed_file_offset
== 0);
588 lzma_index_end(i
, NULL
);
595 const size_t alloc_size
= 128 * 1024;
596 uint8_t *buf
= malloc(alloc_size
);
598 lzma_stream strm
= LZMA_STREAM_INIT
;
600 lzma_index
*i
= create_empty();
601 expect(lzma_index_append(i
, NULL
, 0, 1) == LZMA_PROG_ERROR
);
602 lzma_index_end(i
, NULL
);
604 // Create a valid Index and corrupt it in different ways.
606 expect(lzma_index_encoder(&strm
, i
) == LZMA_OK
);
607 succeed(coder_loop(&strm
, NULL
, 0, buf
, 20,
608 LZMA_STREAM_END
, LZMA_RUN
));
609 lzma_index_end(i
, NULL
);
611 // Wrong Index Indicator
613 expect(lzma_index_decoder(&strm
, &i
, MEMLIMIT
) == LZMA_OK
);
614 succeed(decoder_loop_ret(&strm
, buf
, 1, LZMA_DATA_ERROR
));
617 // Wrong Number of Records and thus CRC32 fails.
619 expect(lzma_index_decoder(&strm
, &i
, MEMLIMIT
) == LZMA_OK
);
620 succeed(decoder_loop_ret(&strm
, buf
, 10, LZMA_DATA_ERROR
));
625 expect(lzma_index_decoder(&strm
, &i
, MEMLIMIT
) == LZMA_OK
);
626 succeed(decoder_loop_ret(&strm
, buf
, 16, LZMA_DATA_ERROR
));
640 lzma_index
*i
= create_empty();
642 lzma_index_end(i
, NULL
);
646 lzma_index_end(i
, NULL
);
650 lzma_index_end(i
, NULL
);