aboutsummaryrefslogtreecommitdiff
path: root/tests/test_block_header.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_block_header.c')
-rw-r--r--tests/test_block_header.c352
1 files changed, 352 insertions, 0 deletions
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;
+}