kusano 7d535a
/*
kusano 7d535a
    fuzzer.c - Fuzzer test tool for LZ4
kusano 7d535a
    Copyright (C) Yann Collet 2012-2015
kusano 7d535a
kusano 7d535a
    GPL v2 License
kusano 7d535a
kusano 7d535a
    This program is free software; you can redistribute it and/or modify
kusano 7d535a
    it under the terms of the GNU General Public License as published by
kusano 7d535a
    the Free Software Foundation; either version 2 of the License, or
kusano 7d535a
    (at your option) any later version.
kusano 7d535a
kusano 7d535a
    This program is distributed in the hope that it will be useful,
kusano 7d535a
    but WITHOUT ANY WARRANTY; without even the implied warranty of
kusano 7d535a
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
kusano 7d535a
    GNU General Public License for more details.
kusano 7d535a
kusano 7d535a
    You should have received a copy of the GNU General Public License along
kusano 7d535a
    with this program; if not, write to the Free Software Foundation, Inc.,
kusano 7d535a
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
kusano 7d535a
kusano 7d535a
    You can contact the author at :
kusano 7d535a
    - LZ4 source mirror : https://github.com/Cyan4973/lz4
kusano 7d535a
    - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
kusano 7d535a
*/
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Compiler options
kusano 7d535a
**************************************/
kusano 7d535a
#ifdef _MSC_VER    /* Visual Studio */
kusano 7d535a
#  define _CRT_SECURE_NO_WARNINGS    /* fgets */
kusano 7d535a
#  pragma warning(disable : 4127)    /* disable: C4127: conditional expression is constant */
kusano 7d535a
#  pragma warning(disable : 4146)    /* disable: C4146: minus unsigned expression */
kusano 7d535a
#  pragma warning(disable : 4310)    /* disable: C4310: constant char value > 127 */
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/* S_ISREG & gettimeofday() are not supported by MSVC */
kusano 7d535a
#if defined(_MSC_VER) || defined(_WIN32)
kusano 7d535a
#  define FUZ_LEGACY_TIMER 1
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Includes
kusano 7d535a
**************************************/
kusano 7d535a
#include <stdlib.h></stdlib.h>
kusano 7d535a
#include <stdio.h>      /* fgets, sscanf */</stdio.h>
kusano 7d535a
#include <string.h>     /* strcmp */</string.h>
kusano 7d535a
#include "lz4.h"
kusano 7d535a
#include "lz4hc.h"
kusano 7d535a
#include "xxhash.h"
kusano 7d535a
kusano 7d535a
/* Use ftime() if gettimeofday() is not available on your target */
kusano 7d535a
#if defined(FUZ_LEGACY_TIMER)
kusano 7d535a
#  include <sys timeb.h="">   /* timeb, ftime */</sys>
kusano 7d535a
#else
kusano 7d535a
#  include <sys time.h="">    /* gettimeofday */</sys>
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Basic Types
kusano 7d535a
**************************************/
kusano 7d535a
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)   /* C99 */
kusano 7d535a
# include <stdint.h></stdint.h>
kusano 7d535a
typedef  uint8_t BYTE;
kusano 7d535a
typedef uint16_t U16;
kusano 7d535a
typedef uint32_t U32;
kusano 7d535a
typedef  int32_t S32;
kusano 7d535a
typedef uint64_t U64;
kusano 7d535a
#else
kusano 7d535a
typedef unsigned char       BYTE;
kusano 7d535a
typedef unsigned short      U16;
kusano 7d535a
typedef unsigned int        U32;
kusano 7d535a
typedef   signed int        S32;
kusano 7d535a
typedef unsigned long long  U64;
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Constants
kusano 7d535a
**************************************/
kusano 7d535a
#ifndef LZ4_VERSION
kusano 7d535a
#  define LZ4_VERSION ""
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
#define NB_ATTEMPTS (1<<16)
kusano 7d535a
#define COMPRESSIBLE_NOISE_LENGTH (1 << 21)
kusano 7d535a
#define FUZ_MAX_BLOCK_SIZE (1 << 17)
kusano 7d535a
#define FUZ_MAX_DICT_SIZE  (1 << 15)
kusano 7d535a
#define FUZ_COMPRESSIBILITY_DEFAULT 60
kusano 7d535a
#define PRIME1   2654435761U
kusano 7d535a
#define PRIME2   2246822519U
kusano 7d535a
#define PRIME3   3266489917U
kusano 7d535a
kusano 7d535a
#define KB *(1U<<10)
kusano 7d535a
#define MB *(1U<<20)
kusano 7d535a
#define GB *(1U<<30)
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*****************************************
kusano 7d535a
*  Macros
kusano 7d535a
*****************************************/
kusano 7d535a
#define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
kusano 7d535a
#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
kusano 7d535a
static int g_displayLevel = 2;
kusano 7d535a
static const U32 g_refreshRate = 250;
kusano 7d535a
static U32 g_time = 0;
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*********************************************************
kusano 7d535a
*  Fuzzer functions
kusano 7d535a
*********************************************************/
kusano 7d535a
#if defined(FUZ_LEGACY_TIMER)
kusano 7d535a
kusano 7d535a
static U32 FUZ_GetMilliStart(void)
kusano 7d535a
{
kusano 7d535a
    struct timeb tb;
kusano 7d535a
    U32 nCount;
kusano 7d535a
    ftime( &tb );
kusano 7d535a
    nCount = (U32) (((tb.time & 0xFFFFF) * 1000) +  tb.millitm);
kusano 7d535a
    return nCount;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#else
kusano 7d535a
kusano 7d535a
static U32 FUZ_GetMilliStart(void)
kusano 7d535a
{
kusano 7d535a
    struct timeval tv;
kusano 7d535a
    U32 nCount;
kusano 7d535a
    gettimeofday(&tv, NULL);
kusano 7d535a
    nCount = (U32) (tv.tv_usec/1000 + (tv.tv_sec & 0xfffff) * 1000);
kusano 7d535a
    return nCount;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
static U32 FUZ_GetMilliSpan(U32 nTimeStart)
kusano 7d535a
{
kusano 7d535a
    U32 nCurrent = FUZ_GetMilliStart();
kusano 7d535a
    U32 nSpan = nCurrent - nTimeStart;
kusano 7d535a
    if (nTimeStart > nCurrent)
kusano 7d535a
        nSpan += 0x100000 * 1000;
kusano 7d535a
    return nSpan;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static U32 FUZ_rotl32(U32 u32, U32 nbBits)
kusano 7d535a
{
kusano 7d535a
    return ((u32 << nbBits) | (u32 >> (32 - nbBits)));
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static U32 FUZ_rand(U32* src)
kusano 7d535a
{
kusano 7d535a
    U32 rand32 = *src;
kusano 7d535a
    rand32 *= PRIME1;
kusano 7d535a
    rand32 ^= PRIME2;
kusano 7d535a
    rand32  = FUZ_rotl32(rand32, 13);
kusano 7d535a
    *src = rand32;
kusano 7d535a
    return rand32;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
#define FUZ_RAND15BITS  ((FUZ_rand(seed) >> 3) & 32767)
kusano 7d535a
#define FUZ_RANDLENGTH  ( ((FUZ_rand(seed) >> 7) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
kusano 7d535a
static void FUZ_fillCompressibleNoiseBuffer(void* buffer, size_t bufferSize, double proba, U32* seed)
kusano 7d535a
{
kusano 7d535a
    BYTE* BBuffer = (BYTE*)buffer;
kusano 7d535a
    size_t pos = 0;
kusano 7d535a
    U32 P32 = (U32)(32768 * proba);
kusano 7d535a
kusano 7d535a
    /* First Bytes */
kusano 7d535a
    while (pos < 20)
kusano 7d535a
        BBuffer[pos++] = (BYTE)(FUZ_rand(seed));
kusano 7d535a
kusano 7d535a
    while (pos < bufferSize)
kusano 7d535a
    {
kusano 7d535a
        /* Select : Literal (noise) or copy (within 64K) */
kusano 7d535a
        if (FUZ_RAND15BITS < P32)
kusano 7d535a
        {
kusano 7d535a
            /* Copy (within 64K) */
kusano 7d535a
            size_t match, d;
kusano 7d535a
            size_t length = FUZ_RANDLENGTH + 4;
kusano 7d535a
            size_t offset = FUZ_RAND15BITS + 1;
kusano 7d535a
            while (offset > pos) offset >>= 1;
kusano 7d535a
            d = pos + length;
kusano 7d535a
            while (d > bufferSize) d = bufferSize;
kusano 7d535a
            match = pos - offset;
kusano 7d535a
            while (pos < d) BBuffer[pos++] = BBuffer[match++];
kusano 7d535a
        }
kusano 7d535a
        else
kusano 7d535a
        {
kusano 7d535a
            /* Literal (noise) */
kusano 7d535a
            size_t d;
kusano 7d535a
            size_t length = FUZ_RANDLENGTH;
kusano 7d535a
            d = pos + length;
kusano 7d535a
            if (d > bufferSize) d = bufferSize;
kusano 7d535a
            while (pos < d) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5);
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
#define MAX_NB_BUFF_I134 150
kusano 7d535a
#define BLOCKSIZE_I134   (32 MB)
kusano 7d535a
static int FUZ_AddressOverflow(void)
kusano 7d535a
{
kusano 7d535a
    char* buffers[MAX_NB_BUFF_I134+1];
kusano 7d535a
    int i, nbBuff=0;
kusano 7d535a
    int highAddress = 0;
kusano 7d535a
kusano 7d535a
    DISPLAY("Overflow tests : ");
kusano 7d535a
kusano 7d535a
    /* Only possible in 32-bits */
kusano 7d535a
    if (sizeof(void*)==8)
kusano 7d535a
    {
kusano 7d535a
        DISPLAY("64 bits mode : no overflow \n");
kusano 7d535a
        fflush(stdout);
kusano 7d535a
        return 0;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    buffers[0] = (char*)malloc(BLOCKSIZE_I134);
kusano 7d535a
    buffers[1] = (char*)malloc(BLOCKSIZE_I134);
kusano 7d535a
    if ((!buffers[0]) || (!buffers[1]))
kusano 7d535a
    {
kusano 7d535a
        DISPLAY("not enough memory for tests \n");
kusano 7d535a
        return 0;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    for (nbBuff=2; nbBuff < MAX_NB_BUFF_I134; nbBuff++)
kusano 7d535a
    {
kusano 7d535a
        DISPLAY("%3i \b\b\b\b", nbBuff);
kusano 7d535a
        buffers[nbBuff] = (char*)malloc(BLOCKSIZE_I134);
kusano 7d535a
        if (buffers[nbBuff]==NULL) goto _endOfTests;
kusano 7d535a
        //DISPLAY("%08X ", (U32)(size_t)(buffers[nbBuff])); fflush(stdout);
kusano 7d535a
kusano 7d535a
        if (((size_t)buffers[nbBuff] > (size_t)0x80000000) && (!highAddress))
kusano 7d535a
        {
kusano 7d535a
            DISPLAY("high address detected : ");
kusano 7d535a
            fflush(stdout);
kusano 7d535a
            highAddress=1;
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        {
kusano 7d535a
            size_t sizeToGenerateOverflow = (size_t)(- ((size_t)buffers[nbBuff-1]) + 512);
kusano 7d535a
            int nbOf255 = (int)((sizeToGenerateOverflow / 255) + 1);
kusano 7d535a
            char* input = buffers[nbBuff-1];
kusano 7d535a
            char* output = buffers[nbBuff];
kusano 7d535a
            int r;
kusano 7d535a
            input[0] = (char)0xF0;   // Literal length overflow
kusano 7d535a
            input[1] = (char)0xFF;
kusano 7d535a
            input[2] = (char)0xFF;
kusano 7d535a
            input[3] = (char)0xFF;
kusano 7d535a
            for(i = 4; i <= nbOf255+4; i++) input[i] = (char)0xff;
kusano 7d535a
            r = LZ4_decompress_safe(input, output, nbOf255+64, BLOCKSIZE_I134);
kusano 7d535a
            if (r>0) goto _overflowError;
kusano 7d535a
            input[0] = (char)0x1F;   // Match length overflow
kusano 7d535a
            input[1] = (char)0x01;
kusano 7d535a
            input[2] = (char)0x01;
kusano 7d535a
            input[3] = (char)0x00;
kusano 7d535a
            r = LZ4_decompress_safe(input, output, nbOf255+64, BLOCKSIZE_I134);
kusano 7d535a
            if (r>0) goto _overflowError;
kusano 7d535a
kusano 7d535a
            output = buffers[nbBuff-2];   // Reverse in/out pointer order
kusano 7d535a
            input[0] = (char)0xF0;   // Literal length overflow
kusano 7d535a
            input[1] = (char)0xFF;
kusano 7d535a
            input[2] = (char)0xFF;
kusano 7d535a
            input[3] = (char)0xFF;
kusano 7d535a
            r = LZ4_decompress_safe(input, output, nbOf255+64, BLOCKSIZE_I134);
kusano 7d535a
            if (r>0) goto _overflowError;
kusano 7d535a
            input[0] = (char)0x1F;   // Match length overflow
kusano 7d535a
            input[1] = (char)0x01;
kusano 7d535a
            input[2] = (char)0x01;
kusano 7d535a
            input[3] = (char)0x00;
kusano 7d535a
            r = LZ4_decompress_safe(input, output, nbOf255+64, BLOCKSIZE_I134);
kusano 7d535a
            if (r>0) goto _overflowError;
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    nbBuff++;
kusano 7d535a
_endOfTests:
kusano 7d535a
    for (i=0 ; i
kusano 7d535a
    if (!highAddress) DISPLAY("high address not possible \n");
kusano 7d535a
    else DISPLAY("all overflows correctly detected \n");
kusano 7d535a
    return 0;
kusano 7d535a
kusano 7d535a
_overflowError:
kusano 7d535a
    DISPLAY("Address space overflow error !! \n");
kusano 7d535a
    exit(1);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static void FUZ_displayUpdate(unsigned testNb)
kusano 7d535a
{
kusano 7d535a
    if ((FUZ_GetMilliSpan(g_time) > g_refreshRate) || (g_displayLevel>=3))
kusano 7d535a
    {
kusano 7d535a
        g_time = FUZ_GetMilliStart();
kusano 7d535a
        DISPLAY("\r%5u   ", testNb);
kusano 7d535a
        if (g_displayLevel>=3) fflush(stdout);
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static void FUZ_findDiff(const void* buff1, const void* buff2)
kusano 7d535a
{
kusano 7d535a
    const BYTE* b1 = (const BYTE*)buff1;
kusano 7d535a
    const BYTE* b2 = (const BYTE*)buff2;
kusano 7d535a
    size_t i=0;
kusano 7d535a
    while (b1[i]==b2[i]) i++;
kusano 7d535a
    DISPLAY("Wrong Byte at position %u\n", (unsigned)i);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double compressibility, U32 duration)
kusano 7d535a
{
kusano 7d535a
    unsigned long long bytes = 0;
kusano 7d535a
    unsigned long long cbytes = 0;
kusano 7d535a
    unsigned long long hcbytes = 0;
kusano 7d535a
    unsigned long long ccbytes = 0;
kusano 7d535a
    void* CNBuffer;
kusano 7d535a
    char* compressedBuffer;
kusano 7d535a
    char* decodedBuffer;
kusano 7d535a
#   define FUZ_max   LZ4_COMPRESSBOUND(LEN)
kusano 7d535a
    int ret;
kusano 7d535a
    unsigned cycleNb;
kusano 7d535a
#   define FUZ_CHECKTEST(cond, ...) if (cond) { printf("Test %u : ", testNb); printf(__VA_ARGS__); \
kusano 7d535a
                                                printf(" (seed %u, cycle %u) \n", seed, cycleNb); goto _output_error; }
kusano 7d535a
#   define FUZ_DISPLAYTEST          { testNb++; g_displayLevel<3 ? 0 : printf("%2u\b\b", testNb); if (g_displayLevel==4) fflush(stdout); }
kusano 7d535a
    void* stateLZ4   = malloc(LZ4_sizeofState());
kusano 7d535a
    void* stateLZ4HC = malloc(LZ4_sizeofStateHC());
kusano 7d535a
    LZ4_stream_t LZ4dict;
kusano 7d535a
    LZ4_streamHC_t LZ4dictHC;
kusano 7d535a
    U32 crcOrig, crcCheck;
kusano 7d535a
    U32 coreRandState = seed;
kusano 7d535a
    U32 randState = coreRandState ^ PRIME3;
kusano 7d535a
    int result = 0;
kusano 7d535a
    const U32 startTime = FUZ_GetMilliStart();
kusano 7d535a
kusano 7d535a
kusano 7d535a
    /* init */
kusano 7d535a
    memset(&LZ4dict, 0, sizeof(LZ4dict));
kusano 7d535a
    duration *= 1000;
kusano 7d535a
kusano 7d535a
    /* Create compressible test buffer */
kusano 7d535a
    CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
kusano 7d535a
    FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState);
kusano 7d535a
    compressedBuffer = (char*)malloc(LZ4_compressBound(FUZ_MAX_BLOCK_SIZE));
kusano 7d535a
    decodedBuffer = (char*)malloc(FUZ_MAX_DICT_SIZE + FUZ_MAX_BLOCK_SIZE);
kusano 7d535a
kusano 7d535a
    /* move to startCycle */
kusano 7d535a
    for (cycleNb = 0; cycleNb < startCycle; cycleNb++)
kusano 7d535a
    {
kusano 7d535a
        (void)FUZ_rand(&coreRandState);
kusano 7d535a
kusano 7d535a
        if (0)   /* some problems are related to dictionary re-use; in this case, enable this loop */
kusano 7d535a
        {
kusano 7d535a
            int dictSize, blockSize, blockStart;
kusano 7d535a
            char* dict;
kusano 7d535a
            char* block;
kusano 7d535a
            FUZ_displayUpdate(cycleNb);
kusano 7d535a
            randState = coreRandState ^ PRIME3;
kusano 7d535a
            blockSize  = FUZ_rand(&randState) % FUZ_MAX_BLOCK_SIZE;
kusano 7d535a
            blockStart = FUZ_rand(&randState) % (COMPRESSIBLE_NOISE_LENGTH - blockSize);
kusano 7d535a
            dictSize   = FUZ_rand(&randState) % FUZ_MAX_DICT_SIZE;
kusano 7d535a
            if (dictSize > blockStart) dictSize = blockStart;
kusano 7d535a
            block = ((char*)CNBuffer) + blockStart;
kusano 7d535a
            dict = block - dictSize;
kusano 7d535a
            LZ4_loadDict(&LZ4dict, dict, dictSize);
kusano 7d535a
            LZ4_compress_continue(&LZ4dict, block, compressedBuffer, blockSize);
kusano 7d535a
            LZ4_loadDict(&LZ4dict, dict, dictSize);
kusano 7d535a
            LZ4_compress_continue(&LZ4dict, block, compressedBuffer, blockSize);
kusano 7d535a
            LZ4_loadDict(&LZ4dict, dict, dictSize);
kusano 7d535a
            LZ4_compress_continue(&LZ4dict, block, compressedBuffer, blockSize);
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* Main test loop */
kusano 7d535a
    for (cycleNb = startCycle; (cycleNb < nbCycles) || (FUZ_GetMilliSpan(startTime) < duration) ; cycleNb++)
kusano 7d535a
    {
kusano 7d535a
        U32 testNb = 0;
kusano 7d535a
        char* dict;
kusano 7d535a
        char* block;
kusano 7d535a
        int dictSize, blockSize, blockStart, compressedSize, HCcompressedSize;
kusano 7d535a
        int blockContinueCompressedSize;
kusano 7d535a
kusano 7d535a
        FUZ_displayUpdate(cycleNb);
kusano 7d535a
        (void)FUZ_rand(&coreRandState);
kusano 7d535a
        randState = coreRandState ^ PRIME3;
kusano 7d535a
kusano 7d535a
        /* Select block to test */
kusano 7d535a
        blockSize  = FUZ_rand(&randState) % FUZ_MAX_BLOCK_SIZE;
kusano 7d535a
        blockStart = FUZ_rand(&randState) % (COMPRESSIBLE_NOISE_LENGTH - blockSize);
kusano 7d535a
        dictSize   = FUZ_rand(&randState) % FUZ_MAX_DICT_SIZE;
kusano 7d535a
        if (dictSize > blockStart) dictSize = blockStart;
kusano 7d535a
        block = ((char*)CNBuffer) + blockStart;
kusano 7d535a
        dict = block - dictSize;
kusano 7d535a
kusano 7d535a
        /* Compression tests */
kusano 7d535a
kusano 7d535a
        /* Test compression destSize */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        {
kusano 7d535a
            int srcSize = blockSize;
kusano 7d535a
            int targetSize = srcSize * ((FUZ_rand(&randState) & 127)+1) >> 7;
kusano 7d535a
            char endCheck = FUZ_rand(&randState) & 255;
kusano 7d535a
            compressedBuffer[targetSize] = endCheck;
kusano 7d535a
            ret = LZ4_compress_destSize(block, compressedBuffer, &srcSize, targetSize);
kusano 7d535a
            FUZ_CHECKTEST(ret > targetSize, "LZ4_compress_destSize() result larger than dst buffer !");
kusano 7d535a
            FUZ_CHECKTEST(compressedBuffer[targetSize] != endCheck, "LZ4_compress_destSize() overwrite dst buffer !");
kusano 7d535a
            FUZ_CHECKTEST(srcSize > blockSize, "LZ4_compress_destSize() fed more than src buffer !");
kusano 7d535a
            DISPLAYLEVEL(5, "destSize : %7i/%7i; content%7i/%7i ", ret, targetSize, srcSize, blockSize);
kusano 7d535a
            if (targetSize>0)
kusano 7d535a
            {
kusano 7d535a
                FUZ_CHECKTEST((ret==0), "LZ4_compress_destSize() compression failed");
kusano 7d535a
                /* check correctness */
kusano 7d535a
                FUZ_DISPLAYTEST;
kusano 7d535a
kusano 7d535a
                crcOrig = XXH32(block, srcSize, 0);
kusano 7d535a
                compressedSize = ret;
kusano 7d535a
                endCheck = FUZ_rand(&randState) & 255;
kusano 7d535a
                decodedBuffer[srcSize] = endCheck;
kusano 7d535a
                ret = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize, srcSize);
kusano 7d535a
                FUZ_CHECKTEST(ret<0, "LZ4_decompress_safe() failed on data compressed by LZ4_compress_destSize");
kusano 7d535a
                FUZ_CHECKTEST(ret!=srcSize, "LZ4_decompress_safe() failed : did not fully decompressed data");
kusano 7d535a
                FUZ_CHECKTEST(decodedBuffer[srcSize] != endCheck, "LZ4_decompress_safe() overwrite dst buffer !");
kusano 7d535a
                crcCheck = XXH32(decodedBuffer, srcSize, 0);
kusano 7d535a
                FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe() corrupted decoded data");
kusano 7d535a
kusano 7d535a
                DISPLAYLEVEL(5, " OK \n");
kusano 7d535a
            }
kusano 7d535a
            else
kusano 7d535a
                DISPLAYLEVEL(5, " \n");
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* Test compression HC */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_compressHC(block, compressedBuffer, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret==0, "LZ4_compressHC() failed");
kusano 7d535a
        HCcompressedSize = ret;
kusano 7d535a
kusano 7d535a
        /* Test compression HC using external state */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_compressHC_withStateHC(stateLZ4HC, block, compressedBuffer, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret==0, "LZ4_compressHC_withStateHC() failed");
kusano 7d535a
kusano 7d535a
        /* Test compression using external state */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_compress_withState(stateLZ4, block, compressedBuffer, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret==0, "LZ4_compress_withState() failed");
kusano 7d535a
kusano 7d535a
        /* Test compression */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_compress(block, compressedBuffer, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret==0, "LZ4_compress() failed");
kusano 7d535a
        compressedSize = ret;
kusano 7d535a
kusano 7d535a
        /* Decompression tests */
kusano 7d535a
kusano 7d535a
        crcOrig = XXH32(block, blockSize, 0);
kusano 7d535a
kusano 7d535a
        /* Test decoding with output size being exactly what's necessary => must work */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_decompress_fast(compressedBuffer, decodedBuffer, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret<0, "LZ4_decompress_fast failed despite correct space");
kusano 7d535a
        FUZ_CHECKTEST(ret!=compressedSize, "LZ4_decompress_fast failed : did not fully read compressed data");
kusano 7d535a
        crcCheck = XXH32(decodedBuffer, blockSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast corrupted decoded data");
kusano 7d535a
kusano 7d535a
        /* Test decoding with one byte missing => must fail */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize-1] = 0;
kusano 7d535a
        ret = LZ4_decompress_fast(compressedBuffer, decodedBuffer, blockSize-1);
kusano 7d535a
        FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast should have failed, due to Output Size being too small");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_fast overrun specified output buffer");
kusano 7d535a
kusano 7d535a
        /* Test decoding with one byte too much => must fail */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_decompress_fast(compressedBuffer, decodedBuffer, blockSize+1);
kusano 7d535a
        FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast should have failed, due to Output Size being too large");
kusano 7d535a
kusano 7d535a
        /* Test decoding with output size exactly what's necessary => must work */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize] = 0;
kusano 7d535a
        ret = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret<0, "LZ4_decompress_safe failed despite sufficient space");
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe did not regenerate original data");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe overrun specified output buffer size");
kusano 7d535a
        crcCheck = XXH32(decodedBuffer, blockSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe corrupted decoded data");
kusano 7d535a
kusano 7d535a
        // Test decoding with more than enough output size => must work
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize] = 0;
kusano 7d535a
        decodedBuffer[blockSize+1] = 0;
kusano 7d535a
        ret = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize, blockSize+1);
kusano 7d535a
        FUZ_CHECKTEST(ret<0, "LZ4_decompress_safe failed despite amply sufficient space");
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe did not regenerate original data");
kusano 7d535a
        //FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe wrote more than (unknown) target size");   // well, is that an issue ?
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize+1], "LZ4_decompress_safe overrun specified output buffer size");
kusano 7d535a
        crcCheck = XXH32(decodedBuffer, blockSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe corrupted decoded data");
kusano 7d535a
kusano 7d535a
        // Test decoding with output size being one byte too short => must fail
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize-1] = 0;
kusano 7d535a
        ret = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize, blockSize-1);
kusano 7d535a
        FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe should have failed, due to Output Size being one byte too short");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_safe overrun specified output buffer size");
kusano 7d535a
kusano 7d535a
        // Test decoding with output size being 10 bytes too short => must fail
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        if (blockSize>10)
kusano 7d535a
        {
kusano 7d535a
            decodedBuffer[blockSize-10] = 0;
kusano 7d535a
            ret = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize, blockSize-10);
kusano 7d535a
            FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe should have failed, due to Output Size being 10 bytes too short");
kusano 7d535a
            FUZ_CHECKTEST(decodedBuffer[blockSize-10], "LZ4_decompress_safe overrun specified output buffer size");
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        // Test decoding with input size being one byte too short => must fail
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize-1, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe should have failed, due to input size being one byte too short (blockSize=%i, ret=%i, compressedSize=%i)", blockSize, ret, compressedSize);
kusano 7d535a
kusano 7d535a
        // Test decoding with input size being one byte too large => must fail
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize] = 0;
kusano 7d535a
        ret = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize+1, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe should have failed, due to input size being too large");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe overrun specified output buffer size");
kusano 7d535a
kusano 7d535a
        // Test partial decoding with target output size being max/2 => must work
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_decompress_safe_partial(compressedBuffer, decodedBuffer, compressedSize, blockSize/2, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret<0, "LZ4_decompress_safe_partial failed despite sufficient space");
kusano 7d535a
kusano 7d535a
        // Test partial decoding with target output size being just below max => must work
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_decompress_safe_partial(compressedBuffer, decodedBuffer, compressedSize, blockSize-3, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(ret<0, "LZ4_decompress_safe_partial failed despite sufficient space");
kusano 7d535a
kusano 7d535a
        /* Test Compression with limited output size */
kusano 7d535a
kusano 7d535a
        /* Test compression with output size being exactly what's necessary (should work) */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_compress_limitedOutput(block, compressedBuffer, blockSize, compressedSize);
kusano 7d535a
        FUZ_CHECKTEST(ret==0, "LZ4_compress_limitedOutput() failed despite sufficient space");
kusano 7d535a
kusano 7d535a
        /* Test compression with output size being exactly what's necessary and external state (should work) */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_compress_limitedOutput_withState(stateLZ4, block, compressedBuffer, blockSize, compressedSize);
kusano 7d535a
        FUZ_CHECKTEST(ret==0, "LZ4_compress_limitedOutput_withState() failed despite sufficient space");
kusano 7d535a
kusano 7d535a
        /* Test HC compression with output size being exactly what's necessary (should work) */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_compressHC_limitedOutput(block, compressedBuffer, blockSize, HCcompressedSize);
kusano 7d535a
        FUZ_CHECKTEST(ret==0, "LZ4_compressHC_limitedOutput() failed despite sufficient space");
kusano 7d535a
kusano 7d535a
        /* Test HC compression with output size being exactly what's necessary (should work) */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_compressHC_limitedOutput_withStateHC(stateLZ4HC, block, compressedBuffer, blockSize, HCcompressedSize);
kusano 7d535a
        FUZ_CHECKTEST(ret==0, "LZ4_compressHC_limitedOutput_withStateHC() failed despite sufficient space");
kusano 7d535a
kusano 7d535a
        /* Test compression with missing bytes into output buffer => must fail */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        {
kusano 7d535a
            int missingBytes = (FUZ_rand(&randState) % 0x3F) + 1;
kusano 7d535a
            if (missingBytes >= compressedSize) missingBytes = compressedSize-1;
kusano 7d535a
            missingBytes += !missingBytes;   /* avoid special case missingBytes==0 */
kusano 7d535a
            compressedBuffer[compressedSize-missingBytes] = 0;
kusano 7d535a
            ret = LZ4_compress_limitedOutput(block, compressedBuffer, blockSize, compressedSize-missingBytes);
kusano 7d535a
            FUZ_CHECKTEST(ret, "LZ4_compress_limitedOutput should have failed (output buffer too small by %i byte)", missingBytes);
kusano 7d535a
            FUZ_CHECKTEST(compressedBuffer[compressedSize-missingBytes], "LZ4_compress_limitedOutput overran output buffer ! (%i missingBytes)", missingBytes)
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* Test HC compression with missing bytes into output buffer => must fail */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        {
kusano 7d535a
            int missingBytes = (FUZ_rand(&randState) % 0x3F) + 1;
kusano 7d535a
            if (missingBytes >= HCcompressedSize) missingBytes = HCcompressedSize-1;
kusano 7d535a
            missingBytes += !missingBytes;   /* avoid special case missingBytes==0 */
kusano 7d535a
            compressedBuffer[HCcompressedSize-missingBytes] = 0;
kusano 7d535a
            ret = LZ4_compressHC_limitedOutput(block, compressedBuffer, blockSize, HCcompressedSize-missingBytes);
kusano 7d535a
            FUZ_CHECKTEST(ret, "LZ4_compressHC_limitedOutput should have failed (output buffer too small by %i byte)", missingBytes);
kusano 7d535a
            FUZ_CHECKTEST(compressedBuffer[HCcompressedSize-missingBytes], "LZ4_compressHC_limitedOutput overran output buffer ! (%i missingBytes)", missingBytes)
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
kusano 7d535a
        /********************/
kusano 7d535a
        /* Dictionary tests */
kusano 7d535a
        /********************/
kusano 7d535a
kusano 7d535a
        /* Compress using dictionary */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        {
kusano 7d535a
            LZ4_stream_t LZ4_stream;
kusano 7d535a
            LZ4_resetStream(&LZ4_stream);
kusano 7d535a
            LZ4_compress_continue (&LZ4_stream, dict, compressedBuffer, dictSize);   /* Just to fill hash tables */
kusano 7d535a
            blockContinueCompressedSize = LZ4_compress_continue (&LZ4_stream, block, compressedBuffer, blockSize);
kusano 7d535a
            FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_continue failed");
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* Decompress with dictionary as prefix */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        memcpy(decodedBuffer, dict, dictSize);
kusano 7d535a
        ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer+dictSize, blockSize, decodedBuffer, dictSize);
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_withPrefix64k did not read all compressed block input");
kusano 7d535a
        crcCheck = XXH32(decodedBuffer+dictSize, blockSize, 0);
kusano 7d535a
        if (crcCheck!=crcOrig)
kusano 7d535a
        {
kusano 7d535a
            int i=0;
kusano 7d535a
            while (block[i]==decodedBuffer[i]) i++;
kusano 7d535a
            printf("Wrong Byte at position %i/%i\n", i, blockSize);
kusano 7d535a
kusano 7d535a
        }
kusano 7d535a
        FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast_withPrefix64k corrupted decoded data (dict %i)", dictSize);
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer+dictSize, blockContinueCompressedSize, blockSize, decodedBuffer, dictSize);
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data");
kusano 7d535a
        crcCheck = XXH32(decodedBuffer+dictSize, blockSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data");
kusano 7d535a
kusano 7d535a
        /* Compress using External dictionary */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        dict -= (FUZ_rand(&randState) & 0xF) + 1;   /* Separation, so it is an ExtDict */
kusano 7d535a
        if (dict < (char*)CNBuffer) dict = (char*)CNBuffer;
kusano 7d535a
        LZ4_loadDict(&LZ4dict, dict, dictSize);
kusano 7d535a
        blockContinueCompressedSize = LZ4_compress_continue(&LZ4dict, block, compressedBuffer, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_continue failed");
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        LZ4_loadDict(&LZ4dict, dict, dictSize);
kusano 7d535a
        ret = LZ4_compress_limitedOutput_continue(&LZ4dict, block, compressedBuffer, blockSize, blockContinueCompressedSize-1);
kusano 7d535a
        FUZ_CHECKTEST(ret>0, "LZ4_compress_limitedOutput_continue using ExtDict should fail : one missing byte for output buffer : %i written, %i buffer", ret, blockContinueCompressedSize);
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        LZ4_loadDict(&LZ4dict, dict, dictSize);
kusano 7d535a
        ret = LZ4_compress_limitedOutput_continue(&LZ4dict, block, compressedBuffer, blockSize, blockContinueCompressedSize);
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_limitedOutput_compressed size is different (%i != %i)", ret, blockContinueCompressedSize);
kusano 7d535a
        FUZ_CHECKTEST(ret<=0, "LZ4_compress_limitedOutput_continue should work : enough size available within output buffer");
kusano 7d535a
kusano 7d535a
        /* Decompress with dictionary as external */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize] = 0;
kusano 7d535a
        ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer, blockSize, dict, dictSize);
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_usingDict did not read all compressed block input");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_fast_usingDict overrun specified output buffer size")
kusano 7d535a
            crcCheck = XXH32(decodedBuffer, blockSize, 0);
kusano 7d535a
        if (crcCheck!=crcOrig)
kusano 7d535a
            FUZ_findDiff(block, decodedBuffer);
kusano 7d535a
        FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize);
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize] = 0;
kusano 7d535a
        ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize);
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size")
kusano 7d535a
            crcCheck = XXH32(decodedBuffer, blockSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data");
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize-1] = 0;
kusano 7d535a
        ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer, blockSize-1, dict, dictSize);
kusano 7d535a
        FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast_usingDict should have failed : wrong original size (-1 byte)");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_fast_usingDict overrun specified output buffer size");
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize-1] = 0;
kusano 7d535a
        ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize-1, dict, dictSize);
kusano 7d535a
        FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe_usingDict should have failed : not enough output size (-1 byte)");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_safe_usingDict overrun specified output buffer size");
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        {
kusano 7d535a
            U32 missingBytes = (FUZ_rand(&randState) & 0xF) + 2;
kusano 7d535a
            if ((U32)blockSize > missingBytes)
kusano 7d535a
            {
kusano 7d535a
                decodedBuffer[blockSize-missingBytes] = 0;
kusano 7d535a
                ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize-missingBytes, dict, dictSize);
kusano 7d535a
                FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe_usingDict should have failed : output buffer too small (-%u byte)", missingBytes);
kusano 7d535a
                FUZ_CHECKTEST(decodedBuffer[blockSize-missingBytes], "LZ4_decompress_safe_usingDict overrun specified output buffer size (-%u byte) (blockSize=%i)", missingBytes, blockSize);
kusano 7d535a
            }
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* Compress HC using External dictionary */
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        dict -= (FUZ_rand(&randState) & 7);    /* even bigger separation */
kusano 7d535a
        if (dict < (char*)CNBuffer) dict = (char*)CNBuffer;
