aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJia Tan <jiat0218@gmail.com>2023-01-12 22:29:07 +0800
committerJia Tan <jiat0218@gmail.com>2023-03-13 20:53:12 +0800
commit7479a69a45a1b8fdb9a209e11f247dce11ac1ba0 (patch)
tree7379577eecfae86737c4f4b959f26ba16c2a0a29 /tests
parentxz: Make Capsicum sandbox more strict with stdin and stdout. (diff)
downloadxz-7479a69a45a1b8fdb9a209e11f247dce11ac1ba0.tar.xz
Tests: Refactors existing lzma_index tests.
Converts the existing lzma_index tests into tuktests and covers every API function from index.h except for lzma_file_info_decoder, which can be tested in the future.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_index.c2036
1 files changed, 1492 insertions, 544 deletions
diff --git a/tests/test_index.c b/tests/test_index.c
index 31b958d5..f63d2a79 100644
--- a/tests/test_index.c
+++ b/tests/test_index.c
@@ -2,8 +2,12 @@
//
/// \file test_index.c
/// \brief Tests functions handling the lzma_index structure
+///
+/// \todo Implement tests for lzma_file_info_decoder
+//
+// Authors: Jia Tan
+// Lasse Collin
//
-// Author: Lasse Collin
//
// This file has been put into the public domain.
// You can do whatever you want with this file.
@@ -12,668 +16,1219 @@
#include "tests.h"
-#define MEMLIMIT (LZMA_VLI_C(1) << 20)
+// liblzma internal header file needed for:
+// UNPADDED_SIZE_MIN
+// UNPADDED_SIZE_MAX
+// vli_ceil4
+#include "common/index.h"
+
+
+#define MEMLIMIT (UINT64_C(1) << 20)
+
+static uint8_t *decode_buffer;
+static size_t decode_buffer_size = 0;
+static lzma_index *decode_test_index;
+
-#define SMALL_COUNT 3
-#define BIG_COUNT 5555
+static void
+test_lzma_index_memusage(void)
+{
+ // The return value from lzma_index_memusage is an approximation
+ // of the amount of memory needed for lzma_index for a given
+ // amount of Streams and Blocks. It will be an upperbound,
+ // so this test will mostly sanity check and error check the
+ // function.
+
+ // The maximum number of Streams should be UINT32_MAX in the
+ // current implementation even though the parameter is lzma_vli.
+ assert_uint_eq(lzma_index_memusage((lzma_vli)UINT32_MAX + 1, 1),
+ UINT64_MAX);
+
+ // The maximum number of Blocks should be LZMA_VLI_MAX
+ assert_uint_eq(lzma_index_memusage(1, LZMA_VLI_MAX), UINT64_MAX);
+
+ // Number of Streams must be non-zero
+ assert_uint_eq(lzma_index_memusage(0, 1), UINT64_MAX);
+
+ // Number of Blocks CAN be zero
+ assert_uint(lzma_index_memusage(1, 0), !=, UINT64_MAX);
+
+ // Arbitrary values for Stream and Block should work without error
+ // and should always increase
+ uint64_t previous = 1;
+ lzma_vli streams = 1;
+ lzma_vli blocks = 1;
+
+ // Test 100 different increasing values for Streams and Block
+ for (int i = 0; i < 100; i++) {
+ uint64_t current = lzma_index_memusage(streams, blocks);
+ assert_uint(current, >, previous);
+ previous = current;
+ streams += 29;
+ blocks += 107;
+ }
+
+ // Force integer overflow in calculation (should result in an error)
+ assert_uint_eq(lzma_index_memusage(UINT32_MAX, LZMA_VLI_MAX),
+ UINT64_MAX);
+}
-static lzma_index *
-create_empty(void)
+static void
+test_lzma_index_memused(void)
{
- lzma_index *i = lzma_index_init(NULL);
- expect(i != NULL);
- return i;
+ // Very similar to test_lzma_index_memusage above since
+ // lzma_index_memused is essentially a wrapper for
+ // lzma_index_memusage
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ // Test with empty Index
+ assert_uint(lzma_index_memused(idx), <, UINT64_MAX);
+
+ // Append small Blocks and then test again (should pass).
+ for (lzma_vli i = 0; i < 10; i++)
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
+
+ assert_uint(lzma_index_memused(idx), <, UINT64_MAX);
+
+ lzma_index_end(idx, NULL);
}
-static lzma_index *
-create_small(void)
+static void
+test_lzma_index_append(void)
{
- lzma_index *i = lzma_index_init(NULL);
- expect(i != NULL);
- expect(lzma_index_append(i, NULL, 101, 555) == LZMA_OK);
- expect(lzma_index_append(i, NULL, 602, 777) == LZMA_OK);
- expect(lzma_index_append(i, NULL, 804, 999) == LZMA_OK);
- return i;
+ // Basic input-ouput test done here.
+ // Less trivial tests for this function are done throughout
+ // other tests.
+
+ // First test with NULL lzma_index
+ assert_lzma_ret(lzma_index_append(NULL, NULL, UNPADDED_SIZE_MIN,
+ 1), LZMA_PROG_ERROR);
+
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ // Test with invalid Unpadded Size
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN - 1, 1), LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MAX + 1, 1), LZMA_PROG_ERROR);
+
+ // Test with invalid Uncompressed Size
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MAX, LZMA_VLI_MAX + 1),
+ LZMA_PROG_ERROR);
+
+ // Test expected successful Block appends
+ assert_lzma_ret(lzma_index_append(idx, NULL, UNPADDED_SIZE_MIN,
+ 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN * 2,
+ 2), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN * 3,
+ 3), LZMA_OK);
+
+ lzma_index_end(idx, NULL);
+
+ // Test uncompressed .xz file size growing too large.
+ // Should result in LZMA_DATA_ERROR.
+ idx = lzma_index_init(NULL);
+
+ assert_lzma_ret(lzma_index_append(idx, NULL, UNPADDED_SIZE_MAX,
+ 1), LZMA_DATA_ERROR);
+
+ // Test compressed size growing too large.
+ // Should result in LZMA_DATA_ERROR.
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, LZMA_VLI_MAX), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_DATA_ERROR);
+
+ // Currently not testing for error case when the size of the Index
+ // grows too large to be stored. This was not practical to test for
+ // since too many Blocks needed to be created to cause this.
+
+ lzma_index_end(idx, NULL);
}
-static lzma_index *
-create_big(void)
+static void
+test_lzma_index_stream_flags(void)
{
- lzma_index *i = lzma_index_init(NULL);
- expect(i != NULL);
-
- lzma_vli total_size = 0;
- lzma_vli uncompressed_size = 0;
-
- // Add pseudo-random sizes (but always the same size values).
- uint32_t n = 11;
- for (size_t j = 0; j < BIG_COUNT; ++j) {
- n = 7019 * n + 7607;
- const uint32_t t = n * 3011;
- expect(lzma_index_append(i, NULL, t, n) == LZMA_OK);
- total_size += (t + 3) & ~LZMA_VLI_C(3);
- uncompressed_size += n;
- }
+ // Only trivial tests done here testing for basic functionality.
+ // More in-depth testing for this function will be done in
+ // test_lzma_index_checks.
+
+ // Testing for NULL inputs
+ assert_lzma_ret(lzma_index_stream_flags(NULL, NULL),
+ LZMA_PROG_ERROR);
+
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
- expect(lzma_index_block_count(i) == BIG_COUNT);
- expect(lzma_index_total_size(i) == total_size);
- expect(lzma_index_uncompressed_size(i) == uncompressed_size);
- expect(lzma_index_total_size(i) + lzma_index_size(i)
- + 2 * LZMA_STREAM_HEADER_SIZE
- == lzma_index_stream_size(i));
+ assert_lzma_ret(lzma_index_stream_flags(idx, NULL),
+ LZMA_PROG_ERROR);
- return i;
+ lzma_stream_flags stream_flags = {
+ .version = 0,
+ .backward_size = LZMA_BACKWARD_SIZE_MIN,
+ .check = LZMA_CHECK_CRC32
+ };
+
+ assert_lzma_ret(lzma_index_stream_flags(idx, &stream_flags),
+ LZMA_OK);
+
+ lzma_index_end(idx, NULL);
}
-static bool
-is_equal(const lzma_index *a, const lzma_index *b)
+static void
+test_lzma_index_checks(void)
{
- // Compare only the Stream and Block sizes and offsets.
- lzma_index_iter ra, rb;
- lzma_index_iter_init(&ra, a);
- lzma_index_iter_init(&rb, b);
+ // Tests should still pass, even if some of the check types
+ // are disabled.
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
- while (true) {
- bool reta = lzma_index_iter_next(&ra, LZMA_INDEX_ITER_ANY);
- bool retb = lzma_index_iter_next(&rb, LZMA_INDEX_ITER_ANY);
- if (reta)
- return !(reta ^ retb);
+ lzma_stream_flags stream_flags = {
+ .version = 0,
+ .backward_size = LZMA_BACKWARD_SIZE_MIN,
+ .check = LZMA_CHECK_NONE
+ };
- if (ra.stream.number != rb.stream.number
- || ra.stream.block_count
- != rb.stream.block_count
- || ra.stream.compressed_offset
- != rb.stream.compressed_offset
- || ra.stream.uncompressed_offset
- != rb.stream.uncompressed_offset
- || ra.stream.compressed_size
- != rb.stream.compressed_size
- || ra.stream.uncompressed_size
- != rb.stream.uncompressed_size
- || ra.stream.padding
- != rb.stream.padding)
- return false;
+ // First set the check type to None
+ assert_lzma_ret(lzma_index_stream_flags(idx, &stream_flags),
+ LZMA_OK);
+ assert_uint_eq(lzma_index_checks(idx),
+ UINT32_C(1) << LZMA_CHECK_NONE);
+
+ // Set the check type to CRC32 and repeat
+ stream_flags.check = LZMA_CHECK_CRC32;
+ assert_lzma_ret(lzma_index_stream_flags(idx, &stream_flags),
+ LZMA_OK);
+ assert_uint_eq(lzma_index_checks(idx),
+ UINT32_C(1) << LZMA_CHECK_CRC32);
+
+ // Set the check type to CRC64 and repeat
+ stream_flags.check = LZMA_CHECK_CRC64;
+ assert_lzma_ret(lzma_index_stream_flags(idx, &stream_flags),
+ LZMA_OK);
+ assert_uint_eq(lzma_index_checks(idx),
+ UINT32_C(1) << LZMA_CHECK_CRC64);
+
+ // Set the check type to SHA256 and repeat
+ stream_flags.check = LZMA_CHECK_SHA256;
+ assert_lzma_ret(lzma_index_stream_flags(idx, &stream_flags),
+ LZMA_OK);
+ assert_uint_eq(lzma_index_checks(idx),
+ UINT32_C(1) << LZMA_CHECK_SHA256);
+
+ // Create second lzma_index and cat to first
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
+
+ // Set the check type to CRC32 for the second lzma_index
+ stream_flags.check = LZMA_CHECK_CRC32;
+ assert_lzma_ret(lzma_index_stream_flags(second, &stream_flags),
+ LZMA_OK);
+
+ assert_uint_eq(lzma_index_checks(second),
+ UINT32_C(1) << LZMA_CHECK_CRC32);
+
+ assert_lzma_ret(lzma_index_cat(idx, second, NULL), LZMA_OK);
+
+ // Index should now have both CRC32 and SHA256
+ assert_uint_eq(lzma_index_checks(idx),
+ (UINT32_C(1) << LZMA_CHECK_CRC32) |
+ (UINT32_C(1) << LZMA_CHECK_SHA256));
+
+ // Change the check type of the second Stream to SHA256
+ stream_flags.check = LZMA_CHECK_SHA256;
+ assert_lzma_ret(lzma_index_stream_flags(idx, &stream_flags),
+ LZMA_OK);
+
+ // Index should now have only SHA256
+ assert_uint_eq(lzma_index_checks(idx),
+ UINT32_C(1) << LZMA_CHECK_SHA256);
+
+ // Test with a third Stream
+ lzma_index *third = lzma_index_init(NULL);
+ assert_true(third != NULL);
+
+ stream_flags.check = LZMA_CHECK_CRC64;
+ assert_lzma_ret(lzma_index_stream_flags(third, &stream_flags),
+ LZMA_OK);
+
+ assert_uint_eq(lzma_index_checks(third),
+ UINT32_C(1) << LZMA_CHECK_CRC64);
+
+ assert_lzma_ret(lzma_index_cat(idx, third, NULL), LZMA_OK);
+
+ // Index should now have CRC64 and SHA256
+ assert_uint_eq(lzma_index_checks(idx),
+ (UINT32_C(1) << LZMA_CHECK_CRC64) |
+ (UINT32_C(1) << LZMA_CHECK_SHA256));
+
+ lzma_index_end(idx, NULL);
+}
- if (ra.stream.block_count == 0)
- continue;
- if (ra.block.number_in_file != rb.block.number_in_file
- || ra.block.compressed_file_offset
- != rb.block.compressed_file_offset
- || ra.block.uncompressed_file_offset
- != rb.block.uncompressed_file_offset
- || ra.block.number_in_stream
- != rb.block.number_in_stream
- || ra.block.compressed_stream_offset
- != rb.block.compressed_stream_offset
- || ra.block.uncompressed_stream_offset
- != rb.block.uncompressed_stream_offset
- || ra.block.uncompressed_size
- != rb.block.uncompressed_size
- || ra.block.unpadded_size
- != rb.block.unpadded_size
- || ra.block.total_size
- != rb.block.total_size)
- return false;
- }
+static void
+test_lzma_index_stream_padding(void)
+{
+ // Test NULL lzma_index
+ assert_lzma_ret(lzma_index_stream_padding(NULL, 0),
+ LZMA_PROG_ERROR);
+
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ // Test Stream Padding not a multiple of 4
+ assert_lzma_ret(lzma_index_stream_padding(idx, 3),
+ LZMA_PROG_ERROR);
+
+ // Test Stream Padding too large
+ assert_lzma_ret(lzma_index_stream_padding(idx, LZMA_VLI_MAX - 3),
+ LZMA_DATA_ERROR);
+
+ // Test Stream Padding valid
+ assert_lzma_ret(lzma_index_stream_padding(idx, 0x1000),
+ LZMA_OK);
+ assert_lzma_ret(lzma_index_stream_padding(idx, 4),
+ LZMA_OK);
+ assert_lzma_ret(lzma_index_stream_padding(idx, 0),
+ LZMA_OK);
+
+ // Test Stream Padding causing the file size to grow too large
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ LZMA_VLI_MAX - 0x1000, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_stream_padding(idx, 0x1000),
+ LZMA_DATA_ERROR);
+
+ lzma_index_end(idx, NULL);
}
static void
-test_equal(void)
+test_lzma_index_stream_count(void)
{
- lzma_index *a = create_empty();
- lzma_index *b = create_small();
- lzma_index *c = create_big();
- expect(a && b && c);
-
- expect(is_equal(a, a));
- expect(is_equal(b, b));
- expect(is_equal(c, c));
-
- expect(!is_equal(a, b));
- expect(!is_equal(a, c));
- expect(!is_equal(b, c));
-
- lzma_index_end(a, NULL);
- lzma_index_end(b, NULL);
- lzma_index_end(c, NULL);
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ assert_uint_eq(lzma_index_stream_count(idx), 1);
+
+ // Appending Blocks should not change the Stream count value
+ assert_lzma_ret(lzma_index_append(idx, NULL, UNPADDED_SIZE_MIN,
+ 1), LZMA_OK);
+
+ assert_uint_eq(lzma_index_stream_count(idx), 1);
+
+ // Test with multiple Streams
+ for (uint32_t i = 0; i < 100; i++) {
+ lzma_index *idx_cat = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+ assert_lzma_ret(lzma_index_cat(idx, idx_cat, NULL), LZMA_OK);
+ assert_uint_eq(lzma_index_stream_count(idx), i + 2);
+ }
+
+ lzma_index_end(idx, NULL);
}
static void
-test_overflow(void)
+test_lzma_index_block_count(void)
{
- // Integer overflow tests
- lzma_index *i = create_empty();
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ assert_uint_eq(lzma_index_block_count(idx), 0);
+
+ const uint32_t iterations = 0x1000;
+ for (uint32_t i = 0; i < iterations; i++) {
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
+ assert_uint_eq(lzma_index_block_count(idx), i + 1);
+ }
+
+ // Create new lzma_index with a few Blocks
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
+
+ assert_lzma_ret(lzma_index_append(second, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(second, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(second, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
+
+ assert_uint_eq(lzma_index_block_count(second), 3);
+
+ // Concatenate the lzma_indexes together and the result should have
+ // the sum of the two individual counts.
+ assert_lzma_ret(lzma_index_cat(idx, second, NULL), LZMA_OK);
+ assert_uint_eq(lzma_index_block_count(idx), iterations + 3);
- expect(lzma_index_append(i, NULL, LZMA_VLI_MAX - 5, 1234)
- == LZMA_DATA_ERROR);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
- // TODO
+ assert_uint_eq(lzma_index_block_count(idx), iterations + 4);
- lzma_index_end(i, NULL);
+ lzma_index_end(idx, NULL);
}
static void
-test_copy(const lzma_index *i)
+test_lzma_index_size(void)
{
- lzma_index *d = lzma_index_dup(i, NULL);
- expect(d != NULL);
- expect(is_equal(i, d));
- lzma_index_end(d, NULL);
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ // Base size should be:
+ // 1 byte Index Indicator
+ // 1 byte Number of Records
+ // 0 bytes Records
+ // 2 bytes Index Padding
+ // 4 bytes CRC32
+ // Total: 8 bytes
+ assert_uint_eq(lzma_index_size(idx), 8);
+
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
+
+ // New size should be:
+ // 1 byte Index Indicator
+ // 1 byte Number of Records
+ // 2 bytes Records
+ // 0 bytes Index Padding
+ // 4 bytes CRC32
+ // Total: 8 bytes
+ assert_uint_eq(lzma_index_size(idx), 8);
+
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ LZMA_VLI_MAX / 4, LZMA_VLI_MAX / 4), LZMA_OK);
+
+ // New size should be:
+ // 1 byte Index Indicator
+ // 1 byte Number of Records
+ // 20 bytes Records
+ // 2 bytes Index Padding
+ // 4 bytes CRC32
+ // Total: 28 bytes
+ assert_uint_eq(lzma_index_size(idx), 28);
+
+ lzma_index_end(idx, NULL);
}
static void
-test_read(lzma_index *i)
+test_lzma_index_stream_size(void)
{
- lzma_index_iter r;
- lzma_index_iter_init(&r, i);
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ // Stream size calculated by:
+ // Size of Stream Header (12 bytes)
+ // Size of all Blocks
+ // Size of the Index
+ // Size of the Stream Footer (12 bytes)
+
+ // First test with empty Index
+ // Stream size should be:
+ // Size of Stream Header - 12 bytes
+ // Size of all Blocks - 0 bytes
+ // Size of Index - 8 bytes
+ // Size of Stream Footer - 12 bytes
+ // Total: 32 bytes
+ assert_uint_eq(lzma_index_stream_size(idx), 32);
+
+ // Next, append a few Blocks and retest
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+
+ // Stream size should be:
+ // Size of Stream Header - 12 bytes
+ // Size of all Blocks - 3000 bytes
+ // Size of Index - 16 bytes
+ // Size of Stream Footer - 12 bytes
+ // Total: 3040 bytes
+ assert_uint_eq(lzma_index_stream_size(idx), 3040);
+
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
+
+ assert_uint_eq(lzma_index_stream_size(second), 32);
+ assert_lzma_ret(lzma_index_append(second, NULL, 1000, 1), LZMA_OK);
+
+ // Stream size should be:
+ // Size of Stream Header - 12 bytes
+ // Size of all Blocks - 1000 bytes
+ // Size of Index - 12 bytes
+ // Size of Stream Footer - 12 bytes
+ // Total: 1036 bytes
+ assert_uint_eq(lzma_index_stream_size(second), 1036);
+
+ assert_lzma_ret(lzma_index_cat(idx, second, NULL), LZMA_OK);
+
+ // Stream size should be:
+ // Size of Stream Header - 12 bytes
+ // Size of all Blocks - 4000 bytes
+ // Size of Index - 20 bytes
+ // Size of Stream Footer - 12 bytes
+ // Total: 4044 bytes
+ assert_uint_eq(lzma_index_stream_size(idx), 4044);
+
+ lzma_index_end(idx, NULL);
+}
- // Try twice so we see that rewinding works.
- for (size_t j = 0; j < 2; ++j) {
- lzma_vli total_size = 0;
- lzma_vli uncompressed_size = 0;
- lzma_vli stream_offset = LZMA_STREAM_HEADER_SIZE;
- lzma_vli uncompressed_offset = 0;
- uint32_t count = 0;
- while (!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)) {
- ++count;
+static void
+test_lzma_index_total_size(void)
+{
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
- total_size += r.block.total_size;
- uncompressed_size += r.block.uncompressed_size;
+ // First test empty lzma_index.
+ // Result should be 0 since no Blocks have been added.
+ assert_uint_eq(lzma_index_total_size(idx), 0);
- expect(r.block.compressed_file_offset
- == stream_offset);
- expect(r.block.uncompressed_file_offset
- == uncompressed_offset);
+ // Add a few Blocks and retest after each append
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+ assert_uint_eq(lzma_index_total_size(idx), 1000);
- stream_offset += r.block.total_size;
- uncompressed_offset += r.block.uncompressed_size;
- }
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+ assert_uint_eq(lzma_index_total_size(idx), 2000);
- expect(lzma_index_total_size(i) == total_size);
- expect(lzma_index_uncompressed_size(i) == uncompressed_size);
- expect(lzma_index_block_count(i) == count);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+ assert_uint_eq(lzma_index_total_size(idx), 3000);
- lzma_index_iter_rewind(&r);
- }
+ // Create second lzma_index and append Blocks to it.
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
+
+ assert_uint_eq(lzma_index_total_size(second), 0);
+
+ assert_lzma_ret(lzma_index_append(second, NULL, 100, 1), LZMA_OK);
+ assert_uint_eq(lzma_index_total_size(second), 100);
+
+ assert_lzma_ret(lzma_index_append(second, NULL, 100, 1), LZMA_OK);
+ assert_uint_eq(lzma_index_total_size(second), 200);
+
+ // Concatenate the Streams together
+ assert_lzma_ret(lzma_index_cat(idx, second, NULL), LZMA_OK);
+
+ // The resulting total size should be the size of all Blocks
+ // from both Streams
+ assert_uint_eq(lzma_index_total_size(idx), 3200);
+
+ lzma_index_end(idx, NULL);
}
static void
-test_code(lzma_index *i)
+test_lzma_index_file_size(void)
{
-#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
- const size_t alloc_size = 128 * 1024;
- uint8_t *buf = malloc(alloc_size);
- expect(buf != NULL);
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
- // Encode
- lzma_stream strm = LZMA_STREAM_INIT;
- expect(lzma_index_encoder(&strm, i) == LZMA_OK);
- const lzma_vli index_size = lzma_index_size(i);
- succeed(coder_loop(&strm, NULL, 0, buf, index_size,
- LZMA_STREAM_END, LZMA_RUN));
+ // Should be the same as test_lzma_index_stream_size with
+ // only one Stream and no Stream Padding.
+ assert_uint_eq(lzma_index_file_size(idx), 32);
- // Decode
- lzma_index *d;
- expect(lzma_index_decoder(&strm, &d, MEMLIMIT) == LZMA_OK);
- expect(d == NULL);
- succeed(decoder_loop(&strm, buf, index_size));
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
- expect(is_equal(i, d));
+ assert_uint_eq(lzma_index_file_size(idx), 3040);
- lzma_index_end(d, NULL);
- lzma_end(&strm);
+ // Next add Stream Padding
+ assert_lzma_ret(lzma_index_stream_padding(idx, 1000),
+ LZMA_OK);
- // Decode with hashing
- lzma_index_hash *h = lzma_index_hash_init(NULL, NULL);
- expect(h != NULL);
- lzma_index_iter r;
- lzma_index_iter_init(&r, i);
- while (!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK))
- expect(lzma_index_hash_append(h, r.block.unpadded_size,
- r.block.uncompressed_size) == LZMA_OK);
- size_t pos = 0;
- while (pos < index_size - 1)
- expect(lzma_index_hash_decode(h, buf, &pos, pos + 1)
- == LZMA_OK);
- expect(lzma_index_hash_decode(h, buf, &pos, pos + 1)
- == LZMA_STREAM_END);
-
- lzma_index_hash_end(h, NULL);
-
- // Encode buffer
- size_t buf_pos = 1;
- expect(lzma_index_buffer_encode(i, buf, &buf_pos, index_size)
- == LZMA_BUF_ERROR);
- expect(buf_pos == 1);
-
- succeed(lzma_index_buffer_encode(i, buf, &buf_pos, index_size + 1));
- expect(buf_pos == index_size + 1);
-
- // Decode buffer
- buf_pos = 1;
- uint64_t memlimit = MEMLIMIT;
- expect(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos,
- index_size) == LZMA_DATA_ERROR);
- expect(buf_pos == 1);
- expect(d == NULL);
+ assert_uint_eq(lzma_index_file_size(idx), 4040);
- succeed(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos,
- index_size + 1));
- expect(buf_pos == index_size + 1);
- expect(is_equal(i, d));
+ // Create second lzma_index.
+ // Very similar to test_lzma_index_stream_size, but
+ // the values should include the headers of the second Stream.
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
- lzma_index_end(d, NULL);
+ assert_lzma_ret(lzma_index_append(second, NULL, 1000, 1), LZMA_OK);
+ assert_uint_eq(lzma_index_stream_size(second), 1036);
- free(buf);
-#else
- (void)i;
-#endif
+ assert_lzma_ret(lzma_index_cat(idx, second, NULL), LZMA_OK);
+
+ // .xz file size should be:
+ // Size of 2 Stream Headers - 12 * 2 bytes
+ // Size of all Blocks - 3000 + 1000 bytes
+ // Size of 2 Indexes - 16 + 12 bytes
+ // Size of Stream Padding - 1000 bytes
+ // Size of 2 Stream Footers - 12 * 2 bytes
+ // Total: 5076 bytes
+ assert_uint_eq(lzma_index_file_size(idx), 5076);
+
+ lzma_index_end(idx, NULL);
}
static void
-test_many(lzma_index *i)
+test_lzma_index_uncompressed_size(void)
{
- test_copy(i);
- test_read(i);
- test_code(i);
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ // Empty lzma_index should have 0 uncompressed .xz file size.
+ assert_uint_eq(lzma_index_uncompressed_size(idx), 0);
+
+ // Append a few small Blocks
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 10), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 100), LZMA_OK);
+
+ assert_uint_eq(lzma_index_uncompressed_size(idx), 111);
+
+ // Create another lzma_index
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
+
+ // Append a few small Blocks
+ assert_lzma_ret(lzma_index_append(second, NULL, 1000, 2), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(second, NULL, 1000, 20), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(second, NULL, 1000, 200), LZMA_OK);
+
+ assert_uint_eq(lzma_index_uncompressed_size(second), 222);
+
+ // Concatenate second lzma_index to first
+ assert_lzma_ret(lzma_index_cat(idx, second, NULL), LZMA_OK);
+
+ // New uncompressed .xz file size should be the sum of the two Streams
+ assert_uint_eq(lzma_index_uncompressed_size(idx), 333);
+
+ // Append one more Block to the lzma_index and ensure that
+ // it is properly updated
+ assert_lzma_ret(lzma_index_append(idx, NULL, 1000, 111), LZMA_OK);
+ assert_uint_eq(lzma_index_uncompressed_size(idx), 444);
+
+ lzma_index_end(idx, NULL);
}
static void
-test_cat(void)
+test_lzma_index_iter_init(void)
{
- lzma_index *a, *b, *c, *d, *e, *f;
- lzma_index_iter r;
-
- // Empty Indexes
- a = create_empty();
- b = create_empty();
- expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
- expect(lzma_index_block_count(a) == 0);
- expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
- expect(lzma_index_file_size(a)
- == 2 * (2 * LZMA_STREAM_HEADER_SIZE + 8));
- lzma_index_iter_init(&r, a);
- expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
-
- b = create_empty();
- expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
- expect(lzma_index_block_count(a) == 0);
- expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
- expect(lzma_index_file_size(a)
- == 3 * (2 * LZMA_STREAM_HEADER_SIZE + 8));
-
- b = create_empty();
- c = create_empty();
- expect(lzma_index_stream_padding(b, 4) == LZMA_OK);
- expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
- expect(lzma_index_block_count(b) == 0);
- expect(lzma_index_stream_size(b) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
- expect(lzma_index_file_size(b)
- == 2 * (2 * LZMA_STREAM_HEADER_SIZE + 8) + 4);
-
- expect(lzma_index_stream_padding(a, 8) == LZMA_OK);
- expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
- expect(lzma_index_block_count(a) == 0);
- expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
- expect(lzma_index_file_size(a)
- == 5 * (2 * LZMA_STREAM_HEADER_SIZE + 8) + 4 + 8);
-
- expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
- lzma_index_iter_rewind(&r);
- expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
- lzma_index_end(a, NULL);
-
- // Small Indexes
- a = create_small();
- lzma_vli stream_size = lzma_index_stream_size(a);
- lzma_index_iter_init(&r, a);
- for (int i = SMALL_COUNT; i >= 0; --i)
- expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
- ^ (i == 0));
-
- b = create_small();
- expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
- expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
- expect(lzma_index_file_size(a) == stream_size * 2 + 4);
- expect(lzma_index_stream_size(a) > stream_size);
- expect(lzma_index_stream_size(a) < stream_size * 2);
- for (int i = SMALL_COUNT; i >= 0; --i)
- expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
- ^ (i == 0));
-
- lzma_index_iter_rewind(&r);
- for (int i = SMALL_COUNT * 2; i >= 0; --i)
- expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
- ^ (i == 0));
-
- b = create_small();
- c = create_small();
- expect(lzma_index_stream_padding(b, 8) == LZMA_OK);
- expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
- expect(lzma_index_stream_padding(a, 12) == LZMA_OK);
- expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
- expect(lzma_index_file_size(a) == stream_size * 4 + 4 + 8 + 12);
-
- expect(lzma_index_block_count(a) == SMALL_COUNT * 4);
- for (int i = SMALL_COUNT * 2; i >= 0; --i)
- expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
- ^ (i == 0));
-
- lzma_index_iter_rewind(&r);
- for (int i = SMALL_COUNT * 4; i >= 0; --i)
- expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
- ^ (i == 0));
-
- lzma_index_end(a, NULL);
-
- // Mix of empty and small
- a = create_empty();
- b = create_small();
- expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
- expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
- lzma_index_iter_init(&r, a);
- for (int i = SMALL_COUNT; i >= 0; --i)
- expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
- ^ (i == 0));
-
- lzma_index_end(a, NULL);
-
- // Big Indexes
- a = create_big();
- stream_size = lzma_index_stream_size(a);
- b = create_big();
- expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
- expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
- expect(lzma_index_file_size(a) == stream_size * 2 + 4);
- expect(lzma_index_stream_size(a) > stream_size);
- expect(lzma_index_stream_size(a) < stream_size * 2);
-
- b = create_big();
- c = create_big();
- expect(lzma_index_stream_padding(b, 8) == LZMA_OK);
- expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
- expect(lzma_index_stream_padding(a, 12) == LZMA_OK);
- expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
- expect(lzma_index_file_size(a) == stream_size * 4 + 4 + 8 + 12);
-
- lzma_index_iter_init(&r, a);
- for (int i = BIG_COUNT * 4; i >= 0; --i)
- expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
- ^ (i == 0));
-
- lzma_index_end(a, NULL);
-
- // Test for the bug fix 3d5a99ca373a4e86faf671226ca6487febb9eeac.
- // lzma_index_checks would previously only return the checks
- // for the last stream that was concatenated to the index.
- d = create_small();
- e = create_small();
- f = create_small();
-
- lzma_stream_flags crc32_flags = {
- .backward_size = LZMA_BACKWARD_SIZE_MIN,
- .check = LZMA_CHECK_CRC32
- };
- expect(lzma_index_stream_flags(d, &crc32_flags) == LZMA_OK);
+ // Testing basic init functionality.
+ // The init function should call rewind on the iterator.
+ lzma_index *first = lzma_index_init(NULL);
+ assert_true(first != NULL);
- lzma_stream_flags crc64_flags = {
- .backward_size = LZMA_BACKWARD_SIZE_MIN,
- .check = LZMA_CHECK_CRC64
- };
- expect(lzma_index_stream_flags(e, &crc64_flags) == LZMA_OK);
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
- lzma_stream_flags sha256_flags = {
- .backward_size = LZMA_BACKWARD_SIZE_MIN,
- .check = LZMA_CHECK_SHA256
- };
- expect(lzma_index_stream_flags(f, &sha256_flags) == LZMA_OK);
+ lzma_index *third = lzma_index_init(NULL);
+ assert_true(third != NULL);
- expect(lzma_index_checks(d) == (1U << LZMA_CHECK_CRC32));
- expect(lzma_index_checks(e) == (1U << LZMA_CHECK_CRC64));
- expect(lzma_index_checks(f) == (1U << LZMA_CHECK_SHA256));
+ assert_lzma_ret(lzma_index_cat(first, second, NULL), LZMA_OK);
+ assert_lzma_ret(lzma_index_cat(first, third, NULL), LZMA_OK);
- expect(lzma_index_cat(d, e, NULL) == LZMA_OK);
- expect(lzma_index_checks(d) == ((1U << LZMA_CHECK_CRC32) |
- (1U << LZMA_CHECK_CRC64)));
+ lzma_index_iter iter;
+ lzma_index_iter_init(&iter, first);
- expect(lzma_index_cat(d, f, NULL) == LZMA_OK);
- expect(lzma_index_checks(d) == ((1U << LZMA_CHECK_CRC32) |
- (1U << LZMA_CHECK_CRC64) |
- (1U << LZMA_CHECK_SHA256)));
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM));
+ assert_uint_eq(iter.stream.number, 1);
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM));
+ assert_uint_eq(iter.stream.number, 2);
- lzma_index_end(d, NULL);
+ lzma_index_iter_init(&iter, first);
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM));
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM));
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM));
+ assert_uint_eq(iter.stream.number, 3);
}
static void
-test_locate(void)
+test_lzma_index_iter_rewind(void)
{
- lzma_index *i = lzma_index_init(NULL);
- expect(i != NULL);
- lzma_index_iter r;
- lzma_index_iter_init(&r, i);
+ lzma_index *first = lzma_index_init(NULL);
+ assert_true(first != NULL);
+
+ lzma_index_iter iter;
+ lzma_index_iter_init(&iter, first);
+
+ // Append 3 Blocks and iterate over each. This is to test
+ // the LZMA_INDEX_ITER_BLOCK mode.
+ for (uint32_t i = 0; i < 3; i++) {
+ assert_lzma_ret(lzma_index_append(first, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_BLOCK));
+ assert_uint_eq(iter.block.number_in_file, i + 1);
+ }
+
+ // Rewind back to the begining and iterate over the Blocks again
+ lzma_index_iter_rewind(&iter);
+
+ // Should be able to re-iterate over the Blocks again.
+ for (uint32_t i = 0; i < 3; i++) {
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_BLOCK));
+ assert_uint_eq(iter.block.number_in_file, i + 1);
+ }
+
+ // Next concatenate two more lzma_indexes, iterate over them,
+ // rewind, and iterate over them again. This is to test
+ // the LZMA_INDEX_ITER_STREAM mode.
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
+
+ lzma_index *third = lzma_index_init(NULL);
+ assert_true(third != NULL);
+
+ assert_lzma_ret(lzma_index_cat(first, second, NULL), LZMA_OK);
+ assert_lzma_ret(lzma_index_cat(first, third, NULL), LZMA_OK);
+
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_STREAM));
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_STREAM));
+
+ assert_uint_eq(iter.stream.number, 3);
+
+ lzma_index_iter_rewind(&iter);
+
+ for (uint32_t i = 0; i < 3; i++) {
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_STREAM));
+ assert_uint_eq(iter.stream.number, i + 1);
+ }
+
+ lzma_index_end(first, NULL);
+}
+
+
+static void
+test_lzma_index_iter_next(void)
+{
+ lzma_index *first = lzma_index_init(NULL);
+ assert_true(first != NULL);
+
+ lzma_index_iter iter;
+ lzma_index_iter_init(&iter, first);
+
+ // First test bad mode values
+ for (uint32_t i = LZMA_INDEX_ITER_NONEMPTY_BLOCK + 1; i < 100; i++)
+ assert_true(lzma_index_iter_next(&iter, i));
+
+ // Test iterating over Blocks
+ assert_lzma_ret(lzma_index_append(first, NULL,
+ UNPADDED_SIZE_MIN, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(first, NULL,
+ UNPADDED_SIZE_MIN * 2, 10), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(first, NULL,
+ UNPADDED_SIZE_MIN * 3, 100), LZMA_OK);
+
+ // For Blocks, need to verify:
+ // - number_in_file (overall Block number)
+ // - compressed_file_offset
+ // - uncompressed_file_offset
+ // - number_in_stream (Block number relative to current Stream)
+ // - compressed_stream_offset
+ // - uncompressed_stream_offset
+ // - uncompressed_size
+ // - unpadded_size
+ // - total_size
+
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK));
+
+ // Verify Block data stored correctly
+ assert_uint_eq(iter.block.number_in_file, 1);
+
+ // Should start right after the Stream Header
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 0);
+ assert_uint_eq(iter.block.number_in_stream, 1);
+ assert_uint_eq(iter.block.compressed_stream_offset,
+ LZMA_STREAM_HEADER_SIZE);
+ assert_uint_eq(iter.block.uncompressed_stream_offset, 0);
+ assert_uint_eq(iter.block.unpadded_size, UNPADDED_SIZE_MIN);
+ assert_uint_eq(iter.block.total_size, vli_ceil4(UNPADDED_SIZE_MIN));
+
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK));
+
+ // Verify Block data stored correctly
+ assert_uint_eq(iter.block.number_in_file, 2);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE +
+ vli_ceil4(UNPADDED_SIZE_MIN));
+ assert_uint_eq(iter.block.uncompressed_file_offset, 1);
+ assert_uint_eq(iter.block.number_in_stream, 2);
+ assert_uint_eq(iter.block.compressed_stream_offset,
+ LZMA_STREAM_HEADER_SIZE +
+ vli_ceil4(UNPADDED_SIZE_MIN));
+ assert_uint_eq(iter.block.uncompressed_stream_offset, 1);
+ assert_uint_eq(iter.block.unpadded_size, UNPADDED_SIZE_MIN * 2);
+ assert_uint_eq(iter.block.total_size, vli_ceil4(UNPADDED_SIZE_MIN * 2));
+
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK));
+
+ // Verify Block data stored correctly
+ assert_uint_eq(iter.block.number_in_file, 3);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE +
+ vli_ceil4(UNPADDED_SIZE_MIN) +
+ vli_ceil4(UNPADDED_SIZE_MIN * 2));
+ assert_uint_eq(iter.block.uncompressed_file_offset, 11);
+ assert_uint_eq(iter.block.number_in_stream, 3);
+ assert_uint_eq(iter.block.compressed_stream_offset,
+ LZMA_STREAM_HEADER_SIZE +
+ vli_ceil4(UNPADDED_SIZE_MIN) +
+ vli_ceil4(UNPADDED_SIZE_MIN * 2));
+ assert_uint_eq(iter.block.uncompressed_stream_offset, 11);
+ assert_uint_eq(iter.block.unpadded_size, UNPADDED_SIZE_MIN * 3);
+ assert_uint_eq(iter.block.total_size,
+ vli_ceil4(UNPADDED_SIZE_MIN * 3));
+
+ // Only three Blocks were added, so this should return true
+ assert_true(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK));
+
+ const lzma_vli second_stream_compressed_start =
+ LZMA_STREAM_HEADER_SIZE * 2 +
+ vli_ceil4(UNPADDED_SIZE_MIN) +
+ vli_ceil4(UNPADDED_SIZE_MIN * 2) +
+ vli_ceil4(UNPADDED_SIZE_MIN * 3) +
+ lzma_index_size(first);
+ const lzma_vli second_stream_uncompressed_start = 1 + 10 + 100;
+
+ // Test iterating over Streams.
+ // The second Stream will have 0 Blocks
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
+
+ // Set Stream Flags for Stream 2
+ lzma_stream_flags flags = {
+ .version = 0,
+ .backward_size = LZMA_BACKWARD_SIZE_MIN,
+ .check = LZMA_CHECK_CRC32
+ };
+
+ assert_lzma_ret(lzma_index_stream_flags(second, &flags), LZMA_OK);
+
+ // The Second stream will have 8 bytes of Stream Padding
+ assert_lzma_ret(lzma_index_stream_padding(second, 8), LZMA_OK);
+
+ const lzma_vli second_stream_index_size = lzma_index_size(second);
+
+ // The third Stream will have 2 Blocks
+ lzma_index *third = lzma_index_init(NULL);
+ assert_true(third != NULL);
+
+ assert_lzma_ret(lzma_index_append(third, NULL, 32, 20), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(third, NULL, 64, 40), LZMA_OK);
+
+ const lzma_vli third_stream_index_size = lzma_index_size(third);
+
+ assert_lzma_ret(lzma_index_cat(first, second, NULL), LZMA_OK);
+ assert_lzma_ret(lzma_index_cat(first, third, NULL), LZMA_OK);
+
+ // For Streams, need to verify:
+ // - flags (Stream Flags)
+ // - number (Stream count)
+ // - block_count
+ // - compressed_offset
+ // - uncompressed_offset
+ // - compressed_size
+ // - uncompressed_size
+ // - padding (Stream Padding)
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM));
+
+ // Verify Stream
+ assert_uint_eq(iter.stream.flags->backward_size,
+ LZMA_BACKWARD_SIZE_MIN);
+ assert_uint_eq(iter.stream.flags->check, LZMA_CHECK_CRC32);
+ assert_uint_eq(iter.stream.number, 2);
+ assert_uint_eq(iter.stream.block_count, 0);
+ assert_uint_eq(iter.stream.compressed_offset,
+ second_stream_compressed_start);
+ assert_uint_eq(iter.stream.uncompressed_offset,
+ second_stream_uncompressed_start);
+ assert_uint_eq(iter.stream.compressed_size,
+ LZMA_STREAM_HEADER_SIZE * 2 +
+ second_stream_index_size);
+ assert_uint_eq(iter.stream.uncompressed_size, 0);
+ assert_uint_eq(iter.stream.padding, 8);
+
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM));
+
+ // Verify Stream
+ const lzma_vli third_stream_compressed_start =
+ second_stream_compressed_start +
+ LZMA_STREAM_HEADER_SIZE * 2 +
+ 8 + // Stream padding
+ second_stream_index_size;
+ const lzma_vli third_stream_uncompressed_start =
+ second_stream_uncompressed_start;
+
+ assert_uint_eq(iter.stream.number, 3);
+ assert_uint_eq(iter.stream.block_count, 2);
+ assert_uint_eq(iter.stream.compressed_offset,
+ third_stream_compressed_start);
+ assert_uint_eq(iter.stream.uncompressed_offset,
+ third_stream_uncompressed_start);
+ assert_uint_eq(iter.stream.compressed_size,
+ LZMA_STREAM_HEADER_SIZE * 2 +
+ 96 + // Total compressed size
+ third_stream_index_size);
+ assert_uint_eq(iter.stream.uncompressed_size, 60);
+ assert_uint_eq(iter.stream.padding, 0);
+
+ assert_true(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM));
+
+ // Even after a failing call to next with ITER_STREAM mode,
+ // should still be able to iterate over the 2 Blocks in
+ // Stream 3.
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK));
+
+ // Verify both Blocks
+
+ // Next call to iterate Block should return true because the
+ // first Block can already be read from the LZMA_INDEX_ITER_STREAM
+ // call.
+ assert_true(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK));
+
+ // Rewind to test LZMA_INDEX_ITER_ANY
+ lzma_index_iter_rewind(&iter);
+
+ // Iterate past the first three Blocks
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY));
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY));
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY));
+
+ // Iterate past the next Stream
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY));
+
+ // Iterate past the next Stream
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY));
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY));
+
+ // Last call should fail
+ assert_true(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY));
+
+ // Rewind to test LZMA_INDEX_ITER_NONEMPTY_BLOCK
+ lzma_index_iter_rewind(&iter);
+
+ // Iterate past the first three Blocks
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_NONEMPTY_BLOCK));
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_NONEMPTY_BLOCK));
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_NONEMPTY_BLOCK));
+
+ // Skip past the next Stream which has no Blocks.
+ // We will get to the first Block of the third Stream.
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_NONEMPTY_BLOCK));
+
+ // Iterate past the second (the last) Block in the third Stream
+ assert_false(lzma_index_iter_next(&iter,
+ LZMA_INDEX_ITER_NONEMPTY_BLOCK));
+
+ // Last call should fail since there is nothing left to iterate over.
+ assert_true(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY));
+
+ lzma_index_end(first, NULL);
+}
+
+
+static void
+test_lzma_index_iter_locate(void)
+{
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ lzma_index_iter iter;
+ lzma_index_iter_init(&iter, idx);
// Cannot locate anything from an empty Index.
- expect(lzma_index_iter_locate(&r, 0));
- expect(lzma_index_iter_locate(&r, 555));
+ assert_true(lzma_index_iter_locate(&iter, 0));
+ assert_true(lzma_index_iter_locate(&iter, 555));
// One empty Record: nothing is found since there's no uncompressed
// data.
- expect(lzma_index_append(i, NULL, 16, 0) == LZMA_OK);
- expect(lzma_index_iter_locate(&r, 0));
+ assert_lzma_ret(lzma_index_append(idx, NULL, 16, 0), LZMA_OK);
+ assert_true(lzma_index_iter_locate(&iter, 0));
// Non-empty Record and we can find something.
- expect(lzma_index_append(i, NULL, 32, 5) == LZMA_OK);
- expect(!lzma_index_iter_locate(&r, 0));
- expect(r.block.total_size == 32);
- expect(r.block.uncompressed_size == 5);
- expect(r.block.compressed_file_offset
- == LZMA_STREAM_HEADER_SIZE + 16);
- expect(r.block.uncompressed_file_offset == 0);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 32, 5), LZMA_OK);
+ assert_false(lzma_index_iter_locate(&iter, 0));
+ assert_uint_eq(iter.block.total_size, 32);
+ assert_uint_eq(iter.block.uncompressed_size, 5);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE + 16);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 0);
// Still cannot find anything past the end.
- expect(lzma_index_iter_locate(&r, 5));
+ assert_true(lzma_index_iter_locate(&iter, 5));
// Add the third Record.
- expect(lzma_index_append(i, NULL, 40, 11) == LZMA_OK);
-
- expect(!lzma_index_iter_locate(&r, 0));
- expect(r.block.total_size == 32);
- expect(r.block.uncompressed_size == 5);
- expect(r.block.compressed_file_offset
- == LZMA_STREAM_HEADER_SIZE + 16);
- expect(r.block.uncompressed_file_offset == 0);
-
- expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
- expect(r.block.total_size == 40);
- expect(r.block.uncompressed_size == 11);
- expect(r.block.compressed_file_offset
- == LZMA_STREAM_HEADER_SIZE + 16 + 32);
- expect(r.block.uncompressed_file_offset == 5);
-
- expect(!lzma_index_iter_locate(&r, 2));
- expect(r.block.total_size == 32);
- expect(r.block.uncompressed_size == 5);
- expect(r.block.compressed_file_offset
- == LZMA_STREAM_HEADER_SIZE + 16);
- expect(r.block.uncompressed_file_offset == 0);
-
- expect(!lzma_index_iter_locate(&r, 5));
- expect(r.block.total_size == 40);
- expect(r.block.uncompressed_size == 11);
- expect(r.block.compressed_file_offset
- == LZMA_STREAM_HEADER_SIZE + 16 + 32);
- expect(r.block.uncompressed_file_offset == 5);
-
- expect(!lzma_index_iter_locate(&r, 5 + 11 - 1));
- expect(r.block.total_size == 40);
- expect(r.block.uncompressed_size == 11);
- expect(r.block.compressed_file_offset
- == LZMA_STREAM_HEADER_SIZE + 16 + 32);
- expect(r.block.uncompressed_file_offset == 5);
-
- expect(lzma_index_iter_locate(&r, 5 + 11));
- expect(lzma_index_iter_locate(&r, 5 + 15));
+ assert_lzma_ret(lzma_index_append(idx, NULL, 40, 11), LZMA_OK);
+
+ assert_false(lzma_index_iter_locate(&iter, 0));
+ assert_uint_eq(iter.block.total_size, 32);
+ assert_uint_eq(iter.block.uncompressed_size, 5);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE + 16);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 0);
+
+ assert_false(lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK));
+ assert_uint_eq(iter.block.total_size, 40);
+ assert_uint_eq(iter.block.uncompressed_size, 11);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE + 16 + 32);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 5);
+
+ assert_false(lzma_index_iter_locate(&iter, 2));
+ assert_uint_eq(iter.block.total_size, 32);
+ assert_uint_eq(iter.block.uncompressed_size, 5);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE + 16);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 0);
+
+ assert_false(lzma_index_iter_locate(&iter, 5));
+ assert_uint_eq(iter.block.total_size, 40);
+ assert_uint_eq(iter.block.uncompressed_size, 11);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE + 16 + 32);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 5);
+
+ assert_false(lzma_index_iter_locate(&iter, 5 + 11 - 1));
+ assert_uint_eq(iter.block.total_size, 40);
+ assert_uint_eq(iter.block.uncompressed_size, 11);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE + 16 + 32);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 5);
+
+ assert_true(lzma_index_iter_locate(&iter, 5 + 11));
+ assert_true(lzma_index_iter_locate(&iter, 5 + 15));
// Large Index
- lzma_index_end(i, NULL);
- i = lzma_index_init(NULL);
- expect(i != NULL);
- lzma_index_iter_init(&r, i);
+ lzma_index_end(idx, NULL);
+ idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+ lzma_index_iter_init(&iter, idx);
- for (size_t n = 4; n <= 4 * 5555; n += 4)
- expect(lzma_index_append(i, NULL, n + 8, n) == LZMA_OK);
+ for (uint32_t n = 4; n <= 4 * 5555; n += 4)
+ assert_lzma_ret(lzma_index_append(idx, NULL, n + 8, n),
+ LZMA_OK);
- expect(lzma_index_block_count(i) == 5555);
+ assert_uint_eq(lzma_index_block_count(idx), 5555);
// First Record
- expect(!lzma_index_iter_locate(&r, 0));
- expect(r.block.total_size == 4 + 8);
- expect(r.block.uncompressed_size == 4);
- expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE);
- expect(r.block.uncompressed_file_offset == 0);
-
- expect(!lzma_index_iter_locate(&r, 3));
- expect(r.block.total_size == 4 + 8);
- expect(r.block.uncompressed_size == 4);
- expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE);
- expect(r.block.uncompressed_file_offset == 0);
+ assert_false(lzma_index_iter_locate(&iter, 0));
+ assert_uint_eq(iter.block.total_size, 4 + 8);
+ assert_uint_eq(iter.block.uncompressed_size, 4);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 0);
+
+ assert_false(lzma_index_iter_locate(&iter, 3));
+ assert_uint_eq(iter.block.total_size, 4 + 8);
+ assert_uint_eq(iter.block.uncompressed_size, 4);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 0);
// Second Record
- expect(!lzma_index_iter_locate(&r, 4));
- expect(r.block.total_size == 2 * 4 + 8);
- expect(r.block.uncompressed_size == 2 * 4);
- expect(r.block.compressed_file_offset
- == LZMA_STREAM_HEADER_SIZE + 4 + 8);
- expect(r.block.uncompressed_file_offset == 4);
+ assert_false(lzma_index_iter_locate(&iter, 4));
+ assert_uint_eq(iter.block.total_size, 2 * 4 + 8);
+ assert_uint_eq(iter.block.uncompressed_size, 2 * 4);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE + 4 + 8);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 4);
// Last Record
- expect(!lzma_index_iter_locate(
- &r, lzma_index_uncompressed_size(i) - 1));
- expect(r.block.total_size == 4 * 5555 + 8);
- expect(r.block.uncompressed_size == 4 * 5555);
- expect(r.block.compressed_file_offset == lzma_index_total_size(i)
+ assert_false(lzma_index_iter_locate(
+ &iter, lzma_index_uncompressed_size(idx) - 1));
+ assert_uint_eq(iter.block.total_size, 4 * 5555 + 8);
+ assert_uint_eq(iter.block.uncompressed_size, 4 * 5555);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ lzma_index_total_size(idx)
+ LZMA_STREAM_HEADER_SIZE - 4 * 5555 - 8);
- expect(r.block.uncompressed_file_offset
- == lzma_index_uncompressed_size(i) - 4 * 5555);
+ assert_uint_eq(iter.block.uncompressed_file_offset,
+ lzma_index_uncompressed_size(idx) - 4 * 5555);
// Allocation chunk boundaries. See INDEX_GROUP_SIZE in
// liblzma/common/index.c.
- const size_t group_multiple = 256 * 4;
- const size_t radius = 8;
- const size_t start = group_multiple - radius;
+ const uint32_t group_multiple = 256 * 4;
+ const uint32_t radius = 8;
+ const uint32_t start = group_multiple - radius;
lzma_vli ubase = 0;
lzma_vli tbase = 0;
- size_t n;
+ uint32_t n;
for (n = 1; n < start; ++n) {
ubase += n * 4;
tbase += n * 4 + 8;
}
while (n < start + 2 * radius) {
- expect(!lzma_index_iter_locate(&r, ubase + n * 4));
+ assert_false(lzma_index_iter_locate(&iter, ubase + n * 4));
- expect(r.block.compressed_file_offset == tbase + n * 4 + 8
+ assert_uint_eq(iter.block.compressed_file_offset,
+ tbase + n * 4 + 8
+ LZMA_STREAM_HEADER_SIZE);
- expect(r.block.uncompressed_file_offset == ubase + n * 4);
+ assert_uint_eq(iter.block.uncompressed_file_offset,
+ ubase + n * 4);
tbase += n * 4 + 8;
ubase += n * 4;
++n;
- expect(r.block.total_size == n * 4 + 8);
- expect(r.block.uncompressed_size == n * 4);
+ assert_uint_eq(iter.block.total_size, n * 4 + 8);
+ assert_uint_eq(iter.block.uncompressed_size, n * 4);
}
// Do it also backwards.
while (n > start) {
- expect(!lzma_index_iter_locate(&r, ubase + (n - 1) * 4));
+ assert_false(lzma_index_iter_locate(
+ &iter, ubase + (n - 1) * 4));
- expect(r.block.total_size == n * 4 + 8);
- expect(r.block.uncompressed_size == n * 4);
+ assert_uint_eq(iter.block.total_size, n * 4 + 8);
+ assert_uint_eq(iter.block.uncompressed_size, n * 4);
--n;
tbase -= n * 4 + 8;
ubase -= n * 4;
- expect(r.block.compressed_file_offset == tbase + n * 4 + 8
+ assert_uint_eq(iter.block.compressed_file_offset,
+ tbase + n * 4 + 8
+ LZMA_STREAM_HEADER_SIZE);
- expect(r.block.uncompressed_file_offset == ubase + n * 4);
+ assert_uint_eq(iter.block.uncompressed_file_offset,
+ ubase + n * 4);
}
// Test locating in concatenated Index.
- lzma_index_end(i, NULL);
- i = lzma_index_init(NULL);
- expect(i != NULL);
- lzma_index_iter_init(&r, i);
+ lzma_index_end(idx, NULL);
+ idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+ lzma_index_iter_init(&iter, idx);
for (n = 0; n < group_multiple; ++n)
- expect(lzma_index_append(i, NULL, 8, 0) == LZMA_OK);
- expect(lzma_index_append(i, NULL, 16, 1) == LZMA_OK);
- expect(!lzma_index_iter_locate(&r, 0));
- expect(r.block.total_size == 16);
- expect(r.block.uncompressed_size == 1);
- expect(r.block.compressed_file_offset
- == LZMA_STREAM_HEADER_SIZE + group_multiple * 8);
- expect(r.block.uncompressed_file_offset == 0);
-
- lzma_index_end(i, NULL);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 8, 0),
+ LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL, 16, 1), LZMA_OK);
+ assert_false(lzma_index_iter_locate(&iter, 0));
+ assert_uint_eq(iter.block.total_size, 16);
+ assert_uint_eq(iter.block.uncompressed_size, 1);
+ assert_uint_eq(iter.block.compressed_file_offset,
+ LZMA_STREAM_HEADER_SIZE + group_multiple * 8);
+ assert_uint_eq(iter.block.uncompressed_file_offset, 0);
+
+ lzma_index_end(idx, NULL);
}
static void
-test_corrupt(void)
+test_lzma_index_cat(void)
{
-#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
- const size_t alloc_size = 128 * 1024;
- uint8_t *buf = malloc(alloc_size);
- expect(buf != NULL);
- lzma_stream strm = LZMA_STREAM_INIT;
+ // Most complex tests for this function are done in other tests.
+ // This will mostly test basic functionality.
+
+ lzma_index *dest = lzma_index_init(NULL);
+ assert_true(dest != NULL);
+
+ lzma_index *src = lzma_index_init(NULL);
+ assert_true(src != NULL);
+
+ // First test NULL dest or src
+ assert_lzma_ret(lzma_index_cat(NULL, NULL, NULL), LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_cat(dest, NULL, NULL), LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_cat(NULL, src, NULL), LZMA_PROG_ERROR);
+
+ // Check for uncompressed size overflow
+ assert_lzma_ret(lzma_index_append(dest, NULL,
+ (UNPADDED_SIZE_MAX / 2) + 1, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(src, NULL,
+ (UNPADDED_SIZE_MAX / 2) + 1, 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_cat(dest, src, NULL), LZMA_DATA_ERROR);
+
+ // Check for compressed size overflow
+ dest = lzma_index_init(NULL);
+ assert_true(dest != NULL);
+
+ src = lzma_index_init(NULL);
+ assert_true(src != NULL);
+
+ assert_lzma_ret(lzma_index_append(dest, NULL,
+ UNPADDED_SIZE_MIN, LZMA_VLI_MAX - 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(src, NULL,
+ UNPADDED_SIZE_MIN, LZMA_VLI_MAX - 1), LZMA_OK);
+ assert_lzma_ret(lzma_index_cat(dest, src, NULL), LZMA_DATA_ERROR);
+
+ lzma_index_end(dest, NULL);
+ lzma_index_end(src, NULL);
+}
- lzma_index *i = create_empty();
- expect(lzma_index_append(i, NULL, 0, 1) == LZMA_PROG_ERROR);
- lzma_index_end(i, NULL);
-
- // Create a valid Index and corrupt it in different ways.
- i = create_small();
- expect(lzma_index_encoder(&strm, i) == LZMA_OK);
- succeed(coder_loop(&strm, NULL, 0, buf, 20,
- LZMA_STREAM_END, LZMA_RUN));
- lzma_index_end(i, NULL);
-
- // Wrong Index Indicator
- buf[0] ^= 1;
- expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
- succeed(decoder_loop_ret(&strm, buf, 1, LZMA_DATA_ERROR));
- buf[0] ^= 1;
-
- // Wrong Number of Records and thus CRC32 fails.
- --buf[1];
- expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
- succeed(decoder_loop_ret(&strm, buf, 10, LZMA_DATA_ERROR));
- ++buf[1];
-
- // Padding not NULs
- buf[15] ^= 1;
- expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
- succeed(decoder_loop_ret(&strm, buf, 16, LZMA_DATA_ERROR));
- lzma_end(&strm);
- free(buf);
-#endif
+// Helper function for test_lzma_index_dup().
+static bool
+index_is_equal(const lzma_index *a, const lzma_index *b)
+{
+ // Compare only the Stream and Block sizes and offsets.
+ lzma_index_iter ra, rb;
+ lzma_index_iter_init(&ra, a);
+ lzma_index_iter_init(&rb, b);
+
+ while (true) {
+ bool reta = lzma_index_iter_next(&ra, LZMA_INDEX_ITER_ANY);
+ bool retb = lzma_index_iter_next(&rb, LZMA_INDEX_ITER_ANY);
+
+ // If both iterators finish at the same time, then the Indexes
+ // are identical.
+ if (reta)
+ return retb;
+
+ if (ra.stream.number != rb.stream.number
+ || ra.stream.block_count
+ != rb.stream.block_count
+ || ra.stream.compressed_offset
+ != rb.stream.compressed_offset
+ || ra.stream.uncompressed_offset
+ != rb.stream.uncompressed_offset
+ || ra.stream.compressed_size
+ != rb.stream.compressed_size
+ || ra.stream.uncompressed_size
+ != rb.stream.uncompressed_size
+ || ra.stream.padding
+ != rb.stream.padding)
+ return false;
+
+ if (ra.stream.block_count == 0)
+ continue;
+
+ if (ra.block.number_in_file != rb.block.number_in_file
+ || ra.block.compressed_file_offset
+ != rb.block.compressed_file_offset
+ || ra.block.uncompressed_file_offset
+ != rb.block.uncompressed_file_offset
+ || ra.block.number_in_stream
+ != rb.block.number_in_stream
+ || ra.block.compressed_stream_offset
+ != rb.block.compressed_stream_offset
+ || ra.block.uncompressed_stream_offset
+ != rb.block.uncompressed_stream_offset
+ || ra.block.uncompressed_size
+ != rb.block.uncompressed_size
+ || ra.block.unpadded_size
+ != rb.block.unpadded_size
+ || ra.block.total_size
+ != rb.block.total_size)
+ return false;
+ }
}
@@ -690,47 +1245,440 @@ my_alloc(void *opaque, size_t a, size_t b)
return malloc(a * b);
}
-static const lzma_allocator my_allocator = { &my_alloc, NULL, NULL };
+static const lzma_allocator test_index_dup_alloc = { &my_alloc, NULL, NULL };
-int
-main(void)
+static void
+test_lzma_index_dup(void)
{
- test_equal();
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
- test_overflow();
+ // Test for the bug fix 21515d79d778b8730a434f151b07202d52a04611:
+ // liblzma: Fix lzma_index_dup() for empty Streams.
+ assert_lzma_ret(lzma_index_stream_padding(idx, 4), LZMA_OK);
+ lzma_index *copy = lzma_index_dup(idx, NULL);
+ assert_true(copy != NULL);
+ assert_true(index_is_equal(idx, copy));
+ lzma_index_end(copy, NULL);
- lzma_index *i = create_empty();
- test_many(i);
- lzma_index_end(i, NULL);
+ // Test for the bug fix 3bf857edfef51374f6f3fffae3d817f57d3264a0:
+ // liblzma: Fix a memory leak in error path of lzma_index_dup().
+ // Use Valgrind to see that there are no leaks.
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, 10), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN * 2, 100), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN * 3, 1000), LZMA_OK);
- i = create_small();
- test_many(i);
- lzma_index_end(i, NULL);
+ assert_true(lzma_index_dup(idx, &test_index_dup_alloc) == NULL);
- i = create_big();
- test_many(i);
- lzma_index_end(i, NULL);
+ // Test a few streams and blocks
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
- test_cat();
+ assert_lzma_ret(lzma_index_stream_padding(second, 16), LZMA_OK);
- test_locate();
+ lzma_index *third = lzma_index_init(NULL);
+ assert_true(third != NULL);
- test_corrupt();
+ assert_lzma_ret(lzma_index_append(third, NULL,
+ UNPADDED_SIZE_MIN * 10, 40), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(third, NULL,
+ UNPADDED_SIZE_MIN * 20, 400), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(third, NULL,
+ UNPADDED_SIZE_MIN * 30, 4000), LZMA_OK);
- // Test for the bug fix 21515d79d778b8730a434f151b07202d52a04611:
- // liblzma: Fix lzma_index_dup() for empty Streams.
- i = create_empty();
- expect(lzma_index_stream_padding(i, 4) == LZMA_OK);
- test_copy(i);
- lzma_index_end(i, NULL);
+ assert_lzma_ret(lzma_index_cat(idx, second, NULL), LZMA_OK);
+ assert_lzma_ret(lzma_index_cat(idx, third, NULL), LZMA_OK);
+
+ copy = lzma_index_dup(idx, NULL);
+ assert_true(copy != NULL);
+ assert_true(index_is_equal(idx, copy));
+
+ lzma_index_end(idx, NULL);
+}
+
+#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
+static void
+verify_index_buffer(const lzma_index *idx, const uint8_t *buffer,
+ const size_t buffer_size)
+{
+ lzma_index_iter iter;
+ lzma_index_iter_init(&iter, idx);
+
+ size_t buffer_pos = 0;
+
+ // Verify Index Indicator
+ assert_uint_eq(buffer[buffer_pos++], 0);
+
+ // Get Number of Records
+ lzma_vli number_of_records = 0;
+ lzma_vli block_count = 0;
+ assert_lzma_ret(lzma_vli_decode(&number_of_records, NULL, buffer,
+ &buffer_pos, buffer_size), LZMA_OK);
+
+ while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_ANY)) {
+ // Verify each Record (Unpadded Size, then Uncompressed Size).
+ // Verify Unpadded Size.
+ lzma_vli unpadded_size, uncompressed_size;
+ assert_lzma_ret(lzma_vli_decode(&unpadded_size,
+ NULL, buffer, &buffer_pos,
+ buffer_size), LZMA_OK);
+ assert_uint_eq(unpadded_size,
+ iter.block.unpadded_size);
+
+ // Verify Uncompressed Size
+ assert_lzma_ret(lzma_vli_decode(&uncompressed_size,
+ NULL, buffer, &buffer_pos,
+ buffer_size), LZMA_OK);
+ assert_uint_eq(uncompressed_size,
+ iter.block.uncompressed_size);
+
+ block_count++;
+ }
+
+ // Verify Number of Records
+ assert_uint_eq(number_of_records, block_count);
+
+ // Verify Index Padding
+ for (; buffer_pos % 4 != 0; buffer_pos++)
+ assert_uint_eq(buffer[buffer_pos], 0);
+
+ // Verify CRC32
+ uint32_t crc32 = lzma_crc32(buffer, buffer_pos, 0);
+ assert_uint_eq(read32le(buffer + buffer_pos), crc32);
+}
+
+
+// In a few places the Index size is needed as a size_t but lzma_index_size()
+// returns lzma_vli.
+static size_t
+get_index_size(const lzma_index *idx)
+{
+ const lzma_vli size = lzma_index_size(idx);
+ assert_uint(size, <, SIZE_MAX);
+ return (size_t)size;
+}
+#endif
- // Test for the bug fix 3bf857edfef51374f6f3fffae3d817f57d3264a0:
- // liblzma: Fix a memory leak in error path of lzma_index_dup().
- // Use Valgrind to see that there are no leaks.
- i = create_small();
- expect(lzma_index_dup(i, &my_allocator) == NULL);
- lzma_index_end(i, NULL);
- return 0;
+static void
+test_lzma_index_encoder(void)
+{
+#if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
+ assert_skip("Encoder or decoder support disabled");
+#else
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ lzma_stream strm = LZMA_STREAM_INIT;
+
+ // First do basic NULL checks
+ assert_lzma_ret(lzma_index_encoder(NULL, NULL), LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_encoder(&strm, NULL), LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_encoder(NULL, idx), LZMA_PROG_ERROR);
+
+ // Append three small Blocks
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, 10), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN * 2, 100), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN * 3, 1000), LZMA_OK);
+
+ // Encode this lzma_index into a buffer
+ size_t buffer_size = get_index_size(idx);
+ uint8_t *buffer = tuktest_malloc(buffer_size);
+
+ assert_lzma_ret(lzma_index_encoder(&strm, idx), LZMA_OK);
+
+ strm.avail_out = buffer_size;
+ strm.next_out = buffer;
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END);
+ assert_uint_eq(strm.avail_out, 0);
+
+ lzma_end(&strm);
+
+ verify_index_buffer(idx, buffer, buffer_size);
+
+ // Test with multiple Streams concatenated into 1 Index
+ lzma_index *second = lzma_index_init(NULL);
+ assert_true(second != NULL);
+
+ // Include 1 Block
+ assert_lzma_ret(lzma_index_append(second, NULL,
+ UNPADDED_SIZE_MIN * 4, 20), LZMA_OK);
+
+ // Include Stream Padding
+ assert_lzma_ret(lzma_index_stream_padding(second, 16), LZMA_OK);
+
+ assert_lzma_ret(lzma_index_cat(idx, second, NULL), LZMA_OK);
+ buffer_size = get_index_size(idx);
+ buffer = tuktest_malloc(buffer_size);
+ assert_lzma_ret(lzma_index_encoder(&strm, idx), LZMA_OK);
+
+ strm.avail_out = buffer_size;
+ strm.next_out = buffer;
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END);
+ assert_uint_eq(strm.avail_out, 0);
+
+ verify_index_buffer(idx, buffer, buffer_size);
+
+ lzma_end(&strm);
+#endif
+}
+
+static void
+generate_index_decode_buffer(void)
+{
+#ifdef HAVE_ENCODERS
+ decode_test_index = lzma_index_init(NULL);
+ if (decode_test_index == NULL)
+ return;
+
+ // Add 4 Blocks
+ for (uint32_t i = 1; i < 5; i++)
+ if (lzma_index_append(decode_test_index, NULL,
+ 0x1000 * i, 0x100 * i) != LZMA_OK)
+ return;
+
+ size_t size = lzma_index_size(decode_test_index);
+ decode_buffer = tuktest_malloc(size);
+
+ if (lzma_index_buffer_encode(decode_test_index,
+ decode_buffer, &decode_buffer_size, size) != LZMA_OK)
+ decode_buffer_size = 0;
+#endif
+}
+
+
+#ifdef HAVE_DECODERS
+static void
+decode_index(const uint8_t *buffer, const size_t size, lzma_stream *strm,
+ lzma_ret expected_error)
+{
+ strm->avail_in = size;
+ strm->next_in = buffer;
+ assert_lzma_ret(lzma_code(strm, LZMA_FINISH), expected_error);
+}
+#endif
+
+
+static void
+test_lzma_index_decoder(void)
+{
+#ifndef HAVE_DECODERS
+ assert_skip("Decoder support disabled");
+#else
+ if (decode_buffer_size == 0)
+ assert_skip("Could not initialize decode test buffer");
+
+ lzma_stream strm = LZMA_STREAM_INIT;
+
+ assert_lzma_ret(lzma_index_decoder(NULL, NULL, MEMLIMIT),
+ LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_decoder(&strm, NULL, MEMLIMIT),
+ LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_decoder(NULL, &decode_test_index,
+ MEMLIMIT), LZMA_PROG_ERROR);
+
+ // Do actual decode
+ lzma_index *idx;
+ assert_lzma_ret(lzma_index_decoder(&strm, &idx, MEMLIMIT),
+ LZMA_OK);
+
+ decode_index(decode_buffer, decode_buffer_size, &strm,
+ LZMA_STREAM_END);
+
+ // Compare results with expected
+ assert_true(index_is_equal(decode_test_index, idx));
+
+ lzma_index_end(idx, NULL);
+
+ // Test again with too low memory limit
+ assert_lzma_ret(lzma_index_decoder(&strm, &idx, 0), LZMA_OK);
+
+ decode_index(decode_buffer, decode_buffer_size, &strm,
+ LZMA_MEMLIMIT_ERROR);
+
+ uint8_t *corrupt_buffer = tuktest_malloc(decode_buffer_size);
+ memcpy(corrupt_buffer, decode_buffer, decode_buffer_size);
+
+ assert_lzma_ret(lzma_index_decoder(&strm, &idx, MEMLIMIT),
+ LZMA_OK);
+
+ // First corrupt the Index Indicator
+ corrupt_buffer[0] ^= 1;
+ decode_index(corrupt_buffer, decode_buffer_size, &strm,
+ LZMA_DATA_ERROR);
+ corrupt_buffer[0] ^= 1;
+
+ // Corrupt something in the middle of Index
+ corrupt_buffer[decode_buffer_size / 2] ^= 1;
+ assert_lzma_ret(lzma_index_decoder(&strm, &idx, MEMLIMIT),
+ LZMA_OK);
+ decode_index(corrupt_buffer, decode_buffer_size, &strm,
+ LZMA_DATA_ERROR);
+ corrupt_buffer[decode_buffer_size / 2] ^= 1;
+
+ // Corrupt CRC32
+ corrupt_buffer[decode_buffer_size - 1] ^= 1;
+ assert_lzma_ret(lzma_index_decoder(&strm, &idx, MEMLIMIT),
+ LZMA_OK);
+ decode_index(corrupt_buffer, decode_buffer_size, &strm,
+ LZMA_DATA_ERROR);
+ corrupt_buffer[decode_buffer_size - 1] ^= 1;
+
+ // Corrupt Index Padding by setting it to non-zero
+ corrupt_buffer[decode_buffer_size - 5] ^= 1;
+ assert_lzma_ret(lzma_index_decoder(&strm, &idx, MEMLIMIT),
+ LZMA_OK);
+ decode_index(corrupt_buffer, decode_buffer_size, &strm,
+ LZMA_DATA_ERROR);
+ corrupt_buffer[decode_buffer_size - 1] ^= 1;
+
+ lzma_end(&strm);
+#endif
+}
+
+
+static void
+test_lzma_index_buffer_encode(void)
+{
+#if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
+ assert_skip("Encoder or decoder support disabled");
+#else
+ // More simple test than test_lzma_index_encoder() because
+ // currently lzma_index_buffer_encode() is mostly a wrapper
+ // around lzma_index_encoder() anyway.
+ lzma_index *idx = lzma_index_init(NULL);
+ assert_true(idx != NULL);
+
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN, 10), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN * 2, 100), LZMA_OK);
+ assert_lzma_ret(lzma_index_append(idx, NULL,
+ UNPADDED_SIZE_MIN * 3, 1000), LZMA_OK);
+
+ size_t buffer_size = get_index_size(idx);
+ uint8_t *buffer = tuktest_malloc(buffer_size);
+ size_t out_pos = 1;
+
+ // First test bad arguments
+ assert_lzma_ret(lzma_index_buffer_encode(NULL, NULL, NULL, 0),
+ LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_buffer_encode(idx, NULL, NULL, 0),
+ LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_buffer_encode(idx, buffer, NULL, 0),
+ LZMA_PROG_ERROR);
+ assert_lzma_ret(lzma_index_buffer_encode(idx, buffer, &out_pos,
+ 0), LZMA_PROG_ERROR);
+ out_pos = 0;
+ assert_lzma_ret(lzma_index_buffer_encode(idx, buffer, &out_pos,
+ 1), LZMA_BUF_ERROR);
+
+ // Do encoding
+ assert_lzma_ret(lzma_index_buffer_encode(idx, buffer, &out_pos,
+ buffer_size), LZMA_OK);
+ assert_uint_eq(out_pos, buffer_size);
+
+ // Validate results
+ verify_index_buffer(idx, buffer, buffer_size);
+#endif
+}
+
+
+static void
+test_lzma_index_buffer_decode(void)
+{
+#ifndef HAVE_DECODERS
+ assert_skip("Decoder support disabled");
+#else
+ if (decode_buffer_size == 0)
+ assert_skip("Could not initialize decode test buffer");
+
+ // Simple test since test_lzma_index_decoder() covers most of the
+ // lzma_index_buffer_decode() code anyway.
+
+ // First test NULL checks
+ assert_lzma_ret(lzma_index_buffer_decode(NULL, NULL, NULL, NULL,
+ NULL, 0), LZMA_PROG_ERROR);
+
+ lzma_index *idx;
+ uint64_t memlimit = MEMLIMIT;
+ size_t in_pos = 0;
+
+ assert_lzma_ret(lzma_index_buffer_decode(&idx, NULL, NULL, NULL,
+ NULL, 0), LZMA_PROG_ERROR);
+
+ assert_lzma_ret(lzma_index_buffer_decode(&idx, &memlimit, NULL,
+ NULL, NULL, 0), LZMA_PROG_ERROR);
+
+ assert_lzma_ret(lzma_index_buffer_decode(&idx, &memlimit, NULL,
+ decode_buffer, NULL, 0), LZMA_PROG_ERROR);
+
+ assert_lzma_ret(lzma_index_buffer_decode(&idx, &memlimit, NULL,
+ decode_buffer, NULL, 0), LZMA_PROG_ERROR);
+
+ assert_lzma_ret(lzma_index_buffer_decode(&idx, &memlimit, NULL,
+ decode_buffer, &in_pos, 0), LZMA_DATA_ERROR);
+
+ in_pos = 1;
+ assert_lzma_ret(lzma_index_buffer_decode(&idx, &memlimit, NULL,
+ decode_buffer, &in_pos, 0), LZMA_PROG_ERROR);
+ in_pos = 0;
+
+ // Test expected successful decode
+ assert_lzma_ret(lzma_index_buffer_decode(&idx, &memlimit, NULL,
+ decode_buffer, &in_pos, decode_buffer_size), LZMA_OK);
+
+ assert_true(index_is_equal(decode_test_index, idx));
+
+ // Test too small memlimit
+ in_pos = 0;
+ memlimit = 1;
+ assert_lzma_ret(lzma_index_buffer_decode(&idx, &memlimit, NULL,
+ decode_buffer, &in_pos, decode_buffer_size),
+ LZMA_MEMLIMIT_ERROR);
+ assert_uint(memlimit, >, 1);
+ assert_uint(memlimit, <, MEMLIMIT);
+#endif
+}
+
+
+extern int
+main(int argc, char **argv)
+{
+ tuktest_start(argc, argv);
+ generate_index_decode_buffer();
+ tuktest_run(test_lzma_index_memusage);
+ tuktest_run(test_lzma_index_memused);
+ tuktest_run(test_lzma_index_append);
+ tuktest_run(test_lzma_index_stream_flags);
+ tuktest_run(test_lzma_index_checks);
+ tuktest_run(test_lzma_index_stream_padding);
+ tuktest_run(test_lzma_index_stream_count);
+ tuktest_run(test_lzma_index_block_count);
+ tuktest_run(test_lzma_index_size);
+ tuktest_run(test_lzma_index_stream_size);
+ tuktest_run(test_lzma_index_total_size);
+ tuktest_run(test_lzma_index_file_size);
+ tuktest_run(test_lzma_index_uncompressed_size);
+ tuktest_run(test_lzma_index_iter_init);
+ tuktest_run(test_lzma_index_iter_rewind);
+ tuktest_run(test_lzma_index_iter_next);
+ tuktest_run(test_lzma_index_iter_locate);
+ tuktest_run(test_lzma_index_cat);
+ tuktest_run(test_lzma_index_dup);
+ tuktest_run(test_lzma_index_encoder);
+ tuktest_run(test_lzma_index_decoder);
+ tuktest_run(test_lzma_index_buffer_encode);
+ tuktest_run(test_lzma_index_buffer_decode);
+ lzma_index_end(decode_test_index, NULL);
+ return tuktest_end();
}