2014-08-30 17:14:44 +00:00
/*
frameTest - test tool for lz4frame
2016-06-29 19:48:27 +00:00
Copyright ( C ) Yann Collet 2014 - 2016
2015-03-15 13:19:47 +00:00
2014-08-30 17:14:44 +00:00
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 :
2016-06-29 19:48:27 +00:00
- LZ4 homepage : http : //www.lz4.org
2016-11-03 14:12:57 +00:00
- LZ4 source repository : https : //github.com/lz4/lz4
2014-08-30 17:14:44 +00:00
*/
2016-06-29 19:48:27 +00:00
/*-************************************
2015-03-07 18:30:45 +00:00
* Compiler specific
2014-08-30 17:14:44 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# 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
2016-06-29 19:48:27 +00:00
/*-************************************
2015-03-07 18:30:45 +00:00
* Includes
2014-08-30 17:14:44 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-03-16 16:52:14 +00:00
# include <stdlib.h> /* malloc, free */
# include <stdio.h> /* fprintf */
# include <string.h> /* strcmp */
2016-09-03 04:46:02 +00:00
# include <time.h> /* clock_t, clock(), CLOCKS_PER_SEC */
2014-12-13 14:05:46 +00:00
# include "lz4frame_static.h"
2016-09-03 04:46:02 +00:00
# include "lz4.h" /* LZ4_VERSION_STRING */
2016-06-29 19:48:27 +00:00
# define XXH_STATIC_LINKING_ONLY
2015-03-16 16:52:14 +00:00
# include "xxhash.h" /* XXH64 */
2014-08-30 17:14:44 +00:00
2016-06-30 11:44:58 +00:00
/*-************************************
2015-03-07 18:30:45 +00:00
* Basic Types
2014-08-30 17:14:44 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-11-11 23:11:56 +00:00
# if !defined(__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ ) )
2014-08-30 17:14:44 +00:00
# include <stdint.h>
2014-09-22 17:42:00 +00:00
typedef uint8_t BYTE ;
typedef uint16_t U16 ;
typedef uint32_t U32 ;
typedef int32_t S32 ;
typedef uint64_t U64 ;
2014-08-30 17:14:44 +00:00
# else
2014-09-22 17:42:00 +00:00
typedef unsigned char BYTE ;
typedef unsigned short U16 ;
typedef unsigned int U32 ;
typedef signed int S32 ;
typedef unsigned long long U64 ;
2014-08-30 17:14:44 +00:00
# endif
2015-03-16 16:52:14 +00:00
/* unoptimized version; solves endianess & alignment issues */
static void FUZ_writeLE32 ( void * dstVoidPtr , U32 value32 )
{
BYTE * dstPtr = ( BYTE * ) dstVoidPtr ;
dstPtr [ 0 ] = ( BYTE ) value32 ;
dstPtr [ 1 ] = ( BYTE ) ( value32 > > 8 ) ;
dstPtr [ 2 ] = ( BYTE ) ( value32 > > 16 ) ;
dstPtr [ 3 ] = ( BYTE ) ( value32 > > 24 ) ;
}
2016-06-30 11:44:58 +00:00
/*-************************************
2015-03-07 18:30:45 +00:00
* Constants
2014-08-30 17:14:44 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-03-16 16:52:14 +00:00
# define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U
2014-09-01 21:44:02 +00:00
# define KB *(1U<<10)
# define MB *(1U<<20)
# define GB *(1U<<30)
2014-10-21 23:36:32 +00:00
static const U32 nbTestsDefault = 256 KB ;
2014-09-01 21:44:02 +00:00
# define COMPRESSIBLE_NOISE_LENGTH (2 MB)
2014-08-30 17:14:44 +00:00
# define FUZ_COMPRESSIBILITY_DEFAULT 50
2014-09-07 08:13:02 +00:00
static const U32 prime1 = 2654435761U ;
static const U32 prime2 = 2246822519U ;
2014-08-30 17:14:44 +00:00
2016-06-30 11:44:58 +00:00
/*-************************************
2015-03-16 16:52:14 +00:00
* Macros
2014-08-30 17:14:44 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-09-05 15:32:04 +00:00
# define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
# define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
2014-09-06 12:06:28 +00:00
# define DISPLAYUPDATE(l, ...) if (displayLevel>=l) { \
2016-09-03 04:46:02 +00:00
if ( ( FUZ_GetClockSpan ( g_clockTime ) > refreshRate ) | | ( displayLevel > = 4 ) ) \
{ g_clockTime = clock ( ) ; DISPLAY ( __VA_ARGS__ ) ; \
2014-09-06 12:06:28 +00:00
if ( displayLevel > = 4 ) fflush ( stdout ) ; } }
2016-09-03 04:46:02 +00:00
static const clock_t refreshRate = CLOCKS_PER_SEC / 6 ;
static clock_t g_clockTime = 0 ;
2014-08-30 17:14:44 +00:00
2016-06-30 11:44:58 +00:00
/*-***************************************
2015-03-16 16:52:14 +00:00
* Local Parameters
2014-08-30 17:14:44 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-09-06 12:06:28 +00:00
static U32 no_prompt = 0 ;
static U32 displayLevel = 2 ;
2014-09-21 08:56:21 +00:00
static U32 pause = 0 ;
2014-08-30 17:14:44 +00:00
2016-06-30 11:44:58 +00:00
/*-*******************************************************
2015-03-07 18:30:45 +00:00
* Fuzzer functions
2014-08-30 17:14:44 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-11-11 23:11:56 +00:00
# define MIN(a,b) ( (a) < (b) ? (a) : (b) )
# define MAX(a,b) ( (a) > (b) ? (a) : (b) )
2016-09-03 04:46:02 +00:00
static clock_t FUZ_GetClockSpan ( clock_t clockStart )
2014-08-30 17:14:44 +00:00
{
2016-09-03 04:46:02 +00:00
return clock ( ) - clockStart ; /* works even if overflow; max span ~ 30 mn */
2014-08-30 17:14:44 +00:00
}
2015-03-07 18:30:45 +00:00
2016-09-03 04:46:02 +00:00
# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
2014-08-30 17:14:44 +00:00
unsigned int FUZ_rand ( unsigned int * src )
{
U32 rand32 = * src ;
2014-09-07 08:13:02 +00:00
rand32 * = prime1 ;
rand32 + = prime2 ;
2014-08-30 17:14:44 +00:00
rand32 = FUZ_rotl32 ( rand32 , 13 ) ;
* src = rand32 ;
2014-09-05 15:32:04 +00:00
return rand32 > > 5 ;
2014-08-30 17:14:44 +00:00
}
2014-09-05 15:32:04 +00:00
# define FUZ_RAND15BITS (FUZ_rand(seed) & 0x7FFF)
# define FUZ_RANDLENGTH ( (FUZ_rand(seed) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
2016-11-14 15:10:31 +00:00
static void FUZ_fillCompressibleNoiseBuffer ( void * buffer , size_t bufferSize , double proba , U32 * seed )
2014-08-30 17:14:44 +00:00
{
BYTE * BBuffer = ( BYTE * ) buffer ;
2016-11-14 15:10:31 +00:00
size_t pos = 0 ;
2014-08-30 17:14:44 +00:00
U32 P32 = ( U32 ) ( 32768 * proba ) ;
2015-03-16 16:52:14 +00:00
/* First Byte */
2014-08-30 17:14:44 +00:00
BBuffer [ pos + + ] = ( BYTE ) ( FUZ_rand ( seed ) ) ;
2016-06-30 11:44:58 +00:00
while ( pos < bufferSize ) {
2015-03-16 16:52:14 +00:00
/* Select : Literal (noise) or copy (within 64K) */
2016-06-30 11:44:58 +00:00
if ( FUZ_RAND15BITS < P32 ) {
2015-03-16 16:52:14 +00:00
/* Copy (within 64K) */
2016-11-14 15:10:31 +00:00
size_t const lengthRand = FUZ_RANDLENGTH + 4 ;
size_t const length = MIN ( lengthRand , bufferSize - pos ) ;
size_t const end = pos + length ;
size_t const offsetRand = FUZ_RAND15BITS + 1 ;
size_t const offset = MIN ( offsetRand , pos ) ;
size_t match = pos - offset ;
2014-08-31 22:14:20 +00:00
while ( pos < end ) BBuffer [ pos + + ] = BBuffer [ match + + ] ;
2016-06-30 11:44:58 +00:00
} else {
2015-03-16 16:52:14 +00:00
/* Literal (noise) */
2016-11-14 15:10:31 +00:00
size_t const lengthRand = FUZ_RANDLENGTH + 4 ;
size_t const length = MIN ( lengthRand , bufferSize - pos ) ;
size_t const end = pos + length ;
2014-08-31 22:14:20 +00:00
while ( pos < end ) BBuffer [ pos + + ] = ( BYTE ) ( FUZ_rand ( seed ) > > 5 ) ;
2014-08-30 17:14:44 +00:00
}
}
}
2014-09-05 15:32:04 +00:00
static unsigned FUZ_highbit ( U32 v32 )
{
unsigned nbBits = 0 ;
if ( v32 = = 0 ) return 0 ;
2016-08-11 12:44:53 +00:00
while ( v32 ) v32 > > = 1 , nbBits + + ;
2014-09-05 15:32:04 +00:00
return nbBits ;
}
2014-08-30 17:14:44 +00:00
2014-09-05 15:32:04 +00:00
2016-11-11 23:11:56 +00:00
/*-*******************************************************
* Tests
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-09-11 21:27:14 +00:00
int basicTests ( U32 seed , double compressibility )
2014-08-30 17:14:44 +00:00
{
2014-09-22 17:42:00 +00:00
int testResult = 0 ;
2016-11-11 23:11:56 +00:00
void * const CNBuffer = malloc ( COMPRESSIBLE_NOISE_LENGTH ) ;
size_t const cBuffSize = LZ4F_compressFrameBound ( COMPRESSIBLE_NOISE_LENGTH , NULL ) ;
void * const compressedBuffer = malloc ( cBuffSize ) ;
void * const decodedBuffer = malloc ( COMPRESSIBLE_NOISE_LENGTH ) ;
2014-09-22 17:42:00 +00:00
U32 randState = seed ;
size_t cSize , testSize ;
2015-04-12 07:21:35 +00:00
LZ4F_decompressionContext_t dCtx = NULL ;
LZ4F_compressionContext_t cctx = NULL ;
2014-09-22 17:42:00 +00:00
U64 crcOrig ;
2016-11-11 23:11:56 +00:00
LZ4F_preferences_t prefs ;
2015-03-10 15:57:42 +00:00
memset ( & prefs , 0 , sizeof ( prefs ) ) ;
2016-11-11 23:11:56 +00:00
if ( ! CNBuffer | | ! compressedBuffer | | ! decodedBuffer ) {
DISPLAY ( " allocation error, not enough memory to start fuzzer tests \n " ) ;
goto _output_error ;
}
2014-09-22 17:42:00 +00:00
FUZ_fillCompressibleNoiseBuffer ( CNBuffer , COMPRESSIBLE_NOISE_LENGTH , compressibility , & randState ) ;
crcOrig = XXH64 ( CNBuffer , COMPRESSIBLE_NOISE_LENGTH , 1 ) ;
2016-08-11 12:44:53 +00:00
/* Special case : null-content frame */
testSize = 0 ;
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame, compress null content : \n " ) ;
cSize = LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , NULL ) , CNBuffer , testSize , NULL ) ;
if ( LZ4F_isError ( cSize ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " Compressed null content into a %i bytes frame \n " , ( int ) cSize ) ;
DISPLAYLEVEL ( 3 , " LZ4F_createDecompressionContext \n " ) ;
{ LZ4F_errorCode_t const errorCode = LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ; }
DISPLAYLEVEL ( 3 , " LZ4F_getFrameInfo on null-content frame (#157) \n " ) ;
{ size_t avail_in = cSize ;
LZ4F_frameInfo_t frame_info ;
LZ4F_errorCode_t const errorCode = LZ4F_getFrameInfo ( dCtx , & frame_info , compressedBuffer , & avail_in ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
}
DISPLAYLEVEL ( 3 , " LZ4F_freeDecompressionContext \n " ) ;
{ LZ4F_errorCode_t const errorCode = LZ4F_freeDecompressionContext ( dCtx ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ; }
2016-11-11 23:11:56 +00:00
dCtx = NULL ;
2016-08-11 12:44:53 +00:00
2016-11-11 23:11:56 +00:00
/* test one-pass frame compression */
2014-09-22 17:42:00 +00:00
testSize = COMPRESSIBLE_NOISE_LENGTH ;
2016-08-11 12:44:53 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame, using default preferences : \n " ) ;
2014-09-22 17:42:00 +00:00
cSize = LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , NULL ) , CNBuffer , testSize , NULL ) ;
if ( LZ4F_isError ( cSize ) ) goto _output_error ;
2016-11-11 23:11:56 +00:00
DISPLAYLEVEL ( 3 , " Compressed %u bytes into a %u bytes frame \n " , ( U32 ) testSize , ( U32 ) cSize ) ;
2014-09-22 17:42:00 +00:00
DISPLAYLEVEL ( 3 , " Decompression test : \n " ) ;
2016-08-11 12:44:53 +00:00
{ size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH ;
2014-09-03 18:49:59 +00:00
size_t compressedBufferSize = cSize ;
2014-09-04 21:56:51 +00:00
BYTE * ip = ( BYTE * ) compressedBuffer ;
BYTE * const iend = ( BYTE * ) compressedBuffer + cSize ;
2014-09-05 15:32:04 +00:00
LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ;
2014-09-03 18:49:59 +00:00
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
2014-09-04 21:56:51 +00:00
2016-11-11 23:11:56 +00:00
DISPLAYLEVEL ( 3 , " Single Pass decompression : \n " ) ;
{ size_t const decompressError = LZ4F_decompress ( dCtx , decodedBuffer , & decodedBufferSize , compressedBuffer , & compressedBufferSize , NULL ) ;
if ( LZ4F_isError ( decompressError ) ) goto _output_error ; }
{ U64 const crcDest = XXH64 ( decodedBuffer , COMPRESSIBLE_NOISE_LENGTH , 1 ) ;
if ( crcDest ! = crcOrig ) goto _output_error ; }
DISPLAYLEVEL ( 3 , " Regenerated %u bytes \n " , ( U32 ) decodedBufferSize ) ;
2014-09-04 21:56:51 +00:00
2016-08-11 12:44:53 +00:00
DISPLAYLEVEL ( 3 , " Reusing decompression context \n " ) ;
2016-11-11 23:11:56 +00:00
{ size_t const missingBytes = 4 ;
size_t iSize = compressedBufferSize - missingBytes ;
2015-04-20 08:51:00 +00:00
const BYTE * cBuff = ( const BYTE * ) compressedBuffer ;
2016-11-11 23:11:56 +00:00
BYTE * const ostart = ( BYTE * ) decodedBuffer ;
BYTE * op = ostart ;
BYTE * const oend = ( BYTE * ) decodedBuffer + COMPRESSIBLE_NOISE_LENGTH ;
size_t decResult , oSize = COMPRESSIBLE_NOISE_LENGTH ;
DISPLAYLEVEL ( 3 , " Missing last %u bytes : " , ( U32 ) missingBytes ) ;
decResult = LZ4F_decompress ( dCtx , op , & oSize , cBuff , & iSize , NULL ) ;
2016-08-11 12:44:53 +00:00
if ( LZ4F_isError ( decResult ) ) goto _output_error ;
2016-11-11 23:11:56 +00:00
if ( decResult ! = missingBytes ) {
DISPLAY ( " %u bytes missing != %u bytes requested \n " , ( U32 ) missingBytes , ( U32 ) decResult ) ;
goto _output_error ;
}
DISPLAYLEVEL ( 3 , " indeed, requests %u bytes \n " , ( unsigned ) decResult ) ;
2015-04-20 08:51:00 +00:00
cBuff + = iSize ;
2016-08-11 12:44:53 +00:00
iSize = decResult ;
2016-11-11 23:11:56 +00:00
op + = oSize ;
oSize = ( size_t ) ( oend - op ) ;
decResult = LZ4F_decompress ( dCtx , op , & oSize , cBuff , & iSize , NULL ) ;
2016-08-11 12:44:53 +00:00
if ( decResult ! = 0 ) goto _output_error ; /* should finish now */
2016-11-11 23:11:56 +00:00
op + = oSize ;
if ( op > oend ) { DISPLAY ( " decompression write overflow \n " ) ; goto _output_error ; }
{ U64 const crcDest = XXH64 ( decodedBuffer , op - ostart , 1 ) ;
if ( crcDest ! = crcOrig ) goto _output_error ;
} }
2015-04-20 08:24:25 +00:00
2016-06-30 11:44:58 +00:00
{ size_t oSize = 0 ;
2015-04-19 14:23:53 +00:00
size_t iSize = 0 ;
LZ4F_frameInfo_t fi ;
DISPLAYLEVEL ( 3 , " Start by feeding 0 bytes, to get next input size : " ) ;
errorCode = LZ4F_decompress ( dCtx , NULL , & oSize , ip , & iSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " %u \n " , ( unsigned ) errorCode ) ;
DISPLAYLEVEL ( 3 , " get FrameInfo on null input : " ) ;
errorCode = LZ4F_getFrameInfo ( dCtx , & fi , ip , & iSize ) ;
if ( errorCode ! = ( size_t ) - LZ4F_ERROR_frameHeader_incomplete ) goto _output_error ;
DISPLAYLEVEL ( 3 , " correctly failed : %s \n " , LZ4F_getErrorName ( errorCode ) ) ;
DISPLAYLEVEL ( 3 , " get FrameInfo on not enough input : " ) ;
iSize = 6 ;
errorCode = LZ4F_getFrameInfo ( dCtx , & fi , ip , & iSize ) ;
if ( errorCode ! = ( size_t ) - LZ4F_ERROR_frameHeader_incomplete ) goto _output_error ;
DISPLAYLEVEL ( 3 , " correctly failed : %s \n " , LZ4F_getErrorName ( errorCode ) ) ;
ip + = iSize ;
DISPLAYLEVEL ( 3 , " get FrameInfo on enough input : " ) ;
iSize = 15 - iSize ;
errorCode = LZ4F_getFrameInfo ( dCtx , & fi , ip , & iSize ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " correctly decoded \n " ) ;
ip + = iSize ;
}
2014-09-05 15:32:04 +00:00
DISPLAYLEVEL ( 3 , " Byte after byte : \n " ) ;
2016-11-11 23:11:56 +00:00
{ BYTE * const ostart = ( BYTE * ) decodedBuffer ;
BYTE * op = ostart ;
BYTE * const oend = ( BYTE * ) decodedBuffer + COMPRESSIBLE_NOISE_LENGTH ;
while ( ip < iend ) {
size_t oSize = oend - op ;
size_t iSize = 1 ;
errorCode = LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = oSize ;
ip + = iSize ;
}
{ U64 const crcDest = XXH64 ( decodedBuffer , COMPRESSIBLE_NOISE_LENGTH , 1 ) ;
if ( crcDest ! = crcOrig ) goto _output_error ; }
DISPLAYLEVEL ( 3 , " Regenerated %u/%u bytes \n " , ( unsigned ) ( op - ostart ) , COMPRESSIBLE_NOISE_LENGTH ) ;
}
2014-09-04 21:56:51 +00:00
2014-09-03 18:49:59 +00:00
errorCode = LZ4F_freeDecompressionContext ( dCtx ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
2016-11-11 23:11:56 +00:00
dCtx = NULL ;
2014-09-22 17:42:00 +00:00
}
DISPLAYLEVEL ( 3 , " Using 64 KB block : \n " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . blockSizeID = LZ4F_max64KB ;
prefs . frameInfo . contentChecksumFlag = LZ4F_contentChecksumEnabled ;
2014-09-22 17:42:00 +00:00
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 " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . contentChecksumFlag = LZ4F_noContentChecksum ;
2014-09-22 17:42:00 +00:00
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 " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . blockSizeID = LZ4F_max256KB ;
prefs . frameInfo . contentChecksumFlag = LZ4F_contentChecksumEnabled ;
2014-09-22 17:42:00 +00:00
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 " ) ;
2016-11-11 23:11:56 +00:00
{ size_t const decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH ;
unsigned const maxBits = FUZ_highbit ( ( U32 ) decodedBufferSize ) ;
BYTE * const ostart = ( BYTE * ) decodedBuffer ;
BYTE * op = ostart ;
BYTE * const oend = ostart + COMPRESSIBLE_NOISE_LENGTH ;
const BYTE * ip = ( const BYTE * ) compressedBuffer ;
const BYTE * const iend = ( const BYTE * ) compressedBuffer + cSize ;
2014-09-05 15:32:04 +00:00
2016-11-11 23:11:56 +00:00
{ LZ4F_errorCode_t const createError = LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ;
if ( LZ4F_isError ( createError ) ) goto _output_error ; }
2014-09-05 15:32:04 +00:00
DISPLAYLEVEL ( 3 , " random segment sizes : \n " ) ;
2016-06-30 11:44:58 +00:00
while ( ip < iend ) {
2016-11-11 23:11:56 +00:00
unsigned const nbBits = FUZ_rand ( & randState ) % maxBits ;
2014-09-05 15:32:04 +00:00
size_t iSize = ( FUZ_rand ( & randState ) & ( ( 1 < < nbBits ) - 1 ) ) + 1 ;
size_t oSize = oend - op ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = iend - ip ;
2016-11-11 23:11:56 +00:00
{ size_t const decompressError = LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ;
if ( LZ4F_isError ( decompressError ) ) goto _output_error ; }
2014-09-05 15:32:04 +00:00
op + = oSize ;
ip + = iSize ;
}
2016-11-11 23:11:56 +00:00
{ size_t const decodedSize = ( size_t ) ( op - ostart ) ;
U64 const crcDest = XXH64 ( decodedBuffer , decodedSize , 1 ) ;
if ( crcDest ! = crcOrig ) goto _output_error ;
DISPLAYLEVEL ( 3 , " Regenerated %u bytes \n " , ( U32 ) decodedSize ) ;
}
2014-09-05 15:32:04 +00:00
2016-11-11 23:11:56 +00:00
{ LZ4F_errorCode_t const freeError = LZ4F_freeDecompressionContext ( dCtx ) ;
if ( LZ4F_isError ( freeError ) ) goto _output_error ; }
dCtx = NULL ;
2014-09-22 17:42:00 +00:00
}
DISPLAYLEVEL ( 3 , " without checksum : \n " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . contentChecksumFlag = LZ4F_noContentChecksum ;
2014-09-22 17:42:00 +00:00
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 " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . blockSizeID = LZ4F_max1MB ;
prefs . frameInfo . contentChecksumFlag = LZ4F_contentChecksumEnabled ;
2014-09-22 17:42:00 +00:00
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 " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . contentChecksumFlag = LZ4F_noContentChecksum ;
2014-09-22 17:42:00 +00:00
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 " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . blockSizeID = LZ4F_max4MB ;
prefs . frameInfo . contentChecksumFlag = LZ4F_contentChecksumEnabled ;
2016-11-11 23:11:56 +00:00
{ size_t const dstCapacity = LZ4F_compressFrameBound ( testSize , & prefs ) ;
DISPLAYLEVEL ( 4 , " dstCapacity = %u \n " , ( U32 ) dstCapacity )
cSize = LZ4F_compressFrame ( compressedBuffer , dstCapacity , CNBuffer , testSize , & prefs ) ;
if ( LZ4F_isError ( cSize ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " Compressed %u bytes into a %u bytes frame \n " , ( U32 ) testSize , ( U32 ) cSize ) ;
}
2014-09-22 17:42:00 +00:00
DISPLAYLEVEL ( 3 , " without checksum : \n " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . contentChecksumFlag = LZ4F_noContentChecksum ;
2016-11-11 23:11:56 +00:00
{ size_t const dstCapacity = LZ4F_compressFrameBound ( testSize , & prefs ) ;
DISPLAYLEVEL ( 4 , " dstCapacity = %u \n " , ( U32 ) dstCapacity )
cSize = LZ4F_compressFrame ( compressedBuffer , dstCapacity , CNBuffer , testSize , & prefs ) ;
if ( LZ4F_isError ( cSize ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " Compressed %u bytes into a %u bytes frame \n " , ( U32 ) testSize , ( U32 ) cSize ) ;
}
2014-09-22 17:42:00 +00:00
2016-08-11 12:44:53 +00:00
{ size_t errorCode ;
2015-03-18 20:38:27 +00:00
BYTE * const ostart = ( BYTE * ) compressedBuffer ;
BYTE * op = ostart ;
errorCode = LZ4F_createCompressionContext ( & cctx , LZ4F_VERSION ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " compress without frameSize : \n " ) ;
memset ( & ( prefs . frameInfo ) , 0 , sizeof ( prefs . frameInfo ) ) ;
errorCode = LZ4F_compressBegin ( cctx , compressedBuffer , testSize , & prefs ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = errorCode ;
errorCode = LZ4F_compressUpdate ( cctx , op , LZ4F_compressBound ( testSize , & prefs ) , CNBuffer , testSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = errorCode ;
errorCode = LZ4F_compressEnd ( cctx , compressedBuffer , testSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) ( op - ostart ) ) ;
DISPLAYLEVEL ( 3 , " compress with frameSize : \n " ) ;
2015-03-29 10:20:09 +00:00
prefs . frameInfo . contentSize = testSize ;
2015-03-18 20:38:27 +00:00
op = ostart ;
errorCode = LZ4F_compressBegin ( cctx , compressedBuffer , testSize , & prefs ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = errorCode ;
errorCode = LZ4F_compressUpdate ( cctx , op , LZ4F_compressBound ( testSize , & prefs ) , CNBuffer , testSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = errorCode ;
errorCode = LZ4F_compressEnd ( cctx , compressedBuffer , testSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) ( op - ostart ) ) ;
DISPLAYLEVEL ( 3 , " compress with wrong frameSize : \n " ) ;
2015-03-29 10:20:09 +00:00
prefs . frameInfo . contentSize = testSize + 1 ;
2015-03-18 20:38:27 +00:00
op = ostart ;
errorCode = LZ4F_compressBegin ( cctx , compressedBuffer , testSize , & prefs ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = errorCode ;
errorCode = LZ4F_compressUpdate ( cctx , op , LZ4F_compressBound ( testSize , & prefs ) , CNBuffer , testSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = errorCode ;
errorCode = LZ4F_compressEnd ( cctx , op , testSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) { DISPLAYLEVEL ( 3 , " Error correctly detected : %s \n " , LZ4F_getErrorName ( errorCode ) ) ; }
else
goto _output_error ;
errorCode = LZ4F_freeCompressionContext ( cctx ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
2015-04-12 07:21:35 +00:00
cctx = NULL ;
2015-03-18 20:38:27 +00:00
}
2015-03-16 16:52:14 +00:00
DISPLAYLEVEL ( 3 , " Skippable frame test : \n " ) ;
2016-08-11 12:44:53 +00:00
{ size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH ;
2015-03-16 16:52:14 +00:00
unsigned maxBits = FUZ_highbit ( ( U32 ) decodedBufferSize ) ;
BYTE * op = ( BYTE * ) decodedBuffer ;
BYTE * const oend = ( BYTE * ) decodedBuffer + COMPRESSIBLE_NOISE_LENGTH ;
BYTE * ip = ( BYTE * ) compressedBuffer ;
2015-03-16 18:19:39 +00:00
BYTE * iend = ( BYTE * ) compressedBuffer + cSize + 8 ;
2015-03-16 16:52:14 +00:00
LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
/* generate skippable frame */
FUZ_writeLE32 ( ip , LZ4F_MAGIC_SKIPPABLE_START ) ;
FUZ_writeLE32 ( ip + 4 , ( U32 ) cSize ) ;
DISPLAYLEVEL ( 3 , " random segment sizes : \n " ) ;
2016-06-30 11:44:58 +00:00
while ( ip < iend ) {
2015-03-16 16:52:14 +00:00
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 ;
errorCode = LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = oSize ;
ip + = iSize ;
}
DISPLAYLEVEL ( 3 , " Skipped %i bytes \n " , ( int ) decodedBufferSize ) ;
2015-03-16 18:19:39 +00:00
/* generate zero-size skippable frame */
2015-03-18 20:38:27 +00:00
DISPLAYLEVEL ( 3 , " zero-size skippable frame \n " ) ;
ip = ( BYTE * ) compressedBuffer ;
op = ( BYTE * ) decodedBuffer ;
2015-03-16 18:19:39 +00:00
FUZ_writeLE32 ( ip , LZ4F_MAGIC_SKIPPABLE_START + 1 ) ;
FUZ_writeLE32 ( ip + 4 , 0 ) ;
iend = ip + 8 ;
2016-06-30 11:44:58 +00:00
while ( ip < iend ) {
2015-03-16 18:19:39 +00:00
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 ;
errorCode = LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = oSize ;
ip + = iSize ;
}
2015-03-18 20:38:27 +00:00
DISPLAYLEVEL ( 3 , " Skipped %i bytes \n " , ( int ) ( ip - ( BYTE * ) compressedBuffer - 8 ) ) ;
DISPLAYLEVEL ( 3 , " Skippable frame header complete in first call \n " ) ;
ip = ( BYTE * ) compressedBuffer ;
op = ( BYTE * ) decodedBuffer ;
FUZ_writeLE32 ( ip , LZ4F_MAGIC_SKIPPABLE_START + 2 ) ;
FUZ_writeLE32 ( ip + 4 , 10 ) ;
iend = ip + 18 ;
2016-06-30 11:44:58 +00:00
while ( ip < iend ) {
2015-03-18 20:38:27 +00:00
size_t iSize = 10 ;
size_t oSize = 10 ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = iend - ip ;
errorCode = LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ;
if ( LZ4F_isError ( errorCode ) ) goto _output_error ;
op + = oSize ;
ip + = iSize ;
}
DISPLAYLEVEL ( 3 , " Skipped %i bytes \n " , ( int ) ( ip - ( BYTE * ) compressedBuffer - 8 ) ) ;
2015-03-16 16:52:14 +00:00
}
2014-09-22 17:42:00 +00:00
DISPLAY ( " Basic tests completed \n " ) ;
2014-08-30 17:14:44 +00:00
_end :
2014-09-22 17:42:00 +00:00
free ( CNBuffer ) ;
free ( compressedBuffer ) ;
free ( decodedBuffer ) ;
2015-04-12 07:21:35 +00:00
LZ4F_freeDecompressionContext ( dCtx ) ; dCtx = NULL ;
LZ4F_freeCompressionContext ( cctx ) ; cctx = NULL ;
2014-09-22 17:42:00 +00:00
return testResult ;
2014-08-30 17:14:44 +00:00
_output_error :
2014-09-22 17:42:00 +00:00
testResult = 1 ;
DISPLAY ( " Error detected ! \n " ) ;
goto _end ;
2014-08-30 17:14:44 +00:00
}
2014-09-21 08:56:21 +00:00
static void locateBuffDiff ( const void * buff1 , const void * buff2 , size_t size , unsigned nonContiguous )
2014-09-11 21:27:14 +00:00
{
int p = 0 ;
2015-05-06 00:58:24 +00:00
const BYTE * b1 = ( const BYTE * ) buff1 ;
const BYTE * b2 = ( const BYTE * ) buff2 ;
2016-06-30 11:44:58 +00:00
if ( nonContiguous ) {
2014-09-22 17:42:00 +00:00
DISPLAY ( " Non-contiguous output test (%i bytes) \n " , ( int ) size ) ;
return ;
}
2014-09-11 21:27:14 +00:00
while ( b1 [ p ] = = b2 [ p ] ) p + + ;
2014-09-21 08:56:21 +00:00
DISPLAY ( " Error at pos %i/%i : %02X != %02X \n " , p , ( int ) size , b1 [ p ] , b2 [ p ] ) ;
2014-09-22 17:42:00 +00:00
}
2014-09-11 21:27:14 +00:00
2016-09-03 04:46:02 +00:00
int fuzzerTests ( U32 seed , unsigned nbTests , unsigned startTest , double compressibility , U32 duration_s )
2014-09-05 15:32:04 +00:00
{
2014-09-22 17:42:00 +00:00
unsigned testResult = 0 ;
unsigned testNb = 0 ;
2016-11-11 23:11:56 +00:00
size_t const srcDataLength = 9 MB ; /* needs to be > 2x4MB to test large blocks */
2014-09-22 17:42:00 +00:00
void * srcBuffer = NULL ;
2016-11-11 23:11:56 +00:00
size_t const compressedBufferSize = LZ4F_compressFrameBound ( srcDataLength , NULL ) ;
2014-09-22 17:42:00 +00:00
void * compressedBuffer = NULL ;
void * decodedBuffer = NULL ;
U32 coreRand = seed ;
LZ4F_decompressionContext_t dCtx = NULL ;
LZ4F_compressionContext_t cCtx = NULL ;
2014-09-07 11:57:09 +00:00
size_t result ;
2016-09-03 04:46:02 +00:00
clock_t const startClock = clock ( ) ;
clock_t const clockDuration = duration_s * CLOCKS_PER_SEC ;
2014-09-06 12:06:28 +00:00
# define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
2014-09-22 17:42:00 +00:00
DISPLAY ( " (seed %u, test nb %u) \n " , seed , testNb ) ; goto _output_error ; }
2014-09-05 15:32:04 +00:00
2015-03-15 00:42:27 +00:00
/* Create buffers */
2014-09-22 17:42:00 +00:00
result = LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ;
2014-09-07 11:57:09 +00:00
CHECK ( LZ4F_isError ( result ) , " Allocation failed (error %i) " , ( int ) result ) ;
2014-09-22 17:42:00 +00:00
result = LZ4F_createCompressionContext ( & cCtx , LZ4F_VERSION ) ;
2014-09-07 11:57:09 +00:00
CHECK ( LZ4F_isError ( result ) , " Allocation failed (error %i) " , ( int ) result ) ;
2014-09-22 17:42:00 +00:00
srcBuffer = malloc ( srcDataLength ) ;
2014-09-07 11:57:09 +00:00
CHECK ( srcBuffer = = NULL , " srcBuffer Allocation failed " ) ;
2016-11-11 23:11:56 +00:00
compressedBuffer = malloc ( compressedBufferSize ) ;
2014-09-07 11:57:09 +00:00
CHECK ( compressedBuffer = = NULL , " compressedBuffer Allocation failed " ) ;
2015-03-15 00:42:27 +00:00
decodedBuffer = calloc ( 1 , srcDataLength ) ; /* calloc avoids decodedBuffer being considered "garbage" by scan-build */
2014-09-07 11:57:09 +00:00
CHECK ( decodedBuffer = = NULL , " decodedBuffer Allocation failed " ) ;
2014-09-22 17:42:00 +00:00
FUZ_fillCompressibleNoiseBuffer ( srcBuffer , srcDataLength , compressibility , & coreRand ) ;
2014-09-07 11:12:46 +00:00
2015-03-15 00:42:27 +00:00
/* jump to requested testNb */
2016-11-11 23:11:56 +00:00
for ( testNb = 0 ; ( testNb < startTest ) ; testNb + + ) ( void ) FUZ_rand ( & coreRand ) ; /* sync randomizer */
2014-09-05 15:32:04 +00:00
2015-03-15 00:42:27 +00:00
/* main fuzzer test loop */
2016-09-03 04:46:02 +00:00
for ( ; ( testNb < nbTests ) | | ( clockDuration > FUZ_GetClockSpan ( startClock ) ) ; testNb + + ) {
2014-09-07 11:12:46 +00:00
U32 randState = coreRand ^ prime1 ;
2016-11-14 15:10:31 +00:00
unsigned const srcBits = ( FUZ_rand ( & randState ) % ( FUZ_highbit ( ( U32 ) ( srcDataLength - 1 ) ) - 1 ) ) + 1 ;
2016-11-11 23:11:56 +00:00
size_t const srcSize = ( FUZ_rand ( & randState ) & ( ( 1 < < srcBits ) - 1 ) ) + 1 ;
size_t const srcStartId = FUZ_rand ( & randState ) % ( srcDataLength - srcSize ) ;
const BYTE * const srcStart = ( const BYTE * ) srcBuffer + srcStartId ;
unsigned const neverFlush = ( FUZ_rand ( & randState ) & 15 ) = = 1 ;
U64 const crcOrig = XXH64 ( srcStart , srcSize , 1 ) ;
2015-03-10 15:57:42 +00:00
LZ4F_preferences_t prefs ;
2016-11-11 23:11:56 +00:00
const LZ4F_preferences_t * prefsPtr = & prefs ;
2014-09-07 08:13:02 +00:00
size_t cSize ;
2014-09-06 11:19:26 +00:00
2015-03-16 16:52:14 +00:00
( void ) FUZ_rand ( & coreRand ) ; /* update seed */
2015-03-10 15:57:42 +00:00
memset ( & prefs , 0 , sizeof ( prefs ) ) ;
2016-11-11 23:11:56 +00:00
prefs . frameInfo . blockMode = ( LZ4F_blockMode_t ) ( FUZ_rand ( & randState ) & 1 ) ;
prefs . frameInfo . blockSizeID = ( LZ4F_blockSizeID_t ) ( 4 + ( FUZ_rand ( & randState ) & 3 ) ) ;
prefs . frameInfo . contentChecksumFlag = ( LZ4F_contentChecksum_t ) ( FUZ_rand ( & randState ) & 1 ) ;
prefs . frameInfo . contentSize = ( ( FUZ_rand ( & randState ) & 0xF ) = = 1 ) ? srcSize : 0 ;
prefs . autoFlush = neverFlush ? 0 : ( FUZ_rand ( & randState ) & 7 ) = = 2 ;
2014-10-27 23:39:06 +00:00
prefs . compressionLevel = FUZ_rand ( & randState ) % 5 ;
2015-03-16 16:52:14 +00:00
if ( ( FUZ_rand ( & randState ) & 0xF ) = = 1 ) prefsPtr = NULL ;
2014-09-13 09:08:55 +00:00
2014-09-22 17:42:00 +00:00
DISPLAYUPDATE ( 2 , " \r %5u " , testNb ) ;
2014-09-07 08:13:02 +00:00
2016-06-30 11:44:58 +00:00
if ( ( FUZ_rand ( & randState ) & 0xFFF ) = = 0 ) {
2015-03-16 16:52:14 +00:00
/* create a skippable frame (rare case) */
BYTE * op = ( BYTE * ) compressedBuffer ;
FUZ_writeLE32 ( op , LZ4F_MAGIC_SKIPPABLE_START + ( FUZ_rand ( & randState ) & 15 ) ) ;
2015-03-31 12:17:38 +00:00
FUZ_writeLE32 ( op + 4 , ( U32 ) srcSize ) ;
2015-03-16 16:52:14 +00:00
cSize = srcSize + 8 ;
2016-11-11 23:11:56 +00:00
} else if ( ( FUZ_rand ( & randState ) & 0xF ) = = 2 ) { /* single pass compression (simple) */
cSize = LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( srcSize , prefsPtr ) , srcStart , srcSize , prefsPtr ) ;
2014-09-22 01:59:42 +00:00
CHECK ( LZ4F_isError ( cSize ) , " LZ4F_compressFrame failed : error %i (%s) " , ( int ) cSize , LZ4F_getErrorName ( cSize ) ) ;
2016-11-11 23:11:56 +00:00
} else { /* multi-segments compression */
const BYTE * ip = srcStart ;
const BYTE * const iend = srcStart + srcSize ;
2014-10-27 23:39:06 +00:00
BYTE * op = ( BYTE * ) compressedBuffer ;
2016-11-11 23:11:56 +00:00
BYTE * const oend = op + ( neverFlush ? LZ4F_compressFrameBound ( srcSize , prefsPtr ) : compressedBufferSize ) ; /* when flushes are possible, can't guarantee a max compressed size */
unsigned const maxBits = FUZ_highbit ( ( U32 ) srcSize ) ;
LZ4F_compressOptions_t cOptions ;
memset ( & cOptions , 0 , sizeof ( cOptions ) ) ;
2014-10-05 23:48:45 +00:00
result = LZ4F_compressBegin ( cCtx , op , oend - op , prefsPtr ) ;
2014-09-07 08:13:02 +00:00
CHECK ( LZ4F_isError ( result ) , " Compression header failed (error %i) " , ( int ) result ) ;
op + = result ;
2016-06-30 11:44:58 +00:00
while ( ip < iend ) {
2016-11-11 23:11:56 +00:00
unsigned const nbBitsSeg = FUZ_rand ( & randState ) % maxBits ;
size_t const sampleMax = ( FUZ_rand ( & randState ) & ( ( 1 < < nbBitsSeg ) - 1 ) ) + 1 ;
size_t const iSize = MIN ( sampleMax , ( size_t ) ( iend - ip ) ) ;
size_t const oSize = LZ4F_compressBound ( iSize , prefsPtr ) ;
2014-09-22 17:42:00 +00:00
cOptions . stableSrc = ( ( FUZ_rand ( & randState ) & 3 ) = = 1 ) ;
2014-09-13 09:08:55 +00:00
2014-09-14 23:59:30 +00:00
result = LZ4F_compressUpdate ( cCtx , op , oSize , ip , iSize , & cOptions ) ;
2016-11-11 23:11:56 +00:00
CHECK ( LZ4F_isError ( result ) , " Compression failed (error %i : %s) " , ( int ) result , LZ4F_getErrorName ( result ) ) ;
2014-09-07 08:13:02 +00:00
op + = result ;
ip + = iSize ;
2014-09-13 09:08:55 +00:00
2016-11-11 23:11:56 +00:00
{ unsigned const forceFlush = neverFlush ? 0 : ( ( FUZ_rand ( & randState ) & 3 ) = = 1 ) ;
if ( forceFlush ) {
result = LZ4F_flush ( cCtx , op , oend - op , & cOptions ) ;
CHECK ( LZ4F_isError ( result ) , " Compression failed (error %i) " , ( int ) result ) ;
op + = result ;
} }
2014-09-07 08:13:02 +00:00
}
2016-11-11 23:11:56 +00:00
CHECK ( op > = oend , " LZ4F_compressFrameBound overflow " ) ;
2014-09-14 23:59:30 +00:00
result = LZ4F_compressEnd ( cCtx , op , oend - op , & cOptions ) ;
2016-11-11 23:11:56 +00:00
CHECK ( LZ4F_isError ( result ) , " Compression completion failed (error %i : %s) " , ( int ) result , LZ4F_getErrorName ( result ) ) ;
2014-09-07 08:13:02 +00:00
op + = result ;
2014-09-07 10:04:29 +00:00
cSize = op - ( BYTE * ) compressedBuffer ;
2016-11-11 23:11:56 +00:00
DISPLAYLEVEL ( 5 , " \n Compressed %u bytes into %u \n " , ( U32 ) srcSize , ( U32 ) cSize ) ;
2014-09-07 08:13:02 +00:00
}
2014-09-06 21:48:03 +00:00
2016-11-11 23:11:56 +00:00
/* multi-segments decompression */
2016-08-11 12:44:53 +00:00
{ const BYTE * ip = ( const BYTE * ) compressedBuffer ;
2014-09-06 21:48:03 +00:00
const BYTE * const iend = ip + cSize ;
2014-10-27 23:39:06 +00:00
BYTE * op = ( BYTE * ) decodedBuffer ;
2014-09-06 21:48:03 +00:00
BYTE * const oend = op + srcDataLength ;
2016-11-11 23:11:56 +00:00
unsigned const suggestedBits = FUZ_highbit ( ( U32 ) cSize ) ;
unsigned const maxBits = MAX ( 3 , suggestedBits ) ;
unsigned const nonContiguousDst = FUZ_rand ( & randState ) % 3 ; /* 0 : contiguous; 1 : non-contiguous; 2 : dst overwritten */
2015-03-16 16:52:14 +00:00
size_t totalOut = 0 ;
2016-11-11 23:11:56 +00:00
XXH64_state_t xxh64 ;
2014-10-05 23:48:45 +00:00
XXH64_reset ( & xxh64 , 1 ) ;
2016-06-30 11:44:58 +00:00
while ( ip < iend ) {
2016-09-05 13:49:55 +00:00
unsigned const nbBitsI = ( FUZ_rand ( & randState ) % ( maxBits - 1 ) ) + 1 ;
unsigned const nbBitsO = ( FUZ_rand ( & randState ) % ( maxBits ) ) + 1 ;
2016-11-11 23:11:56 +00:00
size_t const iSizeMax = ( FUZ_rand ( & randState ) & ( ( 1 < < nbBitsI ) - 1 ) ) + 1 ;
size_t iSize = MIN ( iSizeMax , ( size_t ) ( iend - ip ) ) ;
size_t const oSizeMax = ( FUZ_rand ( & randState ) & ( ( 1 < < nbBitsO ) - 1 ) ) + 2 ;
size_t oSize = MIN ( oSizeMax , ( size_t ) ( oend - op ) ) ;
LZ4F_decompressOptions_t dOptions ;
memset ( & dOptions , 0 , sizeof ( dOptions ) ) ;
2014-09-14 23:59:30 +00:00
dOptions . stableDst = FUZ_rand ( & randState ) & 1 ;
2016-11-11 23:11:56 +00:00
if ( nonContiguousDst = = 2 ) dOptions . stableDst = 0 ; /* overwrite mode */
2014-09-14 23:59:30 +00:00
result = LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , & dOptions ) ;
2016-11-11 23:11:56 +00:00
if ( LZ4F_getErrorCode ( result ) = = LZ4F_ERROR_contentChecksum_invalid ) locateBuffDiff ( srcStart , decodedBuffer , srcSize , nonContiguousDst ) ;
CHECK ( LZ4F_isError ( result ) , " Decompression failed (error %i:%s) " , ( int ) result , LZ4F_getErrorName ( result ) ) ;
2014-09-21 08:56:21 +00:00
XXH64_update ( & xxh64 , op , ( U32 ) oSize ) ;
2015-03-16 16:52:14 +00:00
totalOut + = oSize ;
2014-09-06 21:48:03 +00:00
op + = oSize ;
ip + = iSize ;
2014-09-21 08:56:21 +00:00
op + = nonContiguousDst ;
2015-03-10 15:57:42 +00:00
if ( nonContiguousDst = = 2 ) op = ( BYTE * ) decodedBuffer ; /* overwritten destination */
2014-09-06 21:48:03 +00:00
}
2014-09-13 11:15:54 +00:00
CHECK ( result ! = 0 , " Frame decompression failed (error %i) " , ( int ) result ) ;
2016-06-30 11:44:58 +00:00
if ( totalOut ) { /* otherwise, it's a skippable frame */
2016-09-05 13:49:55 +00:00
U64 const crcDecoded = XXH64_digest ( & xxh64 ) ;
2016-11-11 23:11:56 +00:00
if ( crcDecoded ! = crcOrig ) locateBuffDiff ( srcStart , decodedBuffer , srcSize , nonContiguousDst ) ;
2015-03-16 16:52:14 +00:00
CHECK ( crcDecoded ! = crcOrig , " Decompression corruption " ) ;
}
2014-09-06 21:48:03 +00:00
}
2014-09-05 15:32:04 +00:00
}
2014-09-22 17:42:00 +00:00
DISPLAYLEVEL ( 2 , " \r All tests completed \n " ) ;
2014-09-05 15:32:04 +00:00
_end :
2014-09-06 12:06:28 +00:00
LZ4F_freeDecompressionContext ( dCtx ) ;
2014-09-07 11:57:09 +00:00
LZ4F_freeCompressionContext ( cCtx ) ;
2014-09-22 17:42:00 +00:00
free ( srcBuffer ) ;
free ( compressedBuffer ) ;
free ( decodedBuffer ) ;
2014-09-21 08:56:21 +00:00
2016-06-30 11:44:58 +00:00
if ( pause ) {
2014-09-21 08:56:21 +00:00
DISPLAY ( " press enter to finish \n " ) ;
2015-04-12 07:21:35 +00:00
( void ) getchar ( ) ;
2014-09-21 08:56:21 +00:00
}
2014-09-22 17:42:00 +00:00
return testResult ;
2014-09-05 15:32:04 +00:00
_output_error :
2014-09-22 17:42:00 +00:00
testResult = 1 ;
goto _end ;
2014-09-05 15:32:04 +00:00
}
2016-11-11 23:11:56 +00:00
int FUZ_usage ( const char * programName )
2014-08-30 17:14:44 +00:00
{
DISPLAY ( " Usage : \n " ) ;
DISPLAY ( " %s [args] \n " , programName ) ;
DISPLAY ( " \n " ) ;
DISPLAY ( " Arguments : \n " ) ;
2014-09-22 17:42:00 +00:00
DISPLAY ( " -i# : Nb of tests (default:%u) \n " , nbTestsDefault ) ;
2015-04-12 15:40:58 +00:00
DISPLAY ( " -T# : Duration of tests, in seconds (default: use Nb of tests) \n " ) ;
2014-08-30 17:14:44 +00:00
DISPLAY ( " -s# : Select seed (default:prompt user) \n " ) ;
DISPLAY ( " -t# : Select starting test number (default:0) \n " ) ;
2016-11-11 23:11:56 +00:00
DISPLAY ( " -P# : Select compressibility in %% (default:%i%%) \n " , FUZ_COMPRESSIBILITY_DEFAULT ) ;
2014-08-30 17:14:44 +00:00
DISPLAY ( " -v : verbose \n " ) ;
DISPLAY ( " -h : display help and exit \n " ) ;
return 0 ;
}
2016-11-11 23:11:56 +00:00
int main ( int argc , const char * * argv )
2014-09-01 21:44:02 +00:00
{
2014-08-30 17:14:44 +00:00
U32 seed = 0 ;
int seedset = 0 ;
int argNb ;
2014-09-07 08:13:02 +00:00
int nbTests = nbTestsDefault ;
2014-08-30 17:14:44 +00:00
int testNb = 0 ;
int proba = FUZ_COMPRESSIBILITY_DEFAULT ;
2014-09-11 21:27:14 +00:00
int result = 0 ;
2015-04-10 22:42:17 +00:00
U32 duration = 0 ;
2016-11-11 23:11:56 +00:00
const char * const programName = argv [ 0 ] ;
2014-08-30 17:14:44 +00:00
2015-03-29 12:28:32 +00:00
/* Check command line */
2016-11-11 23:11:56 +00:00
for ( argNb = 1 ; argNb < argc ; argNb + + ) {
const char * argument = argv [ argNb ] ;
2014-08-30 17:14:44 +00:00
2015-04-10 22:42:17 +00:00
if ( ! argument ) continue ; /* Protection if argument empty */
2014-08-30 17:14:44 +00:00
2016-11-11 23:11:56 +00:00
/* Decode command (note : aggregated short commands are allowed) */
2016-06-30 11:44:58 +00:00
if ( argument [ 0 ] = = ' - ' ) {
if ( ! strcmp ( argument , " --no-prompt " ) ) {
2014-09-22 17:42:00 +00:00
no_prompt = 1 ;
seedset = 1 ;
displayLevel = 1 ;
continue ;
}
2014-09-21 08:56:21 +00:00
argument + + ;
2014-08-30 17:14:44 +00:00
2016-06-30 11:44:58 +00:00
while ( * argument ! = 0 ) {
2014-08-30 17:14:44 +00:00
switch ( * argument )
{
case ' h ' :
2016-11-11 23:11:56 +00:00
return FUZ_usage ( programName ) ;
2014-08-30 17:14:44 +00:00
case ' v ' :
argument + + ;
2016-11-11 23:11:56 +00:00
displayLevel + + ;
2014-08-30 17:14:44 +00:00
break ;
2014-09-05 15:32:04 +00:00
case ' q ' :
argument + + ;
displayLevel - - ;
break ;
2014-10-21 23:36:32 +00:00
case ' p ' : /* pause at the end */
argument + + ;
pause = 1 ;
break ;
2014-10-27 23:39:06 +00:00
case ' i ' :
2014-08-30 17:14:44 +00:00
argument + + ;
2015-04-10 22:42:17 +00:00
nbTests = 0 ; duration = 0 ;
2016-06-30 11:44:58 +00:00
while ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2014-08-30 17:14:44 +00:00
nbTests * = 10 ;
nbTests + = * argument - ' 0 ' ;
argument + + ;
}
break ;
2015-04-10 22:42:17 +00:00
case ' T ' :
argument + + ;
nbTests = 0 ; duration = 0 ;
2016-06-30 11:44:58 +00:00
for ( ; ; ) {
2015-04-12 15:40:58 +00:00
switch ( * argument )
2015-04-10 22:42:17 +00:00
{
2015-04-12 15:40:58 +00:00
case ' m ' : duration * = 60 ; argument + + ; continue ;
case ' s ' :
case ' n ' : argument + + ; continue ;
case ' 0 ' :
case ' 1 ' :
case ' 2 ' :
case ' 3 ' :
case ' 4 ' :
case ' 5 ' :
case ' 6 ' :
case ' 7 ' :
case ' 8 ' :
case ' 9 ' : duration * = 10 ; duration + = * argument + + - ' 0 ' ; continue ;
2015-04-10 22:42:17 +00:00
}
break ;
}
break ;
2014-08-30 17:14:44 +00:00
case ' s ' :
argument + + ;
2014-09-22 17:42:00 +00:00
seed = 0 ;
seedset = 1 ;
2016-06-30 11:44:58 +00:00
while ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2014-08-30 17:14:44 +00:00
seed * = 10 ;
seed + = * argument - ' 0 ' ;
argument + + ;
}
break ;
case ' t ' :
argument + + ;
testNb = 0 ;
2016-06-30 11:44:58 +00:00
while ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2014-08-30 17:14:44 +00:00
testNb * = 10 ;
testNb + = * argument - ' 0 ' ;
argument + + ;
}
break ;
2014-10-21 23:36:32 +00:00
case ' P ' : /* compressibility % */
2014-08-30 17:14:44 +00:00
argument + + ;
proba = 0 ;
2016-06-30 11:44:58 +00:00
while ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2014-08-30 17:14:44 +00:00
proba * = 10 ;
proba + = * argument - ' 0 ' ;
argument + + ;
}
if ( proba < 0 ) proba = 0 ;
if ( proba > 100 ) proba = 100 ;
break ;
2014-09-22 17:42:00 +00:00
default :
;
2016-11-11 23:11:56 +00:00
return FUZ_usage ( programName ) ;
2014-08-30 17:14:44 +00:00
}
}
}
}
2015-03-29 12:28:32 +00:00
/* Get Seed */
2016-11-11 23:11:56 +00:00
DISPLAY ( " Starting lz4frame tester (%i-bits, %s) \n " , ( int ) ( sizeof ( size_t ) * 8 ) , LZ4_VERSION_STRING ) ;
2014-08-30 17:14:44 +00:00
2016-09-03 04:46:02 +00:00
if ( ! seedset ) {
time_t const t = time ( NULL ) ;
U32 const h = XXH32 ( & t , sizeof ( t ) , 1 ) ;
seed = h % 10000 ;
}
2016-11-11 23:11:56 +00:00
DISPLAY ( " Seed = %u \n " , seed ) ;
if ( proba ! = FUZ_COMPRESSIBILITY_DEFAULT ) DISPLAY ( " Compressibility : %i%% \n " , proba ) ;
2014-08-30 17:14:44 +00:00
if ( nbTests < = 0 ) nbTests = 1 ;
2014-11-29 19:19:39 +00:00
if ( testNb = = 0 ) result = basicTests ( seed , ( ( double ) proba ) / 100 ) ;
2014-09-09 22:54:22 +00:00
if ( result ) return 1 ;
2015-04-10 22:42:17 +00:00
return fuzzerTests ( seed , nbTests , testNb , ( ( double ) proba ) / 100 , duration ) ;
2014-08-30 17:14:44 +00:00
}