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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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>
2018-04-24 22:50:03 +00:00
# include "lz4frame.h" /* include multiple times to test correctness/safety */
# 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"
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 ;
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-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 ) ;
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-01-26 16:29:00 +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 ) ;
}
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 " ) ;
{ size_t avail_in = cSize ;
LZ4F_frameInfo_t frame_info ;
2017-08-09 00:43:11 +00:00
CHECK ( LZ4F_getFrameInfo ( dCtx , & frame_info , compressedBuffer , & avail_in ) ) ;
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 ; }
{ 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 ;
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 : " ) ;
2015-04-19 14:23:53 +00:00
iSize = 15 - 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 " ) ;
ip + = iSize ;
}
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 ) {
size_t oSize = oend - op ;
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 ;
size_t oSize = oend - op ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = 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 ) ;
2017-08-09 23:51:19 +00:00
if ( 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 ) ;
DISPLAYLEVEL ( 3 , " Returned block size of %zu bytes for blockID %u \n " ,
result , blockSizeID ) ;
}
/* 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 ;
size_t oSize = oend - op ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = 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 ;
size_t oSize = oend - op ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = 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 ;
if ( iSize > ( size_t ) ( iend - ip ) ) iSize = 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
}
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
{
2018-02-02 16:25:29 +00:00
size_t p = 0 ;
2015-05-06 00:58:24 +00:00
const BYTE * b1 = ( const BYTE * ) buff1 ;
const BYTE * b2 = ( const BYTE * ) buff2 ;
2018-05-06 01:24:11 +00:00
DISPLAY ( " locateBuffDiff: looking for error position \n " ) ;
2016-06-30 11:44:58 +00:00
if ( nonContiguous ) {
2018-05-06 01:24:11 +00:00
DISPLAY ( " mode %u: non-contiguous output (%zu bytes), cannot search \n " , nonContiguous , size ) ;
2014-09-22 17:42:00 +00:00
return ;
}
2018-02-02 16:25:29 +00:00
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 ] ) ;
}
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 ;
2017-08-09 00:43:11 +00:00
# undef CHECK
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 ) ) ;
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 ;
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 ) ;
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
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 " ) ;
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 ) ;
op [ dstEndSize ] = canaryByte ;
result = LZ4F_compressEnd ( cCtx , op , dstEndSize , & cOptions ) ;
CHECK ( op [ dstEndSize ] ! = canaryByte , " LZ4F_compressEnd writes beyond dstCapacity ! " ) ;
if ( LZ4F_isError ( result ) ) {
if ( tooSmallDstEnd ) /* failure is allowed */ continue ;
CHECK ( 1 , " 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 ) ;
2018-05-06 01:24:11 +00:00
if ( LZ4F_getErrorCode ( result ) = = LZ4F_ERROR_contentChecksum_invalid )
locateBuffDiff ( srcStart , decodedBuffer , srcSize , nonContiguousDst ) ;
2016-11-11 23:11:56 +00:00
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-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
}
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 + + ;
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 ;
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
}