aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2007-12-09 00:42:33 +0200
committerLasse Collin <lasse.collin@tukaani.org>2007-12-09 00:42:33 +0200
commit5d018dc03549c1ee4958364712fb0c94e1bf2741 (patch)
tree1b211911fb33fddb3f04b77f99e81df23623ffc4 /tests
downloadxz-5d018dc03549c1ee4958364712fb0c94e1bf2741.tar.xz
Imported to git.
Diffstat (limited to '')
-rw-r--r--tests/Makefile.am43
-rw-r--r--tests/test_block.c59
-rw-r--r--tests/test_block_header.c352
-rw-r--r--tests/test_check.c90
-rw-r--r--tests/test_filter_flags.c326
-rw-r--r--tests/test_index.c43
-rw-r--r--tests/test_info.c717
-rw-r--r--tests/test_stream_flags.c191
-rw-r--r--tests/tests.h148
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