summaryrefslogtreecommitdiffstats
path: root/programs
diff options
context:
space:
mode:
authorYann Collet <yann.collet.73@gmail.com>2014-09-13 22:30:01 (GMT)
committerYann Collet <yann.collet.73@gmail.com>2014-09-13 22:30:01 (GMT)
commit3f80a228193755ffcdaaccc7e8408b7e434c1fbe (patch)
treea235376fc65e9fe4957e01510f2a72484c49e074 /programs
parent3b4e3f2b01df752d82a51d7b7afaa9a2fd5a5ff8 (diff)
parent457dc35e6a56aab12e060af608efd1cbb0eec8a9 (diff)
downloadlz4-3f80a228193755ffcdaaccc7e8408b7e434c1fbe.zip
lz4-3f80a228193755ffcdaaccc7e8408b7e434c1fbe.tar.gz
lz4-3f80a228193755ffcdaaccc7e8408b7e434c1fbe.tar.bz2
Merge pull request #26 from Cyan4973/frame
Frame
Diffstat (limited to 'programs')
-rw-r--r--programs/Makefile22
-rw-r--r--programs/frametest.c619
-rw-r--r--programs/fullbench.c118
3 files changed, 714 insertions, 45 deletions
diff --git a/programs/Makefile b/programs/Makefile
index a04c323..cc139f1 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -30,7 +30,7 @@
# fullbench32: Same as fullbench, but forced to compile in 32-bits mode
# ##########################################################################
-RELEASE=r122
+RELEASE=r123
DESTDIR?=
PREFIX ?= /usr
@@ -68,7 +68,7 @@ endif
default: lz4 lz4c
-all: lz4 lz4c lz4c32 fullbench fullbench32 fuzzer fuzzer32 datagen
+all: lz4 lz4c lz4c32 fullbench fullbench32 fuzzer fuzzer32 frametest datagen
lz4: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c bench.c xxhash.c lz4io.c lz4cli.c
$(CC) $(FLAGS) -DDISABLE_LZ4C_LEGACY_OPTIONS $^ -o $@$(EXT)
@@ -79,10 +79,10 @@ lz4c : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c bench.c xxhash.c lz4io.c lz4cli.c
lz4c32: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c bench.c xxhash.c lz4io.c lz4cli.c
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
-fullbench : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fullbench.c
+fullbench : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c $(LZ4DIR)/lz4frame.c xxhash.c fullbench.c
$(CC) $(FLAGS) $^ -o $@$(EXT)
-fullbench32: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fullbench.c
+fullbench32: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c $(LZ4DIR)/lz4frame.c xxhash.c fullbench.c
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
fuzzer : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fuzzer.c
@@ -91,6 +91,9 @@ fuzzer : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fuzzer.c
fuzzer32: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fuzzer.c
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
+frametest: $(LZ4DIR)/lz4frame.c $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c frametest.c
+ $(CC) $(FLAGS) $^ -o $@$(EXT)
+
datagen : datagen.c
$(CC) $(FLAGS) $^ -o $@$(EXT)
@@ -99,7 +102,8 @@ clean:
@rm -f core *.o \
lz4$(EXT) lz4c$(EXT) lz4c32$(EXT) \
fullbench$(EXT) fullbench32$(EXT) \
- fuzzer$(EXT) fuzzer32$(EXT) datagen$(EXT)
+ fuzzer$(EXT) fuzzer32$(EXT) \
+ frametest$(EXT) datagen$(EXT)
@echo Cleaning completed
@@ -128,7 +132,7 @@ uninstall:
[ -f $(DESTDIR)$(MANDIR)/lz4cat.1 ] && rm -f $(DESTDIR)$(MANDIR)/lz4cat.1
@echo lz4 successfully uninstalled
-test-native: test-lz4 test-lz4c test-fullbench test-fuzzer test-mem
+test-native: test-lz4 test-lz4c test-frame test-fullbench test-fuzzer test-mem
test-force32: test-lz4c32 test-fullbench32 test-fuzzer32 test-mem32
@@ -165,7 +169,10 @@ test-fuzzer: fuzzer
test-fuzzer32: fuzzer32
./fuzzer32 --no-prompt
-test-mem: lz4 datagen
+test-frame: frametest
+ ./frametest
+
+test-mem: lz4 datagen frametest
./datagen -g16KB > tmp
valgrind ./lz4 -9 -BD -f tmp /dev/null
./datagen -g16MB > tmp
@@ -173,6 +180,7 @@ test-mem: lz4 datagen
./datagen -g256MB > tmp
valgrind ./lz4 -B4D -f tmp /dev/null
rm tmp
+ valgrind ./frametest -i100
test-mem32: lz4c32 datagen
# unfortunately, valgrind doesn't seem to work with non-native binary. If someone knows how to do a valgrind-test on a 32-bits exe with a 64-bits system...
diff --git a/programs/frametest.c b/programs/frametest.c
new file mode 100644
index 0000000..ba24fe1
--- /dev/null
+++ b/programs/frametest.c
@@ -0,0 +1,619 @@
+/*
+ frameTest - test tool for lz4frame
+ Copyright (C) Yann Collet 2014
+ GPL v2 License
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ You can contact the author at :
+ - LZ4 source repository : http://code.google.com/p/lz4/
+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
+*/
+
+/**************************************
+ Compiler specific
+**************************************/
+#define _CRT_SECURE_NO_WARNINGS // fgets
+#ifdef _MSC_VER /* Visual Studio */
+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
+# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
+#endif
+#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
+#endif
+
+
+/**************************************
+ Includes
+**************************************/
+#include <stdlib.h>
+#include <stdio.h> // fgets, sscanf
+#include <sys/timeb.h> // timeb
+#include <string.h> // strcmp
+#include "lz4frame.h"
+#include "xxhash.h" // XXH64
+
+
+/**************************************
+ Basic Types
+**************************************/
+#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
+# include <stdint.h>
+ typedef uint8_t BYTE;
+ typedef uint16_t U16;
+ typedef uint32_t U32;
+ typedef int32_t S32;
+ typedef uint64_t U64;
+#else
+ typedef unsigned char BYTE;
+ typedef unsigned short U16;
+ typedef unsigned int U32;
+ typedef signed int S32;
+ typedef unsigned long long U64;
+#endif
+
+
+/**************************************
+ Constants
+**************************************/
+#ifndef LZ4_VERSION
+# define LZ4_VERSION ""
+#endif
+
+#define KB *(1U<<10)
+#define MB *(1U<<20)
+#define GB *(1U<<30)
+
+static const U32 nbTestsDefault = 128 KB;
+#define COMPRESSIBLE_NOISE_LENGTH (2 MB)
+#define FUZ_COMPRESSIBILITY_DEFAULT 50
+static const U32 prime1 = 2654435761U;
+static const U32 prime2 = 2246822519U;
+
+
+
+/**************************************
+ Macros
+**************************************/
+#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
+#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
+#define DISPLAYUPDATE(l, ...) if (displayLevel>=l) { \
+ if ((FUZ_GetMilliSpan(g_time) > refreshRate) || (displayLevel>=4)) \
+ { g_time = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); \
+ if (displayLevel>=4) fflush(stdout); } }
+static const U32 refreshRate = 150;
+static U32 g_time = 0;
+
+
+/*****************************************
+ Local Parameters
+*****************************************/
+static U32 no_prompt = 0;
+static char* programName;
+static U32 displayLevel = 2;
+
+
+/*********************************************************
+ Fuzzer functions
+*********************************************************/
+static U32 FUZ_GetMilliStart(void)
+{
+ struct timeb tb;
+ U32 nCount;
+ ftime( &tb );
+ nCount = (U32) (((tb.time & 0xFFFFF) * 1000) + tb.millitm);
+ return nCount;
+}
+
+
+static U32 FUZ_GetMilliSpan(U32 nTimeStart)
+{
+ U32 nCurrent = FUZ_GetMilliStart();
+ U32 nSpan = nCurrent - nTimeStart;
+ if (nTimeStart > nCurrent)
+ nSpan += 0x100000 * 1000;
+ return nSpan;
+}
+
+
+
+# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
+unsigned int FUZ_rand(unsigned int* src)
+{
+ U32 rand32 = *src;
+ rand32 *= prime1;
+ rand32 += prime2;
+ rand32 = FUZ_rotl32(rand32, 13);
+ *src = rand32;
+ return rand32 >> 5;
+}
+
+
+#define FUZ_RAND15BITS (FUZ_rand(seed) & 0x7FFF)
+#define FUZ_RANDLENGTH ( (FUZ_rand(seed) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
+static void FUZ_fillCompressibleNoiseBuffer(void* buffer, unsigned bufferSize, double proba, U32* seed)
+{
+ BYTE* BBuffer = (BYTE*)buffer;
+ unsigned pos = 0;
+ U32 P32 = (U32)(32768 * proba);
+
+ // First Byte
+ BBuffer[pos++] = (BYTE)(FUZ_rand(seed));
+
+ while (pos < bufferSize)
+ {
+ // Select : Literal (noise) or copy (within 64K)
+ if (FUZ_RAND15BITS < P32)
+ {
+ // Copy (within 64K)
+ unsigned match, end;
+ unsigned length = FUZ_RANDLENGTH + 4;
+ unsigned offset = FUZ_RAND15BITS + 1;
+ if (offset > pos) offset = pos;
+ if (pos + length > bufferSize) length = bufferSize - pos;
+ match = pos - offset;
+ end = pos + length;
+ while (pos < end) BBuffer[pos++] = BBuffer[match++];
+ }
+ else
+ {
+ // Literal (noise)
+ unsigned end;
+ unsigned length = FUZ_RANDLENGTH;
+ if (pos + length > bufferSize) length = bufferSize - pos;
+ end = pos + length;
+ while (pos < end) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5);
+ }
+ }
+}
+
+
+static unsigned FUZ_highbit(U32 v32)
+{
+ unsigned nbBits = 0;
+ if (v32==0) return 0;
+ while (v32) { v32 >>= 1; nbBits ++; }
+ return nbBits;
+}
+
+
+int basicTests(U32 seed, double compressibility)
+{
+ int testResult = 0;
+ void* CNBuffer;
+ void* compressedBuffer;
+ void* decodedBuffer;
+ U32 randState = seed;
+ size_t cSize, testSize;
+ LZ4F_preferences_t prefs = { 0 };
+ LZ4F_decompressionContext_t dCtx;
+ U64 crcOrig;
+
+ // Create compressible test buffer
+ CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
+ compressedBuffer = malloc(LZ4F_compressFrameBound(COMPRESSIBLE_NOISE_LENGTH, NULL));
+ decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
+ FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState);
+ crcOrig = XXH64(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
+
+ // Trivial tests : one-step frame
+ testSize = COMPRESSIBLE_NOISE_LENGTH;
+ DISPLAYLEVEL(3, "Using NULL preferences : \n");
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAYLEVEL(3, "Decompression test : \n");
+ {
+ size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
+ size_t compressedBufferSize = cSize;
+ BYTE* op = (BYTE*)decodedBuffer;
+ BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
+ BYTE* ip = (BYTE*)compressedBuffer;
+ BYTE* const iend = (BYTE*)compressedBuffer + cSize;
+ U64 crcDest;
+
+ LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
+ if (LZ4F_isError(errorCode)) goto _output_error;
+
+ DISPLAYLEVEL(3, "Single Block : \n");
+ errorCode = LZ4F_decompress(dCtx, decodedBuffer, &decodedBufferSize, compressedBuffer, &compressedBufferSize, NULL);
+ crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
+ if (crcDest != crcOrig) goto _output_error;
+ DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
+
+ DISPLAYLEVEL(3, "Byte after byte : \n");
+ while (ip < iend)
+ {
+ size_t oSize = oend-op;
+ size_t iSize = 1;
+ //DISPLAY("%7i \n", (int)(ip-(BYTE*)compressedBuffer));
+ errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
+ if (LZ4F_isError(errorCode)) goto _output_error;
+ op += oSize;
+ ip += iSize;
+ }
+ crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
+ if (crcDest != crcOrig) goto _output_error;
+ DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
+
+ errorCode = LZ4F_freeDecompressionContext(dCtx);
+ if (LZ4F_isError(errorCode)) goto _output_error;
+ }
+
+ DISPLAYLEVEL(3, "Using 64 KB block : \n");
+ prefs.frameInfo.blockSizeID = max64KB;
+ prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAYLEVEL(3, "without checksum : \n");
+ prefs.frameInfo.contentChecksumFlag = noContentChecksum;
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAYLEVEL(3, "Using 256 KB block : \n");
+ prefs.frameInfo.blockSizeID = max256KB;
+ prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAYLEVEL(3, "Decompression test : \n");
+ {
+ size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
+ unsigned maxBits = FUZ_highbit(decodedBufferSize);
+ BYTE* op = (BYTE*)decodedBuffer;
+ BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
+ BYTE* ip = (BYTE*)compressedBuffer;
+ BYTE* const iend = (BYTE*)compressedBuffer + cSize;
+ U64 crcDest;
+
+ LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
+ if (LZ4F_isError(errorCode)) goto _output_error;
+
+ DISPLAYLEVEL(3, "random segment sizes : \n");
+ while (ip < iend)
+ {
+ unsigned nbBits = FUZ_rand(&randState) % maxBits;
+ size_t iSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
+ size_t oSize = oend-op;
+ if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
+ //DISPLAY("%7i : + %6i\n", (int)(ip-(BYTE*)compressedBuffer), (int)iSize);
+ errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
+ if (LZ4F_isError(errorCode)) goto _output_error;
+ op += oSize;
+ ip += iSize;
+ }
+ crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
+ if (crcDest != crcOrig) goto _output_error;
+ DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
+
+ errorCode = LZ4F_freeDecompressionContext(dCtx);
+ if (LZ4F_isError(errorCode)) goto _output_error;
+ }
+
+ DISPLAYLEVEL(3, "without checksum : \n");
+ prefs.frameInfo.contentChecksumFlag = noContentChecksum;
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAYLEVEL(3, "Using 1 MB block : \n");
+ prefs.frameInfo.blockSizeID = max1MB;
+ prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAYLEVEL(3, "without checksum : \n");
+ prefs.frameInfo.contentChecksumFlag = noContentChecksum;
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAYLEVEL(3, "Using 4 MB block : \n");
+ prefs.frameInfo.blockSizeID = max4MB;
+ prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAYLEVEL(3, "without checksum : \n");
+ prefs.frameInfo.contentChecksumFlag = noContentChecksum;
+ cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
+ if (LZ4F_isError(cSize)) goto _output_error;
+ DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
+
+ DISPLAY("Basic tests completed \n");
+_end:
+ free(CNBuffer);
+ free(compressedBuffer);
+ free(decodedBuffer);
+ return testResult;
+
+_output_error:
+ testResult = 1;
+ DISPLAY("Error detected ! \n");
+ goto _end;
+}
+
+
+static void locateBuffDiff(const void* buff1, const void* buff2, size_t size)
+{
+ int p=0;
+ BYTE* b1=(BYTE*)buff1;
+ BYTE* b2=(BYTE*)buff2;
+ while (b1[p]==b2[p]) p++;
+ printf("Error at pos %i/%i : %02X != %02X \n", p, (int)size, b1[p], b2[p]);
+ }
+
+
+static const U32 srcDataLength = 9 MB; /* needs to be > 2x4MB to test large blocks */
+
+int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressibility)
+{
+ unsigned testResult = 0;
+ unsigned testNb = 0;
+ void* srcBuffer = NULL;
+ void* compressedBuffer = NULL;
+ void* decodedBuffer = NULL;
+ U32 coreRand = seed;
+ LZ4F_decompressionContext_t dCtx;
+ LZ4F_compressionContext_t cCtx;
+ size_t result;
+# define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
+ DISPLAY(" (seed %u, test nb %i) \n", seed, testNb); goto _output_error; }
+
+ // Create buffers
+ result = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
+ CHECK(LZ4F_isError(result), "Allocation failed (error %i)", (int)result);
+ result = LZ4F_createCompressionContext(&cCtx, LZ4F_VERSION);
+ CHECK(LZ4F_isError(result), "Allocation failed (error %i)", (int)result);
+ srcBuffer = malloc(srcDataLength);
+ CHECK(srcBuffer==NULL, "srcBuffer Allocation failed");
+ compressedBuffer = malloc(LZ4F_compressFrameBound(srcDataLength, NULL));
+ CHECK(compressedBuffer==NULL, "compressedBuffer Allocation failed");
+ decodedBuffer = malloc(srcDataLength);
+ CHECK(decodedBuffer==NULL, "decodedBuffer Allocation failed");
+ FUZ_fillCompressibleNoiseBuffer(srcBuffer, srcDataLength, compressibility, &coreRand);
+
+ // jump to requested testNb
+ for (testNb =0; testNb < startTest; testNb++) (void)FUZ_rand(&coreRand); // sync randomizer
+
+ // main fuzzer loop
+ for ( ; testNb < nbTests; testNb++)
+ {
+ U32 randState = coreRand ^ prime1;
+ unsigned BSId = 4 + (FUZ_rand(&randState) & 3);
+ unsigned BMId = FUZ_rand(&randState) & 1;
+ unsigned CCflag = FUZ_rand(&randState) & 1;
+ unsigned autoflush = (FUZ_rand(&randState) & 3) == 2;
+ LZ4F_preferences_t prefs = { 0 };
+ LZ4F_compressOptions_t options = { 0 };
+ unsigned nbBits = (FUZ_rand(&randState) % (FUZ_highbit(srcDataLength-1) - 1)) + 1;
+ size_t srcSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
+ size_t srcStart = FUZ_rand(&randState) % (srcDataLength - srcSize);
+ size_t cSize;
+ U64 crcOrig, crcDecoded;
+
+ prefs.frameInfo.blockMode = BMId;
+ prefs.frameInfo.blockSizeID = BSId;
+ prefs.frameInfo.contentChecksumFlag = CCflag;
+ prefs.autoFlush = autoflush;
+
+ DISPLAYUPDATE(2, "\r%5i ", testNb);
+ crcOrig = XXH64((BYTE*)srcBuffer+srcStart, srcSize, 1);
+
+ {
+ const BYTE* ip = (const BYTE*)srcBuffer + srcStart;
+ const BYTE* const iend = ip + srcSize;
+ BYTE* op = compressedBuffer;
+ BYTE* const oend = op + LZ4F_compressFrameBound(srcDataLength, NULL);
+ unsigned maxBits = FUZ_highbit(srcSize);
+ result = LZ4F_compressBegin(cCtx, op, oend-op, &prefs);
+ CHECK(LZ4F_isError(result), "Compression header failed (error %i)", (int)result);
+ op += result;
+ while (ip < iend)
+ {
+ unsigned nbBitsSeg = FUZ_rand(&randState) % maxBits;
+ size_t iSize = (FUZ_rand(&randState) & ((1<<nbBitsSeg)-1)) + 1;
+ size_t oSize = oend-op;
+ unsigned forceFlush = ((FUZ_rand(&randState) & 3) == 1);
+ if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
+ options.stableSrc = ((FUZ_rand(&randState) && 3) == 2);
+
+ result = LZ4F_compressUpdate(cCtx, op, oSize, ip, iSize, &options);
+ CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result);
+ op += result;
+ ip += iSize;
+
+ if (forceFlush)
+ {
+ result = LZ4F_flush(cCtx, op, oend-op, &options);
+ CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result);
+ op += result;
+ }
+ }
+ result = LZ4F_compressEnd(cCtx, op, oend-op, &options);
+ CHECK(LZ4F_isError(result), "Compression completion failed (error %i)", (int)result);
+ op += result;
+ cSize = op-(BYTE*)compressedBuffer;
+ }
+
+ {
+ const BYTE* ip = compressedBuffer;
+ const BYTE* const iend = ip + cSize;
+ BYTE* op = decodedBuffer;
+ BYTE* const oend = op + srcDataLength;
+ unsigned maxBits = FUZ_highbit(cSize);
+ while (ip < iend)
+ {
+ unsigned nbBitsI = (FUZ_rand(&randState) % (maxBits-1)) + 1;
+ unsigned nbBitsO = (FUZ_rand(&randState) % (maxBits)) + 1;
+ size_t iSize = (FUZ_rand(&randState) & ((1<<nbBitsI)-1)) + 1;
+ size_t oSize = (FUZ_rand(&randState) & ((1<<nbBitsO)-1)) + 2;
+ if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
+ if (oSize > (size_t)(oend-op)) oSize = oend-op;
+ result = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
+ if (result == (size_t)-ERROR_checksum_invalid) locateBuffDiff((BYTE*)srcBuffer+srcStart, decodedBuffer, srcSize);
+ CHECK(LZ4F_isError(result), "Decompression failed (error %i)", (int)result);
+ op += oSize;
+ ip += iSize;
+ }
+ CHECK(result != 0, "Frame decompression failed (error %i)", (int)result);
+ crcDecoded = XXH64(decodedBuffer, op-(BYTE*)decodedBuffer, 1);
+ if (crcDecoded != crcOrig) locateBuffDiff((BYTE*)srcBuffer+srcStart, decodedBuffer, srcSize);
+ CHECK(crcDecoded != crcOrig, "Decompression corruption");
+ }
+
+ (void)FUZ_rand(&coreRand); // update rand seed
+ }
+
+ DISPLAYLEVEL(2, "\rAll tests completed \n");
+
+_end:
+ LZ4F_freeDecompressionContext(dCtx);
+ LZ4F_freeCompressionContext(cCtx);
+ free(srcBuffer);
+ free(compressedBuffer);
+ free(decodedBuffer);
+ return testResult;
+
+_output_error:
+ testResult = 1;
+ goto _end;
+}
+
+
+int FUZ_usage(void)
+{
+ DISPLAY( "Usage :\n");
+ DISPLAY( " %s [args]\n", programName);
+ DISPLAY( "\n");
+ DISPLAY( "Arguments :\n");
+ DISPLAY( " -i# : Nb of tests (default:%i) \n", nbTestsDefault);
+ DISPLAY( " -s# : Select seed (default:prompt user)\n");
+ DISPLAY( " -t# : Select starting test number (default:0)\n");
+ DISPLAY( " -p# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
+ DISPLAY( " -v : verbose\n");
+ DISPLAY( " -h : display help and exit\n");
+ return 0;
+}
+
+
+int main(int argc, char** argv)
+{
+ U32 seed=0;
+ int seedset=0;
+ int argNb;
+ int nbTests = nbTestsDefault;
+ int testNb = 0;
+ int proba = FUZ_COMPRESSIBILITY_DEFAULT;
+ int result=0;
+
+ // Check command line
+ programName = argv[0];
+ for(argNb=1; argNb<argc; argNb++)
+ {
+ char* argument = argv[argNb];
+
+ if(!argument) continue; // Protection if argument empty
+
+ // Decode command (note : aggregated commands are allowed)
+ if (argument[0]=='-')
+ {
+ if (!strcmp(argument, "--no-prompt")) { no_prompt=1; seedset=1; displayLevel=1; continue; }
+
+ while (argument[1]!=0)
+ {
+ argument++;
+ switch(*argument)
+ {
+ case 'h':
+ return FUZ_usage();
+ case 'v':
+ argument++;
+ displayLevel=4;
+ break;
+ case 'q':
+ argument++;
+ displayLevel--;
+ break;
+ case 'i':
+ argument++;
+ nbTests=0;
+ while ((*argument>='0') && (*argument<='9'))
+ {
+ nbTests *= 10;
+ nbTests += *argument - '0';
+ argument++;
+ }
+ break;
+ case 's':
+ argument++;
+ seed=0; seedset=1;
+ while ((*argument>='0') && (*argument<='9'))
+ {
+ seed *= 10;
+ seed += *argument - '0';
+ argument++;
+ }
+ break;
+ case 't':
+ argument++;
+ testNb=0;
+ while ((*argument>='0') && (*argument<='9'))
+ {
+ testNb *= 10;
+ testNb += *argument - '0';
+ argument++;
+ }
+ break;
+ case 'p':
+ argument++;
+ proba=0;
+ while ((*argument>='0') && (*argument<='9'))
+ {
+ proba *= 10;
+ proba += *argument - '0';
+ argument++;
+ }
+ if (proba<0) proba=0;
+ if (proba>100) proba=100;
+ break;
+ default: ;
+ }
+ }
+ }
+ }
+
+ // Get Seed
+ printf("Starting lz4frame tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION);
+
+ if (!seedset) seed = FUZ_GetMilliStart() % 10000;
+ printf("Seed = %u\n", seed);
+ if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) printf("Compressibility : %i%%\n", proba);
+
+ if (nbTests<=0) nbTests=1;
+
+ //if (testNb==0) result = basicTests(seed, ((double)proba) / 100);
+ if (result) return 1;
+ return fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
+}
diff --git a/programs/fullbench.c b/programs/fullbench.c
index 3d39458..9292f20 100644
--- a/programs/fullbench.c
+++ b/programs/fullbench.c
@@ -60,10 +60,8 @@
#endif
#include "lz4.h"
-#define COMPRESSOR0 LZ4_compress
#include "lz4hc.h"
-#define COMPRESSOR1 LZ4_compressHC
-#define DEFAULTCOMPRESSOR COMPRESSOR0
+#include "lz4frame.h"
#include "xxhash.h"
@@ -323,6 +321,11 @@ static int local_LZ4_compressHC_limitedOutput_continue(const char* in, char* out
return LZ4_compressHC_limitedOutput_continue(ctx, in, out, inSize, LZ4_compressBound(inSize));
}
+static int local_LZ4F_compressFrame(const char* in, char* out, int inSize)
+{
+ return LZ4F_compressFrame(out, 2*inSize + 16, in, inSize, NULL);
+}
+
static int local_LZ4_decompress_fast(const char* in, char* out, int inSize, int outSize)
{
(void)inSize;
@@ -351,26 +354,51 @@ static int local_LZ4_decompress_safe_usingDict(const char* in, char* out, int in
return outSize;
}
+extern int LZ4_decompress_safe_forceExtDict(const char* in, char* out, int inSize, int outSize, const char* dict, int dictSize);
+
+static int local_LZ4_decompress_safe_forceExtDict(const char* in, char* out, int inSize, int outSize)
+{
+ (void)inSize;
+ LZ4_decompress_safe_forceExtDict(in, out, inSize, outSize, in - 65536, 65536);
+ return outSize;
+}
+
static int local_LZ4_decompress_safe_partial(const char* in, char* out, int inSize, int outSize)
{
return LZ4_decompress_safe_partial(in, out, inSize, outSize - 5, outSize);
}
+static LZ4F_decompressionContext_t g_dCtx;
+
+static int local_LZ4F_decompress(const char* in, char* out, int inSize, int outSize)
+{
+ size_t srcSize = inSize;
+ size_t dstSize = outSize;
+ size_t result;
+ result = LZ4F_decompress(g_dCtx, out, &dstSize, in, &srcSize, NULL);
+ if (result!=0) { DISPLAY("Error decompressing frame : unfinished frame\n"); exit(8); }
+ if (srcSize != (size_t)inSize) { DISPLAY("Error decompressing frame : read size incorrect\n"); exit(9); }
+ return dstSize;
+}
+
+
int fullSpeedBench(char** fileNamesTable, int nbFiles)
{
int fileIdx=0;
char* orig_buff;
-# define NB_COMPRESSION_ALGORITHMS 13
-# define MINCOMPRESSIONCHAR '0'
+# define NB_COMPRESSION_ALGORITHMS 14
double totalCTime[NB_COMPRESSION_ALGORITHMS+1] = {0};
double totalCSize[NB_COMPRESSION_ALGORITHMS+1] = {0};
-# define NB_DECOMPRESSION_ALGORITHMS 7
-# define MINDECOMPRESSIONCHAR '0'
-# define MAXDECOMPRESSIONCHAR (MINDECOMPRESSIONCHAR + NB_DECOMPRESSION_ALGORITHMS)
- static char* decompressionNames[] = { "LZ4_decompress_fast", "LZ4_decompress_fast_withPrefix64k", "LZ4_decompress_fast_usingDict",
- "LZ4_decompress_safe", "LZ4_decompress_safe_withPrefix64k", "LZ4_decompress_safe_usingDict", "LZ4_decompress_safe_partial" };
+# define NB_DECOMPRESSION_ALGORITHMS 9
double totalDTime[NB_DECOMPRESSION_ALGORITHMS+1] = {0};
+ size_t errorCode;
+ errorCode = LZ4F_createDecompressionContext(&g_dCtx, LZ4F_VERSION);
+ if (LZ4F_isError(errorCode))
+ {
+ DISPLAY("dctx allocation issue \n");
+ return 10;
+ }
// Loop for each file
while (fileIdx<nbFiles)
@@ -428,22 +456,6 @@ int fullSpeedBench(char** fileNamesTable, int nbFiles)
return 12;
}
- // Init chunks data
- {
- int i;
- size_t remaining = benchedSize;
- char* in = orig_buff;
- char* out = compressed_buff;
- for (i=0; i<nbChunks; i++)
- {
- chunkP[i].id = i;
- chunkP[i].origBuffer = in; in += chunkSize;
- if ((int)remaining > chunkSize) { chunkP[i].origSize = chunkSize; remaining -= chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; }
- chunkP[i].compressedBuffer = out; out += maxCompressedChunkSize;
- chunkP[i].compressedSize = 0;
- }
- }
-
// Fill input buffer
DISPLAY("Loading %s... \r", inFileName);
readSize = fread(orig_buff, 1, benchedSize, inFile);
@@ -471,10 +483,27 @@ int fullSpeedBench(char** fileNamesTable, int nbFiles)
DISPLAY("\r%79s\r", "");
DISPLAY(" %s : \n", inFileName);
+ // Init chunks data
+ {
+ int i;
+ size_t remaining = benchedSize;
+ char* in = orig_buff;
+ char* out = compressed_buff;
+ nbChunks = (int) ((int)benchedSize / chunkSize) + 1;
+ for (i=0; i<nbChunks; i++)
+ {
+ chunkP[i].id = i;
+ chunkP[i].origBuffer = in; in += chunkSize;
+ if ((int)remaining > chunkSize) { chunkP[i].origSize = chunkSize; remaining -= chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; }
+ chunkP[i].compressedBuffer = out; out += maxCompressedChunkSize;
+ chunkP[i].compressedSize = 0;
+ }
+ }
+
// Compression Algorithms
for (cAlgNb=1; (cAlgNb <= NB_COMPRESSION_ALGORITHMS) && (compressionTest); cAlgNb++)
{
- char* compressorName;
+ const char* compressorName;
int (*compressionFunction)(const char*, char*, int);
void* (*initFunction)(const char*) = NULL;
double bestTime = 100000000.;
@@ -496,6 +525,9 @@ int fullSpeedBench(char** fileNamesTable, int nbFiles)
case 11: compressionFunction = local_LZ4_compressHC_continue; initFunction = LZ4_createHC; compressorName = "LZ4_compressHC_continue"; break;
case 12: compressionFunction = local_LZ4_compressHC_limitedOutput_continue; initFunction = LZ4_createHC; compressorName = "LZ4_compressHC_limitedOutput_continue"; break;
case 13: compressionFunction = local_LZ4_compress_forceDict; initFunction = local_LZ4_resetDictT; compressorName = "LZ4_compress_forceDict"; break;
+ case 14: compressionFunction = local_LZ4F_compressFrame; compressorName = "LZ4F_compressFrame";
+ chunkP[0].origSize = benchedSize; nbChunks=1;
+ break;
default : DISPLAY("ERROR ! Bad algorithm Id !! \n"); free(chunkP); return 1;
}
@@ -546,29 +578,39 @@ int fullSpeedBench(char** fileNamesTable, int nbFiles)
chunkP[chunkNb].compressedSize = LZ4_compress(chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origSize);
if (chunkP[chunkNb].compressedSize==0) DISPLAY("ERROR ! %s() = 0 !! \n", "LZ4_compress"), exit(1);
}
- { size_t i; for (i=0; i<benchedSize; i++) orig_buff[i]=0; } // zeroing source area, for CRC checking
// Decompression Algorithms
- for (dAlgNb=0; (dAlgNb < NB_DECOMPRESSION_ALGORITHMS) && (decompressionTest); dAlgNb++)
+ for (dAlgNb=1; (dAlgNb <= NB_DECOMPRESSION_ALGORITHMS) && (decompressionTest); dAlgNb++)
{
- char* dName = decompressionNames[dAlgNb];
+ //const char* dName = decompressionNames[dAlgNb];
+ const char* dName;
int (*decompressionFunction)(const char*, char*, int, int);
double bestTime = 100000000.;
- if ((decompressionAlgo != ALL_DECOMPRESSORS) && (decompressionAlgo != dAlgNb+1)) continue;
+ if ((decompressionAlgo != ALL_DECOMPRESSORS) && (decompressionAlgo != dAlgNb)) continue;
switch(dAlgNb)
{
- case 0: decompressionFunction = local_LZ4_decompress_fast; break;
- case 1: decompressionFunction = local_LZ4_decompress_fast_withPrefix64k; break;
- case 2: decompressionFunction = local_LZ4_decompress_fast_usingDict; break;
- case 3: decompressionFunction = LZ4_decompress_safe; break;
- case 4: decompressionFunction = LZ4_decompress_safe_withPrefix64k; break;
- case 5: decompressionFunction = local_LZ4_decompress_safe_usingDict; break;
- case 6: decompressionFunction = local_LZ4_decompress_safe_partial; break;
+ case 1: decompressionFunction = local_LZ4_decompress_fast; dName = "LZ4_decompress_fast"; break;
+ case 2: decompressionFunction = local_LZ4_decompress_fast_withPrefix64k; dName = "LZ4_decompress_fast_withPrefix64k"; break;
+ case 3: decompressionFunction = local_LZ4_decompress_fast_usingDict; dName = "LZ4_decompress_fast_usingDict"; break;
+ case 4: decompressionFunction = LZ4_decompress_safe; dName = "LZ4_decompress_safe"; break;
+ case 5: decompressionFunction = LZ4_decompress_safe_withPrefix64k; dName = "LZ4_decompress_safe_withPrefix64k"; break;
+ case 6: decompressionFunction = local_LZ4_decompress_safe_usingDict; dName = "LZ4_decompress_safe_usingDict"; break;
+ case 7: decompressionFunction = local_LZ4_decompress_safe_partial; dName = "LZ4_decompress_safe_partial"; break;
+ case 8: decompressionFunction = local_LZ4_decompress_safe_forceExtDict; dName = "LZ4_decompress_safe_forceExtDict"; break;
+ case 9: decompressionFunction = local_LZ4F_decompress; dName = "LZ4F_decompress";
+ errorCode = LZ4F_compressFrame(compressed_buff, compressedBuffSize, orig_buff, benchedSize, NULL);
+ if (LZ4F_isError(errorCode)) { DISPLAY("Preparation error compressing frame\n"); return 1; }
+ chunkP[0].origSize = benchedSize;
+ chunkP[0].compressedSize = errorCode;
+ nbChunks = 1;
+ break;
default : DISPLAY("ERROR ! Bad decompression algorithm Id !! \n"); free(chunkP); return 1;
}
+ { size_t i; for (i=0; i<benchedSize; i++) orig_buff[i]=0; } // zeroing source area, for CRC checking
+
for (loopNb = 1; loopNb <= nbIterations; loopNb++)
{
double averageTime;