diff options
author | Yann Collet <yann.collet.73@gmail.com> | 2014-09-13 22:30:01 (GMT) |
---|---|---|
committer | Yann Collet <yann.collet.73@gmail.com> | 2014-09-13 22:30:01 (GMT) |
commit | 3f80a228193755ffcdaaccc7e8408b7e434c1fbe (patch) | |
tree | a235376fc65e9fe4957e01510f2a72484c49e074 /programs | |
parent | 3b4e3f2b01df752d82a51d7b7afaa9a2fd5a5ff8 (diff) | |
parent | 457dc35e6a56aab12e060af608efd1cbb0eec8a9 (diff) | |
download | lz4-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/Makefile | 22 | ||||
-rw-r--r-- | programs/frametest.c | 619 | ||||
-rw-r--r-- | programs/fullbench.c | 118 |
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; |