diff --git a/tests/Makefile.am b/tests/Makefile.am index ae63f464..ebf2df92 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,7 +44,8 @@ check_PROGRAMS = \ test_filter_flags \ test_block_header \ test_index \ - test_bcj_exact_size + test_bcj_exact_size \ + test_vli TESTS = \ test_check \ @@ -54,6 +55,7 @@ TESTS = \ test_block_header \ test_index \ test_bcj_exact_size \ + test_vli \ test_files.sh \ test_compress_prepared_bcj_sparc \ test_compress_prepared_bcj_x86 \ diff --git a/tests/test_vli.c b/tests/test_vli.c new file mode 100644 index 00000000..2219ef88 --- /dev/null +++ b/tests/test_vli.c @@ -0,0 +1,308 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_vli.c +/// \brief Tests liblzma vli functions +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +// Pre-encoded VLI values for testing +// VLI can have between 1 and 9 bytes when encoded +// They are encoded little endian where all but the last +// byte must have the leading 1 bit set +static uint8_t one_byte[1] = {0x25}; +static lzma_vli one_byte_value = 37; + +static uint8_t two_bytes[2] = {0x80, 0x56}; +static lzma_vli two_byte_value = 11008; + +static uint8_t three_bytes[3] = {0x99, 0x92, 0x20}; +static lzma_vli three_byte_value = 526617; + +static uint8_t four_bytes[4] = {0x97, 0x83, 0x94, 0x47}; +static lzma_vli four_byte_value = 149225879; + +static uint8_t five_bytes[5] = {0xA6, 0x92, 0x88, 0x89, 0x32}; +static lzma_vli five_byte_value = 13440780582; + +static uint8_t six_bytes[6] = {0xA9, 0x84, 0x99, 0x82, 0x94, 0x12}; +static lzma_vli six_byte_value = 623848604201; + +static uint8_t seven_bytes[7] = {0x90, 0x80, 0x90, 0x80, 0x90, 0x80, 0x79}; +static lzma_vli seven_byte_value = 532167923073040; + +static uint8_t eight_bytes[8] = {0x91, 0x87, 0xF2, 0xB2, 0xC2, 0xD2, 0x93, + 0x63}; +static lzma_vli eight_byte_value = 55818443594433425; + +static uint8_t nine_bytes[9] = {0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, + 0xF1, 0x1}; +static lzma_vli nine_byte_value = 136100349976529025; + + +static void +test_lzma_vli_size(void) +{ + // First test invalid VLI values (should return 0) + // VLI values are unsigned + assert_int_eq(lzma_vli_size(-1), 0); + // VLI UNKNOWN is an invalid VLI + assert_uint_eq(lzma_vli_size(LZMA_VLI_UNKNOWN), 0); + // Loop over a few VLI values just over the maximum + for (uint64_t i = LZMA_VLI_MAX + 1; i < LZMA_VLI_MAX + 10; i++) + assert_uint_eq(lzma_vli_size(i), 0); + + // Number should increment every seven set bits + lzma_vli vli = 1; + for (uint32_t i = 1; i < LZMA_VLI_BYTES_MAX; i++, vli <<= 7) { + // Test the base value and a few others around it + assert_uint_eq(lzma_vli_size(vli), i); + assert_uint_eq(lzma_vli_size(vli * 2), i); + assert_uint_eq(lzma_vli_size(vli + 10), i); + assert_uint_eq(lzma_vli_size(vli * 3 + 39), i); + } +} + + +// Helper function for test_lzma_vli_encode +// Encodes an input VLI and compares against a pre-computed value +static void +encode_single_call_mode(lzma_vli input, uint8_t* expected, uint32_t expected_len) +{ + uint8_t out[LZMA_VLI_BYTES_MAX]; + size_t out_pos = 0; + assert_lzma_ret(lzma_vli_encode(input, NULL, out, &out_pos, + expected_len), LZMA_OK); + assert_uint_eq(out_pos, expected_len); + assert_array_eq(out, expected, expected_len); + +} + + +// Helper function for test_lzma_vli_encode +// Encodes an input VLI one byte at a time with the multi call +// method. Then compares agaist a pre-computed value +static void +encode_multi_call_mode(lzma_vli input, uint8_t* expected, + uint32_t expected_len) +{ + uint8_t out[LZMA_VLI_BYTES_MAX]; + size_t out_pos = 0; + size_t vli_pos = 0; + + for (uint32_t i = 1; i < expected_len; i++) { + assert_lzma_ret(lzma_vli_encode(input, &vli_pos, out, + &out_pos, i), LZMA_OK); + assert_uint_eq(out_pos, i); + assert_uint_eq(vli_pos, i); + } + assert_lzma_ret(lzma_vli_encode(input, &vli_pos, out, &out_pos, + expected_len), LZMA_STREAM_END); + assert_uint_eq(out_pos, expected_len); + assert_uint_eq(vli_pos, expected_len); + assert_array_eq(out, expected, expected_len); +} + + +static void +test_lzma_vli_encode(void) +{ + size_t vli_pos = 0; + uint8_t out[LZMA_VLI_BYTES_MAX]; + uint8_t zeros[LZMA_VLI_BYTES_MAX]; + memzero(out, LZMA_VLI_BYTES_MAX); + memzero(zeros, LZMA_VLI_BYTES_MAX); + size_t out_pos = 0; + + // First test invalid input parameters + // VLI invalid + assert_lzma_ret(lzma_vli_encode(LZMA_VLI_UNKNOWN, &vli_pos, out, + &out_pos, sizeof(out)), LZMA_PROG_ERROR); + // Failure should not change params + assert_uint_eq(vli_pos, 0); + assert_uint_eq(out_pos, 0); + assert_array_eq(out, zeros, LZMA_VLI_BYTES_MAX); + + assert_lzma_ret(lzma_vli_encode(LZMA_VLI_MAX + 1, &vli_pos, out, + &out_pos, sizeof(out)), LZMA_PROG_ERROR); + assert_uint_eq(vli_pos, 0); + assert_uint_eq(out_pos, 0); + assert_array_eq(out, zeros, LZMA_VLI_BYTES_MAX); + + // 0 output size + assert_lzma_ret(lzma_vli_encode(one_byte_value, &vli_pos, out, + &out_pos, 0), LZMA_BUF_ERROR); + assert_uint_eq(vli_pos, 0); + assert_uint_eq(out_pos, 0); + assert_array_eq(out, zeros, LZMA_VLI_BYTES_MAX); + + // Size of VLI does not fit in buffer + size_t phony_out_pos = 3; + assert_lzma_ret(lzma_vli_encode(one_byte_value, NULL, out, + &phony_out_pos, 2), LZMA_PROG_ERROR); + + assert_lzma_ret(lzma_vli_encode(LZMA_VLI_MAX / 2, NULL, out, + &out_pos, 2), LZMA_PROG_ERROR); + + // Test single-call mode (using vli_pos as NULL) + encode_single_call_mode(one_byte_value, one_byte, + sizeof(one_byte)); + encode_single_call_mode(two_byte_value, two_bytes, + sizeof(two_bytes)); + encode_single_call_mode(three_byte_value, three_bytes, + sizeof(three_bytes)); + encode_single_call_mode(four_byte_value, four_bytes, + sizeof(four_bytes)); + encode_single_call_mode(five_byte_value, five_bytes, + sizeof(five_bytes)); + encode_single_call_mode(six_byte_value, six_bytes, + sizeof(six_bytes)); + encode_single_call_mode(seven_byte_value, seven_bytes, + sizeof(seven_bytes)); + encode_single_call_mode(eight_byte_value, eight_bytes, + sizeof(eight_bytes)); + encode_single_call_mode(nine_byte_value, nine_bytes, + sizeof(nine_bytes)); + + // Test multi-call mode + encode_multi_call_mode(one_byte_value, one_byte, + sizeof(one_byte)); + encode_multi_call_mode(two_byte_value, two_bytes, + sizeof(two_bytes)); + encode_multi_call_mode(three_byte_value, three_bytes, + sizeof(three_bytes)); + encode_multi_call_mode(four_byte_value, four_bytes, + sizeof(four_bytes)); + encode_multi_call_mode(five_byte_value, five_bytes, + sizeof(five_bytes)); + encode_multi_call_mode(six_byte_value, six_bytes, + sizeof(six_bytes)); + encode_multi_call_mode(seven_byte_value, seven_bytes, + sizeof(seven_bytes)); + encode_multi_call_mode(eight_byte_value, eight_bytes, + sizeof(eight_bytes)); + encode_multi_call_mode(nine_byte_value, nine_bytes, + sizeof(nine_bytes)); +} + + +static void +decode_single_call_mode(uint8_t* input, uint32_t input_len, lzma_vli expected) +{ + lzma_vli out = 0; + size_t in_pos = 0; + + assert_lzma_ret(lzma_vli_decode(&out, NULL, input, &in_pos, + input_len), LZMA_OK); + assert_uint_eq(in_pos, input_len); + assert_uint_eq(out, expected); +} + + +static void +decode_multi_call_mode(uint8_t* input, uint32_t input_len, lzma_vli expected) +{ + lzma_vli out = 0; + size_t in_pos = 0; + size_t vli_pos = 0; + + for (uint32_t i = 1; i < input_len; i++) { + assert_lzma_ret(lzma_vli_decode(&out, &vli_pos, input, + &in_pos, i), LZMA_OK); + assert_uint_eq(in_pos, i); + assert_uint_eq(vli_pos, i); + } + + assert_lzma_ret(lzma_vli_decode(&out, &vli_pos, input, &in_pos, + input_len), LZMA_STREAM_END); + assert_uint_eq(in_pos, input_len); + assert_uint_eq(vli_pos, input_len); + assert_uint_eq(out, expected); +} + +static void +test_lzma_vli_decode(void) +{ + lzma_vli out = 0; + size_t in_pos = 0; + + // First test invalid input params + // 0 in_size + assert_lzma_ret(lzma_vli_decode(&out, NULL, one_byte, &in_pos, 0), + LZMA_DATA_ERROR); + assert_uint_eq(out, 0); + assert_uint_eq(in_pos, 0); + + // VLI encoded is invalid (last digit has leading 1 set) + uint8_t invalid_vli[3] = {0x80, 0x80, 0x80}; + assert_lzma_ret(lzma_vli_decode(&out, NULL, invalid_vli, &in_pos, + sizeof(invalid_vli)), LZMA_DATA_ERROR); + + // Bad vli_pos + size_t vli_pos = LZMA_VLI_BYTES_MAX; + assert_lzma_ret(lzma_vli_decode(&out, &vli_pos, invalid_vli, &in_pos, + sizeof(invalid_vli)), LZMA_PROG_ERROR); + + // Bad in_pos + in_pos = sizeof(invalid_vli); + assert_lzma_ret(lzma_vli_decode(&out, &in_pos, invalid_vli, &in_pos, + sizeof(invalid_vli)), LZMA_BUF_ERROR); + + // Test single call mode + decode_single_call_mode(one_byte, sizeof(one_byte), + one_byte_value); + decode_single_call_mode(two_bytes, sizeof(two_bytes), + two_byte_value); + decode_single_call_mode(three_bytes, sizeof(three_bytes), + three_byte_value); + decode_single_call_mode(four_bytes, sizeof(four_bytes), + four_byte_value); + decode_single_call_mode(five_bytes, sizeof(five_bytes), + five_byte_value); + decode_single_call_mode(six_bytes, sizeof(six_bytes), + six_byte_value); + decode_single_call_mode(seven_bytes, sizeof(seven_bytes), + seven_byte_value); + decode_single_call_mode(eight_bytes, sizeof(eight_bytes), + eight_byte_value); + decode_single_call_mode(nine_bytes, sizeof(nine_bytes), + nine_byte_value); + + // Test multi call mode + decode_multi_call_mode(one_byte, sizeof(one_byte), + one_byte_value); + decode_multi_call_mode(two_bytes, sizeof(two_bytes), + two_byte_value); + decode_multi_call_mode(three_bytes, sizeof(three_bytes), + three_byte_value); + decode_multi_call_mode(four_bytes, sizeof(four_bytes), + four_byte_value); + decode_multi_call_mode(five_bytes, sizeof(five_bytes), + five_byte_value); + decode_multi_call_mode(six_bytes, sizeof(six_bytes), + six_byte_value); + decode_multi_call_mode(seven_bytes, sizeof(seven_bytes), + seven_byte_value); + decode_multi_call_mode(eight_bytes, sizeof(eight_bytes), + eight_byte_value); + decode_multi_call_mode(nine_bytes, sizeof(nine_bytes), + nine_byte_value); +} + + +extern int +main(int argc, char **argv) +{ + tuktest_start(argc, argv); + tuktest_run(test_lzma_vli_size); + tuktest_run(test_lzma_vli_encode); + tuktest_run(test_lzma_vli_decode); + return tuktest_end(); +}