Doc: Rename Doxygen HTML doc directory name liblzma => api.
[xz/debian.git] / tests / test_stream_flags.c
blob2248e67ab3b45909c028206634ab96036836a9ad
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file test_stream_flags.c
4 /// \brief Tests Stream Header and Stream Footer coders
5 //
6 // Authors: Jia Tan
7 // Lasse Collin
8 //
9 // This file has been put into the public domain.
10 // You can do whatever you want with this file.
12 ///////////////////////////////////////////////////////////////////////////////
14 #include "tests.h"
17 // Size of the Stream Flags field
18 // (taken from src/liblzma/common/stream_flags_common.h)
19 #define XZ_STREAM_FLAGS_SIZE 2
21 #ifdef HAVE_ENCODERS
22 // Header and footer magic bytes for .xz file format
23 // (taken from src/liblzma/common/stream_flags_common.c)
24 static const uint8_t xz_header_magic[6]
25 = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
26 static const uint8_t xz_footer_magic[2] = { 0x59, 0x5A };
27 #endif
30 #ifdef HAVE_ENCODERS
31 static void
32 stream_header_encode_helper(lzma_check check)
34 lzma_stream_flags flags = {
35 .version = 0,
36 .check = check,
39 uint8_t header[LZMA_STREAM_HEADER_SIZE];
41 // Encode Stream Header
42 assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
44 // Stream Header must start with Header Magic Bytes
45 const uint32_t magic_size = sizeof(xz_header_magic);
46 assert_array_eq(header, xz_header_magic, magic_size);
48 // Next must come Stream Flags
49 const uint8_t *encoded_stream_flags = header + magic_size;
51 // First byte is always null-byte.
52 // Second byte must have the Check ID in the lowest four bits
53 // and the highest four bits zero.
54 const uint8_t expected_stream_flags[] = { 0, check };
55 assert_array_eq(encoded_stream_flags, expected_stream_flags,
56 XZ_STREAM_FLAGS_SIZE);
58 // Last part is the CRC32 of the Stream Flags
59 const uint8_t *crc_ptr = encoded_stream_flags + XZ_STREAM_FLAGS_SIZE;
60 const uint32_t expected_crc = lzma_crc32(expected_stream_flags,
61 XZ_STREAM_FLAGS_SIZE, 0);
62 assert_uint_eq(read32le(crc_ptr), expected_crc);
64 #endif
67 static void
68 test_lzma_stream_header_encode(void)
70 #ifndef HAVE_ENCODERS
71 assert_skip("Encoder support disabled");
72 #else
73 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
74 stream_header_encode_helper(i);
76 lzma_stream_flags flags = {
77 .version = 0,
78 .check = LZMA_CHECK_CRC32
81 uint8_t header[LZMA_STREAM_HEADER_SIZE];
83 // Should fail if version > 0
84 flags.version = 1;
85 assert_lzma_ret(lzma_stream_header_encode(&flags, header),
86 LZMA_OPTIONS_ERROR);
87 flags.version = 0;
89 // Should fail if Check ID is invalid
90 flags.check = INVALID_LZMA_CHECK_ID;
91 assert_lzma_ret(lzma_stream_header_encode(&flags, header),
92 LZMA_PROG_ERROR);
93 flags.check = LZMA_CHECK_CRC32;
95 // Should pass even if Backward Size is invalid
96 // because Stream Header doesn't have that field.
97 flags.backward_size = LZMA_VLI_MAX + 1;
98 assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
99 #endif
103 #if defined(HAVE_ENCODERS)
104 static void
105 stream_footer_encode_helper(lzma_check check)
107 lzma_stream_flags flags = {
108 .version = 0,
109 .check = check,
110 .backward_size = LZMA_BACKWARD_SIZE_MIN,
113 uint8_t footer[LZMA_STREAM_HEADER_SIZE];
115 // Encode Stream Footer
116 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
118 // Stream Footer must start with CRC32
119 const uint32_t crc = read32le(footer);
120 const uint32_t expected_crc = lzma_crc32(footer + sizeof(uint32_t),
121 LZMA_STREAM_HEADER_SIZE - (sizeof(uint32_t) +
122 sizeof(xz_footer_magic)), 0);
123 assert_uint_eq(crc, expected_crc);
125 // Next the Backward Size
126 const uint32_t backwards_size = read32le(footer + sizeof(uint32_t));
127 const uint32_t expected_backwards_size = flags.backward_size / 4 - 1;
128 assert_uint_eq(backwards_size, expected_backwards_size);
130 // Next the Stream Flags
131 const uint8_t *stream_flags = footer + sizeof(uint32_t) * 2;
133 // First byte must be null
134 assert_uint_eq(stream_flags[0], 0);
136 // Second byte must have the Check ID in the lowest four bits
137 // and the highest four bits zero.
138 assert_uint_eq(stream_flags[1], check);
140 // And ends with Footer Magic Bytes
141 const uint8_t *expected_footer_magic = stream_flags +
142 XZ_STREAM_FLAGS_SIZE;
143 assert_array_eq(expected_footer_magic, xz_footer_magic,
144 sizeof(xz_footer_magic));
146 #endif
149 static void
150 test_lzma_stream_footer_encode(void)
152 #ifndef HAVE_ENCODERS
153 assert_skip("Encoder support disabled");
154 #else
155 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
156 stream_footer_encode_helper(i);
158 lzma_stream_flags flags = {
159 .version = 0,
160 .backward_size = LZMA_BACKWARD_SIZE_MIN,
161 .check = LZMA_CHECK_CRC32
164 uint8_t footer[LZMA_STREAM_HEADER_SIZE];
166 // Should fail if version > 0
167 flags.version = 1;
168 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
169 LZMA_OPTIONS_ERROR);
170 flags.version = 0;
172 // Should fail if Check ID is invalid
173 flags.check = INVALID_LZMA_CHECK_ID;
174 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
175 LZMA_PROG_ERROR);
177 // Should fail if Backward Size is invalid
178 flags.backward_size -= 1;
179 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
180 LZMA_PROG_ERROR);
181 flags.backward_size += 2;
182 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
183 LZMA_PROG_ERROR);
184 flags.backward_size = LZMA_BACKWARD_SIZE_MAX + 4;
185 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
186 LZMA_PROG_ERROR);
187 #endif
191 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
192 static void
193 stream_header_decode_helper(lzma_check check)
195 lzma_stream_flags flags = {
196 .version = 0,
197 .check = check
200 uint8_t header[LZMA_STREAM_HEADER_SIZE];
202 assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
204 lzma_stream_flags dest_flags;
205 assert_lzma_ret(lzma_stream_header_decode(&dest_flags, header),
206 LZMA_OK);
208 // Version should be 0
209 assert_uint_eq(dest_flags.version, 0);
211 // Backward Size should be LZMA_VLI_UNKNOWN
212 assert_uint_eq(dest_flags.backward_size, LZMA_VLI_UNKNOWN);
214 // Check ID must equal the argument given to this function.
215 assert_uint_eq(dest_flags.check, check);
217 #endif
220 static void
221 test_lzma_stream_header_decode(void)
223 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
224 assert_skip("Encoder or decoder support disabled");
225 #else
226 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
227 stream_header_decode_helper(i);
229 lzma_stream_flags flags = {
230 .version = 0,
231 .check = LZMA_CHECK_CRC32
234 uint8_t header[LZMA_STREAM_HEADER_SIZE];
235 lzma_stream_flags dest;
237 // First encode known flags to header buffer
238 assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
240 // Should fail if magic bytes do not match
241 header[0] ^= 1;
242 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
243 LZMA_FORMAT_ERROR);
244 header[0] ^= 1;
246 // Should fail if a reserved bit is set
247 uint8_t *stream_flags = header + sizeof(xz_header_magic);
248 stream_flags[0] = 1;
250 // Need to adjust CRC32 after making a change since the CRC32
251 // is verified before decoding the Stream Flags field.
252 uint8_t *crc32_ptr = header + sizeof(xz_header_magic)
253 + XZ_STREAM_FLAGS_SIZE;
254 const uint32_t crc_orig = read32le(crc32_ptr);
255 uint32_t new_crc32 = lzma_crc32(
256 stream_flags, XZ_STREAM_FLAGS_SIZE, 0);
257 write32le(crc32_ptr, new_crc32);
258 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
259 LZMA_OPTIONS_ERROR);
260 stream_flags[0] = 0;
261 write32le(crc32_ptr, crc_orig);
263 // Should fail if upper bits of check ID are set
264 stream_flags[1] |= 0xF0;
265 new_crc32 = lzma_crc32(stream_flags, XZ_STREAM_FLAGS_SIZE, 0);
266 write32le(crc32_ptr, new_crc32);
267 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
268 LZMA_OPTIONS_ERROR);
269 stream_flags[1] = flags.check;
270 write32le(crc32_ptr, crc_orig);
272 // Should fail if CRC32 does not match.
273 // First, alter a byte in the Stream Flags.
274 stream_flags[0] = 1;
275 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
276 LZMA_DATA_ERROR);
277 stream_flags[0] = 0;
279 // Next, change the CRC32.
280 *crc32_ptr ^= 1;
281 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
282 LZMA_DATA_ERROR);
283 #endif
287 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
288 static void
289 stream_footer_decode_helper(lzma_check check)
291 lzma_stream_flags flags = {
292 .version = 0,
293 .backward_size = LZMA_BACKWARD_SIZE_MIN,
294 .check = check,
297 uint8_t footer[LZMA_STREAM_HEADER_SIZE];
298 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
300 lzma_stream_flags dest_flags;
301 assert_lzma_ret(lzma_stream_footer_decode(&dest_flags, footer),
302 LZMA_OK);
304 // Version should be 0.
305 assert_uint_eq(dest_flags.version, 0);
307 // Backward Size should equal the value from the flags.
308 assert_uint_eq(dest_flags.backward_size, flags.backward_size);
310 // Check ID must equal argument given to this function.
311 assert_uint_eq(dest_flags.check, check);
313 #endif
316 static void
317 test_lzma_stream_footer_decode(void)
319 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
320 assert_skip("Encoder or decoder support disabled");
321 #else
322 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
323 stream_footer_decode_helper(i);
325 lzma_stream_flags flags = {
326 .version = 0,
327 .check = LZMA_CHECK_CRC32,
328 .backward_size = LZMA_BACKWARD_SIZE_MIN
331 uint8_t footer[LZMA_STREAM_HEADER_SIZE];
332 lzma_stream_flags dest;
334 // First encode known flags to the footer buffer
335 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
337 // Should fail if magic bytes do not match
338 footer[LZMA_STREAM_HEADER_SIZE - 1] ^= 1;
339 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
340 LZMA_FORMAT_ERROR);
341 footer[LZMA_STREAM_HEADER_SIZE - 1] ^= 1;
343 // Should fail if a reserved bit is set.
344 // In the Stream Footer, the Stream Flags follow the CRC32 (4 bytes)
345 // and the Backward Size (4 bytes)
346 uint8_t *stream_flags = footer + sizeof(uint32_t) * 2;
347 stream_flags[0] = 1;
349 // Need to adjust the CRC32 so it will not fail that check instead
350 uint8_t *crc32_ptr = footer;
351 const uint32_t crc_orig = read32le(crc32_ptr);
352 uint8_t *backward_size = footer + sizeof(uint32_t);
353 uint32_t new_crc32 = lzma_crc32(backward_size, sizeof(uint32_t) +
354 XZ_STREAM_FLAGS_SIZE, 0);
355 write32le(crc32_ptr, new_crc32);
356 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
357 LZMA_OPTIONS_ERROR);
358 stream_flags[0] = 0;
359 write32le(crc32_ptr, crc_orig);
361 // Should fail if upper bits of check ID are set
362 stream_flags[1] |= 0xF0;
363 new_crc32 = lzma_crc32(backward_size, sizeof(uint32_t) +
364 XZ_STREAM_FLAGS_SIZE, 0);
365 write32le(crc32_ptr, new_crc32);
366 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
367 LZMA_OPTIONS_ERROR);
368 stream_flags[1] = flags.check;
369 write32le(crc32_ptr, crc_orig);
371 // Should fail if CRC32 does not match.
372 // First, alter a byte in the Stream Flags.
373 stream_flags[0] = 1;
374 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
375 LZMA_DATA_ERROR);
376 stream_flags[0] = 0;
378 // Next, change the CRC32
379 *crc32_ptr ^= 1;
380 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
381 LZMA_DATA_ERROR);
382 #endif
386 static void
387 test_lzma_stream_flags_compare(void)
389 lzma_stream_flags first = {
390 .version = 0,
391 .backward_size = LZMA_BACKWARD_SIZE_MIN,
392 .check = LZMA_CHECK_CRC32,
395 lzma_stream_flags second = first;
397 // First test should pass
398 assert_lzma_ret(lzma_stream_flags_compare(&first, &second), LZMA_OK);
400 // Altering either version should cause an error
401 first.version = 1;
402 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
403 LZMA_OPTIONS_ERROR);
404 second.version = 1;
405 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
406 LZMA_OPTIONS_ERROR);
407 first.version = 0;
408 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
409 LZMA_OPTIONS_ERROR);
410 second.version = 0;
412 // Check types must be under the maximum
413 first.check = INVALID_LZMA_CHECK_ID;
414 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
415 LZMA_PROG_ERROR);
416 second.check = INVALID_LZMA_CHECK_ID;
417 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
418 LZMA_PROG_ERROR);
419 first.check = LZMA_CHECK_CRC32;
420 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
421 LZMA_PROG_ERROR);
422 second.check = LZMA_CHECK_CRC32;
424 // Check types must be equal
425 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++) {
426 first.check = i;
427 if (i == second.check)
428 assert_lzma_ret(lzma_stream_flags_compare(&first,
429 &second), LZMA_OK);
430 else
431 assert_lzma_ret(lzma_stream_flags_compare(&first,
432 &second), LZMA_DATA_ERROR);
434 first.check = LZMA_CHECK_CRC32;
436 // Backward Size comparison is skipped if either are LZMA_VLI_UNKNOWN
437 first.backward_size = LZMA_VLI_UNKNOWN;
438 assert_lzma_ret(lzma_stream_flags_compare(&first, &second), LZMA_OK);
439 second.backward_size = LZMA_VLI_MAX + 1;
440 assert_lzma_ret(lzma_stream_flags_compare(&first, &second), LZMA_OK);
441 second.backward_size = LZMA_BACKWARD_SIZE_MIN;
443 // Backward Sizes need to be valid
444 first.backward_size = LZMA_VLI_MAX + 4;
445 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
446 LZMA_PROG_ERROR);
447 second.backward_size = LZMA_VLI_MAX + 4;
448 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
449 LZMA_PROG_ERROR);
450 first.backward_size = LZMA_BACKWARD_SIZE_MIN;
451 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
452 LZMA_PROG_ERROR);
453 second.backward_size = LZMA_BACKWARD_SIZE_MIN;
455 // Backward Sizes must be equal
456 second.backward_size = first.backward_size + 4;
457 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
458 LZMA_DATA_ERROR);
460 // Should fail if Backward Sizes are > LZMA_BACKWARD_SIZE_MAX
461 // even though they are equal
462 first.backward_size = LZMA_BACKWARD_SIZE_MAX + 1;
463 second.backward_size = LZMA_BACKWARD_SIZE_MAX + 1;
464 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
465 LZMA_PROG_ERROR);
469 extern int
470 main(int argc, char **argv)
472 tuktest_start(argc, argv);
473 tuktest_run(test_lzma_stream_header_encode);
474 tuktest_run(test_lzma_stream_footer_encode);
475 tuktest_run(test_lzma_stream_header_decode);
476 tuktest_run(test_lzma_stream_footer_decode);
477 tuktest_run(test_lzma_stream_flags_compare);
478 return tuktest_end();