diff --git a/tests/Makefile.am b/tests/Makefile.am index d5bb1266..fa78bf81 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -12,7 +12,14 @@ ## Lesser General Public License for more details. ## -EXTRA_DIST = files tests.h test_files.sh +EXTRA_DIST = \ + files \ + tests.h \ + test_files.sh \ + test_compress.sh \ + bcj_test.c \ + compress_prepared_bcj_sparc \ + compress_prepared_bcj_x86 AM_CPPFLAGS = \ -I@top_srcdir@/src/common \ @@ -26,6 +33,7 @@ LDADD += @top_builddir@/lib/libgnu.a endif check_PROGRAMS = \ + create_compress_files \ test_check \ test_stream_flags \ test_filter_flags \ @@ -33,13 +41,15 @@ check_PROGRAMS = \ test_index \ test_info -test_check_SOURCES = test_check.c -test_stream_flags_SOURCES = test_stream_flags.c -test_filter_flags_SOURCES = test_filter_flags.c -test_block_header_SOURCES = test_block_header.c -test_index_SOURCES = test_index.c -test_info_SOURCES = test_info.c - TESTS = \ - $(check_PROGRAMS) \ - test_files.sh + test_check \ + test_stream_flags \ + test_filter_flags \ + test_block_header \ + test_index \ + test_info \ + test_files.sh \ + test_compress.sh + +clean-local: + -rm -f compress_generated_* diff --git a/tests/bcj_test.c b/tests/bcj_test.c new file mode 100644 index 00000000..d64c5a79 --- /dev/null +++ b/tests/bcj_test.c @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \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 bcj_test.c +/// Don't optimize or strip. +// +// This code has been put into the public domain. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +/////////////////////////////////////////////////////////////////////////////// + +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/compress_prepared_bcj_sparc b/tests/compress_prepared_bcj_sparc new file mode 100644 index 00000000..ba3ee297 Binary files /dev/null and b/tests/compress_prepared_bcj_sparc differ diff --git a/tests/compress_prepared_bcj_x86 b/tests/compress_prepared_bcj_x86 new file mode 100644 index 00000000..48dde27c Binary files /dev/null and b/tests/compress_prepared_bcj_x86 differ diff --git a/tests/create_compress_files.c b/tests/create_compress_files.c new file mode 100644 index 00000000..2e394297 --- /dev/null +++ b/tests/create_compress_files.c @@ -0,0 +1,164 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \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. +// +// Copyright (C) 2008 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "sysdefs.h" +#include + + +// 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) + fwrite("abc\n", 4, 1, file); +} + + +// 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(n & 0xFF, file); + putc((n >> 8) & 0xFF, file); + putc((n >> 16) & 0xFF, file); + putc(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/test_compress.sh b/tests/test_compress.sh new file mode 100755 index 00000000..5cf21cf4 --- /dev/null +++ b/tests/test_compress.sh @@ -0,0 +1,183 @@ +#!/bin/sh + +############################################################################### +# +# Copyright (C) 2008 Lasse Collin +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +############################################################################### + +# 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_lzma() { + ################ + # Non-streamed # + ################ + + if $LZMA -c "$@" "$FILE" > tmp_compressed; then + : + else + echo "Non-streamed compressing failed: $* $FILE" + (exit 1) + exit 1 + fi + + if $LZMA -cd tmp_compressed > tmp_uncompressed ; then + : + else + echo "Decoding of non-streamed file failed: $* $FILE" + (exit 1) + exit 1 + fi + + if cmp tmp_uncompressed "$FILE" ; then + : + else + echo "Decoded non-streamed file does not match the original: $* $FILE" + (exit 1) + exit 1 + fi + + if $LZMADEC tmp_compressed > tmp_uncompressed ; then + : + else + echo "Decoding of non-streamed file failed: $* $FILE" + (exit 1) + exit 1 + fi + + if cmp tmp_uncompressed "$FILE" ; then + : + else + echo "Decoded non-streamed file does not match the original: $* $FILE" + (exit 1) + exit 1 + fi + + ############ + # Streamed # + ############ + + if $LZMA -c "$@" < "$FILE" > tmp_compressed; then + : + else + echo "Streamed compressing failed: $* $FILE" + (exit 1) + exit 1 + fi + + if $LZMA -cd < tmp_compressed > tmp_uncompressed ; then + : + else + echo "Decoding of streamed file failed: $* $FILE" + (exit 1) + exit 1 + fi + + if cmp tmp_uncompressed "$FILE" ; then + : + else + echo "Decoded streamed file does not match the original: $* $FILE" + (exit 1) + exit 1 + fi + + if $LZMADEC < tmp_compressed > tmp_uncompressed ; then + : + else + echo "Decoding of streamed file failed: $* $FILE" + (exit 1) + exit 1 + fi + + if cmp tmp_uncompressed "$FILE" ; then + : + else + echo "Decoded streamed file does not match the original: $* $FILE" + (exit 1) + exit 1 + fi + + # Show progress: + echo . | tr -d '\n\r' +} + +LZMA="../src/lzma/lzma --memory=15Mi --threads=1" +LZMADEC="../src/lzmadec/lzmadec --memory=4Mi" +unset LZMA_OPT + +# 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 + +# Encode and decode 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_lzma(). + test_lzma -1 + test_lzma -2 + test_lzma -3 + test_lzma -4 + + for ARGS in \ + --copy \ + --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 \ + --delta=distance=1 \ + --delta=distance=4 \ + --delta=distance=256 \ + --x86 \ + --powerpc \ + --ia64 \ + --arm \ + --armthumb \ + --sparc + do + test_lzma $ARGS + test_lzma --subblock $ARGS + test_lzma $ARGS --subblock + test_lzma --subblock $ARGS --subblock + done + + echo +done + +(exit 0) +exit 0