2014-08-30 17:14:44 +00:00
/*
frameTest - test tool for lz4frame
2020-11-25 22:45:14 +00:00
Copyright ( C ) Yann Collet 2014 - 2020
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 */
2020-11-15 00:24:36 +00:00
# pragma warning(disable : 26451) /* disable: Arithmetic overflow */
2014-08-30 17:14:44 +00:00
# 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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-12-21 08:44:59 +00:00
# include "util.h" /* U32 */
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 */
2017-05-10 23:28:36 +00:00
# include <assert.h>
2019-06-30 20:59:49 +00:00
# include "lz4frame.h" /* included multiple times to test correctness/safety */
2018-04-24 22:50:03 +00:00
# include "lz4frame.h"
2018-04-21 00:55:38 +00:00
# define LZ4F_STATIC_LINKING_ONLY
# include "lz4frame.h"
2018-04-24 22:50:03 +00:00
# include "lz4frame.h"
2019-07-15 19:11:34 +00:00
# define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */
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
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 ;
2019-04-15 17:44:46 +00:00
dstPtr [ 0 ] = ( BYTE ) value32 ;
2015-03-16 16:52:14 +00:00
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-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 ;
2016-12-21 09:22:40 +00:00
static U32 use_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 ) ;
2019-06-30 20:59:49 +00:00
} }
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 ;
2018-12-02 13:39:47 +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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-04-18 19:05:50 +00:00
# define CHECK_V(v,f) v = f; if (LZ4F_isError(v)) { fprintf(stderr, "%s \n", LZ4F_getErrorName(v)); goto _output_error; }
2017-08-09 00:43:11 +00:00
# define CHECK(f) { LZ4F_errorCode_t const CHECK_V(err_ , f); }
2014-09-11 21:27:14 +00:00
int basicTests ( U32 seed , double compressibility )
2014-08-30 17:14:44 +00:00
{
2017-05-10 23:28:36 +00:00
# define COMPRESSIBLE_NOISE_LENGTH (2 MB)
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 ;
2017-05-10 23:28:36 +00:00
int basicTests_error = 0 ;
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 ) ) ;
2017-05-10 23:28:36 +00:00
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-12-21 13:18:01 +00:00
/* LZ4F_compressBound() : special case : srcSize == 0 */
DISPLAYLEVEL ( 3 , " LZ4F_compressBound(0) = " ) ;
{ size_t const cBound = LZ4F_compressBound ( 0 , NULL ) ;
if ( cBound < 64 KB ) goto _output_error ;
DISPLAYLEVEL ( 3 , " %u \n " , ( U32 ) cBound ) ;
}
2020-05-14 03:01:43 +00:00
/* LZ4F_compressBound() : special case : automatic flushing enabled */
DISPLAYLEVEL ( 3 , " LZ4F_compressBound(1 KB, autoFlush=1) = " ) ;
{ size_t cBound ;
LZ4F_preferences_t autoFlushPrefs ;
memset ( & autoFlushPrefs , 0 , sizeof ( autoFlushPrefs ) ) ;
autoFlushPrefs . autoFlush = 1 ;
cBound = LZ4F_compressBound ( 1 KB , & autoFlushPrefs ) ;
if ( cBound > 64 KB ) goto _output_error ;
DISPLAYLEVEL ( 3 , " %u \n " , ( U32 ) cBound ) ;
}
/* LZ4F_compressBound() : special case : automatic flushing disabled */
DISPLAYLEVEL ( 3 , " LZ4F_compressBound(1 KB, autoFlush=0) = " ) ;
{ size_t const cBound = LZ4F_compressBound ( 1 KB , & prefs ) ;
if ( cBound < 64 KB ) goto _output_error ;
DISPLAYLEVEL ( 3 , " %u \n " , ( U32 ) cBound ) ;
}
2016-08-11 12:44:53 +00:00
/* Special case : null-content frame */
testSize = 0 ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame, compress null content : " ) ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , NULL ) , CNBuffer , testSize , NULL ) ) ;
2017-05-10 23:28:36 +00:00
DISPLAYLEVEL ( 3 , " null content encoded into a %u bytes frame \n " , ( unsigned ) cSize ) ;
2016-08-11 12:44:53 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_createDecompressionContext \n " ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ) ;
2016-08-11 12:44:53 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_getFrameInfo on null-content frame (#157) \n " ) ;
2019-04-10 01:10:02 +00:00
assert ( cSize > = LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH ) ;
{ LZ4F_frameInfo_t frame_info ;
size_t const fhs = LZ4F_headerSize ( compressedBuffer , LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH ) ;
size_t avail_in = fhs ;
CHECK ( fhs ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_getFrameInfo ( dCtx , & frame_info , compressedBuffer , & avail_in ) ) ;
2019-04-10 01:10:02 +00:00
if ( avail_in ! = fhs ) goto _output_error ; /* must consume all, since header size is supposed to be exact */
2016-08-11 12:44:53 +00:00
}
DISPLAYLEVEL ( 3 , " LZ4F_freeDecompressionContext \n " ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_freeDecompressionContext ( dCtx ) ) ;
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 ;
2017-04-09 08:41:36 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame, using fast level -3 : " ) ;
{ LZ4F_preferences_t fastCompressPrefs ;
memset ( & fastCompressPrefs , 0 , sizeof ( fastCompressPrefs ) ) ;
fastCompressPrefs . compressionLevel = - 3 ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , NULL ) , CNBuffer , testSize , & fastCompressPrefs ) ) ;
2017-04-09 08:41:36 +00:00
DISPLAYLEVEL ( 3 , " Compressed %u bytes into a %u bytes frame \n " , ( U32 ) testSize , ( U32 ) cSize ) ;
}
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame, using default preferences : " ) ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , NULL ) , CNBuffer , testSize , NULL ) ) ;
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-05 15:32:04 +00:00
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ) ;
2014-09-04 21:56:51 +00:00
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " Single Pass decompression : " ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_decompress ( dCtx , decodedBuffer , & decodedBufferSize , compressedBuffer , & compressedBufferSize , NULL ) ) ;
2017-03-29 00:36:12 +00:00
{ U64 const crcDest = XXH64 ( decodedBuffer , decodedBufferSize , 1 ) ;
2016-11-11 23:11:56 +00:00
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 ) ;
2017-08-09 00:43:11 +00:00
CHECK_V ( decResult , LZ4F_decompress ( dCtx , op , & oSize , cBuff , & iSize , NULL ) ) ;
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 ; }
2019-04-05 18:47:06 +00:00
{ U64 const crcDest = XXH64 ( decodedBuffer , ( size_t ) ( op - ostart ) , 1 ) ;
2016-11-11 23:11:56 +00:00
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 ;
2017-05-10 23:28:36 +00:00
const BYTE * ip = ( BYTE * ) compressedBuffer ;
2015-04-19 14:23:53 +00:00
DISPLAYLEVEL ( 3 , " Start by feeding 0 bytes, to get next input size : " ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_decompress ( dCtx , NULL , & oSize , ip , & iSize , NULL ) ) ;
//DISPLAYLEVEL(3, " %u \n", (unsigned)errorCode);
DISPLAYLEVEL ( 3 , " OK \n " ) ;
2015-04-19 14:23:53 +00:00
2017-03-29 00:10:01 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_getFrameInfo on zero-size input : " ) ;
{ size_t nullSize = 0 ;
size_t const fiError = LZ4F_getFrameInfo ( dCtx , & fi , ip , & nullSize ) ;
if ( LZ4F_getErrorCode ( fiError ) ! = LZ4F_ERROR_frameHeader_incomplete ) {
2017-05-10 21:51:09 +00:00
DISPLAYLEVEL ( 3 , " incorrect error : %s != ERROR_frameHeader_incomplete \n " ,
LZ4F_getErrorName ( fiError ) ) ;
2017-03-29 00:10:01 +00:00
goto _output_error ;
}
DISPLAYLEVEL ( 3 , " correctly failed : %s \n " , LZ4F_getErrorName ( fiError ) ) ;
}
2015-04-19 14:23:53 +00:00
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_getFrameInfo on not enough input : " ) ;
2017-03-29 00:10:01 +00:00
{ size_t inputSize = 6 ;
size_t const fiError = LZ4F_getFrameInfo ( dCtx , & fi , ip , & inputSize ) ;
if ( LZ4F_getErrorCode ( fiError ) ! = LZ4F_ERROR_frameHeader_incomplete ) {
DISPLAYLEVEL ( 3 , " incorrect error : %s != ERROR_frameHeader_incomplete \n " , LZ4F_getErrorName ( fiError ) ) ;
goto _output_error ;
}
DISPLAYLEVEL ( 3 , " correctly failed : %s \n " , LZ4F_getErrorName ( fiError ) ) ;
}
2015-04-19 14:23:53 +00:00
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_getFrameInfo on enough input : " ) ;
2019-04-10 01:10:02 +00:00
iSize = LZ4F_headerSize ( ip , LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH ) ;
CHECK ( iSize ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_getFrameInfo ( dCtx , & fi , ip , & iSize ) ) ;
2015-04-19 14:23:53 +00:00
DISPLAYLEVEL ( 3 , " correctly decoded \n " ) ;
}
2017-05-10 23:28:36 +00:00
DISPLAYLEVEL ( 3 , " Decode a buggy input : " ) ;
assert ( COMPRESSIBLE_NOISE_LENGTH > 64 ) ;
assert ( cSize > 48 ) ;
memcpy ( decodedBuffer , ( char * ) compressedBuffer + 16 , 32 ) ; /* save correct data */
memcpy ( ( char * ) compressedBuffer + 16 , ( const char * ) decodedBuffer + 32 , 32 ) ; /* insert noise */
{ size_t dbSize = COMPRESSIBLE_NOISE_LENGTH ;
size_t cbSize = cSize ;
size_t const decompressError = LZ4F_decompress ( dCtx , decodedBuffer , & dbSize ,
compressedBuffer , & cbSize ,
NULL ) ;
if ( ! LZ4F_isError ( decompressError ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " error detected : %s \n " , LZ4F_getErrorName ( decompressError ) ) ;
}
memcpy ( ( char * ) compressedBuffer + 16 , decodedBuffer , 32 ) ; /* restore correct data */
DISPLAYLEVEL ( 3 , " Reset decompression context, since it's left in error state \n " ) ;
LZ4F_resetDecompressionContext ( dCtx ) ; /* always successful */
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " Byte after byte : " ) ;
2016-11-11 23:11:56 +00:00
{ BYTE * const ostart = ( BYTE * ) decodedBuffer ;
BYTE * op = ostart ;
BYTE * const oend = ( BYTE * ) decodedBuffer + COMPRESSIBLE_NOISE_LENGTH ;
2017-05-11 00:06:31 +00:00
const BYTE * ip = ( const BYTE * ) compressedBuffer ;
2017-05-10 23:28:36 +00:00
const BYTE * const iend = ip + cSize ;
2016-11-11 23:11:56 +00:00
while ( ip < iend ) {
2019-04-05 18:47:06 +00:00
size_t oSize = ( size_t ) ( oend - op ) ;
2016-11-11 23:11:56 +00:00
size_t iSize = 1 ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ) ;
2016-11-11 23:11:56 +00:00
op + = oSize ;
ip + = iSize ;
}
2018-09-19 01:08:59 +00:00
{ 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 ) , ( unsigned ) COMPRESSIBLE_NOISE_LENGTH ) ;
2017-05-10 23:28:36 +00:00
}
2014-09-22 17:42:00 +00:00
}
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " Using 64 KB block : " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . blockSizeID = LZ4F_max64KB ;
prefs . frameInfo . contentChecksumFlag = LZ4F_contentChecksumEnabled ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , & prefs ) , CNBuffer , testSize , & prefs ) ) ;
2014-09-22 17:42:00 +00:00
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) cSize ) ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " without checksum : " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . contentChecksumFlag = LZ4F_noContentChecksum ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , & prefs ) , CNBuffer , testSize , & prefs ) ) ;
2014-09-22 17:42:00 +00:00
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) cSize ) ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " Using 256 KB block : " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . blockSizeID = LZ4F_max256KB ;
prefs . frameInfo . contentChecksumFlag = LZ4F_contentChecksumEnabled ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , & prefs ) , CNBuffer , testSize , & prefs ) ) ;
2014-09-22 17:42:00 +00:00
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
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " random segment sizes : " ) ;
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 ;
2019-04-05 18:47:06 +00:00
size_t oSize = ( size_t ) ( oend - op ) ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = ( size_t ) ( iend - ip ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ) ;
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
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_freeDecompressionContext ( dCtx ) ) ;
2016-11-11 23:11:56 +00:00
dCtx = NULL ;
2014-09-22 17:42:00 +00:00
}
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " without checksum : " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . contentChecksumFlag = LZ4F_noContentChecksum ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , & prefs ) , CNBuffer , testSize , & prefs ) ) ;
2014-09-22 17:42:00 +00:00
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) cSize ) ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " Using 1 MB block : " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . blockSizeID = LZ4F_max1MB ;
prefs . frameInfo . contentChecksumFlag = LZ4F_contentChecksumEnabled ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , & prefs ) , CNBuffer , testSize , & prefs ) ) ;
2014-09-22 17:42:00 +00:00
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) cSize ) ;
2017-08-12 00:46:52 +00:00
DISPLAYLEVEL ( 3 , " without frame checksum : " ) ;
2015-04-14 18:00:36 +00:00
prefs . frameInfo . contentChecksumFlag = LZ4F_noContentChecksum ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , & prefs ) , CNBuffer , testSize , & prefs ) ) ;
2014-09-22 17:42:00 +00:00
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) cSize ) ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " Using 4 MB block : " ) ;
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 ) ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 4 , " dstCapacity = %u ; " , ( U32 ) dstCapacity )
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , dstCapacity , CNBuffer , testSize , & prefs ) ) ;
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
2017-08-12 00:46:52 +00:00
DISPLAYLEVEL ( 3 , " without frame checksum : " ) ;
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 ) ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 4 , " dstCapacity = %u ; " , ( U32 ) dstCapacity )
2017-08-09 00:43:11 +00:00
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , dstCapacity , CNBuffer , testSize , & prefs ) ) ;
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
2017-08-12 00:46:52 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame with block checksum : " ) ;
memset ( & prefs , 0 , sizeof ( prefs ) ) ;
prefs . frameInfo . blockChecksumFlag = LZ4F_blockChecksumEnabled ;
CHECK_V ( cSize , LZ4F_compressFrame ( compressedBuffer , LZ4F_compressFrameBound ( testSize , & prefs ) , CNBuffer , testSize , & prefs ) ) ;
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) cSize ) ;
DISPLAYLEVEL ( 3 , " Decompress with block checksum : " ) ;
{ size_t iSize = cSize ;
size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH ;
LZ4F_decompressionContext_t dctx ;
CHECK ( LZ4F_createDecompressionContext ( & dctx , LZ4F_VERSION ) ) ;
CHECK ( LZ4F_decompress ( dctx , decodedBuffer , & decodedSize , compressedBuffer , & iSize , NULL ) ) ;
if ( decodedSize ! = testSize ) goto _output_error ;
if ( iSize ! = cSize ) goto _output_error ;
{ U64 const crcDest = XXH64 ( decodedBuffer , decodedSize , 1 ) ;
U64 const crcSrc = XXH64 ( CNBuffer , testSize , 1 ) ;
if ( crcDest ! = crcSrc ) goto _output_error ;
}
DISPLAYLEVEL ( 3 , " Regenerated %u bytes \n " , ( U32 ) decodedSize ) ;
CHECK ( LZ4F_freeDecompressionContext ( dctx ) ) ;
}
2017-08-09 00:43:11 +00:00
/* frame content size tests */
{ size_t cErr ;
2015-03-18 20:38:27 +00:00
BYTE * const ostart = ( BYTE * ) compressedBuffer ;
BYTE * op = ostart ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_createCompressionContext ( & cctx , LZ4F_VERSION ) ) ;
2015-03-18 20:38:27 +00:00
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " compress without frameSize : " ) ;
2015-03-18 20:38:27 +00:00
memset ( & ( prefs . frameInfo ) , 0 , sizeof ( prefs . frameInfo ) ) ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cErr , LZ4F_compressBegin ( cctx , compressedBuffer , testSize , & prefs ) ) ;
op + = cErr ;
CHECK_V ( cErr , LZ4F_compressUpdate ( cctx , op , LZ4F_compressBound ( testSize , & prefs ) , CNBuffer , testSize , NULL ) ) ;
op + = cErr ;
CHECK ( LZ4F_compressEnd ( cctx , compressedBuffer , testSize , NULL ) ) ;
2015-03-18 20:38:27 +00:00
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) ( op - ostart ) ) ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " compress with frameSize : " ) ;
2015-03-29 10:20:09 +00:00
prefs . frameInfo . contentSize = testSize ;
2015-03-18 20:38:27 +00:00
op = ostart ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cErr , LZ4F_compressBegin ( cctx , compressedBuffer , testSize , & prefs ) ) ;
op + = cErr ;
CHECK_V ( cErr , LZ4F_compressUpdate ( cctx , op , LZ4F_compressBound ( testSize , & prefs ) , CNBuffer , testSize , NULL ) ) ;
op + = cErr ;
CHECK ( LZ4F_compressEnd ( cctx , compressedBuffer , testSize , NULL ) ) ;
2015-03-18 20:38:27 +00:00
DISPLAYLEVEL ( 3 , " Compressed %i bytes into a %i bytes frame \n " , ( int ) testSize , ( int ) ( op - ostart ) ) ;
2017-03-29 00:36:12 +00:00
DISPLAYLEVEL ( 3 , " compress with wrong frameSize : " ) ;
2015-03-29 10:20:09 +00:00
prefs . frameInfo . contentSize = testSize + 1 ;
2015-03-18 20:38:27 +00:00
op = ostart ;
2017-08-09 00:43:11 +00:00
CHECK_V ( cErr , LZ4F_compressBegin ( cctx , compressedBuffer , testSize , & prefs ) ) ;
op + = cErr ;
CHECK_V ( cErr , LZ4F_compressUpdate ( cctx , op , LZ4F_compressBound ( testSize , & prefs ) , CNBuffer , testSize , NULL ) ) ;
op + = cErr ;
cErr = LZ4F_compressEnd ( cctx , op , testSize , NULL ) ;
if ( ! LZ4F_isError ( cErr ) ) goto _output_error ;
DISPLAYLEVEL ( 3 , " Error correctly detected : %s \n " , LZ4F_getErrorName ( cErr ) ) ;
CHECK ( LZ4F_freeCompressionContext ( cctx ) ) ;
2015-04-12 07:21:35 +00:00
cctx = NULL ;
2015-03-18 20:38:27 +00:00
}
2017-08-09 00:43:11 +00:00
/* dictID tests */
{ size_t cErr ;
U32 const dictID = 0x99 ;
CHECK ( LZ4F_createCompressionContext ( & cctx , LZ4F_VERSION ) ) ;
DISPLAYLEVEL ( 3 , " insert a dictID : " ) ;
memset ( & prefs . frameInfo , 0 , sizeof ( prefs . frameInfo ) ) ;
prefs . frameInfo . dictID = dictID ;
CHECK_V ( cErr , LZ4F_compressBegin ( cctx , compressedBuffer , testSize , & prefs ) ) ;
DISPLAYLEVEL ( 3 , " created frame header of size %i bytes \n " , ( int ) cErr ) ;
DISPLAYLEVEL ( 3 , " read a dictID : " ) ;
CHECK ( LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ) ;
memset ( & prefs . frameInfo , 0 , sizeof ( prefs . frameInfo ) ) ;
CHECK ( LZ4F_getFrameInfo ( dCtx , & prefs . frameInfo , compressedBuffer , & cErr ) ) ;
if ( prefs . frameInfo . dictID ! = dictID ) goto _output_error ;
DISPLAYLEVEL ( 3 , " %u \n " , ( U32 ) prefs . frameInfo . dictID ) ;
CHECK ( LZ4F_freeDecompressionContext ( dCtx ) ) ; dCtx = NULL ;
2017-08-09 23:51:19 +00:00
CHECK ( LZ4F_freeCompressionContext ( cctx ) ) ; cctx = NULL ;
}
/* Dictionary compression test */
{ size_t const dictSize = 63 KB ;
size_t const dstCapacity = LZ4F_compressFrameBound ( dictSize , NULL ) ;
size_t cSizeNoDict , cSizeWithDict ;
LZ4F_CDict * const cdict = LZ4F_createCDict ( CNBuffer , dictSize ) ;
if ( cdict = = NULL ) goto _output_error ;
2018-01-26 16:29:00 +00:00
CHECK ( LZ4F_createCompressionContext ( & cctx , LZ4F_VERSION ) ) ;
2018-09-18 23:52:02 +00:00
2017-08-09 23:51:19 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame_usingCDict, with NULL dict : " ) ;
CHECK_V ( cSizeNoDict ,
2018-01-26 16:29:00 +00:00
LZ4F_compressFrame_usingCDict ( cctx , compressedBuffer , dstCapacity ,
2017-08-09 23:51:19 +00:00
CNBuffer , dictSize ,
NULL , NULL ) ) ;
DISPLAYLEVEL ( 3 , " %u bytes \n " , ( unsigned ) cSizeNoDict ) ;
2018-01-26 16:29:00 +00:00
CHECK ( LZ4F_freeCompressionContext ( cctx ) ) ;
CHECK ( LZ4F_createCompressionContext ( & cctx , LZ4F_VERSION ) ) ;
2017-08-09 23:51:19 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame_usingCDict, with dict : " ) ;
CHECK_V ( cSizeWithDict ,
2018-01-26 16:29:00 +00:00
LZ4F_compressFrame_usingCDict ( cctx , compressedBuffer , dstCapacity ,
2017-08-09 23:51:19 +00:00
CNBuffer , dictSize ,
cdict , NULL ) ) ;
2017-08-10 23:53:57 +00:00
DISPLAYLEVEL ( 3 , " compressed %u bytes into %u bytes \n " ,
( unsigned ) dictSize , ( unsigned ) cSizeWithDict ) ;
2019-07-15 19:11:34 +00:00
if ( ( LZ4_DISTANCE_MAX > dictSize ) & & ( cSizeWithDict > = cSizeNoDict ) ) goto _output_error ; /* must be more efficient */
2017-08-10 23:53:57 +00:00
crcOrig = XXH64 ( CNBuffer , dictSize , 0 ) ;
DISPLAYLEVEL ( 3 , " LZ4F_decompress_usingDict : " ) ;
{ LZ4F_dctx * dctx ;
size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH ;
size_t compressedSize = cSizeWithDict ;
CHECK ( LZ4F_createDecompressionContext ( & dctx , LZ4F_VERSION ) ) ;
CHECK ( LZ4F_decompress_usingDict ( dctx ,
decodedBuffer , & decodedSize ,
compressedBuffer , & compressedSize ,
CNBuffer , dictSize ,
NULL ) ) ;
if ( compressedSize ! = cSizeWithDict ) goto _output_error ;
if ( decodedSize ! = dictSize ) goto _output_error ;
{ U64 const crcDest = XXH64 ( decodedBuffer , decodedSize , 0 ) ;
if ( crcDest ! = crcOrig ) goto _output_error ; }
DISPLAYLEVEL ( 3 , " Regenerated %u bytes \n " , ( U32 ) decodedSize ) ;
CHECK ( LZ4F_freeDecompressionContext ( dctx ) ) ;
}
2017-08-09 23:51:19 +00:00
2017-08-10 07:48:19 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame_usingCDict, with dict, negative level : " ) ;
{ size_t cSizeLevelMax ;
LZ4F_preferences_t cParams ;
memset ( & cParams , 0 , sizeof ( cParams ) ) ;
cParams . compressionLevel = - 3 ;
CHECK_V ( cSizeLevelMax ,
2018-01-26 16:29:00 +00:00
LZ4F_compressFrame_usingCDict ( cctx , compressedBuffer , dstCapacity ,
2017-08-10 07:48:19 +00:00
CNBuffer , dictSize ,
cdict , & cParams ) ) ;
DISPLAYLEVEL ( 3 , " %u bytes \n " , ( unsigned ) cSizeLevelMax ) ;
}
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame_usingCDict, with dict, level max : " ) ;
{ size_t cSizeLevelMax ;
LZ4F_preferences_t cParams ;
memset ( & cParams , 0 , sizeof ( cParams ) ) ;
cParams . compressionLevel = LZ4F_compressionLevel_max ( ) ;
CHECK_V ( cSizeLevelMax ,
2018-01-26 16:29:00 +00:00
LZ4F_compressFrame_usingCDict ( cctx , compressedBuffer , dstCapacity ,
2017-08-10 07:48:19 +00:00
CNBuffer , dictSize ,
cdict , & cParams ) ) ;
DISPLAYLEVEL ( 3 , " %u bytes \n " , ( unsigned ) cSizeLevelMax ) ;
}
2017-08-10 19:12:53 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame_usingCDict, multiple linked blocks : " ) ;
{ size_t cSizeContiguous ;
size_t const inSize = dictSize * 3 ;
size_t const outCapacity = LZ4F_compressFrameBound ( inSize , NULL ) ;
LZ4F_preferences_t cParams ;
memset ( & cParams , 0 , sizeof ( cParams ) ) ;
cParams . frameInfo . blockMode = LZ4F_blockLinked ;
cParams . frameInfo . blockSizeID = LZ4F_max64KB ;
CHECK_V ( cSizeContiguous ,
2018-01-26 16:29:00 +00:00
LZ4F_compressFrame_usingCDict ( cctx , compressedBuffer , outCapacity ,
2017-08-10 19:12:53 +00:00
CNBuffer , inSize ,
cdict , & cParams ) ) ;
2017-08-10 23:53:57 +00:00
DISPLAYLEVEL ( 3 , " compressed %u bytes into %u bytes \n " ,
( unsigned ) inSize , ( unsigned ) cSizeContiguous ) ;
DISPLAYLEVEL ( 3 , " LZ4F_decompress_usingDict on multiple linked blocks : " ) ;
{ LZ4F_dctx * dctx ;
size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH ;
size_t compressedSize = cSizeContiguous ;
CHECK ( LZ4F_createDecompressionContext ( & dctx , LZ4F_VERSION ) ) ;
CHECK ( LZ4F_decompress_usingDict ( dctx ,
decodedBuffer , & decodedSize ,
compressedBuffer , & compressedSize ,
CNBuffer , dictSize ,
NULL ) ) ;
if ( compressedSize ! = cSizeContiguous ) goto _output_error ;
if ( decodedSize ! = inSize ) goto _output_error ;
crcOrig = XXH64 ( CNBuffer , inSize , 0 ) ;
{ U64 const crcDest = XXH64 ( decodedBuffer , decodedSize , 0 ) ;
if ( crcDest ! = crcOrig ) goto _output_error ; }
DISPLAYLEVEL ( 3 , " Regenerated %u bytes \n " , ( U32 ) decodedSize ) ;
CHECK ( LZ4F_freeDecompressionContext ( dctx ) ) ;
}
2017-08-10 19:12:53 +00:00
}
2017-08-10 23:53:57 +00:00
2017-08-10 19:12:53 +00:00
DISPLAYLEVEL ( 3 , " LZ4F_compressFrame_usingCDict, multiple independent blocks : " ) ;
{ size_t cSizeIndep ;
size_t const inSize = dictSize * 3 ;
size_t const outCapacity = LZ4F_compressFrameBound ( inSize , NULL ) ;
LZ4F_preferences_t cParams ;
memset ( & cParams , 0 , sizeof ( cParams ) ) ;
cParams . frameInfo . blockMode = LZ4F_blockIndependent ;
cParams . frameInfo . blockSizeID = LZ4F_max64KB ;
CHECK_V ( cSizeIndep ,
2018-01-26 16:29:00 +00:00
LZ4F_compressFrame_usingCDict ( cctx , compressedBuffer , outCapacity ,
2017-08-10 19:12:53 +00:00
CNBuffer , inSize ,
cdict , & cParams ) ) ;
2017-08-10 23:53:57 +00:00
DISPLAYLEVEL ( 3 , " compressed %u bytes into %u bytes \n " ,
( unsigned ) inSize , ( unsigned ) cSizeIndep ) ;
DISPLAYLEVEL ( 3 , " LZ4F_decompress_usingDict on multiple independent blocks : " ) ;
{ LZ4F_dctx * dctx ;
size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH ;
size_t compressedSize = cSizeIndep ;
CHECK ( LZ4F_createDecompressionContext ( & dctx , LZ4F_VERSION ) ) ;
CHECK ( LZ4F_decompress_usingDict ( dctx ,
decodedBuffer , & decodedSize ,
compressedBuffer , & compressedSize ,
CNBuffer , dictSize ,
NULL ) ) ;
if ( compressedSize ! = cSizeIndep ) goto _output_error ;
if ( decodedSize ! = inSize ) goto _output_error ;
crcOrig = XXH64 ( CNBuffer , inSize , 0 ) ;
{ U64 const crcDest = XXH64 ( decodedBuffer , decodedSize , 0 ) ;
if ( crcDest ! = crcOrig ) goto _output_error ; }
DISPLAYLEVEL ( 3 , " Regenerated %u bytes \n " , ( U32 ) decodedSize ) ;
CHECK ( LZ4F_freeDecompressionContext ( dctx ) ) ;
}
2017-08-10 19:12:53 +00:00
}
2017-08-09 23:51:19 +00:00
LZ4F_freeCDict ( cdict ) ;
2018-01-26 16:29:00 +00:00
CHECK ( LZ4F_freeCompressionContext ( cctx ) ) ; cctx = NULL ;
2017-08-09 00:43:11 +00:00
}
2019-01-09 18:49:49 +00:00
DISPLAYLEVEL ( 3 , " getBlockSize test: \n " ) ;
{ size_t result ;
2019-01-09 19:17:46 +00:00
unsigned blockSizeID ;
for ( blockSizeID = 4 ; blockSizeID < 8 ; + + blockSizeID ) {
2019-01-09 18:49:49 +00:00
result = LZ4F_getBlockSize ( blockSizeID ) ;
CHECK ( result ) ;
2019-04-18 23:06:02 +00:00
DISPLAYLEVEL ( 3 , " Returned block size of %u bytes for blockID %u \n " ,
( unsigned ) result , blockSizeID ) ;
2019-01-09 18:49:49 +00:00
}
/* Test an invalid input that's too large */
result = LZ4F_getBlockSize ( 8 ) ;
if ( ! LZ4F_isError ( result ) | |
LZ4F_getErrorCode ( result ) ! = LZ4F_ERROR_maxBlockSize_invalid )
goto _output_error ;
/* Test an invalid input that's too small */
result = LZ4F_getBlockSize ( 3 ) ;
if ( ! LZ4F_isError ( result ) | |
LZ4F_getErrorCode ( result ) ! = LZ4F_ERROR_maxBlockSize_invalid )
goto _output_error ;
}
2017-08-09 23:51:19 +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
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ) ;
2015-03-16 16:52:14 +00:00
/* 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 ;
2019-06-30 20:59:49 +00:00
size_t oSize = ( size_t ) ( oend - op ) ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = ( size_t ) ( iend - ip ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ) ;
2015-03-16 16:52:14 +00:00
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 ) {
2017-03-29 00:36:12 +00:00
unsigned const nbBits = FUZ_rand ( & randState ) % maxBits ;
2015-03-16 18:19:39 +00:00
size_t iSize = ( FUZ_rand ( & randState ) & ( ( 1 < < nbBits ) - 1 ) ) + 1 ;
2019-06-30 20:59:49 +00:00
size_t oSize = ( size_t ) ( oend - op ) ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = ( size_t ) ( iend - ip ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ) ;
2015-03-16 18:19:39 +00:00
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 ;
2019-06-30 20:59:49 +00:00
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = ( size_t ) ( iend - ip ) ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_decompress ( dCtx , op , & oSize , ip , & iSize , NULL ) ) ;
2015-03-18 20:38:27 +00:00
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 ;
2017-05-10 23:28:36 +00:00
return basicTests_error ;
2014-08-30 17:14:44 +00:00
_output_error :
2017-05-10 23:28:36 +00:00
basicTests_error = 1 ;
2014-09-22 17:42:00 +00:00
DISPLAY ( " Error detected ! \n " ) ;
goto _end ;
2014-08-30 17:14:44 +00:00
}
2019-06-30 20:59:49 +00:00
typedef enum { o_contiguous , o_noncontiguous , o_overwrite } o_scenario_e ;
static void locateBuffDiff ( const void * buff1 , const void * buff2 , size_t size , o_scenario_e o_scenario )
2014-09-11 21:27:14 +00:00
{
2020-09-17 21:43:02 +00:00
if ( displayLevel > = 2 ) {
2019-06-30 21:57:12 +00:00
size_t p = 0 ;
const BYTE * b1 = ( const BYTE * ) buff1 ;
const BYTE * b2 = ( const BYTE * ) buff2 ;
DISPLAY ( " locateBuffDiff: looking for error position \n " ) ;
if ( o_scenario ! = o_contiguous ) {
DISPLAY ( " mode %i: non-contiguous output (%u bytes), cannot search \n " ,
( int ) o_scenario , ( unsigned ) size ) ;
return ;
}
while ( p < size & & b1 [ p ] = = b2 [ p ] ) p + + ;
if ( p ! = size ) {
DISPLAY ( " Error at pos %i/%i : %02X != %02X \n " , ( int ) p , ( int ) size , b1 [ p ] , b2 [ p ] ) ;
}
2018-02-02 16:25:29 +00:00
}
2014-09-22 17:42:00 +00:00
}
2014-09-11 21:27:14 +00:00
2019-06-30 20:59:49 +00:00
# define EXIT_MSG(...) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
DISPLAY ( " (seed %u, test nb %u) \n " , seed , testNb ) ; exit ( 1 ) ; }
# undef CHECK
# define CHECK(cond, ...) { if (cond) { EXIT_MSG(__VA_ARGS__); } }
size_t test_lz4f_decompression_wBuffers (
const void * cSrc , size_t cSize ,
void * dst , size_t dstCapacity , o_scenario_e o_scenario ,
const void * srcRef , size_t decompressedSize ,
U64 crcOrig ,
U32 * const randState ,
LZ4F_dctx * const dCtx ,
2020-09-28 18:39:00 +00:00
U32 seed , U32 testNb ,
int findErrorPos )
2019-06-30 20:59:49 +00:00
{
const BYTE * ip = ( const BYTE * ) cSrc ;
const BYTE * const iend = ip + cSize ;
BYTE * op = ( BYTE * ) dst ;
BYTE * const oend = op + dstCapacity ;
unsigned const suggestedBits = FUZ_highbit ( ( U32 ) cSize ) ;
unsigned const maxBits = MAX ( 3 , suggestedBits ) ;
size_t totalOut = 0 ;
size_t moreToFlush = 0 ;
XXH64_state_t xxh64 ;
XXH64_reset ( & xxh64 , 1 ) ;
assert ( ip < iend ) ;
while ( ip < iend ) {
unsigned const nbBitsI = ( FUZ_rand ( randState ) % ( maxBits - 1 ) ) + 1 ;
unsigned const nbBitsO = ( FUZ_rand ( randState ) % ( maxBits ) ) + 1 ;
size_t const iSizeCand = ( FUZ_rand ( randState ) & ( ( 1 < < nbBitsI ) - 1 ) ) + 1 ;
size_t const iSizeMax = MIN ( iSizeCand , ( size_t ) ( iend - ip ) ) ;
size_t iSize = iSizeMax ;
size_t const oSizeCand = ( FUZ_rand ( randState ) & ( ( 1 < < nbBitsO ) - 1 ) ) + 2 ;
size_t const oSizeMax = MIN ( oSizeCand , ( size_t ) ( oend - op ) ) ;
2020-10-02 06:42:42 +00:00
int const sentinelTest = ( op + oSizeMax < oend ) ;
2019-06-30 20:59:49 +00:00
size_t oSize = oSizeMax ;
BYTE const mark = ( BYTE ) ( FUZ_rand ( randState ) & 255 ) ;
LZ4F_decompressOptions_t dOptions ;
memset ( & dOptions , 0 , sizeof ( dOptions ) ) ;
dOptions . stableDst = FUZ_rand ( randState ) & 1 ;
if ( o_scenario = = o_overwrite ) dOptions . stableDst = 0 ; /* overwrite mode */
2020-10-02 06:42:42 +00:00
if ( sentinelTest ) op [ oSizeMax ] = mark ;
2019-06-30 20:59:49 +00:00
2019-06-30 21:57:12 +00:00
DISPLAYLEVEL ( 7 , " dstCapacity=%u, presentedInput=%u \n " , ( unsigned ) oSize , ( unsigned ) iSize ) ;
2019-06-30 20:59:49 +00:00
/* read data from byte-exact buffer to catch out-of-bound reads */
{ void * const iBuffer = malloc ( iSizeMax ) ;
2020-10-02 02:07:56 +00:00
void * const tmpop = ( FUZ_rand ( randState ) & ( oSize = = 0 ) ) ? NULL : op ;
const void * const tmpip = ( FUZ_rand ( randState ) & ( iSize = = 0 ) ) ? NULL : iBuffer ;
2019-06-30 20:59:49 +00:00
assert ( iBuffer ! = NULL ) ;
memcpy ( iBuffer , ip , iSizeMax ) ;
2020-10-02 02:07:56 +00:00
moreToFlush = LZ4F_decompress ( dCtx , tmpop , & oSize , tmpip , & iSize , & dOptions ) ;
2019-06-30 20:59:49 +00:00
free ( iBuffer ) ;
}
2019-06-30 21:57:12 +00:00
DISPLAYLEVEL ( 7 , " oSize=%u, readSize=%u \n " , ( unsigned ) oSize , ( unsigned ) iSize ) ;
2019-06-30 20:59:49 +00:00
2020-10-02 06:42:42 +00:00
if ( sentinelTest ) {
2019-06-30 20:59:49 +00:00
CHECK ( op [ oSizeMax ] ! = mark , " op[oSizeMax] = %02X != %02X : "
" Decompression overwrites beyond assigned dst size " ,
op [ oSizeMax ] , mark ) ;
}
2020-09-17 21:43:02 +00:00
if ( LZ4F_getErrorCode ( moreToFlush ) = = LZ4F_ERROR_contentChecksum_invalid ) {
2020-09-28 18:39:00 +00:00
if ( findErrorPos ) DISPLAYLEVEL ( 2 , " checksum error detected \n " ) ;
if ( findErrorPos ) locateBuffDiff ( srcRef , dst , decompressedSize , o_scenario ) ;
2020-09-17 21:43:02 +00:00
}
2019-06-30 20:59:49 +00:00
if ( LZ4F_isError ( moreToFlush ) ) return moreToFlush ;
XXH64_update ( & xxh64 , op , oSize ) ;
totalOut + = oSize ;
op + = oSize ;
ip + = iSize ;
2019-06-30 21:57:12 +00:00
if ( o_scenario = = o_noncontiguous ) {
if ( op = = oend ) return LZ4F_ERROR_GENERIC ; /* can theoretically happen with bogus data */
op + + ; /* create a gap between consecutive output */
}
2019-06-30 20:59:49 +00:00
if ( o_scenario = = o_overwrite ) op = ( BYTE * ) dst ; /* overwrite destination */
2019-06-30 21:57:12 +00:00
if ( ( op = = oend ) /* no more room for output; can happen with bogus input */
& & ( iSize = = 0 ) ) /* no input consumed */
break ;
2019-06-30 20:59:49 +00:00
}
if ( moreToFlush ! = 0 ) return LZ4F_ERROR_decompressionFailed ;
if ( totalOut ) { /* otherwise, it's a skippable frame */
U64 const crcDecoded = XXH64_digest ( & xxh64 ) ;
if ( crcDecoded ! = crcOrig ) {
2020-09-28 18:39:00 +00:00
if ( findErrorPos ) locateBuffDiff ( srcRef , dst , decompressedSize , o_scenario ) ;
2019-06-30 20:59:49 +00:00
return LZ4F_ERROR_contentChecksum_invalid ;
} }
return 0 ;
}
size_t test_lz4f_decompression ( const void * cSrc , size_t cSize ,
const void * srcRef , size_t decompressedSize ,
U64 crcOrig ,
U32 * const randState ,
LZ4F_dctx * const dCtx ,
2020-09-28 18:39:00 +00:00
U32 seed , U32 testNb ,
int findErrorPos )
2019-06-30 20:59:49 +00:00
{
o_scenario_e const o_scenario = ( o_scenario_e ) ( FUZ_rand ( randState ) % 3 ) ; /* 0 : contiguous; 1 : non-contiguous; 2 : dst overwritten */
/* tighten dst buffer conditions */
size_t const dstCapacity = ( o_scenario = = o_noncontiguous ) ?
2019-06-30 21:57:12 +00:00
( decompressedSize * 2 ) + 128 :
2019-06-30 20:59:49 +00:00
decompressedSize ;
size_t result ;
void * const dstBuffer = malloc ( dstCapacity ) ;
assert ( dstBuffer ! = NULL ) ;
result = test_lz4f_decompression_wBuffers ( cSrc , cSize ,
dstBuffer , dstCapacity , o_scenario ,
srcRef , decompressedSize ,
crcOrig ,
randState ,
dCtx ,
2020-09-28 18:39:00 +00:00
seed , testNb , findErrorPos ) ;
2019-06-30 20:59:49 +00:00
free ( dstBuffer ) ;
return result ;
}
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 testNb = 0 ;
2019-06-30 20:59:49 +00:00
size_t const CNBufferLength = 9 MB ; /* needs to be > 2x4MB to test large blocks */
void * CNBuffer = NULL ;
size_t const compressedBufferSize = LZ4F_compressFrameBound ( CNBufferLength , NULL ) + 4 MB ; /* needs some margin */
2014-09-22 17:42:00 +00:00
void * compressedBuffer = NULL ;
void * decodedBuffer = NULL ;
U32 coreRand = seed ;
LZ4F_decompressionContext_t dCtx = NULL ;
2019-06-30 20:59:49 +00:00
LZ4F_decompressionContext_t dCtxNoise = NULL ;
2014-09-22 17:42:00 +00:00
LZ4F_compressionContext_t cCtx = NULL ;
2016-09-03 04:46:02 +00:00
clock_t const startClock = clock ( ) ;
clock_t const clockDuration = duration_s * CLOCKS_PER_SEC ;
2014-09-05 15:32:04 +00:00
2015-03-15 00:42:27 +00:00
/* Create buffers */
2019-04-15 08:54:40 +00:00
{ size_t const creationStatus = LZ4F_createDecompressionContext ( & dCtx , LZ4F_VERSION ) ;
CHECK ( LZ4F_isError ( creationStatus ) , " Allocation failed (error %i) " , ( int ) creationStatus ) ; }
2019-06-30 20:59:49 +00:00
{ size_t const creationStatus = LZ4F_createDecompressionContext ( & dCtxNoise , LZ4F_VERSION ) ;
CHECK ( LZ4F_isError ( creationStatus ) , " Allocation failed (error %i) " , ( int ) creationStatus ) ; }
2019-04-15 08:54:40 +00:00
{ size_t const creationStatus = LZ4F_createCompressionContext ( & cCtx , LZ4F_VERSION ) ;
CHECK ( LZ4F_isError ( creationStatus ) , " Allocation failed (error %i) " , ( int ) creationStatus ) ; }
2019-06-30 20:59:49 +00:00
CNBuffer = malloc ( CNBufferLength ) ;
CHECK ( CNBuffer = = NULL , " CNBuffer 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 " ) ;
2019-06-30 20:59:49 +00:00
decodedBuffer = calloc ( 1 , CNBufferLength ) ; /* calloc avoids decodedBuffer being considered "garbage" by scan-build */
2014-09-07 11:57:09 +00:00
CHECK ( decodedBuffer = = NULL , " decodedBuffer Allocation failed " ) ;
2019-06-30 20:59:49 +00:00
FUZ_fillCompressibleNoiseBuffer ( CNBuffer , CNBufferLength , 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 ;
2019-06-30 20:59:49 +00:00
unsigned const srcBits = ( FUZ_rand ( & randState ) % ( FUZ_highbit ( ( U32 ) ( CNBufferLength - 1 ) ) - 1 ) ) + 1 ;
2016-11-11 23:11:56 +00:00
size_t const srcSize = ( FUZ_rand ( & randState ) & ( ( 1 < < srcBits ) - 1 ) ) + 1 ;
2019-06-30 20:59:49 +00:00
size_t const srcStartId = FUZ_rand ( & randState ) % ( CNBufferLength - srcSize ) ;
const BYTE * const srcStart = ( const BYTE * ) CNBuffer + srcStartId ;
2016-11-11 23:11:56 +00:00
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 ) ) ;
2017-08-12 00:46:52 +00:00
prefs . frameInfo . blockChecksumFlag = ( LZ4F_blockChecksum_t ) ( FUZ_rand ( & randState ) & 1 ) ;
2016-11-11 23:11:56 +00:00
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 ;
2017-04-09 08:41:36 +00:00
prefs . compressionLevel = - 5 + ( int ) ( FUZ_rand ( & randState ) % 11 ) ;
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 ;
2019-06-30 20:59:49 +00:00
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 ) ) ;
2019-06-30 20:59:49 +00:00
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 ) ) ;
Clarifies and fix EndMark
EndMark, the 4-bytes value indicating the end of frame,
must be `0x00000000`.
Previously, it was just mentioned as a `0-size` block.
But such definition could encompass uncompressed blocks of size 0,
with a header of value `0x80000000`.
But the intention was to also support uncompressed empty blocks.
They could be used as a keep-alive signal.
Note that compressed empty blocks are already supported,
it's just that they have a size 1 instead of 0 (for the `0` token).
Unfortunately, the decoder implementation was also wrong,
and would also interpret a `0x80000000` block header as an endMark.
This issue evaded detection so far simply because
this situation never happens, as LZ4Frame always issues
a clean 0x00000000 value as a endMark.
It also does not flush empty blocks.
This is fixed in this PR.
The decoder can now deal with empty uncompressed blocks,
and do not confuse them with EndMark.
The specification is also clarified.
Finally, FrameTest is updated to randomly insert empty blocks during fuzzing.
2020-08-13 00:27:33 +00:00
{ size_t const fhSize = LZ4F_compressBegin ( cCtx , op , ( size_t ) ( oend - op ) , prefsPtr ) ;
CHECK ( LZ4F_isError ( fhSize ) , " Compression header failed (error %i) " ,
( int ) fhSize ) ;
op + = fhSize ;
}
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 ) ;
2019-04-15 17:14:36 +00:00
size_t flushedSize ;
2014-09-22 17:42:00 +00:00
cOptions . stableSrc = ( ( FUZ_rand ( & randState ) & 3 ) = = 1 ) ;
2018-09-19 01:08:59 +00:00
DISPLAYLEVEL ( 6 , " Sending %u bytes to compress (stableSrc:%u) \n " ,
( unsigned ) iSize , cOptions . stableSrc ) ;
2014-09-13 09:08:55 +00:00
2019-04-15 17:14:36 +00:00
flushedSize = LZ4F_compressUpdate ( cCtx , op , oSize , ip , iSize , & cOptions ) ;
CHECK ( LZ4F_isError ( flushedSize ) , " Compression failed (error %i : %s) " ,
( int ) flushedSize , LZ4F_getErrorName ( flushedSize ) ) ;
op + = flushedSize ;
2014-09-07 08:13:02 +00:00
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 ) {
2019-04-15 08:54:40 +00:00
size_t const flushSize = LZ4F_flush ( cCtx , op , ( size_t ) ( oend - op ) , & cOptions ) ;
DISPLAYLEVEL ( 6 , " flushing %u bytes \n " , ( unsigned ) flushSize ) ;
CHECK ( LZ4F_isError ( flushSize ) , " Compression failed (error %i) " , ( int ) flushSize ) ;
op + = flushSize ;
Clarifies and fix EndMark
EndMark, the 4-bytes value indicating the end of frame,
must be `0x00000000`.
Previously, it was just mentioned as a `0-size` block.
But such definition could encompass uncompressed blocks of size 0,
with a header of value `0x80000000`.
But the intention was to also support uncompressed empty blocks.
They could be used as a keep-alive signal.
Note that compressed empty blocks are already supported,
it's just that they have a size 1 instead of 0 (for the `0` token).
Unfortunately, the decoder implementation was also wrong,
and would also interpret a `0x80000000` block header as an endMark.
This issue evaded detection so far simply because
this situation never happens, as LZ4Frame always issues
a clean 0x00000000 value as a endMark.
It also does not flush empty blocks.
This is fixed in this PR.
The decoder can now deal with empty uncompressed blocks,
and do not confuse them with EndMark.
The specification is also clarified.
Finally, FrameTest is updated to randomly insert empty blocks during fuzzing.
2020-08-13 00:27:33 +00:00
if ( ( FUZ_rand ( & randState ) % 1024 ) = = 3 ) {
/* add an empty block (requires uncompressed flag) */
op [ 0 ] = op [ 1 ] = op [ 2 ] = 0 ;
op [ 3 ] = 0x80 ; /* 0x80000000U in little-endian format */
op + = 4 ;
if ( ( prefsPtr ! = NULL ) & & prefsPtr - > frameInfo . blockChecksumFlag ) {
U32 const bc32 = XXH32 ( op , 0 , 0 ) ;
2020-10-02 06:27:02 +00:00
op [ 0 ] = ( BYTE ) bc32 ; /* little endian format */
Clarifies and fix EndMark
EndMark, the 4-bytes value indicating the end of frame,
must be `0x00000000`.
Previously, it was just mentioned as a `0-size` block.
But such definition could encompass uncompressed blocks of size 0,
with a header of value `0x80000000`.
But the intention was to also support uncompressed empty blocks.
They could be used as a keep-alive signal.
Note that compressed empty blocks are already supported,
it's just that they have a size 1 instead of 0 (for the `0` token).
Unfortunately, the decoder implementation was also wrong,
and would also interpret a `0x80000000` block header as an endMark.
This issue evaded detection so far simply because
this situation never happens, as LZ4Frame always issues
a clean 0x00000000 value as a endMark.
It also does not flush empty blocks.
This is fixed in this PR.
The decoder can now deal with empty uncompressed blocks,
and do not confuse them with EndMark.
The specification is also clarified.
Finally, FrameTest is updated to randomly insert empty blocks during fuzzing.
2020-08-13 00:27:33 +00:00
op [ 1 ] = ( BYTE ) ( bc32 > > 8 ) ;
op [ 2 ] = ( BYTE ) ( bc32 > > 16 ) ;
op [ 3 ] = ( BYTE ) ( bc32 > > 24 ) ;
op + = 4 ;
} } } }
} /* while (ip<iend) */
2016-11-11 23:11:56 +00:00
CHECK ( op > = oend , " LZ4F_compressFrameBound overflow " ) ;
2018-10-09 21:25:18 +00:00
{ size_t const dstEndSafeSize = LZ4F_compressBound ( 0 , prefsPtr ) ;
int const tooSmallDstEnd = ( ( FUZ_rand ( & randState ) & 31 ) = = 3 ) ;
size_t const dstEndTooSmallSize = ( FUZ_rand ( & randState ) % dstEndSafeSize ) + 1 ;
size_t const dstEndSize = tooSmallDstEnd ? dstEndTooSmallSize : dstEndSafeSize ;
BYTE const canaryByte = ( BYTE ) ( FUZ_rand ( & randState ) & 255 ) ;
2019-04-15 17:14:36 +00:00
size_t flushedSize ;
2019-04-15 08:54:40 +00:00
DISPLAYLEVEL ( 7 , " canaryByte at pos %u / %u \n " ,
( unsigned ) ( ( size_t ) ( op - ( BYTE * ) compressedBuffer ) + dstEndSize ) ,
( unsigned ) compressedBufferSize ) ;
2019-04-15 09:11:59 +00:00
assert ( op + dstEndSize < ( BYTE * ) compressedBuffer + compressedBufferSize ) ;
2018-10-09 21:25:18 +00:00
op [ dstEndSize ] = canaryByte ;
2019-04-15 17:14:36 +00:00
flushedSize = LZ4F_compressEnd ( cCtx , op , dstEndSize , & cOptions ) ;
2018-10-09 21:25:18 +00:00
CHECK ( op [ dstEndSize ] ! = canaryByte , " LZ4F_compressEnd writes beyond dstCapacity ! " ) ;
2019-04-15 17:14:36 +00:00
if ( LZ4F_isError ( flushedSize ) ) {
2018-10-09 21:25:18 +00:00
if ( tooSmallDstEnd ) /* failure is allowed */ continue ;
2020-11-15 01:25:31 +00:00
CHECK ( ! tooSmallDstEnd , " Compression completion failed (error %i : %s) " ,
2019-04-15 17:14:36 +00:00
( int ) flushedSize , LZ4F_getErrorName ( flushedSize ) ) ;
}
op + = flushedSize ;
}
2019-04-15 08:54:40 +00:00
cSize = ( size_t ) ( 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
2019-06-30 20:59:49 +00:00
2016-11-11 23:11:56 +00:00
/* multi-segments decompression */
2019-06-30 21:57:12 +00:00
DISPLAYLEVEL ( 6 , " normal decompression \n " ) ;
2020-09-28 18:39:00 +00:00
{ size_t result = test_lz4f_decompression ( compressedBuffer , cSize , srcStart , srcSize , crcOrig , & randState , dCtx , seed , testNb , 1 /*findError*/ ) ;
2019-06-30 20:59:49 +00:00
CHECK ( LZ4F_isError ( result ) , " multi-segment decompression failed (error %i => %s) " ,
( int ) result , LZ4F_getErrorName ( result ) ) ;
2014-09-06 21:48:03 +00:00
}
2019-06-30 20:59:49 +00:00
# if 1
/* insert noise into src */
{ U32 const maxNbBits = FUZ_highbit ( ( U32 ) cSize ) ;
size_t pos = 0 ;
for ( ; ; ) {
/* keep some original src */
{ U32 const nbBits = FUZ_rand ( & randState ) % maxNbBits ;
size_t const mask = ( 1 < < nbBits ) - 1 ;
size_t const skipLength = FUZ_rand ( & randState ) & mask ;
pos + = skipLength ;
}
if ( pos > = cSize ) break ;
/* add noise */
{ U32 const nbBitsCodes = FUZ_rand ( & randState ) % maxNbBits ;
U32 const nbBits = nbBitsCodes ? nbBitsCodes - 1 : 0 ;
size_t const mask = ( 1 < < nbBits ) - 1 ;
size_t const rNoiseLength = ( FUZ_rand ( & randState ) & mask ) + 1 ;
size_t const noiseLength = MIN ( rNoiseLength , cSize - pos ) ;
2019-08-15 11:59:59 +00:00
size_t const noiseStart = FUZ_rand ( & randState ) % ( CNBufferLength - noiseLength ) ;
2019-06-30 20:59:49 +00:00
memcpy ( ( BYTE * ) compressedBuffer + pos , ( const char * ) CNBuffer + noiseStart , noiseLength ) ;
pos + = noiseLength ;
} } }
/* test decompression on noisy src */
2019-06-30 21:57:12 +00:00
DISPLAYLEVEL ( 6 , " noisy decompression \n " ) ;
2020-09-28 18:39:00 +00:00
test_lz4f_decompression ( compressedBuffer , cSize , srcStart , srcSize , crcOrig , & randState , dCtxNoise , seed , testNb , 0 /*don't search error Pos*/ ) ;
2019-06-30 20:59:49 +00:00
/* note : we don't analyze result here : it probably failed, which is expected.
Clarifies and fix EndMark
EndMark, the 4-bytes value indicating the end of frame,
must be `0x00000000`.
Previously, it was just mentioned as a `0-size` block.
But such definition could encompass uncompressed blocks of size 0,
with a header of value `0x80000000`.
But the intention was to also support uncompressed empty blocks.
They could be used as a keep-alive signal.
Note that compressed empty blocks are already supported,
it's just that they have a size 1 instead of 0 (for the `0` token).
Unfortunately, the decoder implementation was also wrong,
and would also interpret a `0x80000000` block header as an endMark.
This issue evaded detection so far simply because
this situation never happens, as LZ4Frame always issues
a clean 0x00000000 value as a endMark.
It also does not flush empty blocks.
This is fixed in this PR.
The decoder can now deal with empty uncompressed blocks,
and do not confuse them with EndMark.
The specification is also clarified.
Finally, FrameTest is updated to randomly insert empty blocks during fuzzing.
2020-08-13 00:27:33 +00:00
* The sole purpose is to catch potential out - of - bound reads and writes . */
LZ4F_resetDecompressionContext ( dCtxNoise ) ; /* context must be reset after an error */
2019-06-30 20:59:49 +00:00
# endif
} /* for ( ; (testNb < nbTests) ; ) */
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
2014-09-06 12:06:28 +00:00
LZ4F_freeDecompressionContext ( dCtx ) ;
2019-06-30 20:59:49 +00:00
LZ4F_freeDecompressionContext ( dCtxNoise ) ;
2014-09-07 11:57:09 +00:00
LZ4F_freeCompressionContext ( cCtx ) ;
2019-06-30 20:59:49 +00:00
free ( CNBuffer ) ;
2014-09-22 17:42:00 +00:00
free ( compressedBuffer ) ;
free ( decodedBuffer ) ;
2014-09-21 08:56:21 +00:00
2016-12-21 09:22:40 +00:00
if ( use_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
}
2019-06-30 20:59:49 +00:00
return 0 ;
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 ;
2019-06-30 20:59:49 +00:00
unsigned nbTests = nbTestsDefault ;
unsigned testNb = 0 ;
2014-08-30 17:14:44 +00:00
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 + + ;
2016-12-21 09:22:40 +00:00
use_pause = 1 ;
2014-10-21 23:36:32 +00:00
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 ;
2019-06-30 20:59:49 +00:00
nbTests + = ( unsigned ) ( * argument - ' 0 ' ) ;
2014-08-30 17:14:44 +00:00
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 ' :
2019-06-30 20:59:49 +00:00
case ' 9 ' : duration * = 10 ; duration + = ( U32 ) ( * 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 ;
2019-06-30 20:59:49 +00:00
seed + = ( U32 ) ( * argument - ' 0 ' ) ;
2014-08-30 17:14:44 +00:00
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 ;
2019-06-30 20:59:49 +00:00
testNb + = ( unsigned ) ( * argument - ' 0 ' ) ;
2014-08-30 17:14:44 +00:00
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
2019-06-30 22:36:32 +00:00
nbTests + = ( nbTests = = 0 ) ; /* avoid zero */
2014-08-30 17:14:44 +00:00
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
}