kusano 7d535a
        LZ4_resetStreamHC (&LZ4dictHC, FUZ_rand(&randState) & 0x7);
kusano 7d535a
        LZ4_loadDictHC(&LZ4dictHC, dict, dictSize);
kusano 7d535a
        blockContinueCompressedSize = LZ4_compressHC_continue(&LZ4dictHC, block, compressedBuffer, blockSize);
kusano 7d535a
        FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compressHC_continue failed");
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        LZ4_loadDictHC(&LZ4dictHC, dict, dictSize);
kusano 7d535a
        ret = LZ4_compressHC_limitedOutput_continue(&LZ4dictHC, block, compressedBuffer, blockSize, blockContinueCompressedSize-1);
kusano 7d535a
        FUZ_CHECKTEST(ret>0, "LZ4_compressHC_limitedOutput_continue using ExtDict should fail : one missing byte for output buffer");
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        LZ4_loadDictHC(&LZ4dictHC, dict, dictSize);
kusano 7d535a
        ret = LZ4_compressHC_limitedOutput_continue(&LZ4dictHC, block, compressedBuffer, blockSize, blockContinueCompressedSize);
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_limitedOutput_compressed size is different (%i != %i)", ret, blockContinueCompressedSize);
kusano 7d535a
        FUZ_CHECKTEST(ret<=0, "LZ4_compress_limitedOutput_continue should work : enough size available within output buffer");
kusano 7d535a
kusano 7d535a
        FUZ_DISPLAYTEST;
kusano 7d535a
        decodedBuffer[blockSize] = 0;
kusano 7d535a
        ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize);
kusano 7d535a
        FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data");
kusano 7d535a
        FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size")
kusano 7d535a
            crcCheck = XXH32(decodedBuffer, blockSize, 0);
kusano 7d535a
        if (crcCheck!=crcOrig)
kusano 7d535a
            FUZ_findDiff(block, decodedBuffer);
kusano 7d535a
        FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data");
kusano 7d535a
kusano 7d535a
        /* ***** End of tests *** */
kusano 7d535a
        /* Fill stats */
kusano 7d535a
        bytes += blockSize;
kusano 7d535a
        cbytes += compressedSize;
kusano 7d535a
        hcbytes += HCcompressedSize;
kusano 7d535a
        ccbytes += blockContinueCompressedSize;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    if (nbCycles<=1) nbCycles = cycleNb;   /* end by time */
kusano 7d535a
    bytes += !bytes;   /* avoid division by 0 */
kusano 7d535a
    printf("\r%7u /%7u   - ", cycleNb, nbCycles);
kusano 7d535a
    printf("all tests completed successfully \n");
kusano 7d535a
    printf("compression ratio: %0.3f%%\n", (double)cbytes/bytes*100);
kusano 7d535a
    printf("HC compression ratio: %0.3f%%\n", (double)hcbytes/bytes*100);
kusano 7d535a
    printf("ratio with dict: %0.3f%%\n", (double)ccbytes/bytes*100);
kusano 7d535a
kusano 7d535a
    /* release memory */
kusano 7d535a
    {
kusano 7d535a
_exit:
kusano 7d535a
        free(CNBuffer);
kusano 7d535a
        free(compressedBuffer);
kusano 7d535a
        free(decodedBuffer);
kusano 7d535a
        free(stateLZ4);
kusano 7d535a
        free(stateLZ4HC);
kusano 7d535a
        return result;
kusano 7d535a
kusano 7d535a
_output_error:
kusano 7d535a
        result = 1;
kusano 7d535a
        goto _exit;
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
#define testInputSize (192 KB)
kusano 7d535a
#define testCompressedSize (128 KB)
kusano 7d535a
#define ringBufferSize (8 KB)
kusano 7d535a
kusano 7d535a
static void FUZ_unitTests(void)
kusano 7d535a
{
kusano 7d535a
    const unsigned testNb = 0;
kusano 7d535a
    const unsigned seed   = 0;
kusano 7d535a
    const unsigned cycleNb= 0;
kusano 7d535a
    char testInput[testInputSize];
kusano 7d535a
    char testCompressed[testCompressedSize];
kusano 7d535a
    char testVerify[testInputSize];
kusano 7d535a
    char ringBuffer[ringBufferSize];
kusano 7d535a
    U32 randState = 1;
kusano 7d535a
kusano 7d535a
    /* Init */
kusano 7d535a
    FUZ_fillCompressibleNoiseBuffer(testInput, testInputSize, 0.50, &randState);
kusano 7d535a
kusano 7d535a
    /* 32-bits address space overflow test */
kusano 7d535a
    FUZ_AddressOverflow();
kusano 7d535a
kusano 7d535a
    /* LZ4 streaming tests */
kusano 7d535a
    {
kusano 7d535a
        LZ4_stream_t* statePtr;
kusano 7d535a
        LZ4_stream_t  streamingState;
kusano 7d535a
        U64 crcOrig;
kusano 7d535a
        U64 crcNew;
kusano 7d535a
        int result;
kusano 7d535a
kusano 7d535a
        /* Allocation test */
kusano 7d535a
        statePtr = LZ4_createStream();
kusano 7d535a
        FUZ_CHECKTEST(statePtr==NULL, "LZ4_createStream() allocation failed");
kusano 7d535a
        LZ4_freeStream(statePtr);
kusano 7d535a
kusano 7d535a
        /* simple compression test */
kusano 7d535a
        crcOrig = XXH64(testInput, testCompressedSize, 0);
kusano 7d535a
        LZ4_resetStream(&streamingState);
kusano 7d535a
        result = LZ4_compress_limitedOutput_continue(&streamingState, testInput, testCompressed, testCompressedSize, testCompressedSize-1);
kusano 7d535a
        FUZ_CHECKTEST(result==0, "LZ4_compress_limitedOutput_continue() compression failed");
kusano 7d535a
kusano 7d535a
        result = LZ4_decompress_safe(testCompressed, testVerify, result, testCompressedSize);
kusano 7d535a
        FUZ_CHECKTEST(result!=(int)testCompressedSize, "LZ4_decompress_safe() decompression failed");
kusano 7d535a
        crcNew = XXH64(testVerify, testCompressedSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption");
kusano 7d535a
kusano 7d535a
        /* ring buffer test */
kusano 7d535a
        {
kusano 7d535a
            XXH64_state_t xxhOrig;
kusano 7d535a
            XXH64_state_t xxhNew;
kusano 7d535a
            LZ4_streamDecode_t decodeState;
kusano 7d535a
            const U32 maxMessageSizeLog = 10;
kusano 7d535a
            const U32 maxMessageSizeMask = (1<
kusano 7d535a
            U32 messageSize = (FUZ_rand(&randState) & maxMessageSizeMask) + 1;
kusano 7d535a
            U32 iNext = 0;
kusano 7d535a
            U32 rNext = 0;
kusano 7d535a
            U32 dNext = 0;
kusano 7d535a
            const U32 dBufferSize = ringBufferSize + maxMessageSizeMask;
kusano 7d535a
kusano 7d535a
            XXH64_reset(&xxhOrig, 0);
kusano 7d535a
            XXH64_reset(&xxhNew, 0);
kusano 7d535a
            LZ4_resetStream(&streamingState);
kusano 7d535a
            LZ4_setStreamDecode(&decodeState, NULL, 0);
kusano 7d535a
kusano 7d535a
            while (iNext + messageSize < testCompressedSize)
kusano 7d535a
            {
kusano 7d535a
                XXH64_update(&xxhOrig, testInput + iNext, messageSize);
kusano 7d535a
                crcOrig = XXH64_digest(&xxhOrig);
kusano 7d535a
kusano 7d535a
                memcpy (ringBuffer + rNext, testInput + iNext, messageSize);
kusano 7d535a
                result = LZ4_compress_limitedOutput_continue(&streamingState, ringBuffer + rNext, testCompressed, messageSize, testCompressedSize-ringBufferSize);
kusano 7d535a
                FUZ_CHECKTEST(result==0, "LZ4_compress_limitedOutput_continue() compression failed");
kusano 7d535a
kusano 7d535a
                result = LZ4_decompress_safe_continue(&decodeState, testCompressed, testVerify + dNext, result, messageSize);
kusano 7d535a
                FUZ_CHECKTEST(result!=(int)messageSize, "ringBuffer : LZ4_decompress_safe() test failed");
kusano 7d535a
kusano 7d535a
                XXH64_update(&xxhNew, testVerify + dNext, messageSize);
kusano 7d535a
                crcNew = XXH64_digest(&xxhNew);
kusano 7d535a
                FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption");
kusano 7d535a
kusano 7d535a
                /* prepare next message */
kusano 7d535a
                iNext += messageSize;
kusano 7d535a
                rNext += messageSize;
kusano 7d535a
                dNext += messageSize;
kusano 7d535a
                messageSize = (FUZ_rand(&randState) & maxMessageSizeMask) + 1;
kusano 7d535a
                if (rNext + messageSize > ringBufferSize) rNext = 0;
kusano 7d535a
                if (dNext + messageSize > dBufferSize) dNext = 0;
kusano 7d535a
            }
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* LZ4 HC streaming tests */
kusano 7d535a
    {
kusano 7d535a
        LZ4_streamHC_t* sp;
kusano 7d535a
        LZ4_streamHC_t  sHC;
kusano 7d535a
        U64 crcOrig;
kusano 7d535a
        U64 crcNew;
kusano 7d535a
        int result;
kusano 7d535a
kusano 7d535a
        /* Allocation test */
kusano 7d535a
        sp = LZ4_createStreamHC();
kusano 7d535a
        FUZ_CHECKTEST(sp==NULL, "LZ4_createStreamHC() allocation failed");
kusano 7d535a
        LZ4_freeStreamHC(sp);
kusano 7d535a
kusano 7d535a
        /* simple HC compression test */
kusano 7d535a
        crcOrig = XXH64(testInput, testCompressedSize, 0);
kusano 7d535a
        LZ4_resetStreamHC(&sHC, 0);
kusano 7d535a
        result = LZ4_compressHC_limitedOutput_continue(&sHC, testInput, testCompressed, testCompressedSize, testCompressedSize-1);
kusano 7d535a
        FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() compression failed");
kusano 7d535a
kusano 7d535a
        result = LZ4_decompress_safe(testCompressed, testVerify, result, testCompressedSize);
kusano 7d535a
        FUZ_CHECKTEST(result!=(int)testCompressedSize, "LZ4_decompress_safe() decompression failed");
kusano 7d535a
        crcNew = XXH64(testVerify, testCompressedSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption");
kusano 7d535a
kusano 7d535a
        /* simple dictionary HC compression test */
kusano 7d535a
        crcOrig = XXH64(testInput + 64 KB, testCompressedSize, 0);
kusano 7d535a
        LZ4_resetStreamHC(&sHC, 0);
kusano 7d535a
        LZ4_loadDictHC(&sHC, testInput, 64 KB);
kusano 7d535a
        result = LZ4_compressHC_limitedOutput_continue(&sHC, testInput + 64 KB, testCompressed, testCompressedSize, testCompressedSize-1);
kusano 7d535a
        FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i", result);
kusano 7d535a
kusano 7d535a
        result = LZ4_decompress_safe_usingDict(testCompressed, testVerify, result, testCompressedSize, testInput, 64 KB);
kusano 7d535a
        FUZ_CHECKTEST(result!=(int)testCompressedSize, "LZ4_decompress_safe() simple dictionary decompression test failed");
kusano 7d535a
        crcNew = XXH64(testVerify, testCompressedSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() simple dictionary decompression test : corruption");
kusano 7d535a
kusano 7d535a
        /* multiple HC compression test with dictionary */
kusano 7d535a
        {
kusano 7d535a
            int result1, result2;
kusano 7d535a
            int segSize = testCompressedSize / 2;
kusano 7d535a
            crcOrig = XXH64(testInput + segSize, testCompressedSize, 0);
kusano 7d535a
            LZ4_resetStreamHC(&sHC, 0);
kusano 7d535a
            LZ4_loadDictHC(&sHC, testInput, segSize);
kusano 7d535a
            result1 = LZ4_compressHC_limitedOutput_continue(&sHC, testInput + segSize, testCompressed, segSize, segSize -1);
kusano 7d535a
            FUZ_CHECKTEST(result1==0, "LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i", result1);
kusano 7d535a
            result2 = LZ4_compressHC_limitedOutput_continue(&sHC, testInput + 2*segSize, testCompressed+result1, segSize, segSize-1);
kusano 7d535a
            FUZ_CHECKTEST(result2==0, "LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i", result2);
kusano 7d535a
kusano 7d535a
            result = LZ4_decompress_safe_usingDict(testCompressed, testVerify, result1, segSize, testInput, segSize);
kusano 7d535a
            FUZ_CHECKTEST(result!=segSize, "LZ4_decompress_safe() dictionary decompression part 1 failed");
kusano 7d535a
            result = LZ4_decompress_safe_usingDict(testCompressed+result1, testVerify+segSize, result2, segSize, testInput, 2*segSize);
kusano 7d535a
            FUZ_CHECKTEST(result!=segSize, "LZ4_decompress_safe() dictionary decompression part 2 failed");
kusano 7d535a
            crcNew = XXH64(testVerify, testCompressedSize, 0);
kusano 7d535a
            FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() dictionary decompression corruption");
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* remote dictionary HC compression test */
kusano 7d535a
        crcOrig = XXH64(testInput + 64 KB, testCompressedSize, 0);
kusano 7d535a
        LZ4_resetStreamHC(&sHC, 0);
kusano 7d535a
        LZ4_loadDictHC(&sHC, testInput, 32 KB);
kusano 7d535a
        result = LZ4_compressHC_limitedOutput_continue(&sHC, testInput + 64 KB, testCompressed, testCompressedSize, testCompressedSize-1);
kusano 7d535a
        FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() remote dictionary failed : result = %i", result);
kusano 7d535a
kusano 7d535a
        result = LZ4_decompress_safe_usingDict(testCompressed, testVerify, result, testCompressedSize, testInput, 32 KB);
kusano 7d535a
        FUZ_CHECKTEST(result!=(int)testCompressedSize, "LZ4_decompress_safe_usingDict() decompression failed following remote dictionary HC compression test");
kusano 7d535a
        crcNew = XXH64(testVerify, testCompressedSize, 0);
kusano 7d535a
        FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe_usingDict() decompression corruption");
kusano 7d535a
kusano 7d535a
        /* multiple HC compression with ext. dictionary */
kusano 7d535a
        {
kusano 7d535a
            XXH64_state_t crcOrigState;
kusano 7d535a
            XXH64_state_t crcNewState;
kusano 7d535a
            const char* dict = testInput + 3;
kusano 7d535a
            int dictSize = (FUZ_rand(&randState) & 8191);
kusano 7d535a
            char* dst = testVerify;
kusano 7d535a
kusano 7d535a
            size_t segStart = dictSize + 7;
kusano 7d535a
            int segSize = (FUZ_rand(&randState) & 8191);
kusano 7d535a
            int segNb = 1;
kusano 7d535a
kusano 7d535a
            LZ4_resetStreamHC(&sHC, 0);
kusano 7d535a
            LZ4_loadDictHC(&sHC, dict, dictSize);
kusano 7d535a
kusano 7d535a
            XXH64_reset(&crcOrigState, 0);
kusano 7d535a
            XXH64_reset(&crcNewState, 0);
kusano 7d535a
kusano 7d535a
            while (segStart + segSize < testInputSize)
kusano 7d535a
            {
kusano 7d535a
                XXH64_update(&crcOrigState, testInput + segStart, segSize);
kusano 7d535a
                crcOrig = XXH64_digest(&crcOrigState);
kusano 7d535a
                result = LZ4_compressHC_limitedOutput_continue(&sHC, testInput + segStart, testCompressed, segSize, LZ4_compressBound(segSize));
kusano 7d535a
                FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i", result);
kusano 7d535a
kusano 7d535a
                result = LZ4_decompress_safe_usingDict(testCompressed, dst, result, segSize, dict, dictSize);
kusano 7d535a
                FUZ_CHECKTEST(result!=segSize, "LZ4_decompress_safe_usingDict() dictionary decompression part %i failed", segNb);
kusano 7d535a
                XXH64_update(&crcNewState, dst, segSize);
kusano 7d535a
                crcNew = XXH64_digest(&crcNewState);
kusano 7d535a
                if (crcOrig!=crcNew)
kusano 7d535a
                {
kusano 7d535a
                    size_t c=0;
kusano 7d535a
                    while (dst[c] == testInput[segStart+c]) c++;
kusano 7d535a
                    DISPLAY("Bad decompression at %u / %u \n", (U32)c, (U32)segSize);
kusano 7d535a
                }
kusano 7d535a
                FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe_usingDict() part %i corruption", segNb);
kusano 7d535a
kusano 7d535a
                dict = dst;
kusano 7d535a
                //dict = testInput + segStart;
kusano 7d535a
                dictSize = segSize;
kusano 7d535a
kusano 7d535a
                dst += segSize + 1;
kusano 7d535a
                segNb ++;
kusano 7d535a
kusano 7d535a
                segStart += segSize + (FUZ_rand(&randState) & 0xF) + 1;
kusano 7d535a
                segSize = (FUZ_rand(&randState) & 8191);
kusano 7d535a
            }
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* ring buffer test */
kusano 7d535a
        {
kusano 7d535a
            XXH64_state_t xxhOrig;
kusano 7d535a
            XXH64_state_t xxhNew;
kusano 7d535a
            LZ4_streamDecode_t decodeState;
kusano 7d535a
            const U32 maxMessageSizeLog = 10;
kusano 7d535a
            const U32 maxMessageSizeMask = (1<
kusano 7d535a
            U32 messageSize = (FUZ_rand(&randState) & maxMessageSizeMask) + 1;
kusano 7d535a
            U32 iNext = 0;
kusano 7d535a
            U32 rNext = 0;
kusano 7d535a
            U32 dNext = 0;
kusano 7d535a
            const U32 dBufferSize = ringBufferSize + maxMessageSizeMask;
kusano 7d535a
kusano 7d535a
            XXH64_reset(&xxhOrig, 0);
kusano 7d535a
            XXH64_reset(&xxhNew, 0);
kusano 7d535a
            LZ4_resetStreamHC(&sHC, 0);
kusano 7d535a
            LZ4_setStreamDecode(&decodeState, NULL, 0);
kusano 7d535a
kusano 7d535a
            while (iNext + messageSize < testCompressedSize)
kusano 7d535a
            {
kusano 7d535a
                XXH64_update(&xxhOrig, testInput + iNext, messageSize);
kusano 7d535a
                crcOrig = XXH64_digest(&xxhOrig);
kusano 7d535a
kusano 7d535a
                memcpy (ringBuffer + rNext, testInput + iNext, messageSize);
kusano 7d535a
                result = LZ4_compressHC_limitedOutput_continue(&sHC, ringBuffer + rNext, testCompressed, messageSize, testCompressedSize-ringBufferSize);
kusano 7d535a
                FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() compression failed");
kusano 7d535a
kusano 7d535a
                result = LZ4_decompress_safe_continue(&decodeState, testCompressed, testVerify + dNext, result, messageSize);
kusano 7d535a
                FUZ_CHECKTEST(result!=(int)messageSize, "ringBuffer : LZ4_decompress_safe() test failed");
kusano 7d535a
kusano 7d535a
                XXH64_update(&xxhNew, testVerify + dNext, messageSize);
kusano 7d535a
                crcNew = XXH64_digest(&xxhNew);
kusano 7d535a
                FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption");
kusano 7d535a
kusano 7d535a
                // prepare next message
kusano 7d535a
                iNext += messageSize;
kusano 7d535a
                rNext += messageSize;
kusano 7d535a
                dNext += messageSize;
kusano 7d535a
                messageSize = (FUZ_rand(&randState) & maxMessageSizeMask) + 1;
kusano 7d535a
                if (rNext + messageSize > ringBufferSize) rNext = 0;
kusano 7d535a
                if (dNext + messageSize > dBufferSize) dNext = 0;
kusano 7d535a
            }
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* small decoder-side ring buffer test */
kusano 7d535a
        {
kusano 7d535a
            XXH64_state_t xxhOrig;
kusano 7d535a
            XXH64_state_t xxhNew;
kusano 7d535a
            LZ4_streamDecode_t decodeState;
kusano 7d535a
            const U32 maxMessageSizeLog = 12;
kusano 7d535a
            const U32 maxMessageSizeMask = (1<
kusano 7d535a
            U32 messageSize;
kusano 7d535a
            U32 totalMessageSize = 0;
kusano 7d535a
            U32 iNext = 0;
kusano 7d535a
            U32 dNext = 0;
kusano 7d535a
            const U32 dBufferSize = 64 KB;
kusano 7d535a
kusano 7d535a
            XXH64_reset(&xxhOrig, 0);
kusano 7d535a
            XXH64_reset(&xxhNew, 0);
kusano 7d535a
            LZ4_resetStreamHC(&sHC, 0);
kusano 7d535a
            LZ4_setStreamDecode(&decodeState, NULL, 0);
kusano 7d535a
kusano 7d535a
#define BSIZE1 65537
kusano 7d535a
#define BSIZE2 16435
kusano 7d535a
kusano 7d535a
            /* first block */
kusano 7d535a
kusano 7d535a
                messageSize = BSIZE1;
kusano 7d535a
                XXH64_update(&xxhOrig, testInput + iNext, messageSize);
kusano 7d535a
                crcOrig = XXH64_digest(&xxhOrig);
kusano 7d535a
kusano 7d535a
                result = LZ4_compressHC_limitedOutput_continue(&sHC, testInput + iNext, testCompressed, messageSize, testCompressedSize-ringBufferSize);
kusano 7d535a
                FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() compression failed");
kusano 7d535a
kusano 7d535a
                result = LZ4_decompress_safe_continue(&decodeState, testCompressed, testVerify + dNext, result, messageSize);
kusano 7d535a
                FUZ_CHECKTEST(result!=(int)messageSize, "64K D.ringBuffer : LZ4_decompress_safe() test failed");
kusano 7d535a
kusano 7d535a
                XXH64_update(&xxhNew, testVerify + dNext, messageSize);
kusano 7d535a
                crcNew = XXH64_digest(&xxhNew);
kusano 7d535a
                FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption");
kusano 7d535a
kusano 7d535a
                /* prepare next message */
kusano 7d535a
                dNext += messageSize;
kusano 7d535a
                totalMessageSize += messageSize;
kusano 7d535a
                messageSize = BSIZE2;
kusano 7d535a
                iNext = 132000;
kusano 7d535a
                memcpy(testInput + iNext, testInput + 8, messageSize);
kusano 7d535a
                if (dNext > dBufferSize) dNext = 0;
kusano 7d535a
kusano 7d535a
            while (totalMessageSize < 9 MB)
kusano 7d535a
            {
kusano 7d535a
                XXH64_update(&xxhOrig, testInput + iNext, messageSize);
kusano 7d535a
                crcOrig = XXH64_digest(&xxhOrig);
kusano 7d535a
kusano 7d535a
                result = LZ4_compressHC_limitedOutput_continue(&sHC, testInput + iNext, testCompressed, messageSize, testCompressedSize-ringBufferSize);
kusano 7d535a
                FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() compression failed");
kusano 7d535a
kusano 7d535a
                result = LZ4_decompress_safe_continue(&decodeState, testCompressed, testVerify + dNext, result, messageSize);
kusano 7d535a
                FUZ_CHECKTEST(result!=(int)messageSize, "64K D.ringBuffer : LZ4_decompress_safe() test failed");
kusano 7d535a
kusano 7d535a
                XXH64_update(&xxhNew, testVerify + dNext, messageSize);
kusano 7d535a
                crcNew = XXH64_digest(&xxhNew);
kusano 7d535a
                if (crcOrig != crcNew)
kusano 7d535a
                    FUZ_findDiff(testInput + iNext, testVerify + dNext);
kusano 7d535a
                FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption during small decoder-side ring buffer test");
kusano 7d535a
kusano 7d535a
                /* prepare next message */
kusano 7d535a
                dNext += messageSize;
kusano 7d535a
                totalMessageSize += messageSize;
kusano 7d535a
                messageSize = (FUZ_rand(&randState) & maxMessageSizeMask) + 1;
kusano 7d535a
                iNext = (FUZ_rand(&randState) & 65535);
kusano 7d535a
                if (dNext > dBufferSize) dNext = 0;
kusano 7d535a
            }
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    printf("All unit tests completed successfully \n");
kusano 7d535a
    return;
kusano 7d535a
_output_error:
kusano 7d535a
    exit(1);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static int FUZ_usage(char* programName)
kusano 7d535a
{
kusano 7d535a
    DISPLAY( "Usage :\n");
kusano 7d535a
    DISPLAY( "      %s [args]\n", programName);
kusano 7d535a
    DISPLAY( "\n");
kusano 7d535a
    DISPLAY( "Arguments :\n");
kusano 7d535a
    DISPLAY( " -i#    : Nb of tests (default:%i) \n", NB_ATTEMPTS);
kusano 7d535a
    DISPLAY( " -T#    : Duration of tests, in seconds (default: use Nb of tests) \n");
kusano 7d535a
    DISPLAY( " -s#    : Select seed (default:prompt user)\n");
kusano 7d535a
    DISPLAY( " -t#    : Select starting test number (default:0)\n");
kusano 7d535a
    DISPLAY( " -P#    : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
kusano 7d535a
    DISPLAY( " -v     : verbose\n");
kusano 7d535a
    DISPLAY( " -p     : pause at the end\n");
kusano 7d535a
    DISPLAY( " -h     : display help and exit\n");
kusano 7d535a
    return 0;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
int main(int argc, char** argv)
kusano 7d535a
{
kusano 7d535a
    U32 seed=0;
kusano 7d535a
    int seedset=0;
kusano 7d535a
    int argNb;
kusano 7d535a
    int nbTests = NB_ATTEMPTS;
kusano 7d535a
    int testNb = 0;
kusano 7d535a
    int proba = FUZ_COMPRESSIBILITY_DEFAULT;
kusano 7d535a
    int pause = 0;
kusano 7d535a
    char* programName = argv[0];
kusano 7d535a
    U32 duration = 0;
kusano 7d535a
kusano 7d535a
    /* Check command line */
kusano 7d535a
    for(argNb=1; argNb
kusano 7d535a
    {
kusano 7d535a
        char* argument = argv[argNb];
kusano 7d535a
kusano 7d535a
        if(!argument) continue;   // Protection if argument empty
kusano 7d535a
kusano 7d535a
        // Decode command (note : aggregated commands are allowed)
kusano 7d535a
        if (argument[0]=='-')
kusano 7d535a
        {
kusano 7d535a
            if (!strcmp(argument, "--no-prompt")) { pause=0; seedset=1; g_displayLevel=1; continue; }
kusano 7d535a
            argument++;
kusano 7d535a
kusano 7d535a
            while (*argument!=0)
kusano 7d535a
            {
kusano 7d535a
                switch(*argument)
kusano 7d535a
                {
kusano 7d535a
                case 'h':   /* display help */
kusano 7d535a
                    return FUZ_usage(programName);
kusano 7d535a
kusano 7d535a
                case 'v':   /* verbose mode */
kusano 7d535a
                    argument++;
kusano 7d535a
                    g_displayLevel=4;
kusano 7d535a
                    break;
kusano 7d535a
kusano 7d535a
                case 'p':   /* pause at the end */
kusano 7d535a
                    argument++;
kusano 7d535a
                    pause=1;
kusano 7d535a
                    break;
kusano 7d535a
kusano 7d535a
                case 'i':
kusano 7d535a
                    argument++;
kusano 7d535a
                    nbTests = 0; duration = 0;
kusano 7d535a
                    while ((*argument>='0') && (*argument<='9'))
kusano 7d535a
                    {
kusano 7d535a
                        nbTests *= 10;
kusano 7d535a
                        nbTests += *argument - '0';
kusano 7d535a
                        argument++;
kusano 7d535a
                    }
kusano 7d535a
                    break;
kusano 7d535a
kusano 7d535a
                case 'T':
kusano 7d535a
                    argument++;
kusano 7d535a
                    nbTests = 0; duration = 0;
kusano 7d535a
                    for (;;)
kusano 7d535a
                    {
kusano 7d535a
                        switch(*argument)
kusano 7d535a
                        {
kusano 7d535a
                            case 'm': duration *= 60; argument++; continue;
kusano 7d535a
                            case 's':
kusano 7d535a
                            case 'n': argument++; continue;
kusano 7d535a
                            case '0':
kusano 7d535a
                            case '1':
kusano 7d535a
                            case '2':
kusano 7d535a
                            case '3':
kusano 7d535a
                            case '4':
kusano 7d535a
                            case '5':
kusano 7d535a
                            case '6':
kusano 7d535a
                            case '7':
kusano 7d535a
                            case '8':
kusano 7d535a
                            case '9': duration *= 10; duration += *argument++ - '0'; continue;
kusano 7d535a
                        }
kusano 7d535a
                        break;
kusano 7d535a
                    }
kusano 7d535a
                    break;
kusano 7d535a
kusano 7d535a
                case 's':
kusano 7d535a
                    argument++;
kusano 7d535a
                    seed=0; seedset=1;
kusano 7d535a
                    while ((*argument>='0') && (*argument<='9'))
kusano 7d535a
                    {
kusano 7d535a
                        seed *= 10;
kusano 7d535a
                        seed += *argument - '0';
kusano 7d535a
                        argument++;
kusano 7d535a
                    }
kusano 7d535a
                    break;
kusano 7d535a
kusano 7d535a
                case 't':   /* select starting test nb */
kusano 7d535a
                    argument++;
kusano 7d535a
                    testNb=0;
kusano 7d535a
                    while ((*argument>='0') && (*argument<='9'))
kusano 7d535a
                    {
kusano 7d535a
                        testNb *= 10;
kusano 7d535a
                        testNb += *argument - '0';
kusano 7d535a
                        argument++;
kusano 7d535a
                    }
kusano 7d535a
                    break;
kusano 7d535a
kusano 7d535a
                case 'P':  /* change probability */
kusano 7d535a
                    argument++;
kusano 7d535a
                    proba=0;
kusano 7d535a
                    while ((*argument>='0') && (*argument<='9'))
kusano 7d535a
                    {
kusano 7d535a
                        proba *= 10;
kusano 7d535a
                        proba += *argument - '0';
kusano 7d535a
                        argument++;
kusano 7d535a
                    }
kusano 7d535a
                    if (proba<0) proba=0;
kusano 7d535a
                    if (proba>100) proba=100;
kusano 7d535a
                    break;
kusano 7d535a
                default: ;
kusano 7d535a
                }
kusano 7d535a
            }
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    printf("Starting LZ4 fuzzer (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION);
kusano 7d535a
kusano 7d535a
    if (!seedset) seed = FUZ_GetMilliStart() % 10000;
kusano 7d535a
    printf("Seed = %u\n", seed);
kusano 7d535a
    if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) printf("Compressibility : %i%%\n", proba);
kusano 7d535a
kusano 7d535a
    if ((seedset==0) && (testNb==0)) FUZ_unitTests();
kusano 7d535a
kusano 7d535a
    if (nbTests<=0) nbTests=1;
kusano 7d535a
kusano 7d535a
    {
kusano 7d535a
        int result = FUZ_test(seed, nbTests, testNb, ((double)proba) / 100, duration);
kusano 7d535a
        if (pause)
kusano 7d535a
        {
kusano 7d535a
            DISPLAY("press enter ... \n");
kusano 7d535a
            (void)getchar();
kusano 7d535a
        }
kusano 7d535a
        return result;
kusano 7d535a
    }
kusano 7d535a
}