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

Reply via email to