1 // SPDX-License-Identifier: 0BSD
3 ///////////////////////////////////////////////////////////////////////////////
5 /// \file test_index_hash.c
6 /// \brief Tests src/liblzma/common/index_hash.c API functions
8 /// \note No test included for lzma_index_hash_end since it
9 /// would be trivial unless tested for memory leaks
10 /// with something like valgrind
14 ///////////////////////////////////////////////////////////////////////////////
18 // Needed for UNPADDED_SIZE_MIN and UNPADDED_SIZE_MAX macro definitions
19 // and index_size and vli_ceil4 helper functions
20 #include "common/index.h"
24 test_lzma_index_hash_init(void)
27 assert_skip("Decoder support disabled");
29 // First test with NULL index_hash.
30 // This should create a fresh index_hash.
31 lzma_index_hash
*index_hash
= lzma_index_hash_init(NULL
, NULL
);
32 assert_true(index_hash
!= NULL
);
34 // Next test with non-NULL index_hash.
35 lzma_index_hash
*second_hash
= lzma_index_hash_init(index_hash
, NULL
);
37 // It should not create a new index_hash pointer.
38 // Instead it must just re-init the first index_hash.
39 assert_true(index_hash
== second_hash
);
41 lzma_index_hash_end(index_hash
, NULL
);
47 test_lzma_index_hash_append(void)
50 assert_skip("Decoder support disabled");
52 // Test all invalid parameters
53 assert_lzma_ret(lzma_index_hash_append(NULL
, 0, 0),
56 // Test NULL index_hash
57 assert_lzma_ret(lzma_index_hash_append(NULL
, UNPADDED_SIZE_MIN
,
58 LZMA_VLI_MAX
), LZMA_PROG_ERROR
);
60 // Test with invalid Unpadded Size
61 lzma_index_hash
*index_hash
= lzma_index_hash_init(NULL
, NULL
);
62 assert_true(index_hash
!= NULL
);
63 assert_lzma_ret(lzma_index_hash_append(index_hash
,
64 UNPADDED_SIZE_MIN
- 1, LZMA_VLI_MAX
),
67 // Test with invalid Uncompressed Size
68 assert_lzma_ret(lzma_index_hash_append(index_hash
,
69 UNPADDED_SIZE_MIN
, LZMA_VLI_MAX
+ 1),
72 // First append a Record describing a small Block.
73 // This should succeed.
74 assert_lzma_ret(lzma_index_hash_append(index_hash
,
75 UNPADDED_SIZE_MIN
, 1), LZMA_OK
);
77 // Append another small Record.
78 assert_lzma_ret(lzma_index_hash_append(index_hash
,
79 UNPADDED_SIZE_MIN
, 1), LZMA_OK
);
81 // Append a Record that would cause the compressed size to grow
83 assert_lzma_ret(lzma_index_hash_append(index_hash
,
84 UNPADDED_SIZE_MAX
, 1), LZMA_DATA_ERROR
);
86 lzma_index_hash_end(index_hash
, NULL
);
91 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
92 // Fill an index_hash with unpadded and uncompressed VLIs
93 // by calling lzma_index_hash_append
95 fill_index_hash(lzma_index_hash
*index_hash
, const lzma_vli
*unpadded_sizes
,
96 const lzma_vli
*uncomp_sizes
, uint32_t block_count
)
98 for (uint32_t i
= 0; i
< block_count
; ++i
)
99 assert_lzma_ret(lzma_index_hash_append(index_hash
,
100 unpadded_sizes
[i
], uncomp_sizes
[i
]), LZMA_OK
);
104 // Set the contents of buf to the expected Index based on the
105 // .xz specification. This needs the unpadded and uncompressed VLIs
106 // to correctly create the Index.
108 generate_index(uint8_t *buf
, const lzma_vli
*unpadded_sizes
,
109 const lzma_vli
*uncomp_sizes
, uint32_t block_count
,
110 size_t index_max_size
)
115 // First set Index Indicator
116 buf
[out_pos
++] = INDEX_INDICATOR
;
118 // Next write out Number of Records
119 assert_lzma_ret(lzma_vli_encode(block_count
, &in_pos
, buf
,
120 &out_pos
, index_max_size
), LZMA_STREAM_END
);
122 // Next write out each Record.
123 // A Record consists of Unpadded Size and Uncompressed Size
124 // written next to each other as VLIs.
125 for (uint32_t i
= 0; i
< block_count
; ++i
) {
127 assert_lzma_ret(lzma_vli_encode(unpadded_sizes
[i
], &in_pos
,
128 buf
, &out_pos
, index_max_size
), LZMA_STREAM_END
);
130 assert_lzma_ret(lzma_vli_encode(uncomp_sizes
[i
], &in_pos
,
131 buf
, &out_pos
, index_max_size
), LZMA_STREAM_END
);
135 lzma_vli rounded_out_pos
= vli_ceil4(out_pos
);
136 memzero(buf
+ out_pos
, rounded_out_pos
- out_pos
);
137 out_pos
= rounded_out_pos
;
140 write32le(buf
+ out_pos
, lzma_crc32(buf
, out_pos
, 0));
143 assert_uint_eq(out_pos
, index_max_size
);
149 test_lzma_index_hash_decode(void)
151 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
152 assert_skip("Encoder or decoder support disabled");
154 lzma_index_hash
*index_hash
= lzma_index_hash_init(NULL
, NULL
);
155 assert_true(index_hash
!= NULL
);
159 // Six valid values for the Unpadded Size fields in an Index
160 const lzma_vli unpadded_sizes
[6] = {
169 // Six valid values for the Uncompressed Size fields in an Index
170 const lzma_vli uncomp_sizes
[6] = {
179 // Add two Records to an index_hash
180 fill_index_hash(index_hash
, unpadded_sizes
, uncomp_sizes
, 2);
182 const lzma_vli size_two_records
= lzma_index_hash_size(index_hash
);
183 assert_uint(size_two_records
, >, 0);
184 uint8_t *index_two_records
= tuktest_malloc(size_two_records
);
186 generate_index(index_two_records
, unpadded_sizes
, uncomp_sizes
, 2,
189 // First test for basic buffer size error
190 in_pos
= size_two_records
+ 1;
191 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
192 index_two_records
, &in_pos
,
193 size_two_records
), LZMA_BUF_ERROR
);
195 // Next test for invalid Index Indicator
197 index_two_records
[0] ^= 1;
198 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
199 index_two_records
, &in_pos
,
200 size_two_records
), LZMA_DATA_ERROR
);
201 index_two_records
[0] ^= 1;
203 // Next verify the index_hash as expected
205 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
206 index_two_records
, &in_pos
,
207 size_two_records
), LZMA_STREAM_END
);
209 // Next test an index_hash with three Records
210 index_hash
= lzma_index_hash_init(index_hash
, NULL
);
211 fill_index_hash(index_hash
, unpadded_sizes
, uncomp_sizes
, 3);
213 const lzma_vli size_three_records
= lzma_index_hash_size(
215 assert_uint(size_three_records
, >, 0);
216 uint8_t *index_three_records
= tuktest_malloc(size_three_records
);
218 generate_index(index_three_records
, unpadded_sizes
, uncomp_sizes
,
219 3, size_three_records
);
222 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
223 index_three_records
, &in_pos
,
224 size_three_records
), LZMA_STREAM_END
);
226 // Next test an index_hash with five Records
227 index_hash
= lzma_index_hash_init(index_hash
, NULL
);
228 fill_index_hash(index_hash
, unpadded_sizes
, uncomp_sizes
, 5);
230 const lzma_vli size_five_records
= lzma_index_hash_size(
232 assert_uint(size_five_records
, >, 0);
233 uint8_t *index_five_records
= tuktest_malloc(size_five_records
);
235 generate_index(index_five_records
, unpadded_sizes
, uncomp_sizes
, 5,
238 // Instead of testing all input at once, give input
239 // one byte at a time
241 for (lzma_vli i
= 0; i
< size_five_records
- 1; ++i
) {
242 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
243 index_five_records
, &in_pos
, in_pos
+ 1),
247 // Last byte should return LZMA_STREAM_END
248 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
249 index_five_records
, &in_pos
,
250 in_pos
+ 1), LZMA_STREAM_END
);
252 // Next test if the index_hash is given an incorrect Unpadded
253 // Size. Should detect and report LZMA_DATA_ERROR
254 index_hash
= lzma_index_hash_init(index_hash
, NULL
);
255 fill_index_hash(index_hash
, unpadded_sizes
, uncomp_sizes
, 5);
256 // The sixth Record will have an invalid Unpadded Size
257 assert_lzma_ret(lzma_index_hash_append(index_hash
,
258 unpadded_sizes
[5] + 1,
259 uncomp_sizes
[5]), LZMA_OK
);
261 const lzma_vli size_six_records
= lzma_index_hash_size(
264 assert_uint(size_six_records
, >, 0);
265 uint8_t *index_six_records
= tuktest_malloc(size_six_records
);
267 generate_index(index_six_records
, unpadded_sizes
, uncomp_sizes
, 6,
270 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
271 index_six_records
, &in_pos
,
272 size_six_records
), LZMA_DATA_ERROR
);
274 // Next test if the Index is corrupt (invalid CRC32).
275 // Should detect and report LZMA_DATA_ERROR
276 index_hash
= lzma_index_hash_init(index_hash
, NULL
);
277 fill_index_hash(index_hash
, unpadded_sizes
, uncomp_sizes
, 2);
279 index_two_records
[size_two_records
- 1] ^= 1;
282 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
283 index_two_records
, &in_pos
,
284 size_two_records
), LZMA_DATA_ERROR
);
286 // Next test with Index and index_hash struct not matching
288 index_hash
= lzma_index_hash_init(index_hash
, NULL
);
289 fill_index_hash(index_hash
, unpadded_sizes
, uncomp_sizes
, 2);
290 // Recalculate Index with invalid Unpadded Size
291 const lzma_vli unpadded_sizes_invalid
[2] = {
293 unpadded_sizes
[1] + 1
296 generate_index(index_two_records
, unpadded_sizes_invalid
,
297 uncomp_sizes
, 2, size_two_records
);
300 assert_lzma_ret(lzma_index_hash_decode(index_hash
,
301 index_two_records
, &in_pos
,
302 size_two_records
), LZMA_DATA_ERROR
);
304 lzma_index_hash_end(index_hash
, NULL
);
310 test_lzma_index_hash_size(void)
312 #ifndef HAVE_DECODERS
313 assert_skip("Decoder support disabled");
315 lzma_index_hash
*index_hash
= lzma_index_hash_init(NULL
, NULL
);
316 assert_true(index_hash
!= NULL
);
318 // First test empty index_hash
319 // Expected size should be:
320 // Index Indicator - 1 byte
321 // Number of Records - 1 byte
322 // List of Records - 0 bytes
323 // Index Padding - 2 bytes
326 assert_uint_eq(lzma_index_hash_size(index_hash
), 8);
328 // Append a Record describing a small Block to the index_hash
329 assert_lzma_ret(lzma_index_hash_append(index_hash
,
330 UNPADDED_SIZE_MIN
, 1), LZMA_OK
);
332 // Expected size should be:
333 // Index Indicator - 1 byte
334 // Number of Records - 1 byte
335 // List of Records - 2 bytes
336 // Index Padding - 0 bytes
339 lzma_vli expected_size
= 8;
340 assert_uint_eq(lzma_index_hash_size(index_hash
), expected_size
);
342 // Append additional small Record
343 assert_lzma_ret(lzma_index_hash_append(index_hash
,
344 UNPADDED_SIZE_MIN
, 1), LZMA_OK
);
346 // Expected size should be:
347 // Index Indicator - 1 byte
348 // Number of Records - 1 byte
349 // List of Records - 4 bytes
350 // Index Padding - 2 bytes
354 assert_uint_eq(lzma_index_hash_size(index_hash
), expected_size
);
356 // Append a larger Record to the index_hash (3 bytes for each VLI)
357 const lzma_vli three_byte_vli
= 0x10000;
358 assert_lzma_ret(lzma_index_hash_append(index_hash
,
359 three_byte_vli
, three_byte_vli
), LZMA_OK
);
361 // Expected size should be:
362 // Index Indicator - 1 byte
363 // Number of Records - 1 byte
364 // List of Records - 10 bytes
365 // Index Padding - 0 bytes
369 assert_uint_eq(lzma_index_hash_size(index_hash
), expected_size
);
371 lzma_index_hash_end(index_hash
, NULL
);
377 main(int argc
, char **argv
)
379 tuktest_start(argc
, argv
);
380 tuktest_run(test_lzma_index_hash_init
);
381 tuktest_run(test_lzma_index_hash_append
);
382 tuktest_run(test_lzma_index_hash_decode
);
383 tuktest_run(test_lzma_index_hash_size
);
384 return tuktest_end();