summaryrefslogtreecommitdiffstats
path: root/tests/test_check.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/test_check.c390
1 files changed, 390 insertions, 0 deletions
diff --git a/tests/test_check.c b/tests/test_check.c
new file mode 100644
index 0000000..bc52f40
--- /dev/null
+++ b/tests/test_check.c
@@ -0,0 +1,390 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file test_check.c
+/// \brief Tests integrity checks
+//
+// Authors: Lasse Collin
+// Jia Tan
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tests.h"
+#include "mythread.h"
+
+
+// These must be specified as numbers so that the test works on EBCDIC
+// systems too.
+// static const uint8_t test_string[9] = "123456789";
+// static const uint8_t test_unaligned[12] = "xxx123456789";
+static const uint8_t test_string[9] = { 49, 50, 51, 52, 53, 54, 55, 56, 57 };
+static const uint8_t test_unaligned[12]
+ = { 120, 120, 120, 49, 50, 51, 52, 53, 54, 55, 56, 57 };
+
+// 2 MB is more than enough for the tests. Actually a tiny value would
+// work because we don't actually decompress the files, we only test
+// decoding of the Stream Header fields.
+#define TEST_CHECK_MEMLIMIT (2U << 20)
+
+static size_t no_check_size;
+static uint8_t *no_check_xz_data;
+
+static size_t unsupported_check_size;
+static uint8_t *unsupported_check_xz_data;
+
+#ifdef HAVE_CHECK_CRC32
+static size_t crc32_size;
+static uint8_t *crc32_xz_data;
+#endif
+
+#ifdef HAVE_CHECK_CRC64
+static size_t crc64_size;
+static uint8_t *crc64_xz_data;
+#endif
+
+#ifdef HAVE_CHECK_SHA256
+static size_t sha256_size;
+static uint8_t *sha256_xz_data;
+#endif
+
+
+#ifdef HAVE_CHECK_CRC64
+static const uint8_t *
+get_random256(uint32_t *seed)
+{
+ static uint8_t buf[256];
+
+ for (size_t i = 0; i < sizeof(buf); ++i) {
+ *seed = *seed * 1103515245 + 12345;
+ buf[i] = (uint8_t)(*seed >> 22);
+ }
+
+ return buf;
+}
+#endif
+
+
+static void
+test_lzma_crc32(void)
+{
+ // CRC32 is always enabled.
+ assert_true(lzma_check_is_supported(LZMA_CHECK_CRC32));
+
+ const uint32_t test_vector = 0xCBF43926;
+
+ // Test 1
+ assert_uint_eq(lzma_crc32(test_string, sizeof(test_string), 0),
+ test_vector);
+
+ // Test 2
+ assert_uint_eq(lzma_crc32(test_unaligned + 3, sizeof(test_string), 0),
+ test_vector);
+
+ // Test 3
+ uint32_t crc = 0;
+ for (size_t i = 0; i < sizeof(test_string); ++i)
+ crc = lzma_crc32(test_string + i, 1, crc);
+ assert_uint_eq(crc, test_vector);
+}
+
+
+static void
+test_lzma_crc64(void)
+{
+ // CRC64 can be disabled.
+ if (!lzma_check_is_supported(LZMA_CHECK_CRC64))
+ assert_skip("CRC64 support is disabled");
+
+ // If CRC64 is disabled then lzma_crc64() will be missing.
+ // Using an ifdef here avoids a linker error.
+#ifdef HAVE_CHECK_CRC64
+ const uint64_t test_vector = 0x995DC9BBDF1939FA;
+
+ // Test 1
+ assert_uint_eq(lzma_crc64(test_string, sizeof(test_string), 0),
+ test_vector);
+
+ // Test 2
+ assert_uint_eq(lzma_crc64(test_unaligned + 3, sizeof(test_string), 0),
+ test_vector);
+
+ // Test 3
+ uint64_t crc = 0;
+ for (size_t i = 0; i < sizeof(test_string); ++i)
+ crc = lzma_crc64(test_string + i, 1, crc);
+ assert_uint_eq(crc, test_vector);
+
+ // Test 4: The CLMUL implementation works on 16-byte chunks.
+ // Test combination of different start and end alignments
+ // and also short buffer lengths where special handling is needed.
+ uint32_t seed = 29;
+ crc = 0x96E30D5184B7FA2C; // Random initial value
+ for (size_t start = 0; start < 32; ++start)
+ for (size_t size = 1; size < 256 - 32; ++size)
+ crc = lzma_crc64(get_random256(&seed), size, crc);
+
+ assert_uint_eq(crc, 0x23AB787177231C9F);
+#endif
+}
+
+
+static void
+test_lzma_supported_checks(void)
+{
+ static const int expected_check_ids[] = {
+ LZMA_CHECK_NONE,
+#ifdef HAVE_CHECK_CRC32
+ LZMA_CHECK_CRC32,
+#endif
+#ifdef HAVE_CHECK_CRC64
+ LZMA_CHECK_CRC64,
+#endif
+#ifdef HAVE_CHECK_SHA256
+ LZMA_CHECK_SHA256,
+#endif
+ };
+
+ for (int i = 0; i <= LZMA_CHECK_ID_MAX + 1; i++) {
+ bool matched = false;
+ for (unsigned int j = 0; j < ARRAY_SIZE(expected_check_ids);
+ j++) {
+ if (expected_check_ids[j] == i) {
+ matched = true;
+ break;
+ }
+ }
+
+ if (matched)
+ assert_true(lzma_check_is_supported(i));
+ else
+ assert_false(lzma_check_is_supported(i));
+ }
+}
+
+
+static void
+test_lzma_check_size(void)
+{
+ // Expected check sizes taken from src/liblzma/api/lzma/check.h
+ static const uint32_t expected_check_sizes[] = {
+ 0, 4, 4, 4, 8, 8, 8, 16, 16, 16,
+ 32, 32, 32, 64, 64, 64
+ };
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(expected_check_sizes); i++)
+ assert_uint_eq(expected_check_sizes[i], lzma_check_size(i));
+
+ assert_uint_eq(lzma_check_size(LZMA_CHECK_ID_MAX + 1), UINT32_MAX);
+}
+
+
+// Test the single threaded decoder for lzma_get_check
+static void
+test_lzma_get_check_st(void)
+{
+#ifndef HAVE_DECODERS
+ assert_skip("Decoder support disabled");
+#else
+ const uint32_t flags = LZMA_TELL_ANY_CHECK |
+ LZMA_TELL_UNSUPPORTED_CHECK |
+ LZMA_TELL_NO_CHECK;
+
+ uint8_t outbuf[128];
+ lzma_stream strm = LZMA_STREAM_INIT;
+
+ // Test a file with no integrity check:
+ assert_lzma_ret(lzma_stream_decoder(&strm, TEST_CHECK_MEMLIMIT,
+ flags), LZMA_OK);
+ strm.next_in = no_check_xz_data;
+ strm.avail_in = no_check_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_NO_CHECK);
+ assert_lzma_check(lzma_get_check(&strm), LZMA_CHECK_NONE);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+
+ // Test a file with an unsupported integrity check type:
+ assert_lzma_ret(lzma_stream_decoder(&strm, TEST_CHECK_MEMLIMIT,
+ flags), LZMA_OK);
+ strm.next_in = unsupported_check_xz_data;
+ strm.avail_in = unsupported_check_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_UNSUPPORTED_CHECK);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+
+ // Test a file with CRC32 as the integrity check:
+#ifdef HAVE_CHECK_CRC32
+ assert_lzma_ret(lzma_stream_decoder(&strm, TEST_CHECK_MEMLIMIT,
+ flags), LZMA_OK);
+ strm.next_in = crc32_xz_data;
+ strm.avail_in = crc32_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_GET_CHECK);
+ assert_lzma_check(lzma_get_check(&strm), LZMA_CHECK_CRC32);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+#endif
+
+ // Test a file with CRC64 as the integrity check:
+#ifdef HAVE_CHECK_CRC64
+ assert_lzma_ret(lzma_stream_decoder(&strm, TEST_CHECK_MEMLIMIT,
+ flags), LZMA_OK);
+ strm.next_in = crc64_xz_data;
+ strm.avail_in = crc64_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_GET_CHECK);
+ assert_lzma_check(lzma_get_check(&strm), LZMA_CHECK_CRC64);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+#endif
+
+ // Test a file with SHA-256 as the integrity check:
+#ifdef HAVE_CHECK_SHA256
+ assert_lzma_ret(lzma_stream_decoder(&strm, TEST_CHECK_MEMLIMIT,
+ flags), LZMA_OK);
+ strm.next_in = sha256_xz_data;
+ strm.avail_in = sha256_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_GET_CHECK);
+ assert_lzma_check(lzma_get_check(&strm), LZMA_CHECK_SHA256);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+#endif
+
+ lzma_end(&strm);
+#endif
+}
+
+
+static void
+test_lzma_get_check_mt(void)
+{
+#ifndef MYTHREAD_ENABLED
+ assert_skip("Threading support disabled");
+#elif !defined(HAVE_DECODERS)
+ assert_skip("Decoder support disabled");
+#else
+ const uint32_t flags = LZMA_TELL_ANY_CHECK |
+ LZMA_TELL_UNSUPPORTED_CHECK |
+ LZMA_TELL_NO_CHECK;
+
+ const lzma_mt options = {
+ .flags = flags,
+ .threads = 2,
+ .timeout = 0,
+ .memlimit_threading = TEST_CHECK_MEMLIMIT,
+ .memlimit_stop = TEST_CHECK_MEMLIMIT
+ };
+
+ uint8_t outbuf[128];
+ lzma_stream strm = LZMA_STREAM_INIT;
+
+ // Test a file with no integrity check:
+ assert_lzma_ret(lzma_stream_decoder_mt(&strm, &options), LZMA_OK);
+ strm.next_in = no_check_xz_data;
+ strm.avail_in = no_check_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_NO_CHECK);
+ assert_lzma_check(lzma_get_check(&strm), LZMA_CHECK_NONE);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+
+ // Test a file with an unsupported integrity check type:
+ assert_lzma_ret(lzma_stream_decoder_mt(&strm, &options), LZMA_OK);
+ strm.next_in = unsupported_check_xz_data;
+ strm.avail_in = unsupported_check_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_UNSUPPORTED_CHECK);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+
+ // Test a file with CRC32 as the integrity check:
+#ifdef HAVE_CHECK_CRC32
+ assert_lzma_ret(lzma_stream_decoder_mt(&strm, &options), LZMA_OK);
+ strm.next_in = crc32_xz_data;
+ strm.avail_in = crc32_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_GET_CHECK);
+ assert_lzma_check(lzma_get_check(&strm), LZMA_CHECK_CRC32);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+#endif
+
+ // Test a file with CRC64 as the integrity check:
+#ifdef HAVE_CHECK_CRC64
+ assert_lzma_ret(lzma_stream_decoder_mt(&strm, &options), LZMA_OK);
+ strm.next_in = crc64_xz_data;
+ strm.avail_in = crc64_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_GET_CHECK);
+ assert_lzma_check(lzma_get_check(&strm), LZMA_CHECK_CRC64);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+#endif
+
+ // Test a file with SHA-256 as the integrity check:
+#ifdef HAVE_CHECK_SHA256
+ assert_lzma_ret(lzma_stream_decoder_mt(&strm,&options), LZMA_OK);
+ strm.next_in = sha256_xz_data;
+ strm.avail_in = sha256_size;
+ strm.next_out = outbuf;
+ strm.avail_out = sizeof(outbuf);
+
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_GET_CHECK);
+ assert_lzma_check(lzma_get_check(&strm), LZMA_CHECK_SHA256);
+ assert_lzma_ret(lzma_code(&strm, LZMA_RUN), LZMA_STREAM_END);
+#endif
+
+ lzma_end(&strm);
+#endif
+}
+
+
+extern int
+main(int argc, char **argv)
+{
+ tuktest_start(argc, argv);
+
+ no_check_xz_data = tuktest_file_from_srcdir(
+ "files/good-1-check-none.xz", &no_check_size);
+
+ unsupported_check_xz_data = tuktest_file_from_srcdir(
+ "files/unsupported-check.xz",
+ &unsupported_check_size);
+
+#ifdef HAVE_CHECK_CRC32
+ crc32_xz_data = tuktest_file_from_srcdir(
+ "files/good-1-check-crc32.xz", &crc32_size);
+#endif
+
+#ifdef HAVE_CHECK_CRC64
+ crc64_xz_data = tuktest_file_from_srcdir(
+ "files/good-1-check-crc64.xz", &crc64_size);
+#endif
+
+#ifdef HAVE_CHECK_SHA256
+ sha256_xz_data = tuktest_file_from_srcdir(
+ "files/good-1-check-sha256.xz", &sha256_size);
+#endif
+
+ tuktest_run(test_lzma_crc32);
+ tuktest_run(test_lzma_crc64);
+ tuktest_run(test_lzma_supported_checks);
+ tuktest_run(test_lzma_check_size);
+ tuktest_run(test_lzma_get_check_st);
+ tuktest_run(test_lzma_get_check_mt);
+
+ return tuktest_end();
+}