diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 43 | ||||
-rw-r--r-- | tests/test_block.c | 59 | ||||
-rw-r--r-- | tests/test_block_header.c | 352 | ||||
-rw-r--r-- | tests/test_check.c | 90 | ||||
-rw-r--r-- | tests/test_filter_flags.c | 326 | ||||
-rw-r--r-- | tests/test_index.c | 43 | ||||
-rw-r--r-- | tests/test_info.c | 717 | ||||
-rw-r--r-- | tests/test_stream_flags.c | 191 | ||||
-rw-r--r-- | tests/tests.h | 148 |
9 files changed, 1969 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..30392390 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,43 @@ +## +## Copyright (C) 2007 Lasse Collin +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## + +EXTRA_DIST = files tests.h + +AM_CPPFLAGS = \ + -I@top_srcdir@/src/common \ + -I@top_srcdir@/src/liblzma/api \ + -I@top_builddir@/lib + +LDADD = @top_builddir@/src/liblzma/liblzma.la + +if COND_GNULIB +LDADD += @top_builddir/lib/libgnu.a +endif + +check_PROGRAMS = \ + test_check \ + test_stream_flags \ + test_filter_flags \ + test_block_header \ + test_index \ + test_info + +test_check_SOURCES = test_check.c +test_stream_flags_SOURCES = test_stream_flags.c +test_filter_flags_SOURCES = test_filter_flags.c +test_block_header_SOURCES = test_block_header.c +test_index_SOURCES = test_index.c +test_info_SOURCES = test_info.c + +TESTS = $(check_PROGRAMS) diff --git a/tests/test_block.c b/tests/test_block.c new file mode 100644 index 00000000..89063b93 --- /dev/null +++ b/tests/test_block.c @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_block.c +/// \brief Tests Block coders +// +// Copyright (C) 2007 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +static uint8_t text[] = "Hello world!"; +static uint8_t buffer[4096]; +static lzma_options_block block_options; +static lzma_stream strm = LZMA_STREAM_INIT; + + +static void +test1(void) +{ + +} + + +int +main() +{ + lzma_init(); + + block_options = (lzma_options_block){ + .check_type = LZMA_CHECK_NONE, + .has_eopm = true, + .has_uncompressed_size_in_footer = false, + .has_backward_size = false, + .handle_padding = false, + .total_size = LZMA_VLI_VALUE_UNKNOWN, + .compressed_size = LZMA_VLI_VALUE_UNKNOWN, + .uncompressed_size = LZMA_VLI_VALUE_UNKNOWN, + .header_size = 5, + }; + block_options.filters[0].id = LZMA_VLI_VALUE_UNKNOWN; + block_options.filters[0].options = NULL; + + + lzma_end(&strm); + + return 0; +} diff --git a/tests/test_block_header.c b/tests/test_block_header.c new file mode 100644 index 00000000..c6767e38 --- /dev/null +++ b/tests/test_block_header.c @@ -0,0 +1,352 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_block_header.c +/// \brief Tests Block Header coders +// +// Copyright (C) 2007 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +static uint8_t buffer[4096]; +static lzma_stream strm = LZMA_STREAM_INIT; +static lzma_options_block known_options; +static lzma_options_block decoded_options; + +// We want to test zero, one, and two filters in the chain. + +static const lzma_options_filter filters_none[1] = { + { + .id = LZMA_VLI_VALUE_UNKNOWN, + .options = NULL, + }, +}; + +static const lzma_options_filter filters_powerpc[2] = { + { + .id = LZMA_FILTER_POWERPC, + .options = NULL, + }, { + .id = LZMA_VLI_VALUE_UNKNOWN, + .options = NULL, + }, +}; + +static const lzma_options_delta options_delta = { + .distance = 4, +}; + +static const lzma_options_filter filters_delta[3] = { + { + .id = LZMA_FILTER_DELTA, + .options = (void *)(&options_delta), + }, { + .id = LZMA_FILTER_COPY, + .options = NULL, + }, { + .id = LZMA_VLI_VALUE_UNKNOWN, + .options = NULL, + }, +}; + + +static bool +encode(uint32_t header_size) +{ + memcrap(buffer, sizeof(buffer)); + + if (lzma_block_header_size(&known_options) != LZMA_OK) + return true; + + if (known_options.header_size != header_size) + return true; + + if (lzma_block_header_encode(buffer, &known_options) != LZMA_OK) + return true; + + return false; +} + + +static bool +decode_ret(uint32_t header_size, lzma_ret ret_ok) +{ + memcrap(&decoded_options, sizeof(decoded_options)); + decoded_options.has_crc32 = known_options.has_crc32; + + expect(lzma_block_header_decoder(&strm, &decoded_options) == LZMA_OK); + + return decoder_loop_ret(&strm, buffer, header_size, ret_ok); +} + + +static bool +decode(uint32_t header_size) +{ + memcrap(&decoded_options, sizeof(decoded_options)); + decoded_options.has_crc32 = known_options.has_crc32; + + expect(lzma_block_header_decoder(&strm, &decoded_options) == LZMA_OK); + + if (decoder_loop(&strm, buffer, header_size)) + return true; + + if (known_options.has_eopm != decoded_options.has_eopm) + return true; + + if (known_options.is_metadata != decoded_options.is_metadata) + return true; + + if (known_options.compressed_size == LZMA_VLI_VALUE_UNKNOWN + && known_options.compressed_reserve != 0) { + if (decoded_options.compressed_size != 0) + return true; + } else if (known_options.compressed_size + != decoded_options.compressed_size) { + return true; + } + + if (known_options.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN + && known_options.uncompressed_reserve != 0) { + if (decoded_options.uncompressed_size != 0) + return true; + } else if (known_options.uncompressed_size + != decoded_options.uncompressed_size) { + return true; + } + + if (known_options.compressed_reserve != 0 + && known_options.compressed_reserve + != decoded_options.compressed_reserve) + return true; + + if (known_options.uncompressed_reserve != 0 + && known_options.uncompressed_reserve + != decoded_options.uncompressed_reserve) + return true; + + if (known_options.padding != decoded_options.padding) + return true; + + return false; +} + + +static bool +code(uint32_t header_size) +{ + return encode(header_size) || decode(header_size); +} + + +static bool +helper_loop(uint32_t unpadded_size, uint32_t multiple) +{ + for (int i = 0; i <= LZMA_BLOCK_HEADER_PADDING_MAX; ++i) { + known_options.padding = i; + if (code(unpadded_size + i)) + return true; + } + + for (int i = 0 - LZMA_BLOCK_HEADER_PADDING_MAX - 1; + i <= LZMA_BLOCK_HEADER_PADDING_MAX + 1; ++i) { + known_options.alignment = i; + + uint32_t size = unpadded_size; + while ((size + known_options.alignment) % multiple) + ++size; + + known_options.padding = LZMA_BLOCK_HEADER_PADDING_AUTO; + if (code(size)) + return true; + + } while (++known_options.alignment + <= LZMA_BLOCK_HEADER_PADDING_MAX + 1); + + return false; +} + + +static bool +helper(uint32_t unpadded_size, uint32_t multiple) +{ + known_options.has_crc32 = false; + known_options.is_metadata = false; + if (helper_loop(unpadded_size, multiple)) + return true; + + known_options.has_crc32 = false; + known_options.is_metadata = true; + if (helper_loop(unpadded_size, multiple)) + return true; + + known_options.has_crc32 = true; + known_options.is_metadata = false; + if (helper_loop(unpadded_size + 4, multiple)) + return true; + + known_options.has_crc32 = true; + known_options.is_metadata = true; + if (helper_loop(unpadded_size + 4, multiple)) + return true; + + return false; +} + + +static void +test1(void) +{ + known_options = (lzma_options_block){ + .has_eopm = true, + .compressed_size = LZMA_VLI_VALUE_UNKNOWN, + .uncompressed_size = LZMA_VLI_VALUE_UNKNOWN, + .compressed_reserve = 0, + .uncompressed_reserve = 0, + }; + memcpy(known_options.filters, filters_none, sizeof(filters_none)); + expect(!helper(2, 1)); + + memcpy(known_options.filters, filters_powerpc, + sizeof(filters_powerpc)); + expect(!helper(3, 4)); + + memcpy(known_options.filters, filters_delta, sizeof(filters_delta)); + expect(!helper(5, 1)); + + known_options.padding = LZMA_BLOCK_HEADER_PADDING_MAX + 1; + expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); +} + + +static void +test2_helper(uint32_t unpadded_size, uint32_t multiple) +{ + known_options.has_eopm = true; + known_options.compressed_size = LZMA_VLI_VALUE_UNKNOWN; + known_options.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN; + known_options.compressed_reserve = 1; + known_options.uncompressed_reserve = 1; + expect(!helper(unpadded_size + 2, multiple)); + + known_options.compressed_reserve = LZMA_VLI_BYTES_MAX; + known_options.uncompressed_reserve = LZMA_VLI_BYTES_MAX; + expect(!helper(unpadded_size + 18, multiple)); + + known_options.compressed_size = 1234; + known_options.uncompressed_size = 2345; + expect(!helper(unpadded_size + 18, multiple)); + + known_options.compressed_reserve = 1; + known_options.uncompressed_reserve = 1; + expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); +} + + +static void +test2(void) +{ + memcpy(known_options.filters, filters_none, sizeof(filters_none)); + test2_helper(2, 1); + + memcpy(known_options.filters, filters_powerpc, + sizeof(filters_powerpc)); + test2_helper(3, 4); + + memcpy(known_options.filters, filters_delta, + sizeof(filters_delta)); + test2_helper(5, 1); +} + + +static void +test3(void) +{ + known_options = (lzma_options_block){ + .has_crc32 = false, + .has_eopm = true, + .is_metadata = false, + .is_metadata = false, + .compressed_size = LZMA_VLI_VALUE_UNKNOWN, + .uncompressed_size = LZMA_VLI_VALUE_UNKNOWN, + .compressed_reserve = 1, + .uncompressed_reserve = 1, + }; + memcpy(known_options.filters, filters_none, sizeof(filters_none)); + + known_options.header_size = 3; + expect(lzma_block_header_encode(buffer, &known_options) + == LZMA_PROG_ERROR); + + known_options.header_size = 4; + expect(lzma_block_header_encode(buffer, &known_options) == LZMA_OK); + + known_options.header_size = 5; + expect(lzma_block_header_encode(buffer, &known_options) + == LZMA_PROG_ERROR); + + // NOTE: This assumes that Filter ID 0x1F is not supported. Update + // this test to use some other ID if 0x1F becomes supported. + known_options.filters[0].id = 0x1F; + known_options.header_size = 5; + expect(lzma_block_header_encode(buffer, &known_options) + == LZMA_HEADER_ERROR); +} + + +static void +test4(void) +{ + known_options = (lzma_options_block){ + .has_crc32 = false, + .has_eopm = true, + .is_metadata = false, + .compressed_size = 0, + .uncompressed_size = 0, + .compressed_reserve = LZMA_VLI_BYTES_MAX, + .uncompressed_reserve = LZMA_VLI_BYTES_MAX, + .padding = 0, + }; + memcpy(known_options.filters, filters_powerpc, + sizeof(filters_powerpc)); + expect(!code(21)); + + // Reserved bits + buffer[0] ^= 0x40; + expect(!decode_ret(1, LZMA_HEADER_ERROR)); + buffer[0] ^= 0x40; + + buffer[1] ^= 0x40; + expect(decode_ret(21, LZMA_HEADER_ERROR)); + buffer[1] ^= 0x40; + + +} + + +int +main() +{ + lzma_init(); + + test1(); + test2(); + test3(); + test4(); + + lzma_end(&strm); + + return 0; +} diff --git a/tests/test_check.c b/tests/test_check.c new file mode 100644 index 00000000..14df375a --- /dev/null +++ b/tests/test_check.c @@ -0,0 +1,90 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_check.c +/// \brief Tests integrity checks +/// +/// \todo Add SHA256 +// +// Copyright (C) 2007 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +static const uint8_t test_string[9] = "123456789"; +static const uint8_t test_unaligned[12] = "xxx123456789"; + + +static bool +test_crc32(void) +{ + static const uint32_t test_vector = 0xCBF43926; + + // Test 1 + uint32_t crc = lzma_crc32(test_string, sizeof(test_string), 0); + if (crc != test_vector) + return true; + + // Test 2 + crc = lzma_crc32(test_unaligned + 3, sizeof(test_string), 0); + if (crc != test_vector) + return true; + + // Test 3 + crc = 0; + for (size_t i = 0; i < sizeof(test_string); ++i) + crc = lzma_crc32(test_string + i, 1, crc); + if (crc != test_vector) + return true; + + return false; +} + + +static bool +test_crc64(void) +{ + static const uint64_t test_vector = 0x995DC9BBDF1939FA; + + // Test 1 + uint64_t crc = lzma_crc64(test_string, sizeof(test_string), 0); + if (crc != test_vector) + return true; + + // Test 2 + crc = lzma_crc64(test_unaligned + 3, sizeof(test_string), 0); + if (crc != test_vector) + return true; + + // Test 3 + crc = 0; + for (size_t i = 0; i < sizeof(test_string); ++i) + crc = lzma_crc64(test_string + i, 1, crc); + if (crc != test_vector) + return true; + + return false; +} + + +int +main() +{ + bool error = false; + + error |= test_crc32(); + error |= test_crc64(); + + return error ? 1 : 0; +} diff --git a/tests/test_filter_flags.c b/tests/test_filter_flags.c new file mode 100644 index 00000000..0a16f21a --- /dev/null +++ b/tests/test_filter_flags.c @@ -0,0 +1,326 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_filter_flags.c +/// \brief Tests Filter Flags coders +// +// Copyright (C) 2007 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +static uint8_t buffer[4096]; +static lzma_options_filter known_flags; +static lzma_options_filter decoded_flags; +static lzma_stream strm = LZMA_STREAM_INIT; + + +static bool +encode(uint32_t known_size) +{ + memcrap(buffer, sizeof(buffer)); + + uint32_t tmp; + if (lzma_filter_flags_size(&tmp, &known_flags) != LZMA_OK) + return true; + + if (tmp != known_size) + return true; + + size_t out_pos = 0; + if (lzma_filter_flags_encode(buffer, &out_pos, known_size, + &known_flags) != LZMA_OK) + return true; + + if (out_pos != known_size) + return true; + + return false; +} + + +static bool +decode_ret(uint32_t known_size, lzma_ret ret_ok) +{ + memcrap(&decoded_flags, sizeof(decoded_flags)); + + if (lzma_filter_flags_decoder(&strm, &decoded_flags) != LZMA_OK) + return true; + + if (decoder_loop_ret(&strm, buffer, known_size, ret_ok)) + return true; + + return false; +} + + +static bool +decode(uint32_t known_size) +{ + if (decode_ret(known_size, LZMA_STREAM_END)) + return true; + + if (known_flags.id != decoded_flags.id) + return true; + + return false; +} + + +static void +test_copy(void) +{ + // Test 1 (good) + known_flags.id = LZMA_FILTER_COPY; + known_flags.options = NULL; + + expect(!encode(1)); + expect(!decode(1)); + expect(decoded_flags.options == NULL); + + // Test 2 (invalid encoder options) + known_flags.options = &known_flags; + expect(encode(99)); + + // Test 3 (good but unusual Filter Flags field) + buffer[0] = 0xE0; + buffer[1] = LZMA_FILTER_COPY; + expect(!decode(2)); + expect(decoded_flags.options == NULL); + + // Test 4 (invalid Filter Flags field) + buffer[0] = 0xE1; + buffer[1] = LZMA_FILTER_COPY; + buffer[2] = 0; + expect(!decode_ret(3, LZMA_HEADER_ERROR)); + + // Test 5 (good but weird Filter Flags field) + buffer[0] = 0xFF; + buffer[1] = LZMA_FILTER_COPY; + buffer[2] = 0; + expect(!decode(3)); + expect(decoded_flags.options == NULL); + + // Test 6 (invalid Filter Flags field) + buffer[0] = 0xFF; + buffer[1] = LZMA_FILTER_COPY; + buffer[2] = 1; + buffer[3] = 0; + expect(!decode_ret(4, LZMA_HEADER_ERROR)); +} + + +static void +test_subblock(void) +{ + // Test 1 + known_flags.id = LZMA_FILTER_SUBBLOCK; + known_flags.options = NULL; + + expect(!encode(1)); + expect(!decode(1)); + expect(decoded_flags.options != NULL); + expect(((lzma_options_subblock *)(decoded_flags.options)) + ->allow_subfilters); + + // Test 2 + known_flags.options = decoded_flags.options; + expect(!encode(1)); + expect(!decode(1)); + expect(decoded_flags.options != NULL); + expect(((lzma_options_subblock *)(decoded_flags.options)) + ->allow_subfilters); + + free(decoded_flags.options); + free(known_flags.options); + + // Test 3 + buffer[0] = 0xFF; + buffer[1] = LZMA_FILTER_SUBBLOCK; + buffer[2] = 1; + buffer[3] = 0; + expect(!decode_ret(4, LZMA_HEADER_ERROR)); +} + + +static void +test_simple(void) +{ + // Test 1 + known_flags.id = LZMA_FILTER_X86; + known_flags.options = NULL; + + expect(!encode(1)); + expect(!decode(1)); + expect(decoded_flags.options == NULL); + + // Test 2 + lzma_options_simple options; + options.start_offset = 0; + known_flags.options = &options; + expect(!encode(1)); + expect(!decode(1)); + expect(decoded_flags.options == NULL); + + // Test 3 + options.start_offset = 123456; + known_flags.options = &options; + expect(!encode(6)); + expect(!decode(6)); + expect(decoded_flags.options != NULL); + + lzma_options_simple *decoded = decoded_flags.options; + expect(decoded->start_offset == options.start_offset); + + free(decoded); +} + + +static void +test_delta(void) +{ + // Test 1 + known_flags.id = LZMA_FILTER_DELTA; + known_flags.options = NULL; + expect(encode(99)); + + // Test 2 + lzma_options_delta options = { 0 }; + known_flags.options = &options; + expect(encode(99)); + + // Test 3 + options.distance = LZMA_DELTA_DISTANCE_MIN; + expect(!encode(2)); + expect(!decode(2)); + expect(((lzma_options_delta *)(decoded_flags.options)) + ->distance == options.distance); + + free(decoded_flags.options); + + // Test 4 + options.distance = LZMA_DELTA_DISTANCE_MAX; + expect(!encode(2)); + expect(!decode(2)); + expect(((lzma_options_delta *)(decoded_flags.options)) + ->distance == options.distance); + + free(decoded_flags.options); + + // Test 5 + options.distance = LZMA_DELTA_DISTANCE_MAX + 1; + expect(encode(99)); +} + + +static void +validate_lzma(void) +{ + const lzma_options_lzma *known = known_flags.options; + const lzma_options_lzma *decoded = decoded_flags.options; + + expect(known->dictionary_size <= decoded->dictionary_size); + + if (known->dictionary_size == 1) + expect(decoded->dictionary_size == 1); + else + expect(known->dictionary_size + known->dictionary_size / 2 + > decoded->dictionary_size); + + expect(known->literal_context_bits == decoded->literal_context_bits); + expect(known->literal_pos_bits == decoded->literal_pos_bits); + expect(known->pos_bits == decoded->pos_bits); +} + + +static void +test_lzma(void) +{ + // Test 1 + known_flags.id = LZMA_FILTER_LZMA; + known_flags.options = NULL; + expect(encode(99)); + + // Test 2 + lzma_options_lzma options = { + .dictionary_size = 0, + .literal_context_bits = 0, + .literal_pos_bits = 0, + .pos_bits = 0, + .preset_dictionary = NULL, + .preset_dictionary_size = 0, + .mode = LZMA_MODE_INVALID, + .fast_bytes = 0, + .match_finder = LZMA_MF_INVALID, + .match_finder_cycles = 0, + }; + + // Test 3 (empty dictionary not allowed) + known_flags.options = &options; + expect(encode(99)); + + // Test 4 (brute-force test some valid dictionary sizes) + while (options.dictionary_size != LZMA_DICTIONARY_SIZE_MAX) { + if (++options.dictionary_size == 5000) + options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX - 5; + + expect(!encode(3)); + expect(!decode(3)); + validate_lzma(); + + free(decoded_flags.options); + } + + // Test 5 (too big dictionary size) + options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX + 1; + expect(encode(99)); + + // Test 6 (brute-force test lc/lp/pb) + options.dictionary_size = 1; + for (uint32_t lc = LZMA_LITERAL_CONTEXT_BITS_MIN; + lc <= LZMA_LITERAL_CONTEXT_BITS_MAX; ++lc) { + for (uint32_t lp = LZMA_LITERAL_POS_BITS_MIN; + lp <= LZMA_LITERAL_POS_BITS_MAX; ++lp) { + for (uint32_t pb = LZMA_POS_BITS_MIN; + pb <= LZMA_POS_BITS_MAX; ++pb) { + options.literal_context_bits = lc; + options.literal_pos_bits = lp; + options.pos_bits = pb; + + expect(!encode(3)); + expect(!decode(3)); + validate_lzma(); + + free(decoded_flags.options); + } + } + } +} + + +int +main() +{ + lzma_init(); + + test_copy(); + test_subblock(); + test_simple(); + test_delta(); + test_lzma(); + + lzma_end(&strm); + + return 0; +} diff --git a/tests/test_index.c b/tests/test_index.c new file mode 100644 index 00000000..399963d3 --- /dev/null +++ b/tests/test_index.c @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_inndex.c +/// \brief Tests functions handling the lzma_index structure +// +// Copyright (C) 2007 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +int +main() +{ + lzma_index index[3] = { + { 22, 33, index + 1 }, + { 44, 55, index + 2 }, + { 66, 77, NULL }, + }; + + lzma_index *i = lzma_index_dup(index, NULL); + expect(i != NULL); + + expect(lzma_index_is_equal(index, i)); + + i->next->next->uncompressed_size = 99; + expect(!lzma_index_is_equal(index, i)); + + lzma_index_free(i, NULL); + + return 0; +} diff --git a/tests/test_info.c b/tests/test_info.c new file mode 100644 index 00000000..e7899ef3 --- /dev/null +++ b/tests/test_info.c @@ -0,0 +1,717 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_info.c +/// \brief Tests functions handling the lzma_info structure +// +// Copyright (C) 2007 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +static lzma_info *info = NULL; +static lzma_info_iter iter; + +static lzma_vli stream_start = 0; +static lzma_vli header_metadata_size = LZMA_VLI_VALUE_UNKNOWN; +static lzma_vli total_size = LZMA_VLI_VALUE_UNKNOWN; +static lzma_vli uncompressed_size = LZMA_VLI_VALUE_UNKNOWN; +static lzma_vli footer_metadata_size = LZMA_VLI_VALUE_UNKNOWN; + +static lzma_index my_index[3] = { + { 22, 33, my_index + 1 }, + { 44, 55, my_index + 2 }, + { 66, 77, NULL }, +}; + +static lzma_metadata my_metadata = { + .header_metadata_size = 11, + .total_size = 22 + 44 + 66, + .uncompressed_size = 33 + 55 + 77, + .index = my_index, + .extra = NULL, +}; + + +static void +reset(void) +{ + expect(lzma_info_init(info, NULL) == info); + stream_start = 0; + header_metadata_size = LZMA_VLI_VALUE_UNKNOWN; + total_size = LZMA_VLI_VALUE_UNKNOWN; + uncompressed_size = LZMA_VLI_VALUE_UNKNOWN; + footer_metadata_size = LZMA_VLI_VALUE_UNKNOWN; +} + + +static void +validate(void) +{ + expect(lzma_info_size_get(info, LZMA_INFO_STREAM_START) + == stream_start); + expect(lzma_info_size_get(info, LZMA_INFO_HEADER_METADATA) + == header_metadata_size); + expect(lzma_info_size_get(info, LZMA_INFO_TOTAL) == total_size); + expect(lzma_info_size_get(info, LZMA_INFO_UNCOMPRESSED) + == uncompressed_size); + expect(lzma_info_size_get(info, LZMA_INFO_FOOTER_METADATA) + == footer_metadata_size); +} + + +static void +test1(void) +{ + // Basics + expect(lzma_info_size_set(info, LZMA_INFO_STREAM_START, + stream_start = 1234) == LZMA_OK); + validate(); + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, + header_metadata_size = 2345) == LZMA_OK); + validate(); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, total_size = 3456) + == LZMA_OK); + validate(); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, + uncompressed_size = 4567) == LZMA_OK); + validate(); + expect(lzma_info_size_set(info, LZMA_INFO_FOOTER_METADATA, + footer_metadata_size = 5432) == LZMA_OK); + validate(); + + // Not everything allow zero size + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_STREAM_START, + stream_start = 0) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, + header_metadata_size = 0) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, + uncompressed_size = 0) == LZMA_OK); + validate(); + + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, 0) + == LZMA_PROG_ERROR); + + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_FOOTER_METADATA, 0) + == LZMA_PROG_ERROR); + + // Invalid sizes + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_STREAM_START, + LZMA_VLI_VALUE_MAX + 1) == LZMA_PROG_ERROR); + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, + LZMA_VLI_VALUE_MAX + 1) == LZMA_PROG_ERROR); + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, + LZMA_VLI_VALUE_MAX + 1) == LZMA_PROG_ERROR); + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, + LZMA_VLI_VALUE_MAX + 1) == LZMA_PROG_ERROR); + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_FOOTER_METADATA, + LZMA_VLI_VALUE_MAX + 1) == LZMA_PROG_ERROR); + + reset(); +} + + +static bool +test2_helper(lzma_vli *num, lzma_info_size type) +{ + expect(lzma_info_size_set(info, type, *num = 1234) == LZMA_OK); + validate(); + const bool ret = lzma_info_size_set(info, type, 4321) != LZMA_OK; + reset(); + return ret; +} + + +static void +test2(void) +{ + // Excluding start offset of Stream, once a size has been set, + // trying to set some other known value fails. + expect(!test2_helper(&stream_start, LZMA_INFO_STREAM_START)); + expect(test2_helper(&header_metadata_size, LZMA_INFO_HEADER_METADATA)); + expect(test2_helper(&total_size, LZMA_INFO_TOTAL)); + expect(test2_helper(&uncompressed_size, LZMA_INFO_UNCOMPRESSED)); + expect(test2_helper(&footer_metadata_size, LZMA_INFO_FOOTER_METADATA)); +} + + +static void +test3_init(void) +{ + reset(); + lzma_info_iter_begin(info, &iter); + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); +} + + +static void +test3(void) +{ + // Setting the same sizes multiple times for the same Index Record + // is OK, but the values must always be the same. + test3_init(); + expect(lzma_info_index_count_get(info) == 1); + expect(lzma_info_iter_set(&iter, 1234, 2345) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 1); + expect(lzma_info_iter_set(&iter, 1234, 2345) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 1); + expect(lzma_info_iter_set(&iter, 1111, 2345) == LZMA_DATA_ERROR); + + // Cannot finish an empty Index. + test3_init(); + expect(lzma_info_index_finish(info) == LZMA_DATA_ERROR); + + test3_init(); + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 2); + expect(lzma_info_iter_set(&iter, 1234, 2345) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 2); + expect(lzma_info_index_finish(info) == LZMA_DATA_ERROR); + + test3_init(); + expect(lzma_info_iter_set(&iter, 1234, 2345) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 1); + expect(lzma_info_index_finish(info) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, 1234) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, 2345) + == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, 1111) + == LZMA_DATA_ERROR); + + test3_init(); + expect(lzma_info_iter_set(&iter, 1234, 2345) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 1); + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 2); + expect(lzma_info_iter_set(&iter, 4321, 5432) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 2); + expect(lzma_info_index_finish(info) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, 1234 + 4321) + == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, 2345 + 5432) + == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, 1111) + == LZMA_DATA_ERROR); + + test3_init(); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, 1234 + 4321) + == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, 2345 + 5432) + == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, 1111) + == LZMA_DATA_ERROR); + expect(lzma_info_iter_set(&iter, 1234, 2345) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 1); + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 2); + expect(lzma_info_iter_set(&iter, 4321, 5432) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 2); + expect(lzma_info_index_finish(info) == LZMA_OK); + + test3_init(); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, 1000) == LZMA_OK); + expect(lzma_info_iter_set(&iter, 1001, 2001) == LZMA_DATA_ERROR); + + test3_init(); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, 2000) + == LZMA_OK); + expect(lzma_info_iter_set(&iter, 1001, 2001) == LZMA_DATA_ERROR); + + reset(); +} + + +static void +test4(void) +{ + // 4a + lzma_info_iter_begin(info, &iter); + expect(lzma_info_index_count_get(info) == 0); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_offset == 0); + expect(lzma_info_index_count_get(info) == 1); + + expect(lzma_info_iter_set(&iter, 22, 33) == LZMA_OK); + expect(iter.total_size == 22); + expect(iter.uncompressed_size == 33); + expect(iter.stream_offset == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_offset == 0); + expect(lzma_info_index_count_get(info) == 1); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_offset == 33); + + // 4b + reset(); + lzma_info_iter_begin(info, &iter); + expect(lzma_info_index_count_get(info) == 0); + expect(lzma_info_size_set(info, LZMA_INFO_STREAM_START, 5) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, 11) + == LZMA_OK); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11); + expect(iter.uncompressed_offset == 0); + expect(lzma_info_index_count_get(info) == 1); + + expect(lzma_info_iter_set(&iter, 22, 33) == LZMA_OK); + expect(iter.total_size == 22); + expect(iter.uncompressed_size == 33); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11); + expect(iter.uncompressed_offset == 0); + expect(lzma_info_index_count_get(info) == 1); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11 + 22); + expect(iter.uncompressed_offset == 33); + expect(lzma_info_index_count_get(info) == 2); + + expect(lzma_info_iter_set(&iter, 44, 55) == LZMA_OK); + expect(iter.total_size == 44); + expect(iter.uncompressed_size == 55); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11 + 22); + expect(iter.uncompressed_offset == 33); + expect(lzma_info_index_count_get(info) == 2); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44); + expect(iter.uncompressed_offset == 33 + 55); + expect(lzma_info_index_count_get(info) == 3); + + expect(lzma_info_iter_set(&iter, 66, 77) == LZMA_OK); + expect(iter.total_size == 66); + expect(iter.uncompressed_size == 77); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44); + expect(iter.uncompressed_offset == 33 + 55); + expect(lzma_info_index_count_get(info) == 3); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44 + 66); + expect(iter.uncompressed_offset == 33 + 55 + 77); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_set(&iter, 88, 99) == LZMA_OK); + expect(iter.total_size == 88); + expect(iter.uncompressed_size == 99); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44 + 66); + expect(iter.uncompressed_offset == 33 + 55 + 77); + expect(lzma_info_index_count_get(info) == 4); + + // 4c (continues from 4b) + lzma_info_iter_begin(info, &iter); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == 22); + expect(iter.uncompressed_size == 33); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11); + expect(iter.uncompressed_offset == 0); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_set(&iter, 22, LZMA_VLI_VALUE_UNKNOWN) + == LZMA_OK); + expect(iter.total_size == 22); + expect(iter.uncompressed_size == 33); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11); + expect(iter.uncompressed_offset == 0); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == 44); + expect(iter.uncompressed_size == 55); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11 + 22); + expect(iter.uncompressed_offset == 33); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_set(&iter, LZMA_VLI_VALUE_UNKNOWN, 55) + == LZMA_OK); + expect(iter.total_size == 44); + expect(iter.uncompressed_size == 55); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11 + 22); + expect(iter.uncompressed_offset == 33); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == 66); + expect(iter.uncompressed_size == 77); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44); + expect(iter.uncompressed_offset == 33 + 55); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_set(&iter, LZMA_VLI_VALUE_UNKNOWN, + LZMA_VLI_VALUE_UNKNOWN) == LZMA_OK); + expect(iter.total_size == 66); + expect(iter.uncompressed_size == 77); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44); + expect(iter.uncompressed_offset == 33 + 55); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == 88); + expect(iter.uncompressed_size == 99); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44 + 66); + expect(iter.uncompressed_offset == 33 + 55 + 77); + expect(lzma_info_index_count_get(info) == 4); + + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44 + 66 + 88); + expect(iter.uncompressed_offset == 33 + 55 + 77 + 99); + expect(lzma_info_index_count_get(info) == 5); + + expect(lzma_info_iter_set(&iter, 1234, LZMA_VLI_VALUE_UNKNOWN) + == LZMA_OK); + expect(iter.total_size == 1234); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44 + 66 + 88); + expect(iter.uncompressed_offset == 33 + 55 + 77 + 99); + expect(lzma_info_index_count_get(info) == 5); + + // Test 4d (continues from 4c) + lzma_info_iter_begin(info, &iter); + for (size_t i = 0; i < 4; ++i) + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(lzma_info_iter_set(&iter, 88, 99) == LZMA_OK); + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.total_size == 1234); + expect(iter.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44 + 66 + 88); + expect(iter.uncompressed_offset == 33 + 55 + 77 + 99); + expect(lzma_info_index_count_get(info) == 5); + + expect(lzma_info_iter_set(&iter, LZMA_VLI_VALUE_UNKNOWN, 4321) + == LZMA_OK); + expect(iter.total_size == 1234); + expect(iter.uncompressed_size == 4321); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + + 11 + 22 + 44 + 66 + 88); + expect(iter.uncompressed_offset == 33 + 55 + 77 + 99); + expect(lzma_info_index_count_get(info) == 5); + + expect(lzma_info_index_finish(info) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 5); + + // Test 4e (continues from 4d) + lzma_info_iter_begin(info, &iter); + for (size_t i = 0; i < 5; ++i) + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(lzma_info_iter_set(&iter, 1234, 4321) == LZMA_OK); + expect(lzma_info_iter_next(&iter, NULL) == LZMA_DATA_ERROR); + + reset(); +} + + +static void +test5(void) +{ + lzma_index *i; + + expect(lzma_info_index_set(info, NULL, NULL, true) + == LZMA_PROG_ERROR); + + reset(); + expect(lzma_info_index_set(info, NULL, my_index, false) == LZMA_OK); + i = lzma_index_dup(my_index, NULL); + expect(i != NULL); + i->next->uncompressed_size = 99; + expect(lzma_info_index_set(info, NULL, i, true) == LZMA_DATA_ERROR); + + reset(); + expect(lzma_info_index_set(info, NULL, my_index, false) == LZMA_OK); + i = lzma_index_dup(my_index, NULL); + expect(i != NULL); + lzma_index_free(i->next->next, NULL); + i->next->next = NULL; + expect(lzma_info_index_set(info, NULL, i, true) == LZMA_DATA_ERROR); + + reset(); + expect(lzma_info_index_set(info, NULL, my_index, false) == LZMA_OK); + i = lzma_index_dup(my_index, NULL); + expect(i != NULL); + lzma_index_free(i->next->next, NULL); + i->next->next = lzma_index_dup(my_index, NULL); + expect(i->next->next != NULL); + expect(lzma_info_index_set(info, NULL, i, true) == LZMA_DATA_ERROR); + + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, + total_size = 22 + 44 + 66) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, + uncompressed_size = 33 + 55 + 77) == LZMA_OK); + validate(); + expect(lzma_info_index_set(info, NULL, my_index, false) == LZMA_OK); + validate(); + + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, total_size = 77) + == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, + uncompressed_size = 33 + 55 + 77) == LZMA_OK); + validate(); + expect(lzma_info_index_set(info, NULL, my_index, false) + == LZMA_DATA_ERROR); + + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_TOTAL, + total_size = 22 + 44 + 66) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_UNCOMPRESSED, + uncompressed_size = 777777) == LZMA_OK); + validate(); + expect(lzma_info_index_set(info, NULL, my_index, false) + == LZMA_DATA_ERROR); + + reset(); +} + + +static void +test6(void) +{ + lzma_metadata metadata; + + // Same complete Metadata in both Header and Footer + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, + my_metadata.header_metadata_size) == LZMA_OK); + expect(lzma_info_metadata_set(info, NULL, &my_metadata, true, false) + == LZMA_OK); + expect(lzma_info_metadata_set(info, NULL, &my_metadata, false, false) + == LZMA_OK); + + // Header Metadata is not present but Size of Header Metadata is + // still present in Footer. + reset(); + metadata = my_metadata; + metadata.header_metadata_size = LZMA_VLI_VALUE_UNKNOWN; + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, 0) + == LZMA_OK); + expect(lzma_info_metadata_set(info, NULL, &metadata, true, false) + == LZMA_OK); + expect(lzma_info_metadata_set(info, NULL, &my_metadata, false, false) + == LZMA_DATA_ERROR); + + // Header Metadata is present but Size of Header Metadata is missing + // from Footer. + reset(); + metadata = my_metadata; + metadata.header_metadata_size = LZMA_VLI_VALUE_UNKNOWN; + expect(lzma_info_metadata_set(info, NULL, &my_metadata, true, false) + == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, + my_metadata.header_metadata_size) == LZMA_OK); + expect(lzma_info_metadata_set(info, NULL, &metadata, false, false) + == LZMA_DATA_ERROR); + + // Index missing + reset(); + metadata = my_metadata; + metadata.index = NULL; + expect(lzma_info_metadata_set(info, NULL, &metadata, true, false) + == LZMA_OK); + expect(lzma_info_metadata_set(info, NULL, &metadata, false, false) + == LZMA_DATA_ERROR); + + // Index in Header Metadata but not in Footer Metadata + reset(); + expect(lzma_info_metadata_set(info, NULL, &my_metadata, true, false) + == LZMA_OK); + expect(lzma_info_metadata_set(info, NULL, &metadata, false, false) + == LZMA_OK); + + // Index in Header Metadata but not in Footer Metadata but + // Total Size is missing from Footer. + reset(); + metadata.total_size = LZMA_VLI_VALUE_UNKNOWN; + expect(lzma_info_metadata_set(info, NULL, &my_metadata, true, false) + == LZMA_OK); + expect(lzma_info_metadata_set(info, NULL, &metadata, false, false) + == LZMA_DATA_ERROR); + + // Total Size doesn't match the Index + reset(); + metadata = my_metadata; + metadata.total_size = 9999; + expect(lzma_info_metadata_set(info, NULL, &metadata, true, false) + == LZMA_DATA_ERROR); + + // Uncompressed Size doesn't match the Index + reset(); + metadata = my_metadata; + metadata.uncompressed_size = 9999; + expect(lzma_info_metadata_set(info, NULL, &metadata, true, false) + == LZMA_DATA_ERROR); + + reset(); +} + + +static void +test7(void) +{ + // No info yet, so we cannot locate anything. + expect(lzma_info_metadata_locate(info, true) + == LZMA_VLI_VALUE_UNKNOWN); + expect(lzma_info_metadata_locate(info, false) + == LZMA_VLI_VALUE_UNKNOWN); + + // Setting the Stream start offset doesn't change this situation. + expect(lzma_info_size_set(info, LZMA_INFO_STREAM_START, 5) == LZMA_OK); + expect(lzma_info_metadata_locate(info, true) + == LZMA_VLI_VALUE_UNKNOWN); + expect(lzma_info_metadata_locate(info, false) + == LZMA_VLI_VALUE_UNKNOWN); + + // Setting the Size of Header Metadata known allows us to locate + // the Header Metadata Block. + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, 11) + == LZMA_OK); + expect(lzma_info_metadata_locate(info, true) + == 5 + LZMA_STREAM_HEADER_SIZE); + expect(lzma_info_metadata_locate(info, false) + == LZMA_VLI_VALUE_UNKNOWN); + + // Adding a Data Block. As long as Index is not Finished, we cannot + // locate Footer Metadata Block. + lzma_info_iter_begin(info, &iter); + expect(lzma_info_iter_next(&iter, NULL) == LZMA_OK); + expect(iter.stream_offset == 5 + LZMA_STREAM_HEADER_SIZE + 11); + expect(iter.uncompressed_offset == 0); + expect(lzma_info_iter_set(&iter, 22, 33) == LZMA_OK); + expect(lzma_info_metadata_locate(info, true) + == 5 + LZMA_STREAM_HEADER_SIZE); + expect(lzma_info_metadata_locate(info, false) + == LZMA_VLI_VALUE_UNKNOWN); + + // Once the Index is finished, we can locate Footer Metadata Block too. + expect(lzma_info_index_finish(info) == LZMA_OK); + expect(lzma_info_metadata_locate(info, true) + == 5 + LZMA_STREAM_HEADER_SIZE); + expect(lzma_info_metadata_locate(info, false) + == 5 + LZMA_STREAM_HEADER_SIZE + 11 + 22); + + // A retry of most of the above but now with unknown Size of Header + // Metadata Block, which makes locating Footer Metadata Block + // impossible. + reset(); + expect(lzma_info_size_set(info, LZMA_INFO_STREAM_START, 5) == LZMA_OK); + expect(lzma_info_metadata_locate(info, true) + == LZMA_VLI_VALUE_UNKNOWN); + expect(lzma_info_metadata_locate(info, false) + == LZMA_VLI_VALUE_UNKNOWN); + + expect(lzma_info_index_set(info, NULL, my_index, false) == LZMA_OK); + expect(lzma_info_metadata_locate(info, true) + == LZMA_VLI_VALUE_UNKNOWN); + expect(lzma_info_metadata_locate(info, false) + == LZMA_VLI_VALUE_UNKNOWN); + + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, 11) + == LZMA_OK); + expect(lzma_info_metadata_locate(info, true) + == 5 + LZMA_STREAM_HEADER_SIZE); + expect(lzma_info_metadata_locate(info, false) + == LZMA_STREAM_HEADER_SIZE + 5 + 11 + 22 + 44 + 66); + + reset(); +} + + +static void +test8(void) +{ + expect(lzma_info_size_set(info, LZMA_INFO_STREAM_START, 5) == LZMA_OK); + expect(lzma_info_size_set(info, LZMA_INFO_HEADER_METADATA, 11) + == LZMA_OK); + + lzma_info_iter_begin(info, &iter); + expect(lzma_info_iter_locate(&iter, NULL, 0, false) + == LZMA_DATA_ERROR); + expect(lzma_info_index_count_get(info) == 0); + + lzma_info_iter_begin(info, &iter); + expect(lzma_info_iter_locate(&iter, NULL, 0, true) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 1); + expect(lzma_info_iter_locate(&iter, NULL, 0, false) == LZMA_OK); + expect(lzma_info_index_count_get(info) == 1); + + // TODO +} + + +/* +static void +test9(void) +{ + // TODO Various integer overflow checks +} +*/ + + +int +main() +{ + lzma_init(); + + info = lzma_info_init(NULL, NULL); + if (info == NULL) + return 1; + + validate(); + + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + test8(); + + lzma_info_free(info, NULL); + return 0; +} diff --git a/tests/test_stream_flags.c b/tests/test_stream_flags.c new file mode 100644 index 00000000..4cd22576 --- /dev/null +++ b/tests/test_stream_flags.c @@ -0,0 +1,191 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_stream_flags.c +/// \brief Tests Stream Header and Stream tail coders +// +// Copyright (C) 2007 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +static lzma_stream_flags known_flags; +static lzma_stream_flags decoded_flags; +static uint8_t buffer[LZMA_STREAM_HEADER_SIZE + LZMA_STREAM_TAIL_SIZE]; +static lzma_stream strm = LZMA_STREAM_INIT; + + +static bool +validate(void) +{ + if (known_flags.check != decoded_flags.check + || known_flags.has_crc32 != decoded_flags.has_crc32 + || known_flags.is_multi != decoded_flags.is_multi) + return true; + + return false; +} + + +static bool +test_header_decoder(size_t expected_size, lzma_ret expected_ret) +{ + memcrap(&decoded_flags, sizeof(decoded_flags)); + + if (lzma_stream_header_decoder(&strm, &decoded_flags) != LZMA_OK) + return true; + + if (coder_loop(&strm, buffer, expected_size, NULL, 0, + expected_ret, LZMA_RUN)) + return true; + + if (expected_ret != LZMA_STREAM_END) + return false; + + return validate(); +} + + +static void +test_header(void) +{ + memcrap(buffer, sizeof(buffer)); + expect(lzma_stream_header_encode(buffer, &known_flags) == LZMA_OK); + succeed(test_header_decoder(LZMA_STREAM_HEADER_SIZE, LZMA_STREAM_END)); +} + + +static bool +test_tail_decoder(size_t expected_size, lzma_ret expected_ret) +{ + memcrap(&decoded_flags, sizeof(decoded_flags)); + + if (lzma_stream_tail_decoder(&strm, &decoded_flags) != LZMA_OK) + return true; + + if (coder_loop(&strm, buffer, expected_size, NULL, 0, + expected_ret, LZMA_RUN)) + return true; + + if (expected_ret == LZMA_STREAM_END && validate()) + return true; + + return false; +} + + +static void +test_tail(void) +{ + memcrap(buffer, sizeof(buffer)); + expect(lzma_stream_tail_encode(buffer, &known_flags) == LZMA_OK); + succeed(test_tail_decoder(LZMA_STREAM_TAIL_SIZE, LZMA_STREAM_END)); +} + + +static void +test_encode_invalid(void) +{ + known_flags.check = LZMA_CHECK_ID_MAX + 1; + known_flags.has_crc32 = false; + known_flags.is_multi = false; + + expect(lzma_stream_header_encode(buffer, &known_flags) + == LZMA_PROG_ERROR); + + expect(lzma_stream_tail_encode(buffer, &known_flags) + == LZMA_PROG_ERROR); + + known_flags.check = (lzma_check_type)(-1); + + expect(lzma_stream_header_encode(buffer, &known_flags) + == LZMA_PROG_ERROR); + + expect(lzma_stream_tail_encode(buffer, &known_flags) + == LZMA_PROG_ERROR); +} + + +static void +test_decode_invalid(void) +{ + known_flags.check = LZMA_CHECK_NONE; + known_flags.has_crc32 = false; + known_flags.is_multi = false; + + expect(lzma_stream_header_encode(buffer, &known_flags) == LZMA_OK); + + // Test 1 (invalid Magic Bytes) + buffer[5] ^= 1; + succeed(test_header_decoder(6, LZMA_DATA_ERROR)); + buffer[5] ^= 1; + + // Test 2a (valid CRC32) + uint32_t crc = lzma_crc32(buffer + 6, 1, 0); + for (size_t i = 0; i < 4; ++i) + buffer[7 + i] = crc >> (i * 8); + succeed(test_header_decoder(LZMA_STREAM_HEADER_SIZE, LZMA_STREAM_END)); + + // Test 2b (invalid Stream Flags with valid CRC32) + buffer[6] ^= 0x20; + crc = lzma_crc32(buffer + 6, 1, 0); + for (size_t i = 0; i < 4; ++i) + buffer[7 + i] = crc >> (i * 8); + succeed(test_header_decoder(7, LZMA_HEADER_ERROR)); + + // Test 3 (invalid CRC32) + expect(lzma_stream_header_encode(buffer, &known_flags) == LZMA_OK); + buffer[LZMA_STREAM_HEADER_SIZE - 1] ^= 1; + succeed(test_header_decoder(LZMA_STREAM_HEADER_SIZE, LZMA_DATA_ERROR)); + + // Test 4 (invalid Stream Flags) + expect(lzma_stream_tail_encode(buffer, &known_flags) == LZMA_OK); + buffer[0] ^= 0x40; + succeed(test_tail_decoder(1, LZMA_HEADER_ERROR)); + buffer[0] ^= 0x40; + + // Test 5 (invalid Magic Bytes) + buffer[2] ^= 1; + succeed(test_tail_decoder(3, LZMA_DATA_ERROR)); +} + + +int +main() +{ + lzma_init(); + + // Valid headers + for (lzma_check_type check = LZMA_CHECK_NONE; + check <= LZMA_CHECK_ID_MAX; ++check) { + for (int has_crc32 = 0; has_crc32 <= 1; ++has_crc32) { + for (int is_multi = 0; is_multi <= 1; ++is_multi) { + known_flags.check = check; + known_flags.has_crc32 = has_crc32; + known_flags.is_multi = is_multi; + + test_header(); + test_tail(); + } + } + } + + // Invalid headers + test_encode_invalid(); + test_decode_invalid(); + + lzma_end(&strm); + + return 0; +} diff --git a/tests/tests.h b/tests/tests.h new file mode 100644 index 00000000..08a3991c --- /dev/null +++ b/tests/tests.h @@ -0,0 +1,148 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tests.h +/// \brief Common definitions for test applications +// +// Copyright (C) 2006 Lasse Collin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_TESTS_H +#define LZMA_TESTS_H + +#include "sysdefs.h" + +#include <stdio.h> + +#define memcrap(buf, size) memset(buf, 0xFD, size) + +#define expect(test) ((test) ? 0 : (fprintf(stderr, "%s:%u: %s\n", \ + __FILE__, __LINE__, #test), exit(1), 0)) + +#define succeed(test) expect(!test) + +#define fail(test) expect(test) + + +static inline const char * +lzma_ret_sym(lzma_ret ret) +{ + const char *str = ""; + + switch (ret) { + case LZMA_OK: + str = "LZMA_OK"; + break; + + case LZMA_STREAM_END: + str = "LZMA_STREAM_END"; + break; + + case LZMA_PROG_ERROR: + str = "LZMA_PROG_ERROR"; + break; + + case LZMA_DATA_ERROR: + str = "LZMA_DATA_ERROR"; + break; + + case LZMA_MEM_ERROR: + str = "LZMA_MEM_ERROR"; + break; + + case LZMA_BUF_ERROR: + str = "LZMA_BUF_ERROR"; + break; + + case LZMA_HEADER_ERROR: + str = "LZMA_HEADER_ERROR"; + break; + + case LZMA_UNSUPPORTED_CHECK: + str = "LZMA_UNSUPPORTED_CHECK"; + break; + } + + return str; +} + + +static inline bool +coder_loop(lzma_stream *strm, uint8_t *in, size_t in_size, + uint8_t *out, size_t out_size, + lzma_ret expected_ret, lzma_action finishing_action) +{ + size_t in_left = in_size; + size_t out_left = out_size > 0 ? out_size + 1 : 0; + lzma_action action = LZMA_RUN; + lzma_ret ret; + + strm->next_in = NULL; + strm->avail_in = 0; + strm->next_out = NULL; + strm->avail_out = 0; + + while (true) { + if (in_left > 0) { + if (--in_left == 0) + action = finishing_action; + + strm->next_in = in++; + strm->avail_in = 1; + } + + if (out_left > 0) { + --out_left; + strm->next_out = out++; + strm->avail_out = 1; + } + + ret = lzma_code(strm, action); + if (ret != LZMA_OK) + break; + } + + bool error = false; + + if (ret != expected_ret) + error = true; + + if (expected_ret == LZMA_STREAM_END) { + if (strm->total_in != in_size || strm->total_out != out_size) + error = true; + } else { + if (strm->total_in + 1 != in_size + || strm->total_out != out_size) + error = true; + } + + return error; +} + + +static inline bool +decoder_loop_ret(lzma_stream *strm, uint8_t *in, size_t in_size, + lzma_ret expected_ret) +{ + return coder_loop(strm, in, in_size, NULL, 0, expected_ret, LZMA_RUN); +} + + +static inline bool +decoder_loop(lzma_stream *strm, uint8_t *in, size_t in_size) +{ + return coder_loop(strm, in, in_size, NULL, 0, + LZMA_STREAM_END, LZMA_RUN); +} + +#endif |