This patch converts the existing test framework to use an open source C testing framework called Seatest. For now, I only converted the existing tests. I wanted your feedback before I used this framework to add new tests. Let me know what changes you would like to see.
--- .gitignore | 12 +- tests/Makefile.am | 58 ++-- tests/README | 105 ++++++ tests/bcj_test.c | 65 ---- tests/create_compress_files.c | 158 --------- tests/liblzma_tests.c | 31 ++ tests/liblzma_tests.h | 26 ++ tests/seatest/seatest.c | 563 ++++++++++++++++++++++++++++++++ tests/seatest/seatest.h | 116 +++++++ tests/test_bcj_exact_size.c | 40 +-- tests/test_block_header.c | 74 ++--- tests/test_check.c | 52 ++- tests/test_compress.sh | 142 -------- tests/test_files.sh | 57 ---- tests/test_filter_flags.c | 62 ++-- tests/test_index.c | 596 +++++++++++++++++++--------------- tests/test_scripts.sh | 76 ----- tests/test_stream_flags.c | 76 ++--- tests/test_utils.c | 68 ++++ tests/test_utils.h | 37 +++ tests/test_xz_compress.c | 312 ++++++++++++++++++ tests/test_xz_decompress.c | 100 ++++++ tests/test_xz_diff.c | 74 +++++ tests/test_xz_grep.c | 231 +++++++++++++ tests/tests.h | 119 ------- tests/xz_tests.c | 28 ++ tests/xz_tests.h | 19 ++ tests/xzgrep_expected_output | 39 --- 28 files changed, 2228 insertions(+), 1108 deletions(-) create mode 100644 tests/README delete mode 100644 tests/bcj_test.c delete mode 100644 tests/create_compress_files.c create mode 100644 tests/liblzma_tests.c create mode 100644 tests/liblzma_tests.h create mode 100644 tests/seatest/seatest.c create mode 100644 tests/seatest/seatest.h delete mode 100755 tests/test_compress.sh delete mode 100755 tests/test_files.sh delete mode 100755 tests/test_scripts.sh create mode 100644 tests/test_utils.c create mode 100644 tests/test_utils.h create mode 100644 tests/test_xz_compress.c create mode 100644 tests/test_xz_decompress.c create mode 100644 tests/test_xz_diff.c create mode 100644 tests/test_xz_grep.c delete mode 100644 tests/tests.h create mode 100644 tests/xz_tests.c create mode 100644 tests/xz_tests.h delete mode 100644 tests/xzgrep_expected_output diff --git a/.gitignore b/.gitignore index 11dbc59..b516fae 100644 --- a/.gitignore +++ b/.gitignore @@ -46,16 +46,12 @@ build-aux/test-driver /tests/compress_generated_abc /tests/compress_generated_random /tests/compress_generated_text -/tests/create_compress_files -/tests/test_bcj_exact_size -/tests/test_block_header -/tests/test_check -/tests/test_filter_flags -/tests/test_index -/tests/test_stream_flags +/tests/tmp_compressed +/tests/tmp_uncompressed +/tests/xz_tests +/tests/liblzma_tests /tests/xzgrep_test_1.xz /tests/xzgrep_test_2.xz -/tests/xzgrep_test_output /lib/Makefile /tests/Makefile diff --git a/tests/Makefile.am b/tests/Makefile.am index 4116b81..b9622d6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -5,22 +5,24 @@ ## You can do whatever you want with this file. ## +seatest_SOURCES = \ + seatest/seatest.c \ + seatest/seatest.h + EXTRA_DIST = \ files \ ossfuzz \ - tests.h \ - test_files.sh \ - test_compress.sh \ - test_scripts.sh \ - bcj_test.c \ + liblzma_tests.h \ + xz_tests.h \ compress_prepared_bcj_sparc \ compress_prepared_bcj_x86 \ - xzgrep_expected_output + $(seatest_SOURCES) AM_CPPFLAGS = \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/liblzma/api \ - -I$(top_builddir)/lib + -I$(top_builddir)/lib \ + -I$(top_srcdir)/tests/seatest LDADD = $(top_builddir)/src/liblzma/liblzma.la @@ -30,28 +32,32 @@ endif LDADD += $(LTLIBINTL) +liblzma_tests_SOURCES = \ + $(seatest_SOURCES) \ + test_check.c \ + test_block_header.c \ + test_bcj_exact_size.c \ + test_filter_flags.c \ + test_index.c \ + test_stream_flags.c \ + liblzma_tests.c + +xz_tests_SOURCES = \ + $(seatest_SOURCES) \ + test_xz_decompress.c \ + test_xz_diff.c \ + test_xz_grep.c \ + test_xz_compress.c \ + test_utils.c \ + xz_tests.c + check_PROGRAMS = \ - create_compress_files \ - test_check \ - test_stream_flags \ - test_filter_flags \ - test_block_header \ - test_index \ - test_bcj_exact_size + liblzma_tests \ + xz_tests TESTS = \ - test_check \ - test_stream_flags \ - test_filter_flags \ - test_block_header \ - test_index \ - test_bcj_exact_size \ - test_files.sh \ - test_compress.sh - -if COND_SCRIPTS -TESTS += test_scripts.sh -endif + liblzma_tests \ + xz_tests clean-local: -rm -f compress_generated_* \ diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..c5f15c6 --- /dev/null +++ b/tests/README @@ -0,0 +1,105 @@ + +Testing Framework +================= + + 0. Overview + 1. Seatest + 1.1. Seatest Overview + 1.2. Using Seatest + 1.3. Seatest Asserts + 2. Adding a New Test or Test Fixture + + +0. Overview +----------- + + The testing framework is centered around two binaries: liblzma_tests + and xz_tests. liblzma_tests covers the liblzma shared library and + xz_tests covers the command-line tools. The framework is built on top + of an open source C testing framework called Seatest, originally written + by Keith Nicholas. A few patches have been applied, but the majority of + the code remains the same. + + Currently, the liblzma_tests and xz_tests binaries must be run from + this directory to function correctly. Alternatively, make check + can be run from the root directory. + + +1. Seatest +---------- + +1.1 Seatest Overview + + Seatest is a simple unit testing framework for C based on the xUnit style + of unit testing. It is designed to be portable, lightweight, and easy to + use. Only two files, seatest.c and seatest.h, are required to use Seatest. + +1.2 Using Seatest + + Using Seatest is as simple as including the header file "seatest.h". This + includes many assert statements, in addition to the fixture functions. The + main function for a test suite should look similar to this: + + int main(void) + { + return run_tests(all_tests); + } + + The run_tests function will return 1 if any test fails and 0 if all tests + pass, so Seatest is compatible with autotools and CMake testing. + + Each group of tests is called a fixture. The fixture needs to be surrounded + with test_fixture_start() and test_fixture_end() in order to log the + successes and failures correctly. For example: + + void test_fixture(void) + { + test_fixture_start(); + run_test(test_func_1); + run_test(test_func_2); + run_test(test_func_3); + test_fixture_end(); + } + + The individual tests should be functions that take no arguments and return + void. These functions should use Seatest's asserts to report all successful + or failing tests. + +1.3 Seatest Asserts + + Seatest implements many useful assert functions to test values and record + the results. Here are all of the supported asserts: + + assert_true + assert_false + assert_int_equal + assert_ulong_equal + assert_string_equal + assert_n_array_equal + assert_bit_set + assert_bit_not_set + assert_bit_mask_matches + assert_fail + assert_float_equal + assert_double_equal + assert_string_contains + assert_string_doesnt_contain + assert_string_starts_with + assert_string_ends_with + + +2. Adding a New Test or Test Fixture +------------------------------------ + + Adding a new test to an existing fixture is as simple as creating + a new function, and then calling that function from the fixture + function. + + Adding a new test fixture is a 5 step process: + + 1. Create a new .c file in this directory + 2. Create your fixture function along with all of your tests + 3. Add your fixture function to either liblzma_tests.h or xz_tests.h + 4. Add your fixture file to the Makefile.am under the liblzma_tests_SOURCES + or the xz_tests_SOURCES variable + 5. Call your fixture function in liblzma_tests.c or xz_tests.c diff --git a/tests/bcj_test.c b/tests/bcj_test.c deleted file mode 100644 index 05de38a..0000000 --- a/tests/bcj_test.c +++ /dev/null @@ -1,65 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file bcj_test.c -/// \brief Source code of compress_prepared_bcj_* -/// -/// This is a simple program that should make the compiler to generate -/// PC-relative branches, jumps, and calls. The compiled files can then -/// be used to test the branch conversion filters. Note that this program -/// itself does nothing useful. -/// -/// Compiling: gcc -std=c99 -fPIC -c bcj_test.c -/// Don't optimize or strip. -// -// Author: Lasse Collin -// -// This file has been put into the public domain. -// You can do whatever you want with this file. -// -/////////////////////////////////////////////////////////////////////////////// - -extern int jump(int a, int b); - - -extern int -call(int a, int b) -{ - if (a < b) - a = jump(a, b); - - return a; -} - - -extern int -jump(int a, int b) -{ - // The loop generates conditional jump backwards. - while (1) { - if (a < b) { - a *= 2; - a += 3 * b; - break; - } else { - // Put enough code here to prevent JMP SHORT on x86. - a += b; - a /= 2; - b += b % 5; - a -= b / 3; - b = 2 * b + a - 1; - a *= b + a + 1; - b += a - 1; - a += b * 2 - a / 5; - } - } - - return a; -} - - -int -main(int argc, char **argv) -{ - int a = call(argc, argc + 1); - return a == 0; -} diff --git a/tests/create_compress_files.c b/tests/create_compress_files.c deleted file mode 100644 index 88d60b7..0000000 --- a/tests/create_compress_files.c +++ /dev/null @@ -1,158 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file create_compress_files.c -/// \brief Creates bunch of test files to be compressed -/// -/// Using a test file generator program saves space in the source code -/// package considerably. -// -// Author: Lasse Collin -// -// This file has been put into the public domain. -// You can do whatever you want with this file. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "sysdefs.h" -#include <stdio.h> - - -// Avoid re-creating the test files every time the tests are run. -#define create_test(name) \ -do { \ - if (!file_exists("compress_generated_" #name)) { \ - FILE *file = file_create("compress_generated_" #name); \ - write_ ## name(file); \ - file_finish(file, "compress_generated_" #name); \ - } \ -} while (0) - - -static bool -file_exists(const char *filename) -{ - // Trying to be somewhat portable by avoiding stat(). - FILE *file = fopen(filename, "rb"); - bool ret; - - if (file != NULL) { - fclose(file); - ret = true; - } else { - ret = false; - } - - return ret; -} - - -static FILE * -file_create(const char *filename) -{ - FILE *file = fopen(filename, "wb"); - - if (file == NULL) { - perror(filename); - exit(1); - } - - return file; -} - - -static void -file_finish(FILE *file, const char *filename) -{ - const bool ferror_fail = ferror(file); - const bool fclose_fail = fclose(file); - - if (ferror_fail || fclose_fail) { - perror(filename); - exit(1); - } -} - - -// File that repeats "abc\n" a few thousand times. This is targeted -// especially at Subblock filter's run-length encoder. -static void -write_abc(FILE *file) -{ - for (size_t i = 0; i < 12345; ++i) - if (fwrite("abc\n", 4, 1, file) != 1) - exit(1); -} - - -// File that doesn't compress. We always use the same random seed to -// generate identical files on all systems. -static void -write_random(FILE *file) -{ - uint32_t n = 5; - - for (size_t i = 0; i < 123456; ++i) { - n = 101771 * n + 71777; - - putc((uint8_t)(n), file); - putc((uint8_t)(n >> 8), file); - putc((uint8_t)(n >> 16), file); - putc((uint8_t)(n >> 24), file); - } -} - - -// Text file -static void -write_text(FILE *file) -{ - static const char *lorem[] = { - "Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", - "adipisicing", "elit,", "sed", "do", "eiusmod", "tempor", - "incididunt", "ut", "labore", "et", "dolore", "magna", - "aliqua.", "Ut", "enim", "ad", "minim", "veniam,", "quis", - "nostrud", "exercitation", "ullamco", "laboris", "nisi", - "ut", "aliquip", "ex", "ea", "commodo", "consequat.", - "Duis", "aute", "irure", "dolor", "in", "reprehenderit", - "in", "voluptate", "velit", "esse", "cillum", "dolore", - "eu", "fugiat", "nulla", "pariatur.", "Excepteur", "sint", - "occaecat", "cupidatat", "non", "proident,", "sunt", "in", - "culpa", "qui", "officia", "deserunt", "mollit", "anim", - "id", "est", "laborum." - }; - - // Let the first paragraph be the original text. - for (size_t w = 0; w < ARRAY_SIZE(lorem); ++w) { - fprintf(file, "%s ", lorem[w]); - - if (w % 7 == 6) - fprintf(file, "\n"); - } - - // The rest shall be (hopefully) meaningless combinations of - // the same words. - uint32_t n = 29; - - for (size_t p = 0; p < 500; ++p) { - fprintf(file, "\n\n"); - - for (size_t w = 0; w < ARRAY_SIZE(lorem); ++w) { - n = 101771 * n + 71777; - - fprintf(file, "%s ", lorem[n % ARRAY_SIZE(lorem)]); - - if (w % 7 == 6) - fprintf(file, "\n"); - } - } -} - - -int -main(void) -{ - create_test(abc); - create_test(random); - create_test(text); - return 0; -} diff --git a/tests/liblzma_tests.c b/tests/liblzma_tests.c new file mode 100644 index 0000000..2d7267e --- /dev/null +++ b/tests/liblzma_tests.c @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file liblzma_tests.c +/// \brief Combines all tests for liblzma +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "liblzma_tests.h" + + +static void +all_tests(void) +{ + test_integrity_checks(); + test_block_header_coders(); + test_bcj_filter(); + test_filter_flags(); + test_lzma_index_structure(); + test_stream_header_and_footer_coders(); +} + +int +main(void) +{ + return run_tests(all_tests); +} diff --git a/tests/liblzma_tests.h b/tests/liblzma_tests.h new file mode 100644 index 0000000..16187dd --- /dev/null +++ b/tests/liblzma_tests.h @@ -0,0 +1,26 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file liblzma_tests.h +/// \brief Provides headers for all tests for liblzma +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LIBLZMA_TESTS_H +#define LIBLZMA_TESTS_H + +#include "lzma.h" +#include "seatest.h" + +void test_integrity_checks(void); +void test_block_header_coders(void); +void test_bcj_filter(void); +void test_filter_flags(void); +void test_lzma_index_structure(void); +void test_stream_header_and_footer_coders(void); + +#endif \ No newline at end of file diff --git a/tests/seatest/seatest.c b/tests/seatest/seatest.c new file mode 100644 index 0000000..7ddcbd1 --- /dev/null +++ b/tests/seatest/seatest.c @@ -0,0 +1,563 @@ +/* Copyright (c) 2010 Keith Nicholas + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ + +#include "seatest.h" +#include <string.h> + +typedef enum +{ + SEATEST_DISPLAY_TESTS, + SEATEST_RUN_TESTS, + SEATEST_DO_NOTHING, + SEATEST_DO_ABORT +} seatest_action_t; + +typedef struct +{ + int argc; + char** argv; + seatest_action_t action; +} seatest_testrunner_t; + + +static unsigned int GetTickCount(void); +static int seatest_is_string_equal_i(const char* s1, const char* s2); +static int seatest_is_display_only(void); +static char* test_file_name(const char* path); +static void seatest_header_printer(const char* s, int length, char f); +static void set_magic_marker(const char* marker); +static void seatest_display_test(const char* fixture_name, const char* test_name); +static void seatest_show_help( void ); +static int seatest_commandline_has_value_after(seatest_testrunner_t* runner, int arg); +static void seatest_interpret_commandline(seatest_testrunner_t* runner); +static void seatest_testrunner_create(seatest_testrunner_t* runner, int argc, char** argv ); +static int seatest_parse_commandline_option_with_value(seatest_testrunner_t* runner, int arg, const char* option, seatest_void_string setter); + + +#ifdef WIN32 +#include "windows.h" +int seatest_is_string_equal_i(const char* s1, const char* s2) +{ + #pragma warning(disable: 4996) + return stricmp(s1, s2) == 0; +} + +#else +#include <strings.h> +static unsigned int GetTickCount(void) { return 0;} +static int seatest_is_string_equal_i(const char* s1, const char* s2) +{ + return strcasecmp(s1, s2) == 0; +} +#endif + +#ifdef SEATEST_INTERNAL_TESTS +static int sea_test_last_passed = 0; +#endif + +#define SEATEST_RET_ERROR (-1) +#define SEATEST_RET_OK 0 +#define SEATEST_RET_FAILED_COUNT(tests_failed_count) (tests_failed_count) + +static int seatest_screen_width = 70; +static int sea_tests_run = 0; +static int sea_tests_passed = 0; +static int sea_tests_failed = 0; +static int seatest_display_only = 0; +static int seatest_verbose = 0; +static int vs_mode = 0; +static int seatest_machine_readable = 0; +static char* seatest_current_fixture; +static char* seatest_current_fixture_path; +static char seatest_magic_marker[20] = ""; + +static seatest_void_void seatest_suite_setup_func = 0; +static seatest_void_void seatest_suite_teardown_func = 0; +static seatest_void_void seatest_fixture_setup = 0; +static seatest_void_void seatest_fixture_teardown = 0; + +void (*seatest_simple_test_result)(int passed, const char* reason, const char* function, unsigned int line) = seatest_simple_test_result_log; + +void suite_setup(seatest_void_void setup) +{ + seatest_suite_setup_func = setup; +} +void suite_teardown(seatest_void_void teardown) +{ + seatest_suite_teardown_func = teardown; +} + +static int seatest_is_display_only(void) +{ + return seatest_display_only; +} + +void seatest_suite_setup( void ) +{ + if(seatest_suite_setup_func != 0) seatest_suite_setup_func(); +} + +void seatest_suite_teardown( void ) +{ + if(seatest_suite_teardown_func != 0) seatest_suite_teardown_func(); +} + +void fixture_setup(void (*setup)( void )) +{ + seatest_fixture_setup = setup; +} +void fixture_teardown(void (*teardown)( void )) +{ + seatest_fixture_teardown = teardown; +} + +void seatest_setup( void ) +{ + if(seatest_fixture_setup != 0) seatest_fixture_setup(); +} + +void seatest_teardown( void ) +{ + if(seatest_fixture_teardown != 0) seatest_fixture_teardown(); +} + +static char* test_file_name(const char* path) +{ + char* file = ((char*) path) + strlen(path); + while(file != path && *file!= '\\' ) file--; + if(*file == '\\') file++; + return file; +} + +static int seatest_fixture_tests_run; +static int seatest_fixture_tests_failed; + + +void seatest_simple_test_result_log(int passed, const char* reason, const char* function, unsigned int line) +{ + if (!passed) + { + + if(seatest_machine_readable) + { + if (vs_mode) + { + printf("%s (%u) %s,%s\r\n", seatest_current_fixture_path, line, function, reason ); + } + else + { + printf("%s%s,%s,%u,%s\r\n", seatest_magic_marker, seatest_current_fixture_path, function, line, reason ); + } + + } + else + { + if ( vs_mode ) + { + printf("%s (%u) %s,%s\r\n", seatest_current_fixture_path, line, function, reason ); + } + else + { + printf("%-30s Line %-5d %s\r\n", function, line, reason ); + } + } + sea_tests_failed++; + + #ifdef ABORT_TEST_IF_ASSERT_FAIL + printf("Test has been finished with failure.\r\n"); + longjmp(env,1); + #endif + } + else + { + if(seatest_verbose) + { + if(seatest_machine_readable) + { + printf("%s%s,%s,%u,Passed\r\n", seatest_magic_marker, seatest_current_fixture_path, function, line ); + } + else + { + printf("%-30s Line %-5d Passed\r\n", function, line); + } + } + sea_tests_passed++; + } +} + +void seatest_assert_true(int test, const char* function, unsigned int line) +{ + seatest_simple_test_result(test, "Should have been true", function, line); +} + +void seatest_assert_false(int test, const char* function, unsigned int line) +{ + seatest_simple_test_result(!test, "Should have been false", function, line); +} + + +void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + sprintf(s, "Expected %d but was %d", expected, actual); + seatest_simple_test_result(expected==actual, s, function, line); +} + +void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + sprintf(s, "Expected %lu but was %lu", expected, actual); + seatest_simple_test_result(expected==actual, s, function, line); +} + +void seatest_assert_float_equal( float expected, float actual, float delta, const char* function, unsigned int line ) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + float result = expected-actual; + sprintf(s, "Expected %f but was %f", expected, actual); + if(result < 0.0) result = 0.0f - result; + seatest_simple_test_result( result <= delta, s, function, line); +} + +void seatest_assert_double_equal( double expected, double actual, double delta, const char* function, unsigned int line ) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + double result = expected-actual; + sprintf(s, "Expected %f but was %f", expected, actual); + if(result < 0.0) result = 0.0 - result; + seatest_simple_test_result( result <= delta, s, function, line); +} + +void seatest_assert_string_equal(const char* expected, const char* actual, const char* function, unsigned int line) +{ + int comparison; + char s[SEATEST_PRINT_BUFFER_SIZE]; + + if ((expected == (char *)0) && (actual == (char *)0)) + { + sprintf(s, "Expected <NULL> but was <NULL>"); + comparison = 1; + } + else if (expected == (char *)0) + { + sprintf(s, "Expected <NULL> but was %s", actual); + comparison = 0; + } + else if (actual == (char *)0) + { + sprintf(s, "Expected %s but was <NULL>", expected); + comparison = 0; + } + else + { + comparison = strcmp(expected, actual) == 0; + sprintf(s, "Expected %s but was %s", expected, actual); + } + + seatest_simple_test_result(comparison, s, function, line); +} + +void seatest_assert_string_ends_with(const char* expected, const char* actual, const char* function, unsigned int line) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + sprintf(s, "Expected %s to end with %s", actual, expected); + seatest_simple_test_result(strcmp(expected, actual+(strlen(actual)-strlen(expected)))==0, s, function, line); +} + +void seatest_assert_string_starts_with(const char* expected, const char* actual, const char* function, unsigned int line) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + sprintf(s, "Expected %s to start with %s", actual, expected); + seatest_simple_test_result(strncmp(expected, actual, strlen(expected))==0, s, function, line); +} + +void seatest_assert_string_contains(const char* expected, const char* actual, const char* function, unsigned int line) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + sprintf(s, "Expected %s to be in %s", expected, actual); + seatest_simple_test_result(strstr(actual, expected)!=0, s, function, line); +} + +void seatest_assert_string_doesnt_contain(const char* expected, const char* actual, const char* function, unsigned int line) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + sprintf(s, "Expected %s not to have %s in it", actual, expected); + seatest_simple_test_result(strstr(actual, expected)==0, s, function, line); +} + +void seatest_run_test(const char* fixture, const char* test) +{ + (void) fixture; + (void) test; + sea_tests_run++; +} + +static void seatest_header_printer(const char* s, int length, char f) +{ + int l = strlen(s); + int d = (length- (l + 2)) / 2; + int i; + if(seatest_is_display_only() || seatest_machine_readable) return; + for(i = 0; i<d; i++) printf("%c",f); + if(l==0) printf("%c%c", f, f); + else printf(" %s ", s); + for(i = (d+l+2); i<length; i++) printf("%c",f); + printf("\r\n"); +} + + +void seatest_test_fixture_start(const char* filepath) +{ + seatest_current_fixture_path = (char*) filepath; + seatest_current_fixture = test_file_name(filepath); + seatest_header_printer(seatest_current_fixture, seatest_screen_width, '-'); + seatest_fixture_tests_failed = sea_tests_failed; + seatest_fixture_tests_run = sea_tests_run; + seatest_fixture_teardown = 0; + seatest_fixture_setup = 0; +} + +void seatest_test_fixture_end(void) +{ + char s[SEATEST_PRINT_BUFFER_SIZE]; + sprintf(s, "%d run %d failed", sea_tests_run-seatest_fixture_tests_run, sea_tests_failed-seatest_fixture_tests_failed); + seatest_header_printer(s, seatest_screen_width, ' '); + if(seatest_is_display_only() || seatest_machine_readable) return; + printf("\r\n"); +} + +static char* seatest_fixture_filter = 0; +static char* seatest_test_filter = 0; + +void fixture_filter(const char* filter) +{ + seatest_fixture_filter = (char*) filter; +} + + +void test_filter(const char* filter) +{ + seatest_test_filter = (char*) filter; +} + +static void set_magic_marker(const char* marker) +{ + if(marker == NULL) return; + strcpy(seatest_magic_marker, marker); +} + +static void seatest_display_test(const char* fixture_name, const char* test_name) +{ + if(test_name == NULL) return; + printf("%s,%s\r\n", fixture_name, test_name); +} + +int seatest_should_run( const char* fixture, const char* test) +{ + int run = 1; + + if(seatest_fixture_filter) + { + if(strncmp(seatest_fixture_filter, fixture, strlen(seatest_fixture_filter)) != 0) run = 0; + } + if(seatest_test_filter && test != NULL) + { + if(strncmp(seatest_test_filter, test, strlen(seatest_test_filter)) != 0) run = 0; + } + + if(run && seatest_display_only) + { + seatest_display_test(fixture, test); + run = 0; + } + return run; +} + +void seatest_test(const char* fixture, const char* test, void (*test_function)(void)) +{ + seatest_suite_setup(); + seatest_setup(); + +#ifdef ABORT_TEST_IF_ASSERT_FAIL + skip_failed_test = setjmp(env); + if(!skip_failed_test) test_function(); +#else + test_function(); +#endif + + seatest_teardown(); + seatest_suite_teardown(); + seatest_run_test(fixture, test); +} + +int run_tests(seatest_void_void tests) +{ + unsigned long end; + unsigned long start = GetTickCount(); + char s[40]; + tests(); + end = GetTickCount(); + + if(seatest_is_display_only() || seatest_machine_readable) return SEATEST_RET_OK; + if (sea_tests_failed > 0) { + seatest_header_printer("Failed", seatest_screen_width, ' '); + } + else { + seatest_header_printer("ALL TESTS PASSED", seatest_screen_width, ' '); + } + sprintf(s,"%d tests run", sea_tests_run); + seatest_header_printer(s, seatest_screen_width, ' '); + sprintf(s,"in %lu ms",end - start); + seatest_header_printer(s, seatest_screen_width, ' '); + printf("\r\n"); + seatest_header_printer("", seatest_screen_width, '='); + + return SEATEST_RET_FAILED_COUNT(sea_tests_failed); +} + + +static void seatest_show_help( void ) +{ + printf("Usage: [-t <testname>] [-f <fixturename>] [-d] [help] [-v] [-m] [-k <marker>\r\n"); + printf("Flags:\r\n"); + printf("\thelp:\twill display this help\r\n"); + printf("\t-t:\twill only run tests that match <testname>\r\n"); + printf("\t-f:\twill only run fixtures that match <fixturename>\r\n"); + printf("\t-d:\twill just display test names and fixtures without\r\n"); + printf("\t-d:\trunning the test\r\n"); + printf("\t-v:\twill print a more verbose version of the test run\r\n"); + printf("\t-m:\twill print a machine readable format of the test run, ie :- \r\n"); + printf("\t \t<textfixture>,<testname>,<linenumber>,<testresult><EOL>\r\n"); + printf("\t-k:\twill prepend <marker> before machine readable output \r\n"); + printf("\t \t<marker> cannot start with a '-'\r\n"); +} + + +static int seatest_commandline_has_value_after(seatest_testrunner_t* runner, int arg) +{ + if(!((arg+1) < runner->argc)) return 0; + if(runner->argv[arg+1][0]=='-') return 0; + return 1; +} + +static int seatest_parse_commandline_option_with_value(seatest_testrunner_t* runner, int arg, const char* option, seatest_void_string setter) +{ + if(seatest_is_string_equal_i(runner->argv[arg], option)) + { + if(!seatest_commandline_has_value_after(runner, arg)) + { + printf("Error: The %s option expects to be followed by a value\r\n", option); + runner->action = SEATEST_DO_ABORT; + return 0; + } + setter(runner->argv[arg+1]); + return 1; + } + return 0; +} + +static void seatest_interpret_commandline(seatest_testrunner_t* runner) +{ + int arg; + for(arg=0; (arg < runner->argc) && (runner->action != SEATEST_DO_ABORT); arg++) + { + if(seatest_is_string_equal_i(runner->argv[arg], "help")) + { + seatest_show_help(); + runner->action = SEATEST_DO_NOTHING; + return; + } + if(seatest_is_string_equal_i(runner->argv[arg], "-d")) runner->action = SEATEST_DISPLAY_TESTS; + if(seatest_is_string_equal_i(runner->argv[arg], "-v")) seatest_verbose = 1; + if(seatest_is_string_equal_i(runner->argv[arg], "-vs")) vs_mode = 1; + if(seatest_is_string_equal_i(runner->argv[arg], "-m")) seatest_machine_readable = 1; + if(seatest_parse_commandline_option_with_value(runner,arg,"-t", test_filter)) arg++; + if(seatest_parse_commandline_option_with_value(runner,arg,"-f", fixture_filter)) arg++; + if(seatest_parse_commandline_option_with_value(runner,arg,"-k", set_magic_marker)) arg++; + } +} + +static void seatest_testrunner_create(seatest_testrunner_t* runner, int argc, char** argv ) +{ + runner->action = SEATEST_RUN_TESTS; + runner->argc = argc; + runner->argv = argv; + seatest_interpret_commandline(runner); +} + +int seatest_testrunner(int argc, char** argv, seatest_void_void tests, seatest_void_void setup, seatest_void_void teardown) +{ + seatest_testrunner_t runner; + seatest_testrunner_create(&runner, argc, argv); + switch(runner.action) + { + case SEATEST_DISPLAY_TESTS: + { + seatest_display_only = 1; + run_tests(tests); + return SEATEST_RET_OK; + } + case SEATEST_RUN_TESTS: + { + seatest_display_only = 0; + suite_setup(setup); + suite_teardown(teardown); + return run_tests(tests); + } + case SEATEST_DO_NOTHING: + { + return SEATEST_RET_OK; + } + case SEATEST_DO_ABORT: + default: + { + /* there was an error which should of been already printed out. */ + return SEATEST_RET_ERROR; + } + } + return SEATEST_RET_ERROR; +} + +#ifdef SEATEST_INTERNAL_TESTS +void seatest_simple_test_result_nolog(int passed, char* reason, const char* function, unsigned int line) +{ + sea_test_last_passed = passed; +} + +void seatest_assert_last_passed() +{ + assert_int_equal(1, sea_test_last_passed); +} + +void seatest_assert_last_failed() +{ + assert_int_equal(0, sea_test_last_passed); +} + +void seatest_disable_logging() +{ + seatest_simple_test_result = seatest_simple_test_result_nolog; +} + +void seatest_enable_logging() +{ + seatest_simple_test_result = seatest_simple_test_result_log; +} +#endif diff --git a/tests/seatest/seatest.h b/tests/seatest/seatest.h new file mode 100644 index 0000000..334d8f0 --- /dev/null +++ b/tests/seatest/seatest.h @@ -0,0 +1,116 @@ +/* Copyright (c) 2010 Keith Nicholas + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ + +#ifndef SEATEST_H +#define SEATEST_H +#include <stdio.h> + +/* +Defines +*/ + +#define SEATEST_VERSION "1.0" +#define SEATEST_PROJECT_HOME "http://code.google.com/p/seatest/" +#define SEATEST_PRINT_BUFFER_SIZE 100000 + +#ifdef ABORT_TEST_IF_ASSERT_FAIL +#include <setjmp.h> +jmp_buf env; +int skip_failed_test; +#endif + +/* +Typedefs +*/ + +typedef void (*seatest_void_void)(void); +typedef void (*seatest_void_string)(const char*); + +/* +Declarations +*/ +extern void (*seatest_simple_test_result)(int passed, const char* reason, const char* function, unsigned int line); +void seatest_test_fixture_start(const char* filepath); +void seatest_test_fixture_end( void ); +void seatest_simple_test_result_log(int passed, const char* reason, const char* function, unsigned int line); +void seatest_assert_true(int test, const char* function, unsigned int line); +void seatest_assert_false(int test, const char* function, unsigned int line); +void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line); +void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line); +void seatest_assert_float_equal(float expected, float actual, float delta, const char* function, unsigned int line); +void seatest_assert_double_equal(double expected, double actual, double delta, const char* function, unsigned int line); +void seatest_assert_string_equal(const char* expected, const char* actual, const char* function, unsigned int line); +void seatest_assert_string_ends_with(const char* expected, const char* actual, const char* function, unsigned int line); +void seatest_assert_string_starts_with(const char* expected, const char* actual, const char* function, unsigned int line); +void seatest_assert_string_contains(const char* expected, const char* actual, const char* function, unsigned int line); +void seatest_assert_string_doesnt_contain(const char* expected, const char* actual, const char* function, unsigned int line); +int seatest_should_run( const char* fixture, const char* test); +void seatest_before_run( const char* fixture, const char* test); +void seatest_run_test(const char* fixture, const char* test); +void seatest_setup( void ); +void seatest_teardown( void ); +void seatest_suite_teardown( void ); +void seatest_suite_setup( void ); +void seatest_test(const char* fixture, const char* test, void(*test_function)(void)); +/* +Assert Macros +*/ + +#define assert_true(test) do { seatest_assert_true(test, __FUNCTION__, __LINE__); } while (0) +#define assert_false(test) do { seatest_assert_false(test, __FUNCTION__, __LINE__); } while (0) +#define assert_int_equal(expected, actual) do { seatest_assert_int_equal(expected, actual, __FUNCTION__, __LINE__); } while (0) +#define assert_ulong_equal(expected, actual) do { seatest_assert_ulong_equal(expected, actual, __FUNCTION__, __LINE__); } while (0) +#define assert_string_equal(expected, actual) do { seatest_assert_string_equal(expected, actual, __FUNCTION__, __LINE__); } while (0) +#define assert_n_array_equal(expected, actual, n) do { size_t seatest_count; for(seatest_count=0; seatest_count<n; seatest_count++) { char s_seatest[SEATEST_PRINT_BUFFER_SIZE]; sprintf(s_seatest,"Expected %d to be %d at position %d", actual[seatest_count], expected[seatest_count], (int)seatest_count); seatest_simple_test_result((expected[seatest_count] == actual[seatest_count]), s_seatest, __FUNCTION__, __LINE__);} } while (0) +#define assert_bit_set(bit_number, value) { seatest_simple_test_result(((1 << bit_number) & value), " Expected bit to be set" , __FUNCTION__, __LINE__); } while (0) +#define assert_bit_not_set(bit_number, value) { seatest_simple_test_result(!((1 << bit_number) & value), " Expected bit not to to be set" , __FUNCTION__, __LINE__); } while (0) +#define assert_bit_mask_matches(value, mask) { seatest_simple_test_result(((value & mask) == mask), " Expected all bits of mask to be set" , __FUNCTION__, __LINE__); } while (0) +#define assert_fail(message) { seatest_simple_test_result(0, message, __FUNCTION__, __LINE__); } while (0) +#define assert_float_equal(expected, actual, delta) do { seatest_assert_float_equal(expected, actual, delta, __FUNCTION__, __LINE__); } while (0) +#define assert_double_equal(expected, actual, delta) do { seatest_assert_double_equal(expected, actual, delta, __FUNCTION__, __LINE__); } while (0) +#define assert_string_contains(expected, actual) do { seatest_assert_string_contains(expected, actual, __FUNCTION__, __LINE__); } while (0) +#define assert_string_doesnt_contain(expected, actual) do { seatest_assert_string_doesnt_contain(expected, actual, __FUNCTION__, __LINE__); } while (0) +#define assert_string_starts_with(expected, actual) do { seatest_assert_string_starts_with(expected, actual, __FUNCTION__, __LINE__); } while (0) +#define assert_string_ends_with(expected, actual) do { seatest_assert_string_ends_with(expected, actual, __FUNCTION__, __LINE__); } while (0) + +/* +Fixture / Test Management +*/ + +void fixture_setup(void (*setup)( void )); +void fixture_teardown(void (*teardown)( void )); +#define run_test(test) do { seatest_test(__FILE__, #test, test);} while (0) +#define test_fixture_start() do { seatest_test_fixture_start(__FILE__); } while (0) +#define test_fixture_end() do { seatest_test_fixture_end();} while (0) +void fixture_filter(const char* filter); +void test_filter(const char* filter); +void suite_teardown(seatest_void_void teardown); +void suite_setup(seatest_void_void setup); +int run_tests(seatest_void_void tests); +int seatest_testrunner(int argc, char** argv, seatest_void_void tests, seatest_void_void setup, seatest_void_void teardown); +#endif + +#ifdef SEATEST_INTERNAL_TESTS +void seatest_simple_test_result_nolog(int passed, char* reason, const char* function, unsigned int line); +void seatest_assert_last_passed(); +void seatest_assert_last_failed(); +void seatest_enable_logging(); +void seatest_disable_logging(); +#endif diff --git a/tests/test_bcj_exact_size.c b/tests/test_bcj_exact_size.c index 4a11a9c..c3cee86 100644 --- a/tests/test_bcj_exact_size.c +++ b/tests/test_bcj_exact_size.c @@ -12,7 +12,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#include "tests.h" +#include "liblzma_tests.h" +#include <stdbool.h> /// Something to be compressed @@ -33,7 +34,7 @@ compress(void) // it has fixed 4-byte alignment which makes triggering the potential // bug easy. lzma_options_lzma opt_lzma2; - succeed(lzma_lzma_preset(&opt_lzma2, 0)); + assert_false(lzma_lzma_preset(&opt_lzma2, 0)); lzma_filter filters[3] = { { .id = LZMA_FILTER_POWERPC, .options = NULL }, @@ -41,10 +42,9 @@ compress(void) { .id = LZMA_VLI_UNKNOWN, .options = NULL }, }; - expect(lzma_stream_buffer_encode(filters, LZMA_CHECK_CRC32, NULL, + assert_int_equal(lzma_stream_buffer_encode(filters, LZMA_CHECK_CRC32, NULL, in, sizeof(in), - compressed, &compressed_size, sizeof(compressed)) - == LZMA_OK); + compressed, &compressed_size, sizeof(compressed)), LZMA_OK); } @@ -52,7 +52,7 @@ static void decompress(void) { lzma_stream strm = LZMA_STREAM_INIT; - expect(lzma_stream_decoder(&strm, 10 << 20, 0) == LZMA_OK); + assert_int_equal(lzma_stream_decoder(&strm, 10 << 20, 0), LZMA_OK); strm.next_in = compressed; strm.next_out = out; @@ -63,13 +63,13 @@ decompress(void) const lzma_ret ret = lzma_code(&strm, LZMA_RUN); if (ret == LZMA_STREAM_END) { - expect(strm.total_in == compressed_size); - expect(strm.total_out == sizeof(in)); + assert_int_equal(strm.total_in, compressed_size); + assert_int_equal(strm.total_out, sizeof(in)); lzma_end(&strm); return; } - expect(ret == LZMA_OK); + assert_int_equal(ret, LZMA_OK); if (strm.total_out < sizeof(in)) strm.avail_out = 1; @@ -95,19 +95,19 @@ decompress_empty(void) uint64_t memlimit = 1 << 20; size_t in_pos = 0; size_t out_pos = 0; - expect(lzma_stream_buffer_decode(&memlimit, 0, NULL, + assert_int_equal(lzma_stream_buffer_decode(&memlimit, 0, NULL, empty_bcj_lzma2, &in_pos, sizeof(empty_bcj_lzma2), - out, &out_pos, 0) == LZMA_OK); - expect(in_pos == sizeof(empty_bcj_lzma2)); - expect(out_pos == 0); + out, &out_pos, 0), LZMA_OK); + assert_int_equal(in_pos, sizeof(empty_bcj_lzma2)); + assert_int_equal(out_pos, 0); } - -extern int -main(void) +void +test_bcj_filter(void) { - compress(); - decompress(); - decompress_empty(); - return 0; + test_fixture_start(); + run_test(compress); + run_test(decompress); + run_test(decompress_empty); + test_fixture_end(); } diff --git a/tests/test_block_header.c b/tests/test_block_header.c index 373a807..cf52460 100644 --- a/tests/test_block_header.c +++ b/tests/test_block_header.c @@ -10,7 +10,9 @@ // /////////////////////////////////////////////////////////////////////////////// -#include "tests.h" +#include "liblzma_tests.h" +#include "tuklib_integer.h" +#include "test_utils.h" static uint8_t buf[LZMA_BLOCK_HEADER_SIZE_MAX]; @@ -80,7 +82,7 @@ static lzma_filter filters_five[6] = { static void code(void) { - expect(lzma_block_header_encode(&known_options, buf) == LZMA_OK); + assert_int_equal(lzma_block_header_encode(&known_options, buf), LZMA_OK); lzma_filter filters[LZMA_FILTERS_MAX + 1]; memcrap(filters, sizeof(filters)); @@ -89,17 +91,14 @@ code(void) decoded_options.header_size = known_options.header_size; decoded_options.check = known_options.check; decoded_options.filters = filters; - expect(lzma_block_header_decode(&decoded_options, NULL, buf) - == LZMA_OK); + assert_int_equal(lzma_block_header_decode(&decoded_options, NULL, buf), LZMA_OK); - expect(known_options.compressed_size - == decoded_options.compressed_size); - expect(known_options.uncompressed_size - == decoded_options.uncompressed_size); + assert_int_equal(known_options.compressed_size, decoded_options.compressed_size); + assert_int_equal(known_options.uncompressed_size, decoded_options.uncompressed_size); for (size_t i = 0; known_options.filters[i].id != LZMA_VLI_UNKNOWN; ++i) - expect(known_options.filters[i].id == filters[i].id); + assert_int_equal(known_options.filters[i].id, filters[i].id); for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) free(decoded_options.filters[i].options); @@ -116,39 +115,39 @@ test1(void) .filters = NULL, }; - expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_PROG_ERROR); known_options.filters = filters_none; - expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_PROG_ERROR); known_options.filters = filters_five; - expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_PROG_ERROR); known_options.filters = filters_one; - expect(lzma_block_header_size(&known_options) == LZMA_OK); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_OK); // Some invalid value, which gets ignored. known_options.check = (lzma_check)(99); - expect(lzma_block_header_size(&known_options) == LZMA_OK); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_OK); known_options.compressed_size = 5; - expect(lzma_block_header_size(&known_options) == LZMA_OK); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_OK); known_options.compressed_size = 0; // Cannot be zero. - expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_PROG_ERROR); // LZMA_VLI_MAX is too big to keep the total size of the Block // a valid VLI, but lzma_block_header_size() is not meant // to validate it. (lzma_block_header_encode() must validate it.) known_options.compressed_size = LZMA_VLI_MAX; - expect(lzma_block_header_size(&known_options) == LZMA_OK); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_OK); known_options.compressed_size = LZMA_VLI_UNKNOWN; known_options.uncompressed_size = 0; - expect(lzma_block_header_size(&known_options) == LZMA_OK); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_OK); known_options.uncompressed_size = LZMA_VLI_MAX + 1; - expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_PROG_ERROR); } @@ -162,12 +161,12 @@ test2(void) .filters = filters_four, }; - expect(lzma_block_header_size(&known_options) == LZMA_OK); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_OK); code(); known_options.compressed_size = 123456; known_options.uncompressed_size = 234567; - expect(lzma_block_header_size(&known_options) == LZMA_OK); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_OK); code(); // We can make the sizes smaller while keeping the header size @@ -188,9 +187,9 @@ test3(void) .filters = filters_one, }; - expect(lzma_block_header_size(&known_options) == LZMA_OK); + assert_int_equal(lzma_block_header_size(&known_options), LZMA_OK); known_options.header_size += 4; - expect(lzma_block_header_encode(&known_options, buf) == LZMA_OK); + assert_int_equal(lzma_block_header_encode(&known_options, buf), LZMA_OK); lzma_filter filters[LZMA_FILTERS_MAX + 1]; decoded_options.header_size = known_options.header_size; @@ -199,14 +198,12 @@ test3(void) // Wrong size ++buf[0]; - expect(lzma_block_header_decode(&decoded_options, NULL, buf) - == LZMA_PROG_ERROR); + assert_int_equal(lzma_block_header_decode(&decoded_options, NULL, buf), LZMA_PROG_ERROR); --buf[0]; // Wrong CRC32 buf[known_options.header_size - 1] ^= 1; - expect(lzma_block_header_decode(&decoded_options, NULL, buf) - == LZMA_DATA_ERROR); + assert_int_equal(lzma_block_header_decode(&decoded_options, NULL, buf), LZMA_DATA_ERROR); buf[known_options.header_size - 1] ^= 1; // Unsupported filter @@ -214,28 +211,25 @@ test3(void) buf[2] ^= 0x1F; write32le(buf + known_options.header_size - 4, lzma_crc32(buf, known_options.header_size - 4, 0)); - expect(lzma_block_header_decode(&decoded_options, NULL, buf) - == LZMA_OPTIONS_ERROR); + assert_int_equal(lzma_block_header_decode(&decoded_options, NULL, buf), LZMA_OPTIONS_ERROR); buf[2] ^= 0x1F; // Non-nul Padding buf[known_options.header_size - 4 - 1] ^= 1; write32le(buf + known_options.header_size - 4, lzma_crc32(buf, known_options.header_size - 4, 0)); - expect(lzma_block_header_decode(&decoded_options, NULL, buf) - == LZMA_OPTIONS_ERROR); + assert_int_equal(lzma_block_header_decode(&decoded_options, NULL, buf), LZMA_OPTIONS_ERROR); buf[known_options.header_size - 4 - 1] ^= 1; } -int -main(void) +void +test_block_header_coders(void) { - succeed(lzma_lzma_preset(&opt_lzma, 1)); - - test1(); - test2(); - test3(); - - return 0; + test_fixture_start(); + assert_false(lzma_lzma_preset(&opt_lzma, 1)); + run_test(test1); + run_test(test2); + run_test(test3); + test_fixture_end(); } diff --git a/tests/test_check.c b/tests/test_check.c index 58813a5..be77643 100644 --- a/tests/test_check.c +++ b/tests/test_check.c @@ -12,7 +12,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include "tests.h" +#include "liblzma_tests.h" // These must be specified as numbers so that the test works on EBCDIC @@ -24,65 +24,51 @@ static const uint8_t test_unaligned[12] = { 120, 120, 120, 49, 50, 51, 52, 53, 54, 55, 56, 57 }; -static bool +static void test_crc32(void) { static const uint32_t test_vector = 0xCBF43926; // Test 1 - uint32_t crc = lzma_crc32(test_string, sizeof(test_string), 0); - if (crc != test_vector) - return true; - + assert_int_equal(test_vector, lzma_crc32(test_string, sizeof(test_string), 0)); + // Test 2 - crc = lzma_crc32(test_unaligned + 3, sizeof(test_string), 0); - if (crc != test_vector) - return true; + assert_int_equal(test_vector, lzma_crc32(test_unaligned + 3, sizeof(test_string), 0)); // Test 3 - crc = 0; + uint32_t crc = 0; for (size_t i = 0; i < sizeof(test_string); ++i) crc = lzma_crc32(test_string + i, 1, crc); - if (crc != test_vector) - return true; - - return false; + + assert_int_equal(test_vector, crc); } -static bool +static void test_crc64(void) { static const uint64_t test_vector = 0x995DC9BBDF1939FA; // Test 1 - uint64_t crc = lzma_crc64(test_string, sizeof(test_string), 0); - if (crc != test_vector) - return true; + assert_ulong_equal(test_vector, lzma_crc64(test_string, sizeof(test_string), 0)); // Test 2 - crc = lzma_crc64(test_unaligned + 3, sizeof(test_string), 0); - if (crc != test_vector) - return true; + assert_ulong_equal(test_vector, lzma_crc64(test_unaligned + 3, sizeof(test_string), 0)); // Test 3 - crc = 0; + uint64_t crc = 0; for (size_t i = 0; i < sizeof(test_string); ++i) crc = lzma_crc64(test_string + i, 1, crc); - if (crc != test_vector) - return true; - return false; + assert_ulong_equal(test_vector, crc); } -int -main(void) +void +test_integrity_checks(void) { - bool error = false; - - error |= test_crc32(); - error |= test_crc64(); - - return error ? 1 : 0; + test_fixture_start(); + run_test(test_crc32); + run_test(test_crc64); + test_fixture_end(); } diff --git a/tests/test_compress.sh b/tests/test_compress.sh deleted file mode 100755 index 62da0f9..0000000 --- a/tests/test_compress.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/sh - -############################################################################### -# -# Author: Lasse Collin -# -# This file has been put into the public domain. -# You can do whatever you want with this file. -# -############################################################################### - -# If xz wasn't built, this test is skipped. -if test -x ../src/xz/xz ; then - : -else - (exit 77) - exit 77 -fi - -# Find out if our shell supports functions. -eval 'unset foo ; foo() { return 42; } ; foo' -if test $? != 42 ; then - echo "/bin/sh doesn't support functions, skipping this test." - (exit 77) - exit 77 -fi - -test_xz() { - if $XZ -c "$@" "$FILE" > tmp_compressed; then - : - else - echo "Compressing failed: $* $FILE" - (exit 1) - exit 1 - fi - - if $XZ -cd tmp_compressed > tmp_uncompressed ; then - : - else - echo "Decompressing failed: $* $FILE" - (exit 1) - exit 1 - fi - - if cmp tmp_uncompressed "$FILE" ; then - : - else - echo "Decompressed file does not match" \ - "the original: $* $FILE" - (exit 1) - exit 1 - fi - - if test -n "$XZDEC" ; then - if $XZDEC tmp_compressed > tmp_uncompressed ; then - : - else - echo "Decompressing failed: $* $FILE" - (exit 1) - exit 1 - fi - - if cmp tmp_uncompressed "$FILE" ; then - : - else - echo "Decompressed file does not match" \ - "the original: $* $FILE" - (exit 1) - exit 1 - fi - fi - - # Show progress: - echo . | tr -d '\n\r' -} - -XZ="../src/xz/xz --memlimit-compress=48MiB --memlimit-decompress=5MiB \ - --no-adjust --threads=1 --check=crc64" -XZDEC="../src/xzdec/xzdec" # No memory usage limiter available -test -x ../src/xzdec/xzdec || XZDEC= - -# Create the required input files. -if ./create_compress_files ; then - : -else - rm -f compress_* - echo "Failed to create files to test compression." - (exit 1) - exit 1 -fi - -# Remove temporary now (in case they are something weird), and on exit. -rm -f tmp_compressed tmp_uncompressed -trap 'rm -f tmp_compressed tmp_uncompressed' 0 - -# Compress and decompress each file with various filter configurations. -# This takes quite a bit of time. -echo "test_compress.sh:" -for FILE in compress_generated_* "$srcdir"/compress_prepared_* -do - MSG=`echo "x$FILE" | sed 's,^x,,; s,^.*/,,; s,^compress_,,'` - echo " $MSG" | tr -d '\n\r' - - # Don't test with empty arguments; it breaks some ancient - # proprietary /bin/sh versions due to $@ used in test_xz(). - test_xz -1 - test_xz -2 - test_xz -3 - test_xz -4 - - # Disabled until Subblock format is stable. -# --subblock \ -# --subblock=size=1 \ -# --subblock=size=1,rle=1 \ -# --subblock=size=1,rle=4 \ -# --subblock=size=4,rle=4 \ -# --subblock=size=8,rle=4 \ -# --subblock=size=8,rle=8 \ -# --subblock=size=4096,rle=12 \ -# - for ARGS in \ - --delta=dist=1 \ - --delta=dist=4 \ - --delta=dist=256 \ - --x86 \ - --powerpc \ - --ia64 \ - --arm \ - --armthumb \ - --sparc - do - test_xz $ARGS --lzma2=dict=64KiB,nice=32,mode=fast - - # Disabled until Subblock format is stable. - # test_xz --subblock $ARGS --lzma2=dict=64KiB,nice=32,mode=fast - done - - echo -done - -(exit 0) -exit 0 diff --git a/tests/test_files.sh b/tests/test_files.sh deleted file mode 100755 index 0f8a64d..0000000 --- a/tests/test_files.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh - -############################################################################### -# -# Author: Lasse Collin -# -# This file has been put into the public domain. -# You can do whatever you want with this file. -# -############################################################################### - -# If both xz and xzdec were not build, skip this test. -XZ=../src/xz/xz -XZDEC=../src/xzdec/xzdec -test -x "$XZ" || XZ= -test -x "$XZDEC" || XZDEC= -if test -z "$XZ$XZDEC"; then - (exit 77) - exit 77 -fi - -for I in "$srcdir"/files/good-*.xz -do - if test -z "$XZ" || "$XZ" -dc "$I" > /dev/null; then - : - else - echo "Good file failed: $I" - (exit 1) - exit 1 - fi - - if test -z "$XZDEC" || "$XZDEC" "$I" > /dev/null; then - : - else - echo "Good file failed: $I" - (exit 1) - exit 1 - fi -done - -for I in "$srcdir"/files/bad-*.xz -do - if test -n "$XZ" && "$XZ" -dc "$I" > /dev/null 2>&1; then - echo "Bad file succeeded: $I" - (exit 1) - exit 1 - fi - - if test -n "$XZDEC" && "$XZDEC" "$I" > /dev/null 2>&1; then - echo "Bad file succeeded: $I" - (exit 1) - exit 1 - fi -done - -(exit 0) -exit 0 diff --git a/tests/test_filter_flags.c b/tests/test_filter_flags.c index ccd9ae9..67536eb 100644 --- a/tests/test_filter_flags.c +++ b/tests/test_filter_flags.c @@ -10,8 +10,9 @@ // /////////////////////////////////////////////////////////////////////////////// -#include "tests.h" - +#include "liblzma_tests.h" +#include "test_utils.h" +#include <stdbool.h> static uint8_t buffer[4096]; static lzma_filter known_flags; @@ -79,27 +80,27 @@ test_bcj(void) known_flags.id = LZMA_FILTER_X86; known_flags.options = NULL; - expect(!encode(2)); - expect(!decode(2)); - expect(decoded_flags.options == NULL); + assert_true(!encode(2)); + assert_true(!decode(2)); + assert_true(decoded_flags.options == NULL); // Test 2 lzma_options_bcj options; options.start_offset = 0; known_flags.options = &options; - expect(!encode(2)); - expect(!decode(2)); - expect(decoded_flags.options == NULL); + assert_true(!encode(2)); + assert_true(!decode(2)); + assert_true(decoded_flags.options == NULL); // Test 3 options.start_offset = 123456; known_flags.options = &options; - expect(!encode(6)); - expect(!decode(6)); - expect(decoded_flags.options != NULL); + assert_true(!encode(6)); + assert_true(!decode(6)); + assert_true(decoded_flags.options != NULL); lzma_options_bcj *decoded = decoded_flags.options; - expect(decoded->start_offset == options.start_offset); + assert_true(decoded->start_offset == options.start_offset); free(decoded); } @@ -113,7 +114,7 @@ test_delta(void) // Test 1 known_flags.id = LZMA_FILTER_DELTA; known_flags.options = NULL; - expect(encode(99)); + assert_true(encode(99)); // Test 2 lzma_options_delta options = { @@ -121,29 +122,29 @@ test_delta(void) .dist = 0 }; known_flags.options = &options; - expect(encode(99)); + assert_true(encode(99)); // Test 3 options.dist = LZMA_DELTA_DIST_MIN; - expect(!encode(3)); - expect(!decode(3)); - expect(((lzma_options_delta *)(decoded_flags.options))->dist - == options.dist); + assert_true(!encode(3)); + assert_true(!decode(3)); + assert_int_equal(((lzma_options_delta *)(decoded_flags.options))->dist + , options.dist); free(decoded_flags.options); // Test 4 options.dist = LZMA_DELTA_DIST_MAX; - expect(!encode(3)); - expect(!decode(3)); - expect(((lzma_options_delta *)(decoded_flags.options))->dist - == options.dist); + assert_true(!encode(3)); + assert_true(!decode(3)); + assert_int_equal(((lzma_options_delta *)(decoded_flags.options))->dist + , options.dist); free(decoded_flags.options); // Test 5 options.dist = LZMA_DELTA_DIST_MAX + 1; - expect(encode(99)); + assert_true(encode(99)); } #endif @@ -239,20 +240,21 @@ test_lzma(void) #endif */ -int -main(void) + +void +test_filter_flags(void) { + test_fixture_start(); #if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86) - test_bcj(); + run_test(test_bcj); #endif #if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA) - test_delta(); + run_test(test_delta); #endif // #ifdef HAVE_FILTER_LZMA -// test_lzma(); +// run_test(test_lzma); // #endif lzma_end(&strm); - - return 0; + test_fixture_end(); } diff --git a/tests/test_index.c b/tests/test_index.c index ce2cfe1..2f667d0 100644 --- a/tests/test_index.c +++ b/tests/test_index.c @@ -10,19 +10,97 @@ // /////////////////////////////////////////////////////////////////////////////// -#include "tests.h" +#include "liblzma_tests.h" +#include <stdbool.h> +#include <stdlib.h> #define MEMLIMIT (LZMA_VLI_C(1) << 20) #define SMALL_COUNT 3 #define BIG_COUNT 5555 +// Allocator that succeeds for the first two allocation but fails the rest. +static void * +my_alloc(void *opaque, size_t a, size_t b) +{ + (void)opaque; + + static unsigned count = 0; + if (++count > 2) + return NULL; + + return malloc(a * b); +} + +static const lzma_allocator my_allocator = { &my_alloc, NULL, NULL }; + +static inline bool +coder_loop(lzma_stream *strm, uint8_t *in, size_t in_size, + uint8_t *out, size_t out_size, + lzma_ret expected_ret, lzma_action finishing_action) +{ + size_t in_left = in_size; + size_t out_left = out_size > 0 ? out_size + 1 : 0; + lzma_action action = LZMA_RUN; + lzma_ret ret; + + strm->next_in = NULL; + strm->avail_in = 0; + strm->next_out = NULL; + strm->avail_out = 0; + + while (true) { + if (in_left > 0) { + if (--in_left == 0) + action = finishing_action; + + strm->next_in = in++; + strm->avail_in = 1; + } + + if (out_left > 0) { + --out_left; + strm->next_out = out++; + strm->avail_out = 1; + } + + ret = lzma_code(strm, action); + if (ret != LZMA_OK) + break; + } + + bool error = false; + + if (ret != expected_ret) + error = true; + + if (strm->total_in != in_size || strm->total_out != out_size) + error = true; + + return error; +} + + +static inline bool +decoder_loop_ret(lzma_stream *strm, uint8_t *in, size_t in_size, + lzma_ret expected_ret) +{ + return coder_loop(strm, in, in_size, NULL, 0, expected_ret, LZMA_RUN); +} + + +static inline bool +decoder_loop(lzma_stream *strm, uint8_t *in, size_t in_size) +{ + return coder_loop(strm, in, in_size, NULL, 0, + LZMA_STREAM_END, LZMA_RUN); +} static lzma_index * create_empty(void) { lzma_index *i = lzma_index_init(NULL); - expect(i != NULL); + assert_true(i != NULL); return i; } @@ -31,10 +109,10 @@ static lzma_index * create_small(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); + assert_true(i != NULL); + assert_int_equal(lzma_index_append(i, NULL, 101, 555), LZMA_OK); + assert_int_equal(lzma_index_append(i, NULL, 602, 777), LZMA_OK); + assert_int_equal(lzma_index_append(i, NULL, 804, 999), LZMA_OK); return i; } @@ -43,7 +121,7 @@ static lzma_index * create_big(void) { lzma_index *i = lzma_index_init(NULL); - expect(i != NULL); + assert_true(i != NULL); lzma_vli total_size = 0; lzma_vli uncompressed_size = 0; @@ -53,17 +131,17 @@ create_big(void) 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); + assert_int_equal(lzma_index_append(i, NULL, t, n), LZMA_OK); total_size += (t + 3) & ~LZMA_VLI_C(3); uncompressed_size += n; } - 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_int_equal(lzma_index_block_count(i), BIG_COUNT); + assert_int_equal(lzma_index_total_size(i), total_size); + assert_int_equal(lzma_index_uncompressed_size(i), uncompressed_size); + assert_int_equal(lzma_index_total_size(i) + lzma_index_size(i) + + 2 * LZMA_STREAM_HEADER_SIZE, + lzma_index_stream_size(i)); return i; } @@ -129,15 +207,15 @@ test_equal(void) lzma_index *a = create_empty(); lzma_index *b = create_small(); lzma_index *c = create_big(); - expect(a && b && c); + assert_true(a && b && c); - expect(is_equal(a, a)); - expect(is_equal(b, b)); - expect(is_equal(c, c)); + assert_true(is_equal(a, a)); + assert_true(is_equal(b, b)); + assert_true(is_equal(c, c)); - expect(!is_equal(a, b)); - expect(!is_equal(a, c)); - expect(!is_equal(b, c)); + assert_false(is_equal(a, b)); + assert_false(is_equal(a, c)); + assert_false(is_equal(b, c)); lzma_index_end(a, NULL); lzma_index_end(b, NULL); @@ -151,8 +229,8 @@ test_overflow(void) // Integer overflow tests lzma_index *i = create_empty(); - expect(lzma_index_append(i, NULL, LZMA_VLI_MAX - 5, 1234) - == LZMA_DATA_ERROR); + assert_int_equal(lzma_index_append(i, NULL, LZMA_VLI_MAX - 5, 1234), + LZMA_DATA_ERROR); // TODO @@ -164,8 +242,8 @@ static void test_copy(const lzma_index *i) { lzma_index *d = lzma_index_dup(i, NULL); - expect(d != NULL); - expect(is_equal(i, d)); + assert_true(d != NULL); + assert_true(is_equal(i, d)); lzma_index_end(d, NULL); } @@ -190,18 +268,18 @@ test_read(lzma_index *i) total_size += r.block.total_size; uncompressed_size += r.block.uncompressed_size; - expect(r.block.compressed_file_offset - == stream_offset); - expect(r.block.uncompressed_file_offset - == uncompressed_offset); + assert_int_equal(r.block.compressed_file_offset, + stream_offset); + assert_int_equal(r.block.uncompressed_file_offset, + uncompressed_offset); stream_offset += r.block.total_size; uncompressed_offset += r.block.uncompressed_size; } - expect(lzma_index_total_size(i) == total_size); - expect(lzma_index_uncompressed_size(i) == uncompressed_size); - expect(lzma_index_block_count(i) == count); + assert_int_equal(lzma_index_total_size(i), total_size); + assert_int_equal(lzma_index_uncompressed_size(i), uncompressed_size); + assert_int_equal(lzma_index_block_count(i), count); lzma_index_iter_rewind(&r); } @@ -213,64 +291,64 @@ test_code(lzma_index *i) { const size_t alloc_size = 128 * 1024; uint8_t *buf = malloc(alloc_size); - expect(buf != NULL); + assert_true(buf != NULL); // Encode lzma_stream strm = LZMA_STREAM_INIT; - expect(lzma_index_encoder(&strm, i) == LZMA_OK); + assert_int_equal(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, + assert_false(coder_loop(&strm, NULL, 0, buf, index_size, LZMA_STREAM_END, LZMA_RUN)); // Decode lzma_index *d; - expect(lzma_index_decoder(&strm, &d, MEMLIMIT) == LZMA_OK); - expect(d == NULL); - succeed(decoder_loop(&strm, buf, index_size)); + assert_int_equal(lzma_index_decoder(&strm, &d, MEMLIMIT), LZMA_OK); + assert_true(d == NULL); + assert_false(decoder_loop(&strm, buf, index_size)); - expect(is_equal(i, d)); + assert_true(is_equal(i, d)); lzma_index_end(d, NULL); lzma_end(&strm); // Decode with hashing lzma_index_hash *h = lzma_index_hash_init(NULL, NULL); - expect(h != NULL); + assert_true(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); + assert_int_equal(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); + assert_int_equal(lzma_index_hash_decode(h, buf, &pos, pos + 1), + LZMA_OK); + assert_int_equal(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); + assert_int_equal(lzma_index_buffer_encode(i, buf, &buf_pos, index_size), + LZMA_BUF_ERROR); + assert_int_equal(buf_pos, 1); - succeed(lzma_index_buffer_encode(i, buf, &buf_pos, index_size + 1)); - expect(buf_pos == index_size + 1); + assert_false(lzma_index_buffer_encode(i, buf, &buf_pos, index_size + 1)); + assert_int_equal(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_int_equal(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos, + index_size), LZMA_DATA_ERROR); + assert_int_equal(buf_pos, 1); + assert_true(d == NULL); - succeed(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos, + assert_false(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos, index_size + 1)); - expect(buf_pos == index_size + 1); - expect(is_equal(i, d)); + assert_int_equal(buf_pos, index_size + 1); + assert_true(is_equal(i, d)); lzma_index_end(d, NULL); @@ -296,40 +374,40 @@ test_cat(void) // 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)); + assert_int_equal(lzma_index_cat(a, b, NULL), LZMA_OK); + assert_int_equal(lzma_index_block_count(a), 0); + assert_int_equal(lzma_index_stream_size(a), 2 * LZMA_STREAM_HEADER_SIZE + 8); + assert_int_equal(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)); + assert_true(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)); + assert_int_equal(lzma_index_cat(a, b, NULL), LZMA_OK); + assert_int_equal(lzma_index_block_count(a), 0); + assert_int_equal(lzma_index_stream_size(a), 2 * LZMA_STREAM_HEADER_SIZE + 8); + assert_int_equal(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)); + assert_int_equal(lzma_index_stream_padding(b, 4), LZMA_OK); + assert_int_equal(lzma_index_cat(b, c, NULL), LZMA_OK); + assert_int_equal(lzma_index_block_count(b), 0); + assert_int_equal(lzma_index_stream_size(b), 2 * LZMA_STREAM_HEADER_SIZE + 8); + assert_int_equal(lzma_index_file_size(b), + 2 * (2 * LZMA_STREAM_HEADER_SIZE + 8) + 4); + + assert_int_equal(lzma_index_stream_padding(a, 8), LZMA_OK); + assert_int_equal(lzma_index_cat(a, b, NULL), LZMA_OK); + assert_int_equal(lzma_index_block_count(a), 0); + assert_int_equal(lzma_index_stream_size(a), 2 * LZMA_STREAM_HEADER_SIZE + 8); + assert_int_equal(lzma_index_file_size(a), + 5 * (2 * LZMA_STREAM_HEADER_SIZE + 8) + 4 + 8); + + assert_true(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)); lzma_index_iter_rewind(&r); - expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)); + assert_true(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)); lzma_index_end(a, NULL); // Small Indexes @@ -337,40 +415,40 @@ test_cat(void) 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) + assert_true(!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); + assert_int_equal(lzma_index_stream_padding(a, 4), LZMA_OK); + assert_int_equal(lzma_index_cat(a, b, NULL), LZMA_OK); + assert_int_equal(lzma_index_file_size(a), stream_size * 2 + 4); + assert_true(lzma_index_stream_size(a) > stream_size); + assert_true(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) + assert_true(!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) + assert_true(!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); + assert_int_equal(lzma_index_stream_padding(b, 8), LZMA_OK); + assert_int_equal(lzma_index_cat(b, c, NULL), LZMA_OK); + assert_int_equal(lzma_index_stream_padding(a, 12), LZMA_OK); + assert_int_equal(lzma_index_cat(a, b, NULL), LZMA_OK); + assert_int_equal(lzma_index_file_size(a), stream_size * 4 + 4 + 8 + 12); - expect(lzma_index_block_count(a) == SMALL_COUNT * 4); + assert_int_equal(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) + assert_true(!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) + assert_true(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK) ^ (i == 0)); lzma_index_end(a, NULL); @@ -378,11 +456,11 @@ test_cat(void) // 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); + assert_int_equal(lzma_index_stream_padding(a, 4), LZMA_OK); + assert_int_equal(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) + assert_true(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK) ^ (i == 0)); lzma_index_end(a, NULL); @@ -391,23 +469,23 @@ test_cat(void) 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); + assert_int_equal(lzma_index_stream_padding(a, 4), LZMA_OK); + assert_int_equal(lzma_index_cat(a, b, NULL), LZMA_OK); + assert_int_equal(lzma_index_file_size(a), stream_size * 2 + 4); + assert_true(lzma_index_stream_size(a) > stream_size); + assert_true(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); + assert_int_equal(lzma_index_stream_padding(b, 8), LZMA_OK); + assert_int_equal(lzma_index_cat(b, c, NULL), LZMA_OK); + assert_int_equal(lzma_index_stream_padding(a, 12), LZMA_OK); + assert_int_equal(lzma_index_cat(a, b, NULL), LZMA_OK); + assert_int_equal(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) + assert_true(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK) ^ (i == 0)); lzma_index_end(a, NULL); @@ -418,113 +496,113 @@ static void test_locate(void) { lzma_index *i = lzma_index_init(NULL); - expect(i != NULL); + assert_true(i != NULL); lzma_index_iter r; lzma_index_iter_init(&r, i); // 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(&r, 0)); + assert_true(lzma_index_iter_locate(&r, 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_int_equal(lzma_index_append(i, NULL, 16, 0), LZMA_OK); + assert_true(lzma_index_iter_locate(&r, 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_true(lzma_index_append(i, NULL, 32, 5) == LZMA_OK); + assert_false(lzma_index_iter_locate(&r, 0)); + assert_int_equal(r.block.total_size, 32); + assert_int_equal(r.block.uncompressed_size, 5); + assert_int_equal(r.block.compressed_file_offset, + LZMA_STREAM_HEADER_SIZE + 16); + assert_int_equal(r.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(&r, 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_int_equal(lzma_index_append(i, NULL, 40, 11), LZMA_OK); + + assert_false(lzma_index_iter_locate(&r, 0)); + assert_int_equal(r.block.total_size, 32); + assert_int_equal(r.block.uncompressed_size, 5); + assert_int_equal(r.block.compressed_file_offset, + LZMA_STREAM_HEADER_SIZE + 16); + assert_int_equal(r.block.uncompressed_file_offset, 0); + + assert_false(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)); + assert_int_equal(r.block.total_size, 40); + assert_int_equal(r.block.uncompressed_size, 11); + assert_int_equal(r.block.compressed_file_offset, + LZMA_STREAM_HEADER_SIZE + 16 + 32); + assert_int_equal(r.block.uncompressed_file_offset, 5); + + assert_false(lzma_index_iter_locate(&r, 2)); + assert_int_equal(r.block.total_size, 32); + assert_int_equal(r.block.uncompressed_size, 5); + assert_int_equal(r.block.compressed_file_offset, + LZMA_STREAM_HEADER_SIZE + 16); + assert_int_equal(r.block.uncompressed_file_offset, 0); + + assert_false(lzma_index_iter_locate(&r, 5)); + assert_int_equal(r.block.total_size, 40); + assert_int_equal(r.block.uncompressed_size, 11); + assert_int_equal(r.block.compressed_file_offset, + LZMA_STREAM_HEADER_SIZE + 16 + 32); + assert_int_equal(r.block.uncompressed_file_offset, 5); + + assert_false(lzma_index_iter_locate(&r, 5 + 11 - 1)); + assert_int_equal(r.block.total_size, 40); + assert_int_equal(r.block.uncompressed_size, 11); + assert_int_equal(r.block.compressed_file_offset, + LZMA_STREAM_HEADER_SIZE + 16 + 32); + assert_int_equal(r.block.uncompressed_file_offset, 5); + + assert_true(lzma_index_iter_locate(&r, 5 + 11)); + assert_true(lzma_index_iter_locate(&r, 5 + 15)); // Large Index lzma_index_end(i, NULL); i = lzma_index_init(NULL); - expect(i != NULL); + assert_true(i != NULL); lzma_index_iter_init(&r, i); for (size_t n = 4; n <= 4 * 5555; n += 4) - expect(lzma_index_append(i, NULL, n + 8, n) == LZMA_OK); + assert_int_equal(lzma_index_append(i, NULL, n + 8, n), LZMA_OK); - expect(lzma_index_block_count(i) == 5555); + assert_int_equal(lzma_index_block_count(i), 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(&r, 0)); + assert_int_equal(r.block.total_size, 4 + 8); + assert_int_equal(r.block.uncompressed_size, 4); + assert_int_equal(r.block.compressed_file_offset, LZMA_STREAM_HEADER_SIZE); + assert_int_equal(r.block.uncompressed_file_offset, 0); + + assert_false(lzma_index_iter_locate(&r, 3)); + assert_int_equal(r.block.total_size, 4 + 8); + assert_int_equal(r.block.uncompressed_size, 4); + assert_int_equal(r.block.compressed_file_offset, LZMA_STREAM_HEADER_SIZE); + assert_int_equal(r.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(&r, 4)); + assert_int_equal(r.block.total_size, 2 * 4 + 8); + assert_int_equal(r.block.uncompressed_size, 2 * 4); + assert_int_equal(r.block.compressed_file_offset, + LZMA_STREAM_HEADER_SIZE + 4 + 8); + assert_int_equal(r.block.uncompressed_file_offset, 4); // Last Record - expect(!lzma_index_iter_locate( + assert_false(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_int_equal(r.block.total_size, 4 * 5555 + 8); + assert_int_equal(r.block.uncompressed_size, 4 * 5555); + assert_int_equal(r.block.compressed_file_offset, lzma_index_total_size(i) + LZMA_STREAM_HEADER_SIZE - 4 * 5555 - 8); - expect(r.block.uncompressed_file_offset - == lzma_index_uncompressed_size(i) - 4 * 5555); + assert_int_equal(r.block.uncompressed_file_offset, + lzma_index_uncompressed_size(i) - 4 * 5555); // Allocation chunk boundaries. See INDEX_GROUP_SIZE in // liblzma/common/index.c. @@ -540,50 +618,49 @@ test_locate(void) } while (n < start + 2 * radius) { - expect(!lzma_index_iter_locate(&r, ubase + n * 4)); + assert_false(lzma_index_iter_locate(&r, ubase + n * 4)); - expect(r.block.compressed_file_offset == tbase + n * 4 + 8 + assert_int_equal(r.block.compressed_file_offset, tbase + n * 4 + 8 + LZMA_STREAM_HEADER_SIZE); - expect(r.block.uncompressed_file_offset == ubase + n * 4); + assert_int_equal(r.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_int_equal(r.block.total_size, n * 4 + 8); + assert_int_equal(r.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(&r, ubase + (n - 1) * 4)); - expect(r.block.total_size == n * 4 + 8); - expect(r.block.uncompressed_size == n * 4); + assert_int_equal(r.block.total_size, n * 4 + 8); + assert_int_equal(r.block.uncompressed_size, n * 4); --n; tbase -= n * 4 + 8; ubase -= n * 4; - expect(r.block.compressed_file_offset == tbase + n * 4 + 8 + assert_int_equal(r.block.compressed_file_offset, tbase + n * 4 + 8 + LZMA_STREAM_HEADER_SIZE); - expect(r.block.uncompressed_file_offset == ubase + n * 4); + assert_int_equal(r.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); + assert_true(i != NULL); lzma_index_iter_init(&r, i); 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); + assert_int_equal(lzma_index_append(i, NULL, 8, 0), LZMA_OK); + assert_int_equal(lzma_index_append(i, NULL, 16, 1), LZMA_OK); + assert_false(lzma_index_iter_locate(&r, 0)); + assert_int_equal(r.block.total_size, 16); + assert_int_equal(r.block.uncompressed_size, 1); + assert_int_equal(r.block.compressed_file_offset, LZMA_STREAM_HEADER_SIZE + group_multiple * 8); + assert_int_equal(r.block.uncompressed_file_offset, 0); lzma_index_end(i, NULL); } @@ -594,96 +671,99 @@ test_corrupt(void) { const size_t alloc_size = 128 * 1024; uint8_t *buf = malloc(alloc_size); - expect(buf != NULL); + assert_true(buf != NULL); lzma_stream strm = LZMA_STREAM_INIT; lzma_index *i = create_empty(); - expect(lzma_index_append(i, NULL, 0, 1) == LZMA_PROG_ERROR); + assert_int_equal(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, + assert_int_equal(lzma_index_encoder(&strm, i), LZMA_OK); + assert_false(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)); + assert_int_equal(lzma_index_decoder(&strm, &i, MEMLIMIT), LZMA_OK); + assert_false(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)); + assert_int_equal(lzma_index_decoder(&strm, &i, MEMLIMIT), LZMA_OK); + assert_false(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)); + assert_int_equal(lzma_index_decoder(&strm, &i, MEMLIMIT), LZMA_OK); + assert_false(decoder_loop_ret(&strm, buf, 16, LZMA_DATA_ERROR)); lzma_end(&strm); free(buf); } - -// Allocator that succeeds for the first two allocation but fails the rest. -static void * -my_alloc(void *opaque, size_t a, size_t b) -{ - (void)opaque; - - static unsigned count = 0; - if (++count > 2) - return NULL; - - return malloc(a * b); -} - -static const lzma_allocator my_allocator = { &my_alloc, NULL, NULL }; - - -int -main(void) +static void +test_empty_index(void) { - test_equal(); - - test_overflow(); - lzma_index *i = create_empty(); test_many(i); lzma_index_end(i, NULL); +} - i = create_small(); +static void +test_small_index(void) +{ + lzma_index *i = create_small(); test_many(i); lzma_index_end(i, NULL); +} - i = create_big(); +static void +test_big_index(void) +{ + lzma_index *i = create_big(); test_many(i); lzma_index_end(i, NULL); +} - test_cat(); - - test_locate(); - - test_corrupt(); - +static void +test_lzma_index_dup_empty_stream(void) +{ // 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); + lzma_index *i = create_empty(); + assert_int_equal(lzma_index_stream_padding(i, 4), LZMA_OK); test_copy(i); lzma_index_end(i, NULL); +} +static void +test_memory_leak_error_path_lzma_index_dup(void) +{ // 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 *i = create_small(); + assert_true(lzma_index_dup(i, &my_allocator) == NULL); lzma_index_end(i, NULL); +} - return 0; +void +test_lzma_index_structure(void){ + test_fixture_start(); + run_test(test_equal); + run_test(test_overflow); + run_test(test_empty_index); + run_test(test_small_index); + run_test(test_big_index); + run_test(test_cat); + run_test(test_locate); + run_test(test_corrupt); + run_test(test_lzma_index_dup_empty_stream); + run_test(test_memory_leak_error_path_lzma_index_dup); + test_fixture_end(); } diff --git a/tests/test_scripts.sh b/tests/test_scripts.sh deleted file mode 100755 index 48a9308..0000000 --- a/tests/test_scripts.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh - -############################################################################### -# -# Author: Jonathan Nieder -# -# This file has been put into the public domain. -# You can do whatever you want with this file. -# -############################################################################### - -# If scripts weren't built, this test is skipped. -XZ=../src/xz/xz -XZDIFF=../src/scripts/xzdiff -XZGREP=../src/scripts/xzgrep - -for i in XZ XZDIFF XZGREP; do - eval test -x "\$$i" && continue - (exit 77) - exit 77 -done - -PATH=`pwd`/../src/xz:$PATH -export PATH - -test -z "$srcdir" && srcdir=. -preimage=$srcdir/files/good-1-check-crc32.xz -samepostimage=$srcdir/files/good-1-check-crc64.xz -otherpostimage=$srcdir/files/good-1-lzma2-1.xz - -"$XZDIFF" "$preimage" "$samepostimage" >/dev/null -status=$? -if test "$status" != 0 ; then - echo "xzdiff with no changes exited with status $status != 0" - (exit 1) - exit 1 -fi - -"$XZDIFF" "$preimage" "$otherpostimage" >/dev/null -status=$? -if test "$status" != 1 ; then - echo "xzdiff with changes exited with status $status != 1" - (exit 1) - exit 1 -fi - -"$XZDIFF" "$preimage" "$srcdir/files/missing.xz" >/dev/null 2>&1 -status=$? -if test "$status" != 2 ; then - echo "xzdiff with missing operand exited with status $status != 2" - (exit 1) - exit 1 -fi - -# The exit status must be 0 when a match was found at least from one file, -# and 1 when no match was found in any file. -cp "$srcdir/files/good-1-lzma2-1.xz" xzgrep_test_1.xz -cp "$srcdir/files/good-2-lzma2.xz" xzgrep_test_2.xz -for pattern in el Hello NOMATCH; do - for opts in "" "-l" "-h" "-H"; do - echo "=> xzgrep $opts $pattern <=" - "$XZGREP" $opts $pattern xzgrep_test_1.xz xzgrep_test_2.xz - echo retval $? - done -done > xzgrep_test_output 2>&1 - -if cmp -s "$srcdir/xzgrep_expected_output" xzgrep_test_output ; then - : -else - echo "unexpected output from xzgrep" - (exit 1) - exit 1 -fi - -(exit 0) -exit 0 diff --git a/tests/test_stream_flags.c b/tests/test_stream_flags.c index 39304cd..35ff7b7 100644 --- a/tests/test_stream_flags.c +++ b/tests/test_stream_flags.c @@ -10,7 +10,10 @@ // /////////////////////////////////////////////////////////////////////////////// -#include "tests.h" +#include "liblzma_tests.h" +#include "test_utils.h" +#include "tuklib_integer.h" +#include <stdbool.h> static lzma_stream_flags known_flags; @@ -51,8 +54,8 @@ static void test_header(void) { memcrap(buffer, sizeof(buffer)); - expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK); - succeed(test_header_decoder(LZMA_OK)); + assert_int_equal(lzma_stream_header_encode(&known_flags, buffer), LZMA_OK); + assert_false(test_header_decoder(LZMA_OK)); } @@ -75,8 +78,8 @@ static void test_footer(void) { memcrap(buffer, sizeof(buffer)); - expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK); - succeed(test_footer_decoder(LZMA_OK)); + assert_int_equal(lzma_stream_footer_encode(&known_flags, buffer), LZMA_OK); + assert_false(test_footer_decoder(LZMA_OK)); } @@ -86,35 +89,35 @@ test_encode_invalid(void) known_flags.check = (lzma_check)(LZMA_CHECK_ID_MAX + 1); known_flags.backward_size = 1024; - expect(lzma_stream_header_encode(&known_flags, buffer) - == LZMA_PROG_ERROR); + assert_int_equal(lzma_stream_header_encode(&known_flags, buffer), + LZMA_PROG_ERROR); - expect(lzma_stream_footer_encode(&known_flags, buffer) - == LZMA_PROG_ERROR); + assert_int_equal(lzma_stream_footer_encode(&known_flags, buffer), + LZMA_PROG_ERROR); known_flags.check = (lzma_check)(-1); - expect(lzma_stream_header_encode(&known_flags, buffer) - == LZMA_PROG_ERROR); + assert_int_equal(lzma_stream_header_encode(&known_flags, buffer), + LZMA_PROG_ERROR); - expect(lzma_stream_footer_encode(&known_flags, buffer) - == LZMA_PROG_ERROR); + assert_int_equal(lzma_stream_footer_encode(&known_flags, buffer), + LZMA_PROG_ERROR); known_flags.check = LZMA_CHECK_NONE; known_flags.backward_size = 0; // Header encoder ignores backward_size. - expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK); + assert_int_equal(lzma_stream_header_encode(&known_flags, buffer), LZMA_OK); - expect(lzma_stream_footer_encode(&known_flags, buffer) - == LZMA_PROG_ERROR); + assert_int_equal(lzma_stream_footer_encode(&known_flags, buffer), + LZMA_PROG_ERROR); known_flags.backward_size = LZMA_VLI_MAX; - expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK); + assert_int_equal(lzma_stream_header_encode(&known_flags, buffer), LZMA_OK); - expect(lzma_stream_footer_encode(&known_flags, buffer) - == LZMA_PROG_ERROR); + assert_int_equal(lzma_stream_footer_encode(&known_flags, buffer), + LZMA_PROG_ERROR); } @@ -124,57 +127,56 @@ test_decode_invalid(void) known_flags.check = LZMA_CHECK_NONE; known_flags.backward_size = 1024; - expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK); + assert_int_equal(lzma_stream_header_encode(&known_flags, buffer), LZMA_OK); // Test 1 (invalid Magic Bytes) buffer[5] ^= 1; - succeed(test_header_decoder(LZMA_FORMAT_ERROR)); + assert_false(test_header_decoder(LZMA_FORMAT_ERROR)); buffer[5] ^= 1; // Test 2a (valid CRC32) uint32_t crc = lzma_crc32(buffer + 6, 2, 0); write32le(buffer + 8, crc); - succeed(test_header_decoder(LZMA_OK)); + assert_false(test_header_decoder(LZMA_OK)); // Test 2b (invalid Stream Flags with valid CRC32) buffer[6] ^= 0x20; crc = lzma_crc32(buffer + 6, 2, 0); write32le(buffer + 8, crc); - succeed(test_header_decoder(LZMA_OPTIONS_ERROR)); + assert_false(test_header_decoder(LZMA_OPTIONS_ERROR)); // Test 3 (invalid CRC32) - expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK); + assert_int_equal(lzma_stream_header_encode(&known_flags, buffer), LZMA_OK); buffer[9] ^= 1; - succeed(test_header_decoder(LZMA_DATA_ERROR)); + assert_false(test_header_decoder(LZMA_DATA_ERROR)); // Test 4 (invalid Stream Flags with valid CRC32) - expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK); + assert_int_equal(lzma_stream_footer_encode(&known_flags, buffer), LZMA_OK); buffer[9] ^= 0x40; crc = lzma_crc32(buffer + 4, 6, 0); write32le(buffer, crc); - succeed(test_footer_decoder(LZMA_OPTIONS_ERROR)); + assert_false(test_footer_decoder(LZMA_OPTIONS_ERROR)); // Test 5 (invalid Magic Bytes) - expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK); + assert_int_equal(lzma_stream_footer_encode(&known_flags, buffer), LZMA_OK); buffer[11] ^= 1; - succeed(test_footer_decoder(LZMA_FORMAT_ERROR)); + assert_false(test_footer_decoder(LZMA_FORMAT_ERROR)); } -int -main(void) +void test_stream_header_and_footer_coders(void) { + test_fixture_start(); // Valid headers known_flags.backward_size = 1024; for (lzma_check check = LZMA_CHECK_NONE; check <= LZMA_CHECK_ID_MAX; ++check) { - test_header(); - test_footer(); + run_test(test_header); + run_test(test_footer); } // Invalid headers - test_encode_invalid(); - test_decode_invalid(); - - return 0; + run_test(test_encode_invalid); + run_test(test_decode_invalid); + test_fixture_end(); } diff --git a/tests/test_utils.c b/tests/test_utils.c new file mode 100644 index 0000000..18eb424 --- /dev/null +++ b/tests/test_utils.c @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_utils.c +/// \brief Provides test util function implementations +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "test_utils.h" +#include <stdarg.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +/* + * Call standard system() call, but build up the command line using + * sprintf() conventions. + * + * Function taken and adapted from Tim Kientzle in Libarchive + */ +int +systemf(const char *fmt, ...) +{ + char buff[8192]; + va_list ap; + int r; + + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + r = system(buff); + va_end(ap); + return (r); +} + +bool +can_xz(void) +{ + return file_exists_and_can_execute(XZ_RELATIVE_PATH); +} + +bool +can_xz_diff(void) +{ + return file_exists_and_can_execute(XZ_DIFF_RELATIVE_PATH); +} + +bool +can_xz_grep(void) +{ + return file_exists_and_can_execute(XZ_GREP_RELATIVE_PATH); +} + +bool +can_xz_dec(void) +{ + return file_exists_and_can_execute(XZ_DEC_RELATIVE_PATH); +} + +bool +file_exists_and_can_execute(const char* path) +{ + return access(path, X_OK) == 0; +} diff --git a/tests/test_utils.h b/tests/test_utils.h new file mode 100644 index 0000000..bd847f3 --- /dev/null +++ b/tests/test_utils.h @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_utils.h +/// \brief Test util definitions and function prototypes +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TEST_UTILS_H +#define TEST_UTILS_H + +#include <stdbool.h> +#include <string.h> + +#define memcrap(buf, size) memset(buf, 0xFD, size) +#define MAX_PATH_LENGTH 1024 + +#define XZ_RELATIVE_PATH "../src/xz/xz" +#define XZ_DIFF_RELATIVE_PATH "../src/scripts/xzdiff" +#define XZ_GREP_RELATIVE_PATH "../src/scripts/xzgrep" +#define XZ_DEC_RELATIVE_PATH "../src/xzdec/xzdec" + +int systemf(const char *fmt, ...); + +bool can_xz(void); +bool can_xz_diff(void); +bool can_xz_grep(void); +bool can_xz_dec(void); + +bool file_exists_and_can_execute(const char* path); +void get_path_to_files(char* out_path); + +#endif \ No newline at end of file diff --git a/tests/test_xz_compress.c b/tests/test_xz_compress.c new file mode 100644 index 0000000..9c012e5 --- /dev/null +++ b/tests/test_xz_compress.c @@ -0,0 +1,312 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_xz_compress.c +/// \brief Tests xz compression with various options +/// +/// \todo Add subblock tests when stable +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + + +#include "xz_tests.h" +#include "test_utils.h" +#include "sysdefs.h" + +static bool file_exists(const char *filename); +static FILE *file_create(const char *filename); +static void file_finish(FILE *file, const char *filename); +static void write_random(FILE *file); + +// Tests are unrolled instead of in a loop to improve readability +// on a failing test and show explicitly what is being tested +static void test_xz_compress_and_decompress(const char* option); +static void test_xz_compress_level_1(void); +static void test_xz_compress_level_2(void); +static void test_xz_compress_level_3(void); +static void test_xz_compress_level_4(void); +static void test_xz_compress_delta_dist_1(void); +static void test_xz_compress_delta_dist_4(void); +static void test_xz_compress_delta_dist_256(void); +static void test_xz_compress_x86(void); +static void test_xz_compress_powerpc(void); +static void test_xz_compress_ia64(void); +static void test_xz_compress_arm(void); +static void test_xz_compress_armthumb(void); +static void test_xz_compress_sparc(void); + +static const char* xz_compressed_tmp_filename = "tmp_compressed"; +static const char* xz_decompressed_tmp_filename = "tmp_uncompressed"; +static const char* xz_options = "--memlimit-compress=48MiB --memlimit-decompress=5MiB " \ + "--no-adjust --threads=1 --check=crc64"; +static const char* compress_filenames[] = {"compress_generated_abc", + "compress_generated_random", + "compress_generated_text", + "compress_prepared_bcj_sparc", + "compress_prepared_bcj_x86"}; +#define COMPRESS_FILE_COUNT 5 + + +// Avoid re-creating the test files every time the tests are run. +#define create_test(name) \ +do { \ + if (!file_exists("compress_generated_" #name)) { \ + FILE *file = file_create("compress_generated_" #name); \ + write_ ## name(file); \ + file_finish(file, "compress_generated_" #name); \ + } \ +} while (0) + +static bool +file_exists(const char *filename) +{ + // Trying to be somewhat portable by avoiding stat(). + FILE *file = fopen(filename, "rb"); + bool ret; + + if (file != NULL) { + fclose(file); + ret = true; + } else { + ret = false; + } + + return ret; +} + + +static FILE * +file_create(const char *filename) +{ + FILE *file = fopen(filename, "wb"); + + if (file == NULL) { + perror(filename); + } + + return file; +} + + +static void +file_finish(FILE *file, const char *filename) +{ + const bool ferror_fail = ferror(file); + const bool fclose_fail = fclose(file); + + if (ferror_fail || fclose_fail) { + perror(filename); + } +} + + +// File that repeats "abc\n" a few thousand times. This is targeted +// especially at Subblock filter's run-length encoder. +static void +write_abc(FILE *file) +{ + for (size_t i = 0; i < 12345; ++i) + if (fwrite("abc\n", 4, 1, file) != 1) + printf("Error writing to file\n"); +} + + +// File that doesn't compress. We always use the same random seed to +// generate identical files on all systems. +static void +write_random(FILE *file) +{ + uint32_t n = 5; + + for (size_t i = 0; i < 123456; ++i) { + n = 101771 * n + 71777; + + putc((uint8_t)(n), file); + putc((uint8_t)(n >> 8), file); + putc((uint8_t)(n >> 16), file); + putc((uint8_t)(n >> 24), file); + } +} + + +// Text file +static void +write_text(FILE *file) +{ + static const char *lorem[] = { + "Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", + "adipisicing", "elit,", "sed", "do", "eiusmod", "tempor", + "incididunt", "ut", "labore", "et", "dolore", "magna", + "aliqua.", "Ut", "enim", "ad", "minim", "veniam,", "quis", + "nostrud", "exercitation", "ullamco", "laboris", "nisi", + "ut", "aliquip", "ex", "ea", "commodo", "consequat.", + "Duis", "aute", "irure", "dolor", "in", "reprehenderit", + "in", "voluptate", "velit", "esse", "cillum", "dolore", + "eu", "fugiat", "nulla", "pariatur.", "Excepteur", "sint", + "occaecat", "cupidatat", "non", "proident,", "sunt", "in", + "culpa", "qui", "officia", "deserunt", "mollit", "anim", + "id", "est", "laborum." + }; + + // Let the first paragraph be the original text. + for (size_t w = 0; w < ARRAY_SIZE(lorem); ++w) { + fprintf(file, "%s ", lorem[w]); + + if (w % 7 == 6) + fprintf(file, "\n"); + } + + // The rest shall be (hopefully) meaningless combinations of + // the same words. + uint32_t n = 29; + + for (size_t p = 0; p < 500; ++p) { + fprintf(file, "\n\n"); + + for (size_t w = 0; w < ARRAY_SIZE(lorem); ++w) { + n = 101771 * n + 71777; + + fprintf(file, "%s ", lorem[n % ARRAY_SIZE(lorem)]); + + if (w % 7 == 6) + fprintf(file, "\n"); + } + } +} + +static void +test_xz_compress_and_decompress(const char* option) +{ + for(int i = 0; i < COMPRESS_FILE_COUNT; i++){ + const char* current_file = compress_filenames[i]; + assert_int_equal(systemf("%s %s -c %s %s > %s", + XZ_RELATIVE_PATH, xz_options, option, current_file, + xz_compressed_tmp_filename), 0); + + assert_int_equal(systemf("%s %s -cd > %s", XZ_RELATIVE_PATH, xz_compressed_tmp_filename, + xz_decompressed_tmp_filename), 0); + assert_int_equal(systemf("cmp %s %s", xz_decompressed_tmp_filename, current_file), 0); + } +} + +/* TODO - Add subblock tests when stable +* --subblock +* --subblock=size=1 +* --subblock=size=1,rle=1 +* --subblock=size=1,rle=4 +* --subblock=size=4,rle=4 +* --subblock=size=8,rle=4 +* --subblock=size=8,rle=8 +* --subblock=size=4096,rle=12 +*/ + +static void +test_xz_compress_level_1(void) +{ + test_xz_compress_and_decompress("-1"); +} + +static void +test_xz_compress_level_2(void) +{ + test_xz_compress_and_decompress("-2"); +} + +static void +test_xz_compress_level_3(void) +{ + test_xz_compress_and_decompress("-3"); +} + +static void +test_xz_compress_level_4(void) +{ + test_xz_compress_and_decompress("-4"); +} + +static void +test_xz_compress_delta_dist_1(void) +{ + test_xz_compress_and_decompress("--delta=dist=1 --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +static void +test_xz_compress_delta_dist_4(void) +{ + test_xz_compress_and_decompress("--delta=dist=4 --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +static void +test_xz_compress_delta_dist_256(void) +{ + test_xz_compress_and_decompress("--delta=dist=256 --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +static void +test_xz_compress_x86(void) +{ + test_xz_compress_and_decompress("--x86 --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +static void +test_xz_compress_powerpc(void) +{ + test_xz_compress_and_decompress("--powerpc --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +static void +test_xz_compress_ia64(void) +{ + test_xz_compress_and_decompress("--ia64 --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +static void +test_xz_compress_arm(void) +{ + test_xz_compress_and_decompress("--arm --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +static void +test_xz_compress_armthumb(void) +{ + test_xz_compress_and_decompress("--armthumb --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +static void +test_xz_compress_sparc(void) +{ + test_xz_compress_and_decompress("--sparc --lzma2=dict=64KiB,nice=32,mode=fast"); +} + +void +test_xz_compress(void) +{ + create_test(abc); + create_test(random); + create_test(text); + + test_fixture_start(); + if(!can_xz() || !can_xz_dec()){ + printf("xz or xzdec not built. Skipping xz compression tests\n"); + } + else { + run_test(test_xz_compress_level_1); + run_test(test_xz_compress_level_2); + run_test(test_xz_compress_level_3); + run_test(test_xz_compress_level_4); + run_test(test_xz_compress_delta_dist_1); + run_test(test_xz_compress_delta_dist_4); + run_test(test_xz_compress_delta_dist_256); + run_test(test_xz_compress_x86); + run_test(test_xz_compress_powerpc); + run_test(test_xz_compress_ia64); + run_test(test_xz_compress_arm); + run_test(test_xz_compress_armthumb); + run_test(test_xz_compress_sparc); + } + test_fixture_end(); +} diff --git a/tests/test_xz_decompress.c b/tests/test_xz_decompress.c new file mode 100644 index 0000000..05b5c55 --- /dev/null +++ b/tests/test_xz_decompress.c @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_xz_decompress.c +/// \brief Tests decompression with various options +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "xz_tests.h" +#include "test_utils.h" +#include <glob.h> + +static void test_good_files_xz(void); +static void test_good_files_xz_dec(void); +static void test_bad_files_xz(void); +static void test_bad_files_xz_dec(void); + + +static void +test_good_files_xz(void) +{ + glob_t globbing; + int glob_ret = glob("files/good-*.xz", 0, NULL, &globbing); + assert_false(glob_ret); + if(!glob_ret){ + for(unsigned int i = 0; i < globbing.gl_pathc; i++){ + char* good_file = globbing.gl_pathv[i]; + assert_true(systemf("../src/xz/xz -dc %s > /dev/null 2>&1", good_file) == 0); + } + } +} + +static void +test_good_files_xz_dec(void) +{ + glob_t globbing; + int glob_ret = glob("files/good-*.xz", 0, NULL, &globbing); + assert_false(glob_ret); + if(!glob_ret){ + for(unsigned int i = 0; i < globbing.gl_pathc; i++){ + char* good_file = globbing.gl_pathv[i]; + assert_true(systemf("../src/xzdec/xzdec %s > /dev/null 2>&1", good_file) == 0); + } + } +} + +static void +test_bad_files_xz(void) +{ + glob_t globbing; + int glob_ret = glob("files/bad-*.xz", 0, NULL, &globbing); + assert_false(glob_ret); + if(!glob_ret){ + for(unsigned int i = 0; i < globbing.gl_pathc; i++){ + char* good_file = globbing.gl_pathv[i]; + assert_false(systemf("../src/xz/xz -dc %s > /dev/null 2>&1", good_file) == 0); + } + } +} + +static void +test_bad_files_xz_dec(void) +{ + glob_t globbing; + int glob_ret = glob("files/bad-*.xz", 0, NULL, &globbing); + assert_false(glob_ret); + if(!glob_ret){ + for(unsigned int i = 0; i < globbing.gl_pathc; i++){ + char* good_file = globbing.gl_pathv[i]; + assert_false(systemf("../src/xzdec/xzdec %s > /dev/null 2>&1", good_file) == 0); + } + } +} + +void +test_xz_decompress(void) +{ + test_fixture_start(); + if(!can_xz()){ + printf("xz not built. Skipping xz tests\n"); + } + else { + run_test(test_good_files_xz); + run_test(test_bad_files_xz); + } + + if(!can_xz_dec()){ + printf("xzdec not built. Skipping xz_dec tests\n"); + } + else { + run_test(test_good_files_xz_dec); + run_test(test_bad_files_xz_dec); + } + + test_fixture_end(); +} diff --git a/tests/test_xz_diff.c b/tests/test_xz_diff.c new file mode 100644 index 0000000..1acb339 --- /dev/null +++ b/tests/test_xz_diff.c @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_xz_diff.c +/// \brief Tests xzdiff with several input files +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "xz_tests.h" +#include "test_utils.h" + +static void test_same(void); +static void test_different(void); +static void test_missing(void); + +static const char* preimage_filename = "files/good-1-check-crc32.xz"; +static const char* postimage_filename = "files/good-1-check-crc64.xz"; +static const char* other_postimage_filename = "files/good-1-lzma2-1.xz"; +static const char* missing_filename = "files/missing.xz"; + +static void +test_same(void) +{ + assert_true(systemf("%s %s %s > /dev/null 2>&1", + XZ_DIFF_RELATIVE_PATH, preimage_filename, + postimage_filename) == 0); + + assert_true(systemf("%s %s %s > /dev/null 2>&1", + XZ_DIFF_RELATIVE_PATH, postimage_filename, + preimage_filename) == 0); +} + +static void +test_different(void) +{ + assert_false(systemf("%s %s %s > /dev/null 2>&1", + XZ_DIFF_RELATIVE_PATH, preimage_filename, + other_postimage_filename) == 0); + + assert_false(systemf("%s %s %s > /dev/null 2>&1", + XZ_DIFF_RELATIVE_PATH, other_postimage_filename, + preimage_filename) == 0); +} + +static void +test_missing(void) +{ + assert_false(systemf("%s %s %s > /dev/null 2>&1", + XZ_DIFF_RELATIVE_PATH, preimage_filename, + missing_filename) == 0); + + assert_false(systemf("%s %s %s > /dev/null 2>&1", + XZ_DIFF_RELATIVE_PATH, missing_filename, + preimage_filename) == 0); +} + +void +test_xz_diff(void) +{ + test_fixture_start(); + if(can_xz() && can_xz_diff()){ + run_test(test_same); + run_test(test_different); + run_test(test_missing); + } + else { + printf("xz or xzdiff not built. Skipping tests\n"); + } + test_fixture_end(); +} diff --git a/tests/test_xz_grep.c b/tests/test_xz_grep.c new file mode 100644 index 0000000..05fb04c --- /dev/null +++ b/tests/test_xz_grep.c @@ -0,0 +1,231 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_xz_grep.c +/// \brief Tests xzgrep with various options +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "xz_tests.h" +#include "test_utils.h" +#include <stdio.h> +#include <string.h> +#include <sys/wait.h> + +static const char* xz_grep_filepath_1 = "files/good-1-lzma2-1.xz"; +static const char* xz_grep_filepath_2 = "files/good-2-lzma2.xz"; + +#define COMMAND_MAX_LEN 100 +#define MAX_OUTPUT_LEN 250 + +static void prepare_xz_grep_command(char* command, const char* option, const char* pattern); +static int execute_command_to_buffer(const char* command, char* buffer, size_t buffer_len); +// Tests are unrolled instead of in a loop to improve readability +// on a failing test and show explicitly what is being tested +static void test_xz_grep_el(void); +static void test_xz_grep_l_el(void); +static void test_xz_grep_h_el(void); +static void test_xz_grep_H_el(void); +static void test_xz_grep_hello(void); +static void test_xz_grep_l_hello(void); +static void test_xz_grep_h_hello(void); +static void test_xz_grep_H_hello(void); +static void test_xz_grep_nomatch(void); +static void test_xz_grep_l_nomatch(void); +static void test_xz_grep_h_nomatch(void); +static void test_xz_grep_H_nomatch(void); + + +static void +prepare_xz_grep_command(char* command, const char* option, const char* pattern) +{ + snprintf(command, COMMAND_MAX_LEN, "%s %s %s %s %s", XZ_GREP_RELATIVE_PATH, + option, pattern, xz_grep_filepath_1, xz_grep_filepath_2); +} + +static int +execute_command_to_buffer(const char* command, char* buffer, size_t buffer_len) +{ + memset(buffer, 0, MAX_OUTPUT_LEN); + FILE* r_pipe = popen(command, "r"); + int ret = fread(buffer, buffer_len, 1, r_pipe); + assert_true(feof(r_pipe) && ret == 0); + return WEXITSTATUS(pclose(r_pipe)); +} + +static void +test_xz_grep_el(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep el + const char* xzgrep_el_expected_output = "files/good-1-lzma2-1.xz:elit, sed do eiusmod tempor incididunt ut \n"\ + "files/good-1-lzma2-1.xz:in voluptate velit esse cillum dolore eu \n" \ + "files/good-2-lzma2.xz:Hello\n"; + + prepare_xz_grep_command(command, "", "el"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 0); + assert_string_equal(xzgrep_el_expected_output, output); +} + +static void +test_xz_grep_l_el(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -l el + const char* xzgrep_l_el_expected_output = "files/good-1-lzma2-1.xz\nfiles/good-2-lzma2.xz\n"; + prepare_xz_grep_command(command, "-l", "el"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 0); + assert_string_equal(xzgrep_l_el_expected_output, output); + } + +static void +test_xz_grep_h_el(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -h el + const char* xzgrep_h_el_expected_output = "elit, sed do eiusmod tempor incididunt ut \n" \ + "in voluptate velit esse cillum dolore eu \n" \ + "Hello\n"; + prepare_xz_grep_command(command, "-h", "el"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 0); + assert_string_equal(xzgrep_h_el_expected_output, output); +} + +static void +test_xz_grep_H_el(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -H el + const char* xzgrep_H_el_expected_output = "files/good-1-lzma2-1.xz:elit, sed do eiusmod tempor incididunt ut \n" \ + "files/good-1-lzma2-1.xz:in voluptate velit esse cillum dolore eu \n" \ + "files/good-2-lzma2.xz:Hello\n"; + prepare_xz_grep_command(command, "-H", "el"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 0); + assert_string_equal(xzgrep_H_el_expected_output, output); +} + +static void +test_xz_grep_hello(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep Hello + const char* xzgrep_hello = "files/good-2-lzma2.xz:Hello\n"; + prepare_xz_grep_command(command, "", "Hello"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 0); + assert_string_equal(xzgrep_hello, output); +} + +static void +test_xz_grep_l_hello(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -l Hello + const char* xzgrep_l_hello = "files/good-2-lzma2.xz\n"; + prepare_xz_grep_command(command, "-l", "Hello"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 0); + assert_string_equal(xzgrep_l_hello, output); +} + +static void +test_xz_grep_h_hello(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -h Hello + const char* xzgrep_h_hello = "Hello\n"; + prepare_xz_grep_command(command, "-h", "Hello"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 0); + assert_string_equal(xzgrep_h_hello, output); +} + +static void +test_xz_grep_H_hello(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -H Hello = + const char* xzgrep_H_hello = "files/good-2-lzma2.xz:Hello\n"; + prepare_xz_grep_command(command, "-H", "Hello"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 0); + assert_string_equal(xzgrep_H_hello, output); +} + +static void +test_xz_grep_nomatch(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep NOMATCH + prepare_xz_grep_command(command, "", "NOMATCH"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 1); + assert_string_equal("", output); +} + +static void +test_xz_grep_l_nomatch(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -l NOMATCH + prepare_xz_grep_command(command, "-l", "NOMATCH"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 1); + assert_string_equal("", output); +} + +static void +test_xz_grep_h_nomatch(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -h NOMATCH + prepare_xz_grep_command(command, "-h", "NOMATCH"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 1); + assert_string_equal("", output); +} + +static void +test_xz_grep_H_nomatch(void) +{ + char command[COMMAND_MAX_LEN]; + char output[MAX_OUTPUT_LEN]; + //Testing xzgrep -H NOMATCH + prepare_xz_grep_command(command, "-H", "NOMATCH"); + assert_true(execute_command_to_buffer(command, output, MAX_OUTPUT_LEN) == 1); + assert_string_equal("", output); +} + + +void +test_xz_grep(void) +{ + test_fixture_start(); + if(can_xz() && can_xz_grep()){ + run_test(test_xz_grep_el); + run_test(test_xz_grep_l_el); + run_test(test_xz_grep_h_el); + run_test(test_xz_grep_H_el); + run_test(test_xz_grep_hello); + run_test(test_xz_grep_l_hello); + run_test(test_xz_grep_h_hello); + run_test(test_xz_grep_H_hello); + run_test(test_xz_grep_nomatch); + run_test(test_xz_grep_l_nomatch); + run_test(test_xz_grep_h_nomatch); + run_test(test_xz_grep_H_nomatch); + } + else { + printf("xz or xzgrep not built. Skipping tests\n"); + } + + test_fixture_end(); +} diff --git a/tests/tests.h b/tests/tests.h deleted file mode 100644 index 2fd4237..0000000 --- a/tests/tests.h +++ /dev/null @@ -1,119 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file tests.h -/// \brief Common definitions for test applications -// -// Author: Lasse Collin -// -// This file has been put into the public domain. -// You can do whatever you want with this file. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef LZMA_TESTS_H -#define LZMA_TESTS_H - -#include "sysdefs.h" -#include "tuklib_integer.h" -#include "lzma.h" - -#include <stdio.h> - -#define memcrap(buf, size) memset(buf, 0xFD, size) - -#define expect(test) ((test) ? 0 : (fprintf(stderr, "%s:%d: %s\n", \ - __FILE__, __LINE__, #test), abort(), 0)) - -#define succeed(test) expect(!(test)) - -#define fail(test) expect(test) - - -static inline const char * -lzma_ret_sym(lzma_ret ret) -{ - if ((unsigned int)(ret) > LZMA_PROG_ERROR) - return "UNKNOWN_ERROR"; - - static const char *msgs[] = { - "LZMA_OK", - "LZMA_STREAM_END", - "LZMA_NO_CHECK", - "LZMA_UNSUPPORTED_CHECK", - "LZMA_GET_CHECK", - "LZMA_MEM_ERROR", - "LZMA_MEMLIMIT_ERROR", - "LZMA_FORMAT_ERROR", - "LZMA_OPTIONS_ERROR", - "LZMA_DATA_ERROR", - "LZMA_BUF_ERROR", - "LZMA_PROG_ERROR" - }; - - return msgs[ret]; -} - - -static inline bool -coder_loop(lzma_stream *strm, uint8_t *in, size_t in_size, - uint8_t *out, size_t out_size, - lzma_ret expected_ret, lzma_action finishing_action) -{ - size_t in_left = in_size; - size_t out_left = out_size > 0 ? out_size + 1 : 0; - lzma_action action = LZMA_RUN; - lzma_ret ret; - - strm->next_in = NULL; - strm->avail_in = 0; - strm->next_out = NULL; - strm->avail_out = 0; - - while (true) { - if (in_left > 0) { - if (--in_left == 0) - action = finishing_action; - - strm->next_in = in++; - strm->avail_in = 1; - } - - if (out_left > 0) { - --out_left; - strm->next_out = out++; - strm->avail_out = 1; - } - - ret = lzma_code(strm, action); - if (ret != LZMA_OK) - break; - } - - bool error = false; - - if (ret != expected_ret) - error = true; - - if (strm->total_in != in_size || strm->total_out != out_size) - error = true; - - return error; -} - - -static inline bool -decoder_loop_ret(lzma_stream *strm, uint8_t *in, size_t in_size, - lzma_ret expected_ret) -{ - return coder_loop(strm, in, in_size, NULL, 0, expected_ret, LZMA_RUN); -} - - -static inline bool -decoder_loop(lzma_stream *strm, uint8_t *in, size_t in_size) -{ - return coder_loop(strm, in, in_size, NULL, 0, - LZMA_STREAM_END, LZMA_RUN); -} - -#endif diff --git a/tests/xz_tests.c b/tests/xz_tests.c new file mode 100644 index 0000000..ad71d39 --- /dev/null +++ b/tests/xz_tests.c @@ -0,0 +1,28 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file xz_tests.c +/// \brief Combines all tests for xz util binaries +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "xz_tests.h" + +static void +all_tests(void) +{ + test_xz_decompress(); + test_xz_diff(); + test_xz_grep(); + test_xz_compress(); +} + +int +main(void) +{ + return run_tests(all_tests); +} diff --git a/tests/xz_tests.h b/tests/xz_tests.h new file mode 100644 index 0000000..c5bddb6 --- /dev/null +++ b/tests/xz_tests.h @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file xz_tests.h +/// \brief Provides headers for all tests for xz util binaries +// +// Author: Jia Tan +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "seatest.h" +#include "lzma.h" + +void test_xz_decompress(void); +void test_xz_diff(void); +void test_xz_grep(void); +void test_xz_compress(void); diff --git a/tests/xzgrep_expected_output b/tests/xzgrep_expected_output deleted file mode 100644 index e531d93..0000000 --- a/tests/xzgrep_expected_output +++ /dev/null @@ -1,39 +0,0 @@ -=> xzgrep el <= -xzgrep_test_1.xz:elit, sed do eiusmod tempor incididunt ut -xzgrep_test_1.xz:in voluptate velit esse cillum dolore eu -xzgrep_test_2.xz:Hello -retval 0 -=> xzgrep -l el <= -xzgrep_test_1.xz -xzgrep_test_2.xz -retval 0 -=> xzgrep -h el <= -elit, sed do eiusmod tempor incididunt ut -in voluptate velit esse cillum dolore eu -Hello -retval 0 -=> xzgrep -H el <= -xzgrep_test_1.xz:elit, sed do eiusmod tempor incididunt ut -xzgrep_test_1.xz:in voluptate velit esse cillum dolore eu -xzgrep_test_2.xz:Hello -retval 0 -=> xzgrep Hello <= -xzgrep_test_2.xz:Hello -retval 0 -=> xzgrep -l Hello <= -xzgrep_test_2.xz -retval 0 -=> xzgrep -h Hello <= -Hello -retval 0 -=> xzgrep -H Hello <= -xzgrep_test_2.xz:Hello -retval 0 -=> xzgrep NOMATCH <= -retval 1 -=> xzgrep -l NOMATCH <= -retval 1 -=> xzgrep -h NOMATCH <= -retval 1 -=> xzgrep -H NOMATCH <= -retval 1 -- 2.25.1