1*3117ece4Schristos /* 2*3117ece4Schristos * Copyright (c) Meta Platforms, Inc. and affiliates. 3*3117ece4Schristos * All rights reserved. 4*3117ece4Schristos * 5*3117ece4Schristos * This source code is licensed under both the BSD-style license (found in the 6*3117ece4Schristos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*3117ece4Schristos * in the COPYING file in the root directory of this source tree). 8*3117ece4Schristos * You may select, at your option, one of the above-listed licenses. 9*3117ece4Schristos */ 10*3117ece4Schristos 11*3117ece4Schristos 12*3117ece4Schristos /*-************************************ 13*3117ece4Schristos * Compiler specific 14*3117ece4Schristos **************************************/ 15*3117ece4Schristos #ifdef _MSC_VER /* Visual Studio */ 16*3117ece4Schristos # define _CRT_SECURE_NO_WARNINGS /* fgets */ 17*3117ece4Schristos # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ 18*3117ece4Schristos # pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */ 19*3117ece4Schristos #endif 20*3117ece4Schristos 21*3117ece4Schristos 22*3117ece4Schristos /*-************************************ 23*3117ece4Schristos * Includes 24*3117ece4Schristos **************************************/ 25*3117ece4Schristos #include <stdlib.h> /* free */ 26*3117ece4Schristos #include <stdio.h> /* fgets, sscanf */ 27*3117ece4Schristos #include <string.h> /* strcmp */ 28*3117ece4Schristos #include <time.h> /* time_t, time(), to randomize seed */ 29*3117ece4Schristos #include <assert.h> /* assert */ 30*3117ece4Schristos #include "timefn.h" /* UTIL_time_t, UTIL_getTime */ 31*3117ece4Schristos #include "mem.h" 32*3117ece4Schristos #define ZSTD_DISABLE_DEPRECATE_WARNINGS /* No deprecation warnings, we still test some deprecated functions */ 33*3117ece4Schristos #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel, ZSTD_customMem, ZSTD_getDictID_fromFrame */ 34*3117ece4Schristos #include "zstd.h" /* ZSTD_compressBound */ 35*3117ece4Schristos #include "zstd_errors.h" /* ZSTD_error_srcSize_wrong */ 36*3117ece4Schristos #include "zdict.h" /* ZDICT_trainFromBuffer */ 37*3117ece4Schristos #include "datagen.h" /* RDG_genBuffer */ 38*3117ece4Schristos #define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ 39*3117ece4Schristos #include "xxhash.h" /* XXH64_* */ 40*3117ece4Schristos #include "seqgen.h" 41*3117ece4Schristos #include "util.h" 42*3117ece4Schristos #include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */ 43*3117ece4Schristos #include "external_matchfinder.h" /* zstreamSequenceProducer, EMF_testCase */ 44*3117ece4Schristos 45*3117ece4Schristos /*-************************************ 46*3117ece4Schristos * Constants 47*3117ece4Schristos **************************************/ 48*3117ece4Schristos #define KB *(1U<<10) 49*3117ece4Schristos #define MB *(1U<<20) 50*3117ece4Schristos #define GB *(1U<<30) 51*3117ece4Schristos 52*3117ece4Schristos static const int nbTestsDefault = 10000; 53*3117ece4Schristos static const U32 g_cLevelMax_smallTests = 10; 54*3117ece4Schristos #define COMPRESSIBLE_NOISE_LENGTH (10 MB) 55*3117ece4Schristos #define FUZ_COMPRESSIBILITY_DEFAULT 50 56*3117ece4Schristos static const U32 prime32 = 2654435761U; 57*3117ece4Schristos 58*3117ece4Schristos 59*3117ece4Schristos /*-************************************ 60*3117ece4Schristos * Display Macros 61*3117ece4Schristos **************************************/ 62*3117ece4Schristos #define DISPLAY(...) fprintf(stderr, __VA_ARGS__) 63*3117ece4Schristos #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { \ 64*3117ece4Schristos DISPLAY(__VA_ARGS__); \ 65*3117ece4Schristos if (g_displayLevel>=4) fflush(stderr); } 66*3117ece4Schristos static U32 g_displayLevel = 2; 67*3117ece4Schristos 68*3117ece4Schristos static const U64 g_refreshRate = SEC_TO_MICRO / 6; 69*3117ece4Schristos static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; 70*3117ece4Schristos 71*3117ece4Schristos #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ 72*3117ece4Schristos if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \ 73*3117ece4Schristos { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ 74*3117ece4Schristos if (g_displayLevel>=4) fflush(stderr); } } 75*3117ece4Schristos 76*3117ece4Schristos static U64 g_clockTime = 0; 77*3117ece4Schristos 78*3117ece4Schristos 79*3117ece4Schristos /*-******************************************************* 80*3117ece4Schristos * Check macros 81*3117ece4Schristos *********************************************************/ 82*3117ece4Schristos #undef MIN 83*3117ece4Schristos #undef MAX 84*3117ece4Schristos #define MIN(a,b) ((a)<(b)?(a):(b)) 85*3117ece4Schristos #define MAX(a,b) ((a)>(b)?(a):(b)) 86*3117ece4Schristos /*! FUZ_rand() : 87*3117ece4Schristos @return : a 27 bits random value, from a 32-bits `seed`. 88*3117ece4Schristos `seed` is also modified */ 89*3117ece4Schristos #define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r))) 90*3117ece4Schristos static U32 FUZ_rand(U32* seedPtr) 91*3117ece4Schristos { 92*3117ece4Schristos static const U32 prime2 = 2246822519U; 93*3117ece4Schristos U32 rand32 = *seedPtr; 94*3117ece4Schristos rand32 *= prime32; 95*3117ece4Schristos rand32 += prime2; 96*3117ece4Schristos rand32 = FUZ_rotl32(rand32, 13); 97*3117ece4Schristos *seedPtr = rand32; 98*3117ece4Schristos return rand32 >> 5; 99*3117ece4Schristos } 100*3117ece4Schristos 101*3117ece4Schristos #define CHECK(cond, ...) { \ 102*3117ece4Schristos if (cond) { \ 103*3117ece4Schristos DISPLAY("Error => "); \ 104*3117ece4Schristos DISPLAY(__VA_ARGS__); \ 105*3117ece4Schristos DISPLAY(" (seed %u, test nb %u, line %u) \n", \ 106*3117ece4Schristos (unsigned)seed, testNb, __LINE__); \ 107*3117ece4Schristos goto _output_error; \ 108*3117ece4Schristos } } 109*3117ece4Schristos 110*3117ece4Schristos #define CHECK_Z(f) { \ 111*3117ece4Schristos size_t const err = f; \ 112*3117ece4Schristos CHECK(ZSTD_isError(err), "%s : %s ", \ 113*3117ece4Schristos #f, ZSTD_getErrorName(err)); \ 114*3117ece4Schristos } 115*3117ece4Schristos 116*3117ece4Schristos #define CHECK_RET(ret, cond, ...) { \ 117*3117ece4Schristos if (cond) { \ 118*3117ece4Schristos DISPLAY("Error %llu => ", (unsigned long long)ret); \ 119*3117ece4Schristos DISPLAY(__VA_ARGS__); \ 120*3117ece4Schristos DISPLAY(" (line %u)\n", __LINE__); \ 121*3117ece4Schristos return ret; \ 122*3117ece4Schristos } } 123*3117ece4Schristos 124*3117ece4Schristos #define CHECK_RET_Z(f) { \ 125*3117ece4Schristos size_t const err = f; \ 126*3117ece4Schristos CHECK_RET(err, ZSTD_isError(err), "%s : %s ", \ 127*3117ece4Schristos #f, ZSTD_getErrorName(err)); \ 128*3117ece4Schristos } 129*3117ece4Schristos 130*3117ece4Schristos 131*3117ece4Schristos /*====================================================== 132*3117ece4Schristos * Basic Unit tests 133*3117ece4Schristos *======================================================*/ 134*3117ece4Schristos 135*3117ece4Schristos typedef struct { 136*3117ece4Schristos void* start; 137*3117ece4Schristos size_t size; 138*3117ece4Schristos size_t filled; 139*3117ece4Schristos } buffer_t; 140*3117ece4Schristos 141*3117ece4Schristos static const buffer_t kBuffNull = { NULL, 0 , 0 }; 142*3117ece4Schristos 143*3117ece4Schristos static void FUZ_freeDictionary(buffer_t dict) 144*3117ece4Schristos { 145*3117ece4Schristos free(dict.start); 146*3117ece4Schristos } 147*3117ece4Schristos 148*3117ece4Schristos static buffer_t FUZ_createDictionary(const void* src, size_t srcSize, size_t blockSize, size_t requestedDictSize) 149*3117ece4Schristos { 150*3117ece4Schristos buffer_t dict = kBuffNull; 151*3117ece4Schristos size_t const nbBlocks = (srcSize + (blockSize-1)) / blockSize; 152*3117ece4Schristos size_t* const blockSizes = (size_t*)malloc(nbBlocks * sizeof(size_t)); 153*3117ece4Schristos if (!blockSizes) return kBuffNull; 154*3117ece4Schristos dict.start = malloc(requestedDictSize); 155*3117ece4Schristos if (!dict.start) { free(blockSizes); return kBuffNull; } 156*3117ece4Schristos { size_t nb; 157*3117ece4Schristos for (nb=0; nb<nbBlocks-1; nb++) blockSizes[nb] = blockSize; 158*3117ece4Schristos blockSizes[nbBlocks-1] = srcSize - (blockSize * (nbBlocks-1)); 159*3117ece4Schristos } 160*3117ece4Schristos { size_t const dictSize = ZDICT_trainFromBuffer(dict.start, requestedDictSize, src, blockSizes, (unsigned)nbBlocks); 161*3117ece4Schristos free(blockSizes); 162*3117ece4Schristos if (ZDICT_isError(dictSize)) { FUZ_freeDictionary(dict); return kBuffNull; } 163*3117ece4Schristos dict.size = requestedDictSize; 164*3117ece4Schristos dict.filled = dictSize; 165*3117ece4Schristos return dict; 166*3117ece4Schristos } 167*3117ece4Schristos } 168*3117ece4Schristos 169*3117ece4Schristos /* Round trips data and updates xxh with the decompressed data produced */ 170*3117ece4Schristos static size_t SEQ_roundTrip(ZSTD_CCtx* cctx, ZSTD_DCtx* dctx, 171*3117ece4Schristos XXH64_state_t* xxh, void* data, size_t size, 172*3117ece4Schristos ZSTD_EndDirective endOp) 173*3117ece4Schristos { 174*3117ece4Schristos static BYTE compressed[1024]; 175*3117ece4Schristos static BYTE uncompressed[1024]; 176*3117ece4Schristos 177*3117ece4Schristos ZSTD_inBuffer cin = {data, size, 0}; 178*3117ece4Schristos size_t cret; 179*3117ece4Schristos 180*3117ece4Schristos do { 181*3117ece4Schristos ZSTD_outBuffer cout = { compressed, sizeof(compressed), 0 }; 182*3117ece4Schristos ZSTD_inBuffer din = { compressed, 0, 0 }; 183*3117ece4Schristos ZSTD_outBuffer dout = { uncompressed, 0, 0 }; 184*3117ece4Schristos 185*3117ece4Schristos cret = ZSTD_compressStream2(cctx, &cout, &cin, endOp); 186*3117ece4Schristos if (ZSTD_isError(cret)) 187*3117ece4Schristos return cret; 188*3117ece4Schristos 189*3117ece4Schristos din.size = cout.pos; 190*3117ece4Schristos while (din.pos < din.size || (endOp == ZSTD_e_end && cret == 0)) { 191*3117ece4Schristos size_t dret; 192*3117ece4Schristos 193*3117ece4Schristos dout.pos = 0; 194*3117ece4Schristos dout.size = sizeof(uncompressed); 195*3117ece4Schristos dret = ZSTD_decompressStream(dctx, &dout, &din); 196*3117ece4Schristos if (ZSTD_isError(dret)) 197*3117ece4Schristos return dret; 198*3117ece4Schristos XXH64_update(xxh, dout.dst, dout.pos); 199*3117ece4Schristos if (dret == 0) 200*3117ece4Schristos break; 201*3117ece4Schristos } 202*3117ece4Schristos } while (cin.pos < cin.size || (endOp != ZSTD_e_continue && cret != 0)); 203*3117ece4Schristos return 0; 204*3117ece4Schristos } 205*3117ece4Schristos 206*3117ece4Schristos /* Generates some data and round trips it */ 207*3117ece4Schristos static size_t SEQ_generateRoundTrip(ZSTD_CCtx* cctx, ZSTD_DCtx* dctx, 208*3117ece4Schristos XXH64_state_t* xxh, SEQ_stream* seq, 209*3117ece4Schristos SEQ_gen_type type, unsigned value) 210*3117ece4Schristos { 211*3117ece4Schristos static BYTE data[1024]; 212*3117ece4Schristos size_t gen; 213*3117ece4Schristos 214*3117ece4Schristos do { 215*3117ece4Schristos SEQ_outBuffer sout = {data, sizeof(data), 0}; 216*3117ece4Schristos size_t ret; 217*3117ece4Schristos gen = SEQ_gen(seq, type, value, &sout); 218*3117ece4Schristos 219*3117ece4Schristos ret = SEQ_roundTrip(cctx, dctx, xxh, sout.dst, sout.pos, ZSTD_e_continue); 220*3117ece4Schristos if (ZSTD_isError(ret)) 221*3117ece4Schristos return ret; 222*3117ece4Schristos } while (gen != 0); 223*3117ece4Schristos 224*3117ece4Schristos return 0; 225*3117ece4Schristos } 226*3117ece4Schristos 227*3117ece4Schristos static size_t getCCtxParams(ZSTD_CCtx* zc, ZSTD_parameters* savedParams) 228*3117ece4Schristos { 229*3117ece4Schristos int value; 230*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_windowLog, (int*)&savedParams->cParams.windowLog)); 231*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_hashLog, (int*)&savedParams->cParams.hashLog)); 232*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_chainLog, (int*)&savedParams->cParams.chainLog)); 233*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_searchLog, (int*)&savedParams->cParams.searchLog)); 234*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_minMatch, (int*)&savedParams->cParams.minMatch)); 235*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetLength, (int*)&savedParams->cParams.targetLength)); 236*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_strategy, &value)); 237*3117ece4Schristos savedParams->cParams.strategy = value; 238*3117ece4Schristos 239*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_checksumFlag, &savedParams->fParams.checksumFlag)); 240*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_contentSizeFlag, &savedParams->fParams.contentSizeFlag)); 241*3117ece4Schristos CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_dictIDFlag, &value)); 242*3117ece4Schristos savedParams->fParams.noDictIDFlag = !value; 243*3117ece4Schristos return 0; 244*3117ece4Schristos } 245*3117ece4Schristos 246*3117ece4Schristos static U32 badParameters(ZSTD_CCtx* zc, ZSTD_parameters const savedParams) 247*3117ece4Schristos { 248*3117ece4Schristos ZSTD_parameters params; 249*3117ece4Schristos if (ZSTD_isError(getCCtxParams(zc, ¶ms))) return 10; 250*3117ece4Schristos CHECK_RET(1, params.cParams.windowLog != savedParams.cParams.windowLog, "windowLog"); 251*3117ece4Schristos CHECK_RET(2, params.cParams.hashLog != savedParams.cParams.hashLog, "hashLog"); 252*3117ece4Schristos CHECK_RET(3, params.cParams.chainLog != savedParams.cParams.chainLog, "chainLog"); 253*3117ece4Schristos CHECK_RET(4, params.cParams.searchLog != savedParams.cParams.searchLog, "searchLog"); 254*3117ece4Schristos CHECK_RET(5, params.cParams.minMatch != savedParams.cParams.minMatch, "minMatch"); 255*3117ece4Schristos CHECK_RET(6, params.cParams.targetLength != savedParams.cParams.targetLength, "targetLength"); 256*3117ece4Schristos 257*3117ece4Schristos CHECK_RET(7, params.fParams.checksumFlag != savedParams.fParams.checksumFlag, "checksumFlag"); 258*3117ece4Schristos CHECK_RET(8, params.fParams.contentSizeFlag != savedParams.fParams.contentSizeFlag, "contentSizeFlag"); 259*3117ece4Schristos CHECK_RET(9, params.fParams.noDictIDFlag != savedParams.fParams.noDictIDFlag, "noDictIDFlag"); 260*3117ece4Schristos return 0; 261*3117ece4Schristos } 262*3117ece4Schristos 263*3117ece4Schristos static int basicUnitTests(U32 seed, double compressibility, int bigTests) 264*3117ece4Schristos { 265*3117ece4Schristos size_t const CNBufferSize = COMPRESSIBLE_NOISE_LENGTH; 266*3117ece4Schristos void* CNBuffer = malloc(CNBufferSize); 267*3117ece4Schristos size_t const skippableFrameSize = 200 KB; 268*3117ece4Schristos size_t const compressedBufferSize = (8 + skippableFrameSize) + ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH); 269*3117ece4Schristos void* compressedBuffer = malloc(compressedBufferSize); 270*3117ece4Schristos size_t const decodedBufferSize = CNBufferSize; 271*3117ece4Schristos void* decodedBuffer = malloc(decodedBufferSize); 272*3117ece4Schristos size_t cSize; 273*3117ece4Schristos int testResult = 0; 274*3117ece4Schristos int testNb = 1; 275*3117ece4Schristos U32 coreSeed = 0; /* this name to conform with CHECK_Z macro display */ 276*3117ece4Schristos ZSTD_CStream* zc = ZSTD_createCStream(); 277*3117ece4Schristos ZSTD_DStream* zd = ZSTD_createDStream(); 278*3117ece4Schristos ZSTD_CCtx* mtctx = ZSTD_createCCtx(); 279*3117ece4Schristos 280*3117ece4Schristos ZSTD_inBuffer inBuff, inBuff2; 281*3117ece4Schristos ZSTD_outBuffer outBuff; 282*3117ece4Schristos buffer_t dictionary = kBuffNull; 283*3117ece4Schristos size_t const dictSize = 128 KB; 284*3117ece4Schristos unsigned dictID = 0; 285*3117ece4Schristos 286*3117ece4Schristos /* Create compressible test buffer */ 287*3117ece4Schristos if (!CNBuffer || !compressedBuffer || !decodedBuffer || !zc || !zd || !mtctx) { 288*3117ece4Schristos DISPLAY("Not enough memory, aborting \n"); 289*3117ece4Schristos goto _output_error; 290*3117ece4Schristos } 291*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBufferSize, compressibility, 0., seed); 292*3117ece4Schristos 293*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(mtctx, ZSTD_c_nbWorkers, 2)); 294*3117ece4Schristos 295*3117ece4Schristos /* Create dictionary */ 296*3117ece4Schristos DISPLAYLEVEL(3, "creating dictionary for unit tests \n"); 297*3117ece4Schristos dictionary = FUZ_createDictionary(CNBuffer, CNBufferSize / 3, 16 KB, 48 KB); 298*3117ece4Schristos if (!dictionary.start) { 299*3117ece4Schristos DISPLAY("Error creating dictionary, aborting \n"); 300*3117ece4Schristos goto _output_error; 301*3117ece4Schristos } 302*3117ece4Schristos dictID = ZDICT_getDictID(dictionary.start, dictionary.filled); 303*3117ece4Schristos 304*3117ece4Schristos /* Basic compression test */ 305*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH); 306*3117ece4Schristos CHECK_Z( ZSTD_initCStream(zc, 1 /* cLevel */) ); 307*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer); 308*3117ece4Schristos outBuff.size = compressedBufferSize; 309*3117ece4Schristos outBuff.pos = 0; 310*3117ece4Schristos inBuff.src = CNBuffer; 311*3117ece4Schristos inBuff.size = CNBufferSize; 312*3117ece4Schristos inBuff.pos = 0; 313*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 314*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 315*3117ece4Schristos { size_t const r = ZSTD_endStream(zc, &outBuff); 316*3117ece4Schristos if (r != 0) goto _output_error; } /* error, or some data not flushed */ 317*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes)\n", (unsigned)outBuff.pos); 318*3117ece4Schristos 319*3117ece4Schristos /* generate skippable frame */ 320*3117ece4Schristos MEM_writeLE32(compressedBuffer, ZSTD_MAGIC_SKIPPABLE_START); 321*3117ece4Schristos MEM_writeLE32(((char*)compressedBuffer)+4, (U32)skippableFrameSize); 322*3117ece4Schristos cSize = skippableFrameSize + 8; 323*3117ece4Schristos 324*3117ece4Schristos /* Basic compression test using dict */ 325*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : skipframe + compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH); 326*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 327*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 1) ); 328*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(zc, CNBuffer, dictSize) ); 329*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer)+cSize; 330*3117ece4Schristos assert(compressedBufferSize > cSize); 331*3117ece4Schristos outBuff.size = compressedBufferSize - cSize; 332*3117ece4Schristos outBuff.pos = 0; 333*3117ece4Schristos inBuff.src = CNBuffer; 334*3117ece4Schristos inBuff.size = CNBufferSize; 335*3117ece4Schristos inBuff.pos = 0; 336*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 337*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 338*3117ece4Schristos { size_t const r = ZSTD_endStream(zc, &outBuff); 339*3117ece4Schristos if (r != 0) goto _output_error; } /* error, or some data not flushed */ 340*3117ece4Schristos cSize += outBuff.pos; 341*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", 342*3117ece4Schristos (unsigned)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100); 343*3117ece4Schristos 344*3117ece4Schristos /* context size functions */ 345*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : estimate CStream size : ", testNb++); 346*3117ece4Schristos { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictSize); 347*3117ece4Schristos size_t const cstreamSize = ZSTD_estimateCStreamSize_usingCParams(cParams); 348*3117ece4Schristos size_t const cdictSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); /* uses ZSTD_initCStream_usingDict() */ 349*3117ece4Schristos if (ZSTD_isError(cstreamSize)) goto _output_error; 350*3117ece4Schristos if (ZSTD_isError(cdictSize)) goto _output_error; 351*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes) \n", (unsigned)(cstreamSize + cdictSize)); 352*3117ece4Schristos } 353*3117ece4Schristos 354*3117ece4Schristos /* context size functions */ 355*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : estimate CStream size using CCtxParams : ", testNb++); 356*3117ece4Schristos { ZSTD_CCtx_params* const params = ZSTD_createCCtxParams(); 357*3117ece4Schristos size_t cstreamSize, cctxSize; 358*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_compressionLevel, 19) ); 359*3117ece4Schristos cstreamSize = ZSTD_estimateCStreamSize_usingCCtxParams(params); 360*3117ece4Schristos CHECK_Z(cstreamSize); 361*3117ece4Schristos cctxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); 362*3117ece4Schristos CHECK_Z(cctxSize); 363*3117ece4Schristos if (cstreamSize <= cctxSize + 2 * ZSTD_BLOCKSIZE_MAX) goto _output_error; 364*3117ece4Schristos ZSTD_freeCCtxParams(params); 365*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 366*3117ece4Schristos } 367*3117ece4Schristos 368*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check actual CStream size : ", testNb++); 369*3117ece4Schristos { size_t const s = ZSTD_sizeof_CStream(zc); 370*3117ece4Schristos if (ZSTD_isError(s)) goto _output_error; 371*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes) \n", (unsigned)s); 372*3117ece4Schristos } 373*3117ece4Schristos 374*3117ece4Schristos /* Attempt bad compression parameters */ 375*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : use bad compression parameters with ZSTD_initCStream_advanced : ", testNb++); 376*3117ece4Schristos { size_t r; 377*3117ece4Schristos ZSTD_parameters params = ZSTD_getParams(1, 0, 0); 378*3117ece4Schristos params.cParams.minMatch = 2; 379*3117ece4Schristos r = ZSTD_initCStream_advanced(zc, NULL, 0, params, 0); 380*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 381*3117ece4Schristos DISPLAYLEVEL(3, "init error : %s \n", ZSTD_getErrorName(r)); 382*3117ece4Schristos } 383*3117ece4Schristos 384*3117ece4Schristos /* skippable frame test */ 385*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress skippable frame : ", testNb++); 386*3117ece4Schristos CHECK_Z( ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize) ); 387*3117ece4Schristos inBuff.src = compressedBuffer; 388*3117ece4Schristos inBuff.size = cSize; 389*3117ece4Schristos inBuff.pos = 0; 390*3117ece4Schristos outBuff.dst = decodedBuffer; 391*3117ece4Schristos outBuff.size = CNBufferSize; 392*3117ece4Schristos outBuff.pos = 0; 393*3117ece4Schristos { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff); 394*3117ece4Schristos DISPLAYLEVEL(5, " ( ZSTD_decompressStream => %u ) ", (unsigned)r); 395*3117ece4Schristos if (r != 0) goto _output_error; 396*3117ece4Schristos } 397*3117ece4Schristos if (outBuff.pos != 0) goto _output_error; /* skippable frame output len is 0 */ 398*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 399*3117ece4Schristos 400*3117ece4Schristos /* Basic decompression test */ 401*3117ece4Schristos inBuff2 = inBuff; 402*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH); 403*3117ece4Schristos ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize); 404*3117ece4Schristos CHECK_Z( ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, ZSTD_WINDOWLOG_LIMIT_DEFAULT+1) ); /* large limit */ 405*3117ece4Schristos { size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff); 406*3117ece4Schristos if (remaining != 0) goto _output_error; } /* should reach end of frame == 0; otherwise, some data left, or an error */ 407*3117ece4Schristos if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */ 408*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */ 409*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 410*3117ece4Schristos 411*3117ece4Schristos /* Reuse without init */ 412*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress again without init (reuse previous settings): ", testNb++); 413*3117ece4Schristos outBuff.pos = 0; 414*3117ece4Schristos { size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff2); 415*3117ece4Schristos if (remaining != 0) goto _output_error; } /* should reach end of frame == 0; otherwise, some data left, or an error */ 416*3117ece4Schristos if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */ 417*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */ 418*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 419*3117ece4Schristos 420*3117ece4Schristos /* check regenerated data is byte exact */ 421*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++); 422*3117ece4Schristos { size_t i; 423*3117ece4Schristos for (i=0; i<CNBufferSize; i++) { 424*3117ece4Schristos if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error; 425*3117ece4Schristos } } 426*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 427*3117ece4Schristos 428*3117ece4Schristos /* check decompression fails early if first bytes are wrong */ 429*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : early decompression error if first bytes are incorrect : ", testNb++); 430*3117ece4Schristos { const char buf[3] = { 0 }; /* too short, not enough to start decoding header */ 431*3117ece4Schristos ZSTD_inBuffer inb = { buf, sizeof(buf), 0 }; 432*3117ece4Schristos size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inb); 433*3117ece4Schristos if (!ZSTD_isError(remaining)) goto _output_error; /* should have errored out immediately (note: this does not test the exact error code) */ 434*3117ece4Schristos } 435*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 436*3117ece4Schristos 437*3117ece4Schristos /* context size functions */ 438*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : estimate DStream size : ", testNb++); 439*3117ece4Schristos { ZSTD_frameHeader fhi; 440*3117ece4Schristos const void* cStart = (char*)compressedBuffer + (skippableFrameSize + 8); 441*3117ece4Schristos size_t const gfhError = ZSTD_getFrameHeader(&fhi, cStart, cSize); 442*3117ece4Schristos if (gfhError!=0) goto _output_error; 443*3117ece4Schristos DISPLAYLEVEL(5, " (windowSize : %u) ", (unsigned)fhi.windowSize); 444*3117ece4Schristos { size_t const s = ZSTD_estimateDStreamSize(fhi.windowSize) 445*3117ece4Schristos /* uses ZSTD_initDStream_usingDict() */ 446*3117ece4Schristos + ZSTD_estimateDDictSize(dictSize, ZSTD_dlm_byCopy); 447*3117ece4Schristos if (ZSTD_isError(s)) goto _output_error; 448*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes) \n", (unsigned)s); 449*3117ece4Schristos } } 450*3117ece4Schristos 451*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check actual DStream size : ", testNb++); 452*3117ece4Schristos { size_t const s = ZSTD_sizeof_DStream(zd); 453*3117ece4Schristos if (ZSTD_isError(s)) goto _output_error; 454*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes) \n", (unsigned)s); 455*3117ece4Schristos } 456*3117ece4Schristos 457*3117ece4Schristos /* Decompression by small increment */ 458*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress byte-by-byte : ", testNb++); 459*3117ece4Schristos { /* skippable frame */ 460*3117ece4Schristos size_t r = 1; 461*3117ece4Schristos ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize); 462*3117ece4Schristos inBuff.src = compressedBuffer; 463*3117ece4Schristos outBuff.dst = decodedBuffer; 464*3117ece4Schristos inBuff.pos = 0; 465*3117ece4Schristos outBuff.pos = 0; 466*3117ece4Schristos while (r) { /* skippable frame */ 467*3117ece4Schristos size_t const inSize = (FUZ_rand(&coreSeed) & 15) + 1; 468*3117ece4Schristos size_t const outSize = (FUZ_rand(&coreSeed) & 15) + 1; 469*3117ece4Schristos inBuff.size = inBuff.pos + inSize; 470*3117ece4Schristos outBuff.size = outBuff.pos + outSize; 471*3117ece4Schristos r = ZSTD_decompressStream(zd, &outBuff, &inBuff); 472*3117ece4Schristos if (ZSTD_isError(r)) DISPLAYLEVEL(4, "ZSTD_decompressStream on skippable frame error : %s \n", ZSTD_getErrorName(r)); 473*3117ece4Schristos if (ZSTD_isError(r)) goto _output_error; 474*3117ece4Schristos } 475*3117ece4Schristos /* normal frame */ 476*3117ece4Schristos ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize); 477*3117ece4Schristos r=1; 478*3117ece4Schristos while (r) { 479*3117ece4Schristos size_t const inSize = FUZ_rand(&coreSeed) & 15; 480*3117ece4Schristos size_t const outSize = (FUZ_rand(&coreSeed) & 15) + (!inSize); /* avoid having both sizes at 0 => would trigger a no_forward_progress error */ 481*3117ece4Schristos inBuff.size = inBuff.pos + inSize; 482*3117ece4Schristos outBuff.size = outBuff.pos + outSize; 483*3117ece4Schristos r = ZSTD_decompressStream(zd, &outBuff, &inBuff); 484*3117ece4Schristos if (ZSTD_isError(r)) DISPLAYLEVEL(4, "ZSTD_decompressStream error : %s \n", ZSTD_getErrorName(r)); 485*3117ece4Schristos if (ZSTD_isError(r)) goto _output_error; 486*3117ece4Schristos } 487*3117ece4Schristos } 488*3117ece4Schristos if (outBuff.pos != CNBufferSize) DISPLAYLEVEL(4, "outBuff.pos != CNBufferSize : should have regenerated same amount ! \n"); 489*3117ece4Schristos if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */ 490*3117ece4Schristos if (inBuff.pos != cSize) DISPLAYLEVEL(4, "inBuff.pos != cSize : should have real all input ! \n"); 491*3117ece4Schristos if (inBuff.pos != cSize) goto _output_error; /* should have read the entire frame */ 492*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 493*3117ece4Schristos 494*3117ece4Schristos /* check regenerated data is byte exact */ 495*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++); 496*3117ece4Schristos { size_t i; 497*3117ece4Schristos for (i=0; i<CNBufferSize; i++) { 498*3117ece4Schristos if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error; 499*3117ece4Schristos } } 500*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 501*3117ece4Schristos 502*3117ece4Schristos /* Decompression forward progress */ 503*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : generate error when ZSTD_decompressStream() doesn't progress : ", testNb++); 504*3117ece4Schristos { /* skippable frame */ 505*3117ece4Schristos size_t r = 0; 506*3117ece4Schristos int decNb = 0; 507*3117ece4Schristos int const maxDec = 100; 508*3117ece4Schristos inBuff.src = compressedBuffer; 509*3117ece4Schristos inBuff.size = cSize; 510*3117ece4Schristos inBuff.pos = 0; 511*3117ece4Schristos 512*3117ece4Schristos outBuff.dst = decodedBuffer; 513*3117ece4Schristos outBuff.pos = 0; 514*3117ece4Schristos outBuff.size = CNBufferSize-1; /* 1 byte missing */ 515*3117ece4Schristos 516*3117ece4Schristos for (decNb=0; decNb<maxDec; decNb++) { 517*3117ece4Schristos if (r==0) ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize); 518*3117ece4Schristos r = ZSTD_decompressStream(zd, &outBuff, &inBuff); 519*3117ece4Schristos if (ZSTD_isError(r)) break; 520*3117ece4Schristos } 521*3117ece4Schristos if (!ZSTD_isError(r)) DISPLAYLEVEL(4, "ZSTD_decompressStream should have triggered a no_forward_progress error \n"); 522*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; /* should have triggered no_forward_progress error */ 523*3117ece4Schristos } 524*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 525*3117ece4Schristos 526*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : NULL output and NULL input : ", testNb++); 527*3117ece4Schristos inBuff.src = NULL; 528*3117ece4Schristos inBuff.size = 0; 529*3117ece4Schristos inBuff.pos = 0; 530*3117ece4Schristos outBuff.dst = NULL; 531*3117ece4Schristos outBuff.size = 0; 532*3117ece4Schristos outBuff.pos = 0; 533*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 534*3117ece4Schristos CHECK(inBuff.pos != inBuff.size, "Entire input should be consumed"); 535*3117ece4Schristos CHECK_Z( ZSTD_endStream(zc, &outBuff) ); 536*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer); 537*3117ece4Schristos outBuff.size = compressedBufferSize; 538*3117ece4Schristos outBuff.pos = 0; 539*3117ece4Schristos { size_t const r = ZSTD_endStream(zc, &outBuff); 540*3117ece4Schristos CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r); 541*3117ece4Schristos } 542*3117ece4Schristos inBuff.src = outBuff.dst; 543*3117ece4Schristos inBuff.size = outBuff.pos; 544*3117ece4Schristos inBuff.pos = 0; 545*3117ece4Schristos outBuff.dst = NULL; 546*3117ece4Schristos outBuff.size = 0; 547*3117ece4Schristos outBuff.pos = 0; 548*3117ece4Schristos CHECK_Z( ZSTD_initDStream(zd) ); 549*3117ece4Schristos { size_t const ret = ZSTD_decompressStream(zd, &outBuff, &inBuff); 550*3117ece4Schristos if (ret != 0) goto _output_error; 551*3117ece4Schristos } 552*3117ece4Schristos DISPLAYLEVEL(3, "OK\n"); 553*3117ece4Schristos 554*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : NULL output buffer with non-NULL input : ", testNb++); 555*3117ece4Schristos { 556*3117ece4Schristos const char* test = "aa"; 557*3117ece4Schristos inBuff.src = test; 558*3117ece4Schristos inBuff.size = 2; 559*3117ece4Schristos inBuff.pos = 0; 560*3117ece4Schristos outBuff.dst = NULL; 561*3117ece4Schristos outBuff.size = 0; 562*3117ece4Schristos outBuff.pos = 0; 563*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 564*3117ece4Schristos CHECK(inBuff.pos != inBuff.size, "Entire input should be consumed"); 565*3117ece4Schristos CHECK_Z( ZSTD_endStream(zc, &outBuff) ); 566*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer); 567*3117ece4Schristos outBuff.size = compressedBufferSize; 568*3117ece4Schristos outBuff.pos = 0; 569*3117ece4Schristos { size_t const r = ZSTD_endStream(zc, &outBuff); 570*3117ece4Schristos CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r); 571*3117ece4Schristos } 572*3117ece4Schristos inBuff.src = outBuff.dst; 573*3117ece4Schristos inBuff.size = outBuff.pos; 574*3117ece4Schristos inBuff.pos = 0; 575*3117ece4Schristos outBuff.dst = NULL; 576*3117ece4Schristos outBuff.size = 0; 577*3117ece4Schristos outBuff.pos = 0; 578*3117ece4Schristos CHECK_Z( ZSTD_initDStream(zd) ); 579*3117ece4Schristos CHECK_Z(ZSTD_decompressStream(zd, &outBuff, &inBuff)); 580*3117ece4Schristos } 581*3117ece4Schristos 582*3117ece4Schristos DISPLAYLEVEL(3, "OK\n"); 583*3117ece4Schristos /* _srcSize compression test */ 584*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress_srcSize %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH); 585*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 586*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(zc, NULL) ); 587*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 1) ); 588*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, CNBufferSize) ); 589*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer); 590*3117ece4Schristos outBuff.size = compressedBufferSize; 591*3117ece4Schristos outBuff.pos = 0; 592*3117ece4Schristos inBuff.src = CNBuffer; 593*3117ece4Schristos inBuff.size = CNBufferSize; 594*3117ece4Schristos inBuff.pos = 0; 595*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 596*3117ece4Schristos CHECK(inBuff.pos != inBuff.size, "Entire input should be consumed"); 597*3117ece4Schristos { size_t const r = ZSTD_endStream(zc, &outBuff); 598*3117ece4Schristos CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r); 599*3117ece4Schristos } 600*3117ece4Schristos { unsigned long long origSize = ZSTD_findDecompressedSize(outBuff.dst, outBuff.pos); 601*3117ece4Schristos CHECK(origSize == ZSTD_CONTENTSIZE_UNKNOWN, "Unknown!"); 602*3117ece4Schristos CHECK((size_t)origSize != CNBufferSize, "Exact original size must be present (got %llu)", origSize); 603*3117ece4Schristos } 604*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100); 605*3117ece4Schristos 606*3117ece4Schristos /* wrong _srcSize compression test */ 607*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : too large srcSize : %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH-1); 608*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 609*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(zc, NULL) ); 610*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 1) ); 611*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, CNBufferSize+1) ); 612*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer); 613*3117ece4Schristos outBuff.size = compressedBufferSize; 614*3117ece4Schristos outBuff.pos = 0; 615*3117ece4Schristos inBuff.src = CNBuffer; 616*3117ece4Schristos inBuff.size = CNBufferSize; 617*3117ece4Schristos inBuff.pos = 0; 618*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 619*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 620*3117ece4Schristos { size_t const r = ZSTD_endStream(zc, &outBuff); 621*3117ece4Schristos if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; /* must fail : wrong srcSize */ 622*3117ece4Schristos DISPLAYLEVEL(3, "OK (error detected : %s) \n", ZSTD_getErrorName(r)); } 623*3117ece4Schristos 624*3117ece4Schristos /* wrong _srcSize compression test */ 625*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : too small srcSize : %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH-1); 626*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 627*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(zc, NULL) ); 628*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 1) ); 629*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, CNBufferSize-1) ); 630*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer); 631*3117ece4Schristos outBuff.size = compressedBufferSize; 632*3117ece4Schristos outBuff.pos = 0; 633*3117ece4Schristos inBuff.src = CNBuffer; 634*3117ece4Schristos inBuff.size = CNBufferSize; 635*3117ece4Schristos inBuff.pos = 0; 636*3117ece4Schristos { size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff); 637*3117ece4Schristos if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; /* must fail : wrong srcSize */ 638*3117ece4Schristos DISPLAYLEVEL(3, "OK (error detected : %s) \n", ZSTD_getErrorName(r)); 639*3117ece4Schristos } 640*3117ece4Schristos 641*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : wrong srcSize !contentSizeFlag : %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH-1); 642*3117ece4Schristos { CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 643*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_contentSizeFlag, 0) ); 644*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, CNBufferSize - MIN(CNBufferSize, 200 KB)) ); 645*3117ece4Schristos outBuff.dst = (char*)compressedBuffer; 646*3117ece4Schristos outBuff.size = compressedBufferSize; 647*3117ece4Schristos outBuff.pos = 0; 648*3117ece4Schristos inBuff.src = CNBuffer; 649*3117ece4Schristos inBuff.size = CNBufferSize; 650*3117ece4Schristos inBuff.pos = 0; 651*3117ece4Schristos { size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff); 652*3117ece4Schristos if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; /* must fail : wrong srcSize */ 653*3117ece4Schristos DISPLAYLEVEL(3, "OK (error detected : %s) \n", ZSTD_getErrorName(r)); 654*3117ece4Schristos } } 655*3117ece4Schristos 656*3117ece4Schristos /* Compression state reuse scenario */ 657*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : context reuse : ", testNb++); 658*3117ece4Schristos ZSTD_freeCStream(zc); 659*3117ece4Schristos zc = ZSTD_createCStream(); 660*3117ece4Schristos if (zc==NULL) goto _output_error; /* memory allocation issue */ 661*3117ece4Schristos /* use 1 */ 662*3117ece4Schristos { size_t const inSize = 513; 663*3117ece4Schristos DISPLAYLEVEL(5, "use1 "); 664*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 665*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 19) ); 666*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, inSize) ); 667*3117ece4Schristos inBuff.src = CNBuffer; 668*3117ece4Schristos inBuff.size = inSize; 669*3117ece4Schristos inBuff.pos = 0; 670*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer)+cSize; 671*3117ece4Schristos outBuff.size = ZSTD_compressBound(inSize); 672*3117ece4Schristos outBuff.pos = 0; 673*3117ece4Schristos DISPLAYLEVEL(5, "compress1 "); 674*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 675*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 676*3117ece4Schristos DISPLAYLEVEL(5, "end1 "); 677*3117ece4Schristos if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error; /* error, or some data not flushed */ 678*3117ece4Schristos } 679*3117ece4Schristos /* use 2 */ 680*3117ece4Schristos { size_t const inSize = 1025; /* will not continue, because tables auto-adjust and are therefore different size */ 681*3117ece4Schristos DISPLAYLEVEL(5, "use2 "); 682*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 683*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 19) ); 684*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, inSize) ); 685*3117ece4Schristos inBuff.src = CNBuffer; 686*3117ece4Schristos inBuff.size = inSize; 687*3117ece4Schristos inBuff.pos = 0; 688*3117ece4Schristos outBuff.dst = (char*)(compressedBuffer)+cSize; 689*3117ece4Schristos outBuff.size = ZSTD_compressBound(inSize); 690*3117ece4Schristos outBuff.pos = 0; 691*3117ece4Schristos DISPLAYLEVEL(5, "compress2 "); 692*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 693*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 694*3117ece4Schristos DISPLAYLEVEL(5, "end2 "); 695*3117ece4Schristos if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error; /* error, or some data not flushed */ 696*3117ece4Schristos } 697*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 698*3117ece4Schristos 699*3117ece4Schristos /* Decompression single pass with empty frame */ 700*3117ece4Schristos cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, NULL, 0, 1); 701*3117ece4Schristos CHECK_Z(cSize); 702*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() single pass on empty frame : ", testNb++); 703*3117ece4Schristos { ZSTD_DCtx* dctx = ZSTD_createDCtx(); 704*3117ece4Schristos size_t const dctxSize = ZSTD_sizeof_DCtx(dctx); 705*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1)); 706*3117ece4Schristos 707*3117ece4Schristos outBuff.dst = decodedBuffer; 708*3117ece4Schristos outBuff.pos = 0; 709*3117ece4Schristos outBuff.size = CNBufferSize; 710*3117ece4Schristos 711*3117ece4Schristos inBuff.src = compressedBuffer; 712*3117ece4Schristos inBuff.size = cSize; 713*3117ece4Schristos inBuff.pos = 0; 714*3117ece4Schristos { size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); 715*3117ece4Schristos CHECK_Z(r); 716*3117ece4Schristos CHECK(r != 0, "Entire frame must be decompressed"); 717*3117ece4Schristos CHECK(outBuff.pos != 0, "Wrong size!"); 718*3117ece4Schristos CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!"); 719*3117ece4Schristos } 720*3117ece4Schristos CHECK(dctxSize != ZSTD_sizeof_DCtx(dctx), "No buffers allocated"); 721*3117ece4Schristos ZSTD_freeDCtx(dctx); 722*3117ece4Schristos } 723*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 724*3117ece4Schristos 725*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : maxBlockSize = 2KB : ", testNb++); 726*3117ece4Schristos { 727*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 728*3117ece4Schristos size_t singlePassSize, streamingSize, streaming2KSize; 729*3117ece4Schristos 730*3117ece4Schristos { 731*3117ece4Schristos ZSTD_CCtx* cctx = ZSTD_createCCtx(); 732*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 733*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18)); 734*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0)); 735*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 2048)); 736*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize); 737*3117ece4Schristos CHECK_Z(cSize); 738*3117ece4Schristos ZSTD_freeCCtx(cctx); 739*3117ece4Schristos } 740*3117ece4Schristos 741*3117ece4Schristos CHECK_Z(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBufferSize, compressedBuffer, cSize)); 742*3117ece4Schristos singlePassSize = ZSTD_sizeof_DCtx(dctx); 743*3117ece4Schristos CHECK_Z(singlePassSize); 744*3117ece4Schristos 745*3117ece4Schristos inBuff.src = compressedBuffer; 746*3117ece4Schristos inBuff.size = cSize; 747*3117ece4Schristos 748*3117ece4Schristos outBuff.dst = decodedBuffer; 749*3117ece4Schristos outBuff.size = decodedBufferSize; 750*3117ece4Schristos 751*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 2048)); 752*3117ece4Schristos inBuff.pos = 0; 753*3117ece4Schristos outBuff.pos = 0; 754*3117ece4Schristos { 755*3117ece4Schristos size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); 756*3117ece4Schristos CHECK_Z(r); 757*3117ece4Schristos CHECK(r != 0, "Entire frame must be decompressed"); 758*3117ece4Schristos } 759*3117ece4Schristos streaming2KSize = ZSTD_sizeof_DCtx(dctx); 760*3117ece4Schristos CHECK_Z(streaming2KSize); 761*3117ece4Schristos 762*3117ece4Schristos CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters)); 763*3117ece4Schristos inBuff.pos = 0; 764*3117ece4Schristos outBuff.pos = 0; 765*3117ece4Schristos { 766*3117ece4Schristos size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); 767*3117ece4Schristos CHECK_Z(r); 768*3117ece4Schristos CHECK(r != 0, "Entire frame must be decompressed"); 769*3117ece4Schristos } 770*3117ece4Schristos streamingSize = ZSTD_sizeof_DCtx(dctx); 771*3117ece4Schristos CHECK_Z(streamingSize); 772*3117ece4Schristos 773*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 1024)); 774*3117ece4Schristos inBuff.pos = 0; 775*3117ece4Schristos outBuff.pos = 0; 776*3117ece4Schristos CHECK(!ZSTD_isError(ZSTD_decompressStream(dctx, &outBuff, &inBuff)), "decompression must fail"); 777*3117ece4Schristos 778*3117ece4Schristos CHECK(streamingSize < singlePassSize + (1 << 18) + 3 * ZSTD_BLOCKSIZE_MAX, "Streaming doesn't use the right amount of memory"); 779*3117ece4Schristos CHECK(streamingSize != streaming2KSize + 3 * (ZSTD_BLOCKSIZE_MAX - 2048), "ZSTD_d_blockSizeMax didn't save the right amount of memory"); 780*3117ece4Schristos DISPLAYLEVEL(3, "| %zu | %zu | %zu | ", singlePassSize, streaming2KSize, streamingSize); 781*3117ece4Schristos 782*3117ece4Schristos ZSTD_freeDCtx(dctx); 783*3117ece4Schristos } 784*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 785*3117ece4Schristos 786*3117ece4Schristos /* Decompression with ZSTD_d_stableOutBuffer */ 787*3117ece4Schristos cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize, 1); 788*3117ece4Schristos CHECK_Z(cSize); 789*3117ece4Schristos { ZSTD_DCtx* dctx = ZSTD_createDCtx(); 790*3117ece4Schristos size_t const dctxSize0 = ZSTD_sizeof_DCtx(dctx); 791*3117ece4Schristos size_t dctxSize1; 792*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1)); 793*3117ece4Schristos 794*3117ece4Schristos outBuff.dst = decodedBuffer; 795*3117ece4Schristos outBuff.pos = 0; 796*3117ece4Schristos outBuff.size = CNBufferSize; 797*3117ece4Schristos 798*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() single pass : ", testNb++); 799*3117ece4Schristos inBuff.src = compressedBuffer; 800*3117ece4Schristos inBuff.size = cSize; 801*3117ece4Schristos inBuff.pos = 0; 802*3117ece4Schristos { size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); 803*3117ece4Schristos CHECK_Z(r); 804*3117ece4Schristos CHECK(r != 0, "Entire frame must be decompressed"); 805*3117ece4Schristos CHECK(outBuff.pos != CNBufferSize, "Wrong size!"); 806*3117ece4Schristos CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!"); 807*3117ece4Schristos } 808*3117ece4Schristos CHECK(dctxSize0 != ZSTD_sizeof_DCtx(dctx), "No buffers allocated"); 809*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 810*3117ece4Schristos 811*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer : ", testNb++); 812*3117ece4Schristos outBuff.pos = 0; 813*3117ece4Schristos inBuff.pos = 0; 814*3117ece4Schristos inBuff.size = 0; 815*3117ece4Schristos while (inBuff.pos < cSize) { 816*3117ece4Schristos inBuff.size += MIN(cSize - inBuff.pos, 1 + (FUZ_rand(&coreSeed) & 15)); 817*3117ece4Schristos CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff)); 818*3117ece4Schristos } 819*3117ece4Schristos CHECK(outBuff.pos != CNBufferSize, "Wrong size!"); 820*3117ece4Schristos CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!"); 821*3117ece4Schristos dctxSize1 = ZSTD_sizeof_DCtx(dctx); 822*3117ece4Schristos CHECK(!(dctxSize0 < dctxSize1), "Input buffer allocated"); 823*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 824*3117ece4Schristos 825*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer too small : ", testNb++); 826*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); 827*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1)); 828*3117ece4Schristos inBuff.src = compressedBuffer; 829*3117ece4Schristos inBuff.size = cSize; 830*3117ece4Schristos inBuff.pos = 0; 831*3117ece4Schristos outBuff.pos = 0; 832*3117ece4Schristos outBuff.size = CNBufferSize - 1; 833*3117ece4Schristos { size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); 834*3117ece4Schristos CHECK(ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall, "Must error but got %s", ZSTD_getErrorName(r)); 835*3117ece4Schristos } 836*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 837*3117ece4Schristos 838*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer modified : ", testNb++); 839*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); 840*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1)); 841*3117ece4Schristos inBuff.src = compressedBuffer; 842*3117ece4Schristos inBuff.size = cSize - 1; 843*3117ece4Schristos inBuff.pos = 0; 844*3117ece4Schristos outBuff.pos = 0; 845*3117ece4Schristos outBuff.size = CNBufferSize; 846*3117ece4Schristos CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff)); 847*3117ece4Schristos ++inBuff.size; 848*3117ece4Schristos outBuff.pos = 0; 849*3117ece4Schristos { size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); 850*3117ece4Schristos CHECK(ZSTD_getErrorCode(r) != ZSTD_error_dstBuffer_wrong, "Must error but got %s", ZSTD_getErrorName(r)); 851*3117ece4Schristos } 852*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 853*3117ece4Schristos 854*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() buffered output : ", testNb++); 855*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); 856*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 0)); 857*3117ece4Schristos outBuff.pos = 0; 858*3117ece4Schristos inBuff.pos = 0; 859*3117ece4Schristos inBuff.size = 0; 860*3117ece4Schristos while (inBuff.pos < cSize) { 861*3117ece4Schristos inBuff.size += MIN(cSize - inBuff.pos, 1 + (FUZ_rand(&coreSeed) & 15)); 862*3117ece4Schristos CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff)); 863*3117ece4Schristos } 864*3117ece4Schristos CHECK(outBuff.pos != CNBufferSize, "Wrong size!"); 865*3117ece4Schristos CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!"); 866*3117ece4Schristos CHECK(!(dctxSize1 < ZSTD_sizeof_DCtx(dctx)), "Output buffer allocated"); 867*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 868*3117ece4Schristos 869*3117ece4Schristos ZSTD_freeDCtx(dctx); 870*3117ece4Schristos } 871*3117ece4Schristos 872*3117ece4Schristos /* Compression with ZSTD_c_stable{In,Out}Buffer */ 873*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 874*3117ece4Schristos ZSTD_inBuffer in; 875*3117ece4Schristos ZSTD_outBuffer out; 876*3117ece4Schristos size_t cctxSize1; 877*3117ece4Schristos size_t cctxSize2; 878*3117ece4Schristos assert(cctx != NULL); 879*3117ece4Schristos in.src = CNBuffer; 880*3117ece4Schristos in.size = CNBufferSize; 881*3117ece4Schristos out.dst = compressedBuffer; 882*3117ece4Schristos out.size = compressedBufferSize; 883*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 884*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compress2() uses stable input and output : ", testNb++); 885*3117ece4Schristos CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize)); 886*3117ece4Schristos CHECK(!(cSize < ZSTD_compressBound(CNBufferSize)), "cSize too large for test"); 887*3117ece4Schristos CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, cSize + 4, CNBuffer, CNBufferSize)); 888*3117ece4Schristos CHECK_Z(cctxSize1 = ZSTD_sizeof_CCtx(cctx)); 889*3117ece4Schristos /* @cctxSize2 : sizeof_CCtx when doing full streaming (no stable in/out) */ 890*3117ece4Schristos { ZSTD_CCtx* const cctx2 = ZSTD_createCCtx(); 891*3117ece4Schristos assert(cctx2 != NULL); 892*3117ece4Schristos in.pos = out.pos = 0; 893*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx2, &out, &in, ZSTD_e_continue)); 894*3117ece4Schristos CHECK(!(ZSTD_compressStream2(cctx2, &out, &in, ZSTD_e_end) == 0), "Not finished"); 895*3117ece4Schristos CHECK_Z(cctxSize2 = ZSTD_sizeof_CCtx(cctx2)); 896*3117ece4Schristos ZSTD_freeCCtx(cctx2); 897*3117ece4Schristos } 898*3117ece4Schristos /* @cctxSize1 : sizeof_CCtx when doing single-shot compression (no streaming) */ 899*3117ece4Schristos { ZSTD_CCtx* const cctx1 = ZSTD_createCCtx(); 900*3117ece4Schristos ZSTD_parameters params = ZSTD_getParams(0, CNBufferSize, 0); 901*3117ece4Schristos size_t cSize3; 902*3117ece4Schristos assert(cctx1 != NULL); 903*3117ece4Schristos params.fParams.checksumFlag = 1; 904*3117ece4Schristos cSize3 = ZSTD_compress_advanced(cctx1, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize, NULL, 0, params); 905*3117ece4Schristos CHECK_Z(cSize3); 906*3117ece4Schristos CHECK(!(cSize == cSize3), "Must be same compressed size"); 907*3117ece4Schristos CHECK(!(cctxSize1 == ZSTD_sizeof_CCtx(cctx1)), "Must be same CCtx size"); 908*3117ece4Schristos ZSTD_freeCCtx(cctx1); 909*3117ece4Schristos } 910*3117ece4Schristos CHECK(!(cctxSize1 < cctxSize2), "Stable buffers means less allocated size"); 911*3117ece4Schristos CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize)); 912*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 913*3117ece4Schristos 914*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compress2() doesn't modify user parameters : ", testNb++); 915*3117ece4Schristos { int stableInBuffer; 916*3117ece4Schristos int stableOutBuffer; 917*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_stableInBuffer, &stableInBuffer)); 918*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_stableOutBuffer, &stableOutBuffer)); 919*3117ece4Schristos CHECK(!(stableInBuffer == 0), "Modified"); 920*3117ece4Schristos CHECK(!(stableOutBuffer == 0), "Modified"); 921*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1)); 922*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableOutBuffer, 1)); 923*3117ece4Schristos CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize)); 924*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_stableInBuffer, &stableInBuffer)); 925*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_stableOutBuffer, &stableOutBuffer)); 926*3117ece4Schristos CHECK(!(stableInBuffer == 1), "Modified"); 927*3117ece4Schristos CHECK(!(stableOutBuffer == 1), "Modified"); 928*3117ece4Schristos } 929*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 930*3117ece4Schristos 931*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() with ZSTD_c_stableInBuffer and ZSTD_c_stableOutBuffer : ", testNb++); 932*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters)); 933*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 934*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1)); 935*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableOutBuffer, 1)); 936*3117ece4Schristos in.pos = out.pos = 0; 937*3117ece4Schristos CHECK(!(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) == 0), "Not finished"); 938*3117ece4Schristos CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize)); 939*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 940*3117ece4Schristos 941*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() ZSTD_c_stableInBuffer and ZSTD_c_stableOutBuffer allocated size : ", testNb++); 942*3117ece4Schristos { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx); 943*3117ece4Schristos CHECK(!(cctxSize1 == cctxSize), "Must be the same size as single pass"); 944*3117ece4Schristos } 945*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 946*3117ece4Schristos 947*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() with ZSTD_c_stableInBuffer only : ", testNb++); 948*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters)); 949*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 950*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1)); 951*3117ece4Schristos in.pos = out.pos = 0; 952*3117ece4Schristos out.size = cSize / 4; 953*3117ece4Schristos for (;;) { 954*3117ece4Schristos size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end); 955*3117ece4Schristos CHECK_Z(ret); 956*3117ece4Schristos if (ret == 0) 957*3117ece4Schristos break; 958*3117ece4Schristos out.size = MIN(out.size + cSize / 4, compressedBufferSize); 959*3117ece4Schristos } 960*3117ece4Schristos CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize)); 961*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 962*3117ece4Schristos 963*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() ZSTD_c_stableInBuffer modify buffer : ", testNb++); 964*3117ece4Schristos in.pos = out.pos = 0; 965*3117ece4Schristos out.size = cSize / 4; 966*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 967*3117ece4Schristos in.src = (char const*)in.src + in.pos; 968*3117ece4Schristos in.size -= in.pos; 969*3117ece4Schristos in.pos = 0; 970*3117ece4Schristos { size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end); 971*3117ece4Schristos CHECK(!ZSTD_isError(ret), "Must error"); 972*3117ece4Schristos CHECK(!(ZSTD_getErrorCode(ret) == ZSTD_error_stabilityCondition_notRespected), "Must be this error"); 973*3117ece4Schristos } 974*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 975*3117ece4Schristos 976*3117ece4Schristos /* stableSrc + streaming */ 977*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_c_stableInBuffer compatibility with compressStream, flushStream and endStream : ", testNb++); 978*3117ece4Schristos CHECK_Z( ZSTD_initCStream(cctx, 1) ); 979*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1) ); 980*3117ece4Schristos { ZSTD_inBuffer inBuf; 981*3117ece4Schristos ZSTD_outBuffer outBuf; 982*3117ece4Schristos const size_t nonZeroStartPos = 18; 983*3117ece4Schristos const size_t inputSize = 500; 984*3117ece4Schristos inBuf.src = CNBuffer; 985*3117ece4Schristos inBuf.size = 100; 986*3117ece4Schristos inBuf.pos = nonZeroStartPos; 987*3117ece4Schristos outBuf.dst = (char*)(compressedBuffer)+cSize; 988*3117ece4Schristos outBuf.size = ZSTD_compressBound(inputSize); 989*3117ece4Schristos outBuf.pos = 0; 990*3117ece4Schristos CHECK_Z( ZSTD_compressStream(cctx, &outBuf, &inBuf) ); 991*3117ece4Schristos inBuf.size = 200; 992*3117ece4Schristos CHECK_Z( ZSTD_compressStream(cctx, &outBuf, &inBuf) ); 993*3117ece4Schristos CHECK_Z( ZSTD_flushStream(cctx, &outBuf) ); 994*3117ece4Schristos inBuf.size = nonZeroStartPos + inputSize; 995*3117ece4Schristos CHECK_Z( ZSTD_compressStream(cctx, &outBuf, &inBuf) ); 996*3117ece4Schristos CHECK(ZSTD_endStream(cctx, &outBuf) != 0, "compression should be successful and fully flushed"); 997*3117ece4Schristos { const void* const realSrcStart = (const char*)inBuf.src + nonZeroStartPos; 998*3117ece4Schristos void* const verifBuf = (char*)outBuf.dst + outBuf.pos; 999*3117ece4Schristos const size_t decSize = ZSTD_decompress(verifBuf, inputSize, outBuf.dst, outBuf.pos); 1000*3117ece4Schristos CHECK_Z(decSize); 1001*3117ece4Schristos CHECK(decSize != inputSize, "regenerated %zu bytes, instead of %zu", decSize, inputSize); 1002*3117ece4Schristos CHECK(memcmp(realSrcStart, verifBuf, inputSize) != 0, "regenerated data different from original"); 1003*3117ece4Schristos } } 1004*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1005*3117ece4Schristos 1006*3117ece4Schristos /* stableSrc + streaming */ 1007*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_c_stableInBuffer compatibility with compressStream2, using different end directives : ", testNb++); 1008*3117ece4Schristos CHECK_Z( ZSTD_initCStream(cctx, 1) ); 1009*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1) ); 1010*3117ece4Schristos { ZSTD_inBuffer inBuf; 1011*3117ece4Schristos ZSTD_outBuffer outBuf; 1012*3117ece4Schristos const size_t nonZeroStartPos = 18; 1013*3117ece4Schristos const size_t inputSize = 500; 1014*3117ece4Schristos inBuf.src = CNBuffer; 1015*3117ece4Schristos inBuf.size = 100; 1016*3117ece4Schristos inBuf.pos = nonZeroStartPos; 1017*3117ece4Schristos outBuf.dst = (char*)(compressedBuffer)+cSize; 1018*3117ece4Schristos outBuf.size = ZSTD_compressBound(inputSize); 1019*3117ece4Schristos outBuf.pos = 0; 1020*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_continue) ); 1021*3117ece4Schristos inBuf.size = 200; 1022*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_continue) ); 1023*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_flush) ); 1024*3117ece4Schristos inBuf.size = nonZeroStartPos + inputSize; 1025*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_continue) ); 1026*3117ece4Schristos CHECK( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_end) != 0, "compression should be successful and fully flushed"); 1027*3117ece4Schristos { const void* const realSrcStart = (const char*)inBuf.src + nonZeroStartPos; 1028*3117ece4Schristos void* const verifBuf = (char*)outBuf.dst + outBuf.pos; 1029*3117ece4Schristos const size_t decSize = ZSTD_decompress(verifBuf, inputSize, outBuf.dst, outBuf.pos); 1030*3117ece4Schristos CHECK_Z(decSize); 1031*3117ece4Schristos CHECK(decSize != inputSize, "regenerated %zu bytes, instead of %zu", decSize, inputSize); 1032*3117ece4Schristos CHECK(memcmp(realSrcStart, verifBuf, inputSize) != 0, "regenerated data different from original"); 1033*3117ece4Schristos } } 1034*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1035*3117ece4Schristos 1036*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() with ZSTD_c_stableInBuffer: context size : ", testNb++); 1037*3117ece4Schristos { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx); 1038*3117ece4Schristos DISPLAYLEVEL(4, "cctxSize1=%zu; cctxSize=%zu; cctxSize2=%zu : ", cctxSize1, cctxSize, cctxSize2); 1039*3117ece4Schristos CHECK(!(cctxSize1 < cctxSize), "Must be bigger than single-pass"); 1040*3117ece4Schristos CHECK(!(cctxSize < cctxSize2), "Must be smaller than streaming"); 1041*3117ece4Schristos cctxSize1 = cctxSize; 1042*3117ece4Schristos } 1043*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1044*3117ece4Schristos 1045*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() with ZSTD_c_stableOutBuffer only : ", testNb++); 1046*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters)); 1047*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 1048*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableOutBuffer, 1)); 1049*3117ece4Schristos in.src = CNBuffer; 1050*3117ece4Schristos in.pos = out.pos = 0; 1051*3117ece4Schristos in.size = MIN(CNBufferSize, 10); 1052*3117ece4Schristos out.size = compressedBufferSize; 1053*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)); 1054*3117ece4Schristos in.pos = 0; 1055*3117ece4Schristos in.size = CNBufferSize - in.size; 1056*3117ece4Schristos CHECK(!(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) == 0), "Not finished"); 1057*3117ece4Schristos CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, out.pos)); 1058*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1059*3117ece4Schristos 1060*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() ZSTD_c_stableOutBuffer modify buffer : ", testNb++); 1061*3117ece4Schristos in.pos = out.pos = 0; 1062*3117ece4Schristos in.size = CNBufferSize; 1063*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue)); 1064*3117ece4Schristos in.pos = out.pos = 0; 1065*3117ece4Schristos { size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue); 1066*3117ece4Schristos CHECK(!ZSTD_isError(ret), "Must have errored"); 1067*3117ece4Schristos CHECK(!(ZSTD_getErrorCode(ret) == ZSTD_error_stabilityCondition_notRespected), "Must be this error"); 1068*3117ece4Schristos } 1069*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1070*3117ece4Schristos 1071*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() with ZSTD_c_stableOutBuffer: context size : ", testNb++); 1072*3117ece4Schristos { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx); 1073*3117ece4Schristos DISPLAYLEVEL(4, "cctxSize1=%zu; cctxSize=%zu; cctxSize2=%zu : ", cctxSize1, cctxSize, cctxSize2); 1074*3117ece4Schristos CHECK(!(cctxSize1 < cctxSize), "Must be bigger than single-pass and stableInBuffer"); 1075*3117ece4Schristos CHECK(!(cctxSize < cctxSize2), "Must be smaller than streaming"); 1076*3117ece4Schristos } 1077*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1078*3117ece4Schristos 1079*3117ece4Schristos ZSTD_freeCCtx(cctx); 1080*3117ece4Schristos } 1081*3117ece4Schristos 1082*3117ece4Schristos /* CDict scenario */ 1083*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : digested dictionary : ", testNb++); 1084*3117ece4Schristos { ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, 1 /*byRef*/ ); 1085*3117ece4Schristos size_t const initError = ZSTD_initCStream_usingCDict(zc, cdict); 1086*3117ece4Schristos DISPLAYLEVEL(5, "ZSTD_initCStream_usingCDict result : %u ", (unsigned)initError); 1087*3117ece4Schristos if (ZSTD_isError(initError)) goto _output_error; 1088*3117ece4Schristos outBuff.dst = compressedBuffer; 1089*3117ece4Schristos outBuff.size = compressedBufferSize; 1090*3117ece4Schristos outBuff.pos = 0; 1091*3117ece4Schristos inBuff.src = CNBuffer; 1092*3117ece4Schristos inBuff.size = CNBufferSize; 1093*3117ece4Schristos inBuff.pos = 0; 1094*3117ece4Schristos DISPLAYLEVEL(5, "- starting ZSTD_compressStream "); 1095*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 1096*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 1097*3117ece4Schristos { size_t const r = ZSTD_endStream(zc, &outBuff); 1098*3117ece4Schristos DISPLAYLEVEL(5, "- ZSTD_endStream result : %u ", (unsigned)r); 1099*3117ece4Schristos if (r != 0) goto _output_error; /* error, or some data not flushed */ 1100*3117ece4Schristos } 1101*3117ece4Schristos cSize = outBuff.pos; 1102*3117ece4Schristos ZSTD_freeCDict(cdict); 1103*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBufferSize*100); 1104*3117ece4Schristos } 1105*3117ece4Schristos 1106*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check CStream size : ", testNb++); 1107*3117ece4Schristos { size_t const s = ZSTD_sizeof_CStream(zc); 1108*3117ece4Schristos if (ZSTD_isError(s)) goto _output_error; 1109*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes) \n", (unsigned)s); 1110*3117ece4Schristos } 1111*3117ece4Schristos 1112*3117ece4Schristos DISPLAYLEVEL(4, "test%3i : check Dictionary ID : ", testNb++); 1113*3117ece4Schristos { unsigned const dID = ZSTD_getDictID_fromFrame(compressedBuffer, cSize); 1114*3117ece4Schristos if (dID != dictID) goto _output_error; 1115*3117ece4Schristos DISPLAYLEVEL(4, "OK (%u) \n", dID); 1116*3117ece4Schristos } 1117*3117ece4Schristos 1118*3117ece4Schristos /* DDict scenario */ 1119*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress %u bytes with digested dictionary : ", testNb++, (unsigned)CNBufferSize); 1120*3117ece4Schristos { ZSTD_DDict* const ddict = ZSTD_createDDict(dictionary.start, dictionary.filled); 1121*3117ece4Schristos size_t const initError = ZSTD_initDStream_usingDDict(zd, ddict); 1122*3117ece4Schristos if (ZSTD_isError(initError)) goto _output_error; 1123*3117ece4Schristos outBuff.dst = decodedBuffer; 1124*3117ece4Schristos outBuff.size = CNBufferSize; 1125*3117ece4Schristos outBuff.pos = 0; 1126*3117ece4Schristos inBuff.src = compressedBuffer; 1127*3117ece4Schristos inBuff.size = cSize; 1128*3117ece4Schristos inBuff.pos = 0; 1129*3117ece4Schristos { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff); 1130*3117ece4Schristos if (r != 0) goto _output_error; } /* should reach end of frame == 0; otherwise, some data left, or an error */ 1131*3117ece4Schristos if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */ 1132*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */ 1133*3117ece4Schristos ZSTD_freeDDict(ddict); 1134*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1135*3117ece4Schristos } 1136*3117ece4Schristos 1137*3117ece4Schristos /* Memory restriction */ 1138*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : maxWindowSize < frame requirement : ", testNb++); 1139*3117ece4Schristos ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize); 1140*3117ece4Schristos CHECK_Z( ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, 10) ); /* too small limit */ 1141*3117ece4Schristos outBuff.dst = decodedBuffer; 1142*3117ece4Schristos outBuff.size = CNBufferSize; 1143*3117ece4Schristos outBuff.pos = 0; 1144*3117ece4Schristos inBuff.src = compressedBuffer; 1145*3117ece4Schristos inBuff.size = cSize; 1146*3117ece4Schristos inBuff.pos = 0; 1147*3117ece4Schristos { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff); 1148*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; /* must fail : frame requires > 100 bytes */ 1149*3117ece4Schristos DISPLAYLEVEL(3, "OK (%s)\n", ZSTD_getErrorName(r)); } 1150*3117ece4Schristos ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters); /* leave zd in good shape for next tests */ 1151*3117ece4Schristos 1152*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : dictionary source size and level : ", testNb++); 1153*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 1154*3117ece4Schristos int const maxLevel = 16; /* first level with zstd_opt */ 1155*3117ece4Schristos int level; 1156*3117ece4Schristos assert(maxLevel < ZSTD_maxCLevel()); 1157*3117ece4Schristos CHECK_Z( ZSTD_DCtx_loadDictionary_byReference(dctx, dictionary.start, dictionary.filled) ); 1158*3117ece4Schristos for (level = 1; level <= maxLevel; ++level) { 1159*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, level); 1160*3117ece4Schristos size_t const maxSize = MIN(1 MB, CNBufferSize); 1161*3117ece4Schristos size_t size; 1162*3117ece4Schristos for (size = 512; size <= maxSize; size <<= 1) { 1163*3117ece4Schristos U64 const crcOrig = XXH64(CNBuffer, size, 0); 1164*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1165*3117ece4Schristos ZSTD_parameters savedParams; 1166*3117ece4Schristos getCCtxParams(cctx, &savedParams); 1167*3117ece4Schristos outBuff.dst = compressedBuffer; 1168*3117ece4Schristos outBuff.size = compressedBufferSize; 1169*3117ece4Schristos outBuff.pos = 0; 1170*3117ece4Schristos inBuff.src = CNBuffer; 1171*3117ece4Schristos inBuff.size = size; 1172*3117ece4Schristos inBuff.pos = 0; 1173*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict)); 1174*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &outBuff, &inBuff, ZSTD_e_end)); 1175*3117ece4Schristos CHECK(badParameters(cctx, savedParams), "Bad CCtx params"); 1176*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; 1177*3117ece4Schristos { ZSTD_outBuffer decOut = {decodedBuffer, size, 0}; 1178*3117ece4Schristos ZSTD_inBuffer decIn = {outBuff.dst, outBuff.pos, 0}; 1179*3117ece4Schristos CHECK_Z( ZSTD_decompressStream(dctx, &decOut, &decIn) ); 1180*3117ece4Schristos if (decIn.pos != decIn.size) goto _output_error; 1181*3117ece4Schristos if (decOut.pos != size) goto _output_error; 1182*3117ece4Schristos { U64 const crcDec = XXH64(decOut.dst, decOut.pos, 0); 1183*3117ece4Schristos if (crcDec != crcOrig) goto _output_error; 1184*3117ece4Schristos } } 1185*3117ece4Schristos ZSTD_freeCCtx(cctx); 1186*3117ece4Schristos } 1187*3117ece4Schristos ZSTD_freeCDict(cdict); 1188*3117ece4Schristos } 1189*3117ece4Schristos ZSTD_freeDCtx(dctx); 1190*3117ece4Schristos } 1191*3117ece4Schristos DISPLAYLEVEL(3, "OK\n"); 1192*3117ece4Schristos 1193*3117ece4Schristos ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters); 1194*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dictionary.start, dictionary.filled) ); 1195*3117ece4Schristos cSize = ZSTD_compress2(zc, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBufferSize, 100 KB)); 1196*3117ece4Schristos CHECK_Z(cSize); 1197*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() with dictionary : ", testNb++); 1198*3117ece4Schristos { 1199*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 1200*3117ece4Schristos /* We should fail to decompress without a dictionary. */ 1201*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 1202*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1203*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1204*3117ece4Schristos size_t const ret = ZSTD_decompressStream(dctx, &out, &in); 1205*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 1206*3117ece4Schristos } 1207*3117ece4Schristos /* We should succeed to decompress with the dictionary. */ 1208*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 1209*3117ece4Schristos CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictionary.start, dictionary.filled) ); 1210*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1211*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1212*3117ece4Schristos if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error; 1213*3117ece4Schristos if (in.pos != in.size) goto _output_error; 1214*3117ece4Schristos } 1215*3117ece4Schristos /* The dictionary should persist across calls. */ 1216*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1217*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1218*3117ece4Schristos if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error; 1219*3117ece4Schristos if (in.pos != in.size) goto _output_error; 1220*3117ece4Schristos } 1221*3117ece4Schristos /* The dictionary should not be cleared by ZSTD_reset_session_only. */ 1222*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); 1223*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1224*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1225*3117ece4Schristos if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error; 1226*3117ece4Schristos if (in.pos != in.size) goto _output_error; 1227*3117ece4Schristos } 1228*3117ece4Schristos /* When we reset the context the dictionary is cleared. */ 1229*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 1230*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1231*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1232*3117ece4Schristos size_t const ret = ZSTD_decompressStream(dctx, &out, &in); 1233*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 1234*3117ece4Schristos } 1235*3117ece4Schristos ZSTD_freeDCtx(dctx); 1236*3117ece4Schristos } 1237*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1238*3117ece4Schristos 1239*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_resetDStream() with dictionary : ", testNb++); 1240*3117ece4Schristos { 1241*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 1242*3117ece4Schristos /* We should succeed to decompress with the dictionary. */ 1243*3117ece4Schristos ZSTD_resetDStream(dctx); 1244*3117ece4Schristos CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictionary.start, dictionary.filled) ); 1245*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1246*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1247*3117ece4Schristos if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error; 1248*3117ece4Schristos if (in.pos != in.size) goto _output_error; 1249*3117ece4Schristos } 1250*3117ece4Schristos /* The dictionary should not be cleared by ZSTD_resetDStream(). */ 1251*3117ece4Schristos ZSTD_resetDStream(dctx); 1252*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1253*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1254*3117ece4Schristos if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error; 1255*3117ece4Schristos if (in.pos != in.size) goto _output_error; 1256*3117ece4Schristos } 1257*3117ece4Schristos /* The dictionary should be cleared by ZSTD_initDStream(). */ 1258*3117ece4Schristos CHECK_Z( ZSTD_initDStream(dctx) ); 1259*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1260*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1261*3117ece4Schristos size_t const ret = ZSTD_decompressStream(dctx, &out, &in); 1262*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 1263*3117ece4Schristos } 1264*3117ece4Schristos ZSTD_freeDCtx(dctx); 1265*3117ece4Schristos } 1266*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1267*3117ece4Schristos 1268*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() with ddict : ", testNb++); 1269*3117ece4Schristos { 1270*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 1271*3117ece4Schristos ZSTD_DDict* ddict = ZSTD_createDDict(dictionary.start, dictionary.filled); 1272*3117ece4Schristos /* We should succeed to decompress with the ddict. */ 1273*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 1274*3117ece4Schristos CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) ); 1275*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1276*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1277*3117ece4Schristos if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error; 1278*3117ece4Schristos if (in.pos != in.size) goto _output_error; 1279*3117ece4Schristos } 1280*3117ece4Schristos /* The ddict should persist across calls. */ 1281*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1282*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1283*3117ece4Schristos if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error; 1284*3117ece4Schristos if (in.pos != in.size) goto _output_error; 1285*3117ece4Schristos } 1286*3117ece4Schristos /* When we reset the context the ddict is cleared. */ 1287*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 1288*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1289*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1290*3117ece4Schristos size_t const ret = ZSTD_decompressStream(dctx, &out, &in); 1291*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 1292*3117ece4Schristos } 1293*3117ece4Schristos ZSTD_freeDCtx(dctx); 1294*3117ece4Schristos ZSTD_freeDDict(ddict); 1295*3117ece4Schristos } 1296*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1297*3117ece4Schristos 1298*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with prefix : ", testNb++); 1299*3117ece4Schristos { 1300*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 1301*3117ece4Schristos /* We should succeed to decompress with the prefix. */ 1302*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 1303*3117ece4Schristos CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictionary.start, dictionary.filled, ZSTD_dct_auto) ); 1304*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1305*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1306*3117ece4Schristos if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error; 1307*3117ece4Schristos if (in.pos != in.size) goto _output_error; 1308*3117ece4Schristos } 1309*3117ece4Schristos /* The prefix should be cleared after the first compression. */ 1310*3117ece4Schristos { ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1311*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1312*3117ece4Schristos size_t const ret = ZSTD_decompressStream(dctx, &out, &in); 1313*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 1314*3117ece4Schristos } 1315*3117ece4Schristos ZSTD_freeDCtx(dctx); 1316*3117ece4Schristos } 1317*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1318*3117ece4Schristos 1319*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_initDStream*() with dictionary : ", testNb++); 1320*3117ece4Schristos { 1321*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 1322*3117ece4Schristos ZSTD_DDict* ddict = ZSTD_createDDict(dictionary.start, dictionary.filled); 1323*3117ece4Schristos size_t ret; 1324*3117ece4Schristos /* We should succeed to decompress with the dictionary. */ 1325*3117ece4Schristos CHECK_Z( ZSTD_initDStream_usingDict(dctx, dictionary.start, dictionary.filled) ); 1326*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) ); 1327*3117ece4Schristos /* The dictionary should persist across calls. */ 1328*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) ); 1329*3117ece4Schristos /* We should succeed to decompress with the ddict. */ 1330*3117ece4Schristos CHECK_Z( ZSTD_initDStream_usingDDict(dctx, ddict) ); 1331*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) ); 1332*3117ece4Schristos /* The ddict should persist across calls. */ 1333*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) ); 1334*3117ece4Schristos /* When we reset the context the ddict is cleared. */ 1335*3117ece4Schristos CHECK_Z( ZSTD_initDStream(dctx) ); 1336*3117ece4Schristos ret = ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize); 1337*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 1338*3117ece4Schristos ZSTD_freeDCtx(dctx); 1339*3117ece4Schristos ZSTD_freeDDict(ddict); 1340*3117ece4Schristos } 1341*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1342*3117ece4Schristos 1343*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_usingCDict_advanced with masked dictID : ", testNb++); 1344*3117ece4Schristos { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictionary.filled); 1345*3117ece4Schristos ZSTD_frameParameters const fParams = { 1 /* contentSize */, 1 /* checksum */, 1 /* noDictID */}; 1346*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); 1347*3117ece4Schristos size_t const initError = ZSTD_initCStream_usingCDict_advanced(zc, cdict, fParams, CNBufferSize); 1348*3117ece4Schristos if (ZSTD_isError(initError)) goto _output_error; 1349*3117ece4Schristos outBuff.dst = compressedBuffer; 1350*3117ece4Schristos outBuff.size = compressedBufferSize; 1351*3117ece4Schristos outBuff.pos = 0; 1352*3117ece4Schristos inBuff.src = CNBuffer; 1353*3117ece4Schristos inBuff.size = CNBufferSize; 1354*3117ece4Schristos inBuff.pos = 0; 1355*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 1356*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 1357*3117ece4Schristos { size_t const r = ZSTD_endStream(zc, &outBuff); 1358*3117ece4Schristos if (r != 0) goto _output_error; } /* error, or some data not flushed */ 1359*3117ece4Schristos cSize = outBuff.pos; 1360*3117ece4Schristos ZSTD_freeCDict(cdict); 1361*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBufferSize*100); 1362*3117ece4Schristos } 1363*3117ece4Schristos 1364*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : try retrieving dictID from frame : ", testNb++); 1365*3117ece4Schristos { U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize); 1366*3117ece4Schristos if (did != 0) goto _output_error; 1367*3117ece4Schristos } 1368*3117ece4Schristos DISPLAYLEVEL(3, "OK (not detected) \n"); 1369*3117ece4Schristos 1370*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress without dictionary : ", testNb++); 1371*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize); 1372*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; /* must fail : dictionary not used */ 1373*3117ece4Schristos DISPLAYLEVEL(3, "OK (%s)\n", ZSTD_getErrorName(r)); 1374*3117ece4Schristos } 1375*3117ece4Schristos 1376*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress with ZSTD_CCtx_refPrefix : ", testNb++); 1377*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refPrefix(zc, dictionary.start, dictionary.filled) ); 1378*3117ece4Schristos outBuff.dst = compressedBuffer; 1379*3117ece4Schristos outBuff.size = compressedBufferSize; 1380*3117ece4Schristos outBuff.pos = 0; 1381*3117ece4Schristos inBuff.src = CNBuffer; 1382*3117ece4Schristos inBuff.size = CNBufferSize; 1383*3117ece4Schristos inBuff.pos = 0; 1384*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end) ); 1385*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 1386*3117ece4Schristos cSize = outBuff.pos; 1387*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBufferSize*100); 1388*3117ece4Schristos 1389*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress with ZSTD_DCtx_refPrefix : ", testNb++); 1390*3117ece4Schristos CHECK_Z( ZSTD_DCtx_refPrefix(zd, dictionary.start, dictionary.filled) ); 1391*3117ece4Schristos outBuff.dst = decodedBuffer; 1392*3117ece4Schristos outBuff.size = CNBufferSize; 1393*3117ece4Schristos outBuff.pos = 0; 1394*3117ece4Schristos inBuff.src = compressedBuffer; 1395*3117ece4Schristos inBuff.size = cSize; 1396*3117ece4Schristos inBuff.pos = 0; 1397*3117ece4Schristos CHECK_Z( ZSTD_decompressStream(zd, &outBuff, &inBuff) ); 1398*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 1399*3117ece4Schristos if (outBuff.pos != CNBufferSize) goto _output_error; /* must regenerate whole input */ 1400*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1401*3117ece4Schristos 1402*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress without dictionary (should fail): ", testNb++); 1403*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize); 1404*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; /* must fail : dictionary not used */ 1405*3117ece4Schristos DISPLAYLEVEL(3, "OK (%s)\n", ZSTD_getErrorName(r)); 1406*3117ece4Schristos } 1407*3117ece4Schristos 1408*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress again with ZSTD_compressStream2 : ", testNb++); 1409*3117ece4Schristos outBuff.dst = compressedBuffer; 1410*3117ece4Schristos outBuff.size = compressedBufferSize; 1411*3117ece4Schristos outBuff.pos = 0; 1412*3117ece4Schristos inBuff.src = CNBuffer; 1413*3117ece4Schristos inBuff.size = CNBufferSize; 1414*3117ece4Schristos inBuff.pos = 0; 1415*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end) ); 1416*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 1417*3117ece4Schristos cSize = outBuff.pos; 1418*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBufferSize*100); 1419*3117ece4Schristos 1420*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress without dictionary (should work): ", testNb++); 1421*3117ece4Schristos CHECK_Z( ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize) ); 1422*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1423*3117ece4Schristos 1424*3117ece4Schristos /* Empty srcSize */ 1425*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_advanced with pledgedSrcSize=0 and dict : ", testNb++); 1426*3117ece4Schristos { ZSTD_parameters params = ZSTD_getParams(5, 0, 0); 1427*3117ece4Schristos params.fParams.contentSizeFlag = 1; 1428*3117ece4Schristos CHECK_Z( ZSTD_initCStream_advanced(zc, dictionary.start, dictionary.filled, params, 0 /* pledgedSrcSize==0 means "empty" when params.fParams.contentSizeFlag is set */) ); 1429*3117ece4Schristos } /* cstream advanced shall write content size = 0 */ 1430*3117ece4Schristos outBuff.dst = compressedBuffer; 1431*3117ece4Schristos outBuff.size = compressedBufferSize; 1432*3117ece4Schristos outBuff.pos = 0; 1433*3117ece4Schristos inBuff.src = CNBuffer; 1434*3117ece4Schristos inBuff.size = 0; 1435*3117ece4Schristos inBuff.pos = 0; 1436*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 1437*3117ece4Schristos if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error; 1438*3117ece4Schristos cSize = outBuff.pos; 1439*3117ece4Schristos if (ZSTD_findDecompressedSize(compressedBuffer, cSize) != 0) goto _output_error; 1440*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1441*3117ece4Schristos 1442*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : pledgedSrcSize == 0 behaves properly with ZSTD_initCStream_advanced : ", testNb++); 1443*3117ece4Schristos { ZSTD_parameters params = ZSTD_getParams(5, 0, 0); 1444*3117ece4Schristos params.fParams.contentSizeFlag = 1; 1445*3117ece4Schristos CHECK_Z( ZSTD_initCStream_advanced(zc, NULL, 0, params, 0) ); 1446*3117ece4Schristos } /* cstream advanced shall write content size = 0 */ 1447*3117ece4Schristos inBuff.src = CNBuffer; 1448*3117ece4Schristos inBuff.size = 0; 1449*3117ece4Schristos inBuff.pos = 0; 1450*3117ece4Schristos outBuff.dst = compressedBuffer; 1451*3117ece4Schristos outBuff.size = compressedBufferSize; 1452*3117ece4Schristos outBuff.pos = 0; 1453*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 1454*3117ece4Schristos if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error; 1455*3117ece4Schristos cSize = outBuff.pos; 1456*3117ece4Schristos if (ZSTD_findDecompressedSize(compressedBuffer, cSize) != 0) goto _output_error; 1457*3117ece4Schristos 1458*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 1459*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, ZSTD_CONTENTSIZE_UNKNOWN) ); 1460*3117ece4Schristos outBuff.dst = compressedBuffer; 1461*3117ece4Schristos outBuff.size = compressedBufferSize; 1462*3117ece4Schristos outBuff.pos = 0; 1463*3117ece4Schristos inBuff.src = CNBuffer; 1464*3117ece4Schristos inBuff.size = 0; 1465*3117ece4Schristos inBuff.pos = 0; 1466*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 1467*3117ece4Schristos if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error; 1468*3117ece4Schristos cSize = outBuff.pos; 1469*3117ece4Schristos if (ZSTD_findDecompressedSize(compressedBuffer, cSize) != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error; 1470*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1471*3117ece4Schristos 1472*3117ece4Schristos /* Basic multithreading compression test */ 1473*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress %u bytes with multiple threads : ", testNb++, COMPRESSIBLE_NOISE_LENGTH); 1474*3117ece4Schristos { int jobSize; 1475*3117ece4Schristos CHECK_Z( ZSTD_CCtx_getParameter(mtctx, ZSTD_c_jobSize, &jobSize)); 1476*3117ece4Schristos CHECK(jobSize != 0, "job size non-zero"); 1477*3117ece4Schristos CHECK_Z( ZSTD_CCtx_getParameter(mtctx, ZSTD_c_jobSize, &jobSize)); 1478*3117ece4Schristos CHECK(jobSize != 0, "job size non-zero"); 1479*3117ece4Schristos } 1480*3117ece4Schristos outBuff.dst = compressedBuffer; 1481*3117ece4Schristos outBuff.size = compressedBufferSize; 1482*3117ece4Schristos outBuff.pos = 0; 1483*3117ece4Schristos inBuff.src = CNBuffer; 1484*3117ece4Schristos inBuff.size = CNBufferSize; 1485*3117ece4Schristos inBuff.pos = 0; 1486*3117ece4Schristos { size_t const compressResult = ZSTD_compressStream2(mtctx, &outBuff, &inBuff, ZSTD_e_end); 1487*3117ece4Schristos if (compressResult != 0) goto _output_error; /* compression must be completed in a single round */ 1488*3117ece4Schristos } 1489*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 1490*3117ece4Schristos { size_t const compressedSize = ZSTD_findFrameCompressedSize(compressedBuffer, outBuff.pos); 1491*3117ece4Schristos if (compressedSize != outBuff.pos) goto _output_error; /* must be a full valid frame */ 1492*3117ece4Schristos } 1493*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1494*3117ece4Schristos 1495*3117ece4Schristos /* Complex multithreading + dictionary test */ 1496*3117ece4Schristos { U32 const nbWorkers = 2; 1497*3117ece4Schristos size_t const jobSize = 4 * 1 MB; 1498*3117ece4Schristos size_t const srcSize = jobSize * nbWorkers; /* we want each job to have predictable size */ 1499*3117ece4Schristos size_t const segLength = 2 KB; 1500*3117ece4Schristos size_t const offset = 600 KB; /* must be larger than window defined in cdict */ 1501*3117ece4Schristos size_t const start = jobSize + (offset-1); 1502*3117ece4Schristos const BYTE* const srcToCopy = (const BYTE*)CNBuffer + start; 1503*3117ece4Schristos BYTE* const dst = (BYTE*)CNBuffer + start - offset; 1504*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress %u bytes with multiple threads + dictionary : ", testNb++, (unsigned)srcSize); 1505*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 3) ); 1506*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_nbWorkers, nbWorkers) ); 1507*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_jobSize, jobSize) ); 1508*3117ece4Schristos assert(start > offset); 1509*3117ece4Schristos assert(start + segLength < COMPRESSIBLE_NOISE_LENGTH); 1510*3117ece4Schristos memcpy(dst, srcToCopy, segLength); /* create a long repetition at long distance for job 2 */ 1511*3117ece4Schristos outBuff.dst = compressedBuffer; 1512*3117ece4Schristos outBuff.size = compressedBufferSize; 1513*3117ece4Schristos outBuff.pos = 0; 1514*3117ece4Schristos inBuff.src = CNBuffer; 1515*3117ece4Schristos inBuff.size = srcSize; assert(srcSize < COMPRESSIBLE_NOISE_LENGTH); 1516*3117ece4Schristos inBuff.pos = 0; 1517*3117ece4Schristos } 1518*3117ece4Schristos { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, 4 KB, dictionary.filled); /* intentionally lies on estimatedSrcSize, to push cdict into targeting a small window size */ 1519*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem); 1520*3117ece4Schristos DISPLAYLEVEL(5, "cParams.windowLog = %u : ", cParams.windowLog); 1521*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(zc, cdict) ); 1522*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end) ); 1523*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(zc, NULL) ); /* do not keep a reference to cdict, as its lifetime ends */ 1524*3117ece4Schristos ZSTD_freeCDict(cdict); 1525*3117ece4Schristos } 1526*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 1527*3117ece4Schristos cSize = outBuff.pos; 1528*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1529*3117ece4Schristos 1530*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress large frame created from multiple threads + dictionary : ", testNb++); 1531*3117ece4Schristos { ZSTD_DStream* const dstream = ZSTD_createDCtx(); 1532*3117ece4Schristos ZSTD_frameHeader zfh; 1533*3117ece4Schristos ZSTD_getFrameHeader(&zfh, compressedBuffer, cSize); 1534*3117ece4Schristos DISPLAYLEVEL(5, "frame windowsize = %u : ", (unsigned)zfh.windowSize); 1535*3117ece4Schristos outBuff.dst = decodedBuffer; 1536*3117ece4Schristos outBuff.size = CNBufferSize; 1537*3117ece4Schristos outBuff.pos = 0; 1538*3117ece4Schristos inBuff.src = compressedBuffer; 1539*3117ece4Schristos inBuff.pos = 0; 1540*3117ece4Schristos CHECK_Z( ZSTD_initDStream_usingDict(dstream, dictionary.start, dictionary.filled) ); 1541*3117ece4Schristos inBuff.size = 1; /* avoid shortcut to single-pass mode */ 1542*3117ece4Schristos CHECK_Z( ZSTD_decompressStream(dstream, &outBuff, &inBuff) ); 1543*3117ece4Schristos inBuff.size = cSize; 1544*3117ece4Schristos CHECK_Z( ZSTD_decompressStream(dstream, &outBuff, &inBuff) ); 1545*3117ece4Schristos if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ 1546*3117ece4Schristos ZSTD_freeDStream(dstream); 1547*3117ece4Schristos } 1548*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1549*3117ece4Schristos 1550*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check dictionary FSE tables can represent every code : ", testNb++); 1551*3117ece4Schristos { unsigned const kMaxWindowLog = 24; 1552*3117ece4Schristos unsigned value; 1553*3117ece4Schristos ZSTD_compressionParameters cParams = ZSTD_getCParams(3, 1U << kMaxWindowLog, 1024); 1554*3117ece4Schristos ZSTD_CDict* cdict; 1555*3117ece4Schristos ZSTD_DDict* ddict; 1556*3117ece4Schristos SEQ_stream seq = SEQ_initStream(0x87654321); 1557*3117ece4Schristos SEQ_gen_type type; 1558*3117ece4Schristos XXH64_state_t xxh; 1559*3117ece4Schristos 1560*3117ece4Schristos XXH64_reset(&xxh, 0); 1561*3117ece4Schristos cParams.windowLog = kMaxWindowLog; 1562*3117ece4Schristos cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem); 1563*3117ece4Schristos ddict = ZSTD_createDDict(dictionary.start, dictionary.filled); 1564*3117ece4Schristos 1565*3117ece4Schristos if (!cdict || !ddict) goto _output_error; 1566*3117ece4Schristos 1567*3117ece4Schristos ZSTD_CCtx_reset(zc, ZSTD_reset_session_only); 1568*3117ece4Schristos ZSTD_resetDStream(zd); 1569*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refCDict(zc, cdict)); 1570*3117ece4Schristos CHECK_Z(ZSTD_initDStream_usingDDict(zd, ddict)); 1571*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, kMaxWindowLog)); 1572*3117ece4Schristos /* Test all values < 300 */ 1573*3117ece4Schristos for (value = 0; value < 300; ++value) { 1574*3117ece4Schristos for (type = (SEQ_gen_type)0; type < SEQ_gen_max; ++type) { 1575*3117ece4Schristos CHECK_Z(SEQ_generateRoundTrip(zc, zd, &xxh, &seq, type, value)); 1576*3117ece4Schristos } 1577*3117ece4Schristos } 1578*3117ece4Schristos /* Test values 2^8 to 2^17 */ 1579*3117ece4Schristos for (value = (1 << 8); value < (1 << 17); value <<= 1) { 1580*3117ece4Schristos for (type = (SEQ_gen_type)0; type < SEQ_gen_max; ++type) { 1581*3117ece4Schristos CHECK_Z(SEQ_generateRoundTrip(zc, zd, &xxh, &seq, type, value)); 1582*3117ece4Schristos CHECK_Z(SEQ_generateRoundTrip(zc, zd, &xxh, &seq, type, value + (value >> 2))); 1583*3117ece4Schristos } 1584*3117ece4Schristos } 1585*3117ece4Schristos /* Test offset values up to the max window log */ 1586*3117ece4Schristos for (value = 8; value <= kMaxWindowLog; ++value) { 1587*3117ece4Schristos CHECK_Z(SEQ_generateRoundTrip(zc, zd, &xxh, &seq, SEQ_gen_of, (1U << value) - 1)); 1588*3117ece4Schristos } 1589*3117ece4Schristos 1590*3117ece4Schristos CHECK_Z(SEQ_roundTrip(zc, zd, &xxh, NULL, 0, ZSTD_e_end)); 1591*3117ece4Schristos CHECK(SEQ_digest(&seq) != XXH64_digest(&xxh), "SEQ XXH64 does not match"); 1592*3117ece4Schristos 1593*3117ece4Schristos ZSTD_freeCDict(cdict); 1594*3117ece4Schristos ZSTD_freeDDict(ddict); 1595*3117ece4Schristos } 1596*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1597*3117ece4Schristos 1598*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_srcSize sets requestedParams : ", testNb++); 1599*3117ece4Schristos { int level; 1600*3117ece4Schristos CHECK_Z(ZSTD_initCStream_srcSize(zc, 11, ZSTD_CONTENTSIZE_UNKNOWN)); 1601*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_compressionLevel, &level)); 1602*3117ece4Schristos CHECK(level != 11, "Compression level does not match"); 1603*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 1604*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, ZSTD_CONTENTSIZE_UNKNOWN) ); 1605*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_compressionLevel, &level)); 1606*3117ece4Schristos CHECK(level != 11, "Compression level does not match"); 1607*3117ece4Schristos } 1608*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1609*3117ece4Schristos 1610*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_advanced sets requestedParams : ", testNb++); 1611*3117ece4Schristos { ZSTD_parameters const params = ZSTD_getParams(9, 0, 0); 1612*3117ece4Schristos CHECK_Z(ZSTD_initCStream_advanced(zc, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN)); 1613*3117ece4Schristos CHECK(badParameters(zc, params), "Compression parameters do not match"); 1614*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 1615*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, ZSTD_CONTENTSIZE_UNKNOWN) ); 1616*3117ece4Schristos CHECK(badParameters(zc, params), "Compression parameters do not match"); 1617*3117ece4Schristos } 1618*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1619*3117ece4Schristos 1620*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_c_srcSizeHint bounds : ", testNb++); 1621*3117ece4Schristos ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters); 1622*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_srcSizeHint, INT_MAX)); 1623*3117ece4Schristos { int srcSizeHint; 1624*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_srcSizeHint, &srcSizeHint)); 1625*3117ece4Schristos CHECK(!(srcSizeHint == INT_MAX), "srcSizeHint doesn't match"); 1626*3117ece4Schristos } 1627*3117ece4Schristos CHECK(!ZSTD_isError(ZSTD_CCtx_setParameter(zc, ZSTD_c_srcSizeHint, -1)), "Out of range doesn't error"); 1628*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1629*3117ece4Schristos 1630*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_lazy compress with hashLog = 29 and searchLog = 4 : ", testNb++); 1631*3117ece4Schristos if (MEM_64bits()) { 1632*3117ece4Schristos ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 }; 1633*3117ece4Schristos ZSTD_inBuffer in = { CNBuffer, CNBufferSize, 0 }; 1634*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters)); 1635*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_strategy, ZSTD_lazy)); 1636*3117ece4Schristos /* Force enable the row based match finder */ 1637*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_useRowMatchFinder, ZSTD_ps_enable)); 1638*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_searchLog, 4)); 1639*3117ece4Schristos /* Set windowLog to 29 so the hashLog doesn't get sized down */ 1640*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_windowLog, 29)); 1641*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_hashLog, 29)); 1642*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, 1)); 1643*3117ece4Schristos /* Compress with continue first so the hashLog doesn't get sized down */ 1644*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_continue)); 1645*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_end)); 1646*3117ece4Schristos cSize = out.pos; 1647*3117ece4Schristos CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize)); 1648*3117ece4Schristos } 1649*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1650*3117ece4Schristos 1651*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Test offset == windowSize : ", testNb++); 1652*3117ece4Schristos { 1653*3117ece4Schristos int windowLog; 1654*3117ece4Schristos int const kMaxWindowLog = bigTests ? 29 : 26; 1655*3117ece4Schristos size_t const kNbSequences = 10000; 1656*3117ece4Schristos size_t const kMaxSrcSize = (1u << kMaxWindowLog) + 10 * kNbSequences; 1657*3117ece4Schristos char* src = calloc(kMaxSrcSize, 1); 1658*3117ece4Schristos ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences); 1659*3117ece4Schristos for (windowLog = ZSTD_WINDOWLOG_MIN; windowLog <= kMaxWindowLog; ++windowLog) { 1660*3117ece4Schristos size_t const srcSize = ((size_t)1 << windowLog) + 10 * (kNbSequences - 1); 1661*3117ece4Schristos 1662*3117ece4Schristos sequences[0].offset = 32; 1663*3117ece4Schristos sequences[0].litLength = 32; 1664*3117ece4Schristos sequences[0].matchLength = (1u << windowLog) - 32; 1665*3117ece4Schristos sequences[0].rep = 0; 1666*3117ece4Schristos { 1667*3117ece4Schristos size_t i; 1668*3117ece4Schristos for (i = 1; i < kNbSequences; ++i) { 1669*3117ece4Schristos sequences[i].offset = (1u << windowLog) - (FUZ_rand(&seed) % 8); 1670*3117ece4Schristos sequences[i].litLength = FUZ_rand(&seed) & 7; 1671*3117ece4Schristos sequences[i].matchLength = 10 - sequences[i].litLength; 1672*3117ece4Schristos sequences[i].rep = 0; 1673*3117ece4Schristos } 1674*3117ece4Schristos } 1675*3117ece4Schristos 1676*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters)); 1677*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, 1)); 1678*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_minMatch, 3)); 1679*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_validateSequences, 1)); 1680*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_windowLog, windowLog)); 1681*3117ece4Schristos assert(srcSize <= kMaxSrcSize); 1682*3117ece4Schristos cSize = ZSTD_compressSequences(zc, compressedBuffer, compressedBufferSize, sequences, kNbSequences, src, srcSize); 1683*3117ece4Schristos CHECK_Z(cSize); 1684*3117ece4Schristos CHECK_Z(ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters)); 1685*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, windowLog)) 1686*3117ece4Schristos { 1687*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1688*3117ece4Schristos size_t decompressedBytes = 0; 1689*3117ece4Schristos for (;;) { 1690*3117ece4Schristos ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0}; 1691*3117ece4Schristos size_t const ret = ZSTD_decompressStream(zd, &out, &in); 1692*3117ece4Schristos CHECK_Z(ret); 1693*3117ece4Schristos CHECK(decompressedBytes + out.pos > srcSize, "Output too large"); 1694*3117ece4Schristos CHECK(memcmp(out.dst, src + decompressedBytes, out.pos), "Corrupted"); 1695*3117ece4Schristos decompressedBytes += out.pos; 1696*3117ece4Schristos if (ret == 0) { 1697*3117ece4Schristos break; 1698*3117ece4Schristos } 1699*3117ece4Schristos } 1700*3117ece4Schristos CHECK(decompressedBytes != srcSize, "Output wrong size"); 1701*3117ece4Schristos } 1702*3117ece4Schristos } 1703*3117ece4Schristos free(sequences); 1704*3117ece4Schristos free(src); 1705*3117ece4Schristos } 1706*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1707*3117ece4Schristos 1708*3117ece4Schristos /* Overlen overwriting window data bug */ 1709*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : wildcopy doesn't overwrite potential match data : ", testNb++); 1710*3117ece4Schristos { /* This test has a window size of 1024 bytes and consists of 3 blocks: 1711*3117ece4Schristos 1. 'a' repeated 517 times 1712*3117ece4Schristos 2. 'b' repeated 516 times 1713*3117ece4Schristos 3. a compressed block with no literals and 3 sequence commands: 1714*3117ece4Schristos litlength = 0, offset = 24, match length = 24 1715*3117ece4Schristos litlength = 0, offset = 24, match length = 3 (this one creates an overlength write of length 2*WILDCOPY_OVERLENGTH - 3) 1716*3117ece4Schristos litlength = 0, offset = 1021, match length = 3 (this one will try to read from overwritten data if the buffer is too small) */ 1717*3117ece4Schristos 1718*3117ece4Schristos const char* testCase = 1719*3117ece4Schristos "\x28\xB5\x2F\xFD\x04\x00\x4C\x00\x00\x10\x61\x61\x01\x00\x00\x2A" 1720*3117ece4Schristos "\x80\x05\x44\x00\x00\x08\x62\x01\x00\x00\x2A\x20\x04\x5D\x00\x00" 1721*3117ece4Schristos "\x00\x03\x40\x00\x00\x64\x60\x27\xB0\xE0\x0C\x67\x62\xCE\xE0"; 1722*3117ece4Schristos ZSTD_DStream* const zds = ZSTD_createDStream(); 1723*3117ece4Schristos if (zds==NULL) goto _output_error; 1724*3117ece4Schristos 1725*3117ece4Schristos CHECK_Z( ZSTD_initDStream(zds) ); 1726*3117ece4Schristos inBuff.src = testCase; 1727*3117ece4Schristos inBuff.size = 47; 1728*3117ece4Schristos inBuff.pos = 0; 1729*3117ece4Schristos outBuff.dst = decodedBuffer; 1730*3117ece4Schristos outBuff.size = CNBufferSize; 1731*3117ece4Schristos outBuff.pos = 0; 1732*3117ece4Schristos 1733*3117ece4Schristos while (inBuff.pos < inBuff.size) { 1734*3117ece4Schristos CHECK_Z( ZSTD_decompressStream(zds, &outBuff, &inBuff) ); 1735*3117ece4Schristos } 1736*3117ece4Schristos 1737*3117ece4Schristos ZSTD_freeDStream(zds); 1738*3117ece4Schristos } 1739*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1740*3117ece4Schristos 1741*3117ece4Schristos /* Small Sequence Section bug */ 1742*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress blocks with small sequences section : ", testNb++); 1743*3117ece4Schristos { /* This test consists of 3 blocks. Each block has one sequence. 1744*3117ece4Schristos The sequence has literal length of 10, match length of 10 and offset of 10. 1745*3117ece4Schristos The sequence value and compression mode for the blocks are following: 1746*3117ece4Schristos The order of values are ll, ml, of. 1747*3117ece4Schristos - First block : (10, 7, 13) (rle, rle, rle) 1748*3117ece4Schristos - size of sequences section: 6 bytes (1 byte for nbSeq, 1 byte for encoding mode, 3 bytes for rle, 1 byte bitstream) 1749*3117ece4Schristos - Second block : (10, 7, 1) (repeat, repeat, rle) 1750*3117ece4Schristos - size of sequences section: 4 bytes (1 byte for nbSeq, 1 byte for encoding mode, 1 bytes for rle, 1 byte bitstream) 1751*3117ece4Schristos - Third block : (10, 7, 1) (repeat, repeat, repeat) 1752*3117ece4Schristos - size of sequences section: 3 bytes (1 byte for nbSeq, 1 byte for encoding mode, 1 byte bitstream) */ 1753*3117ece4Schristos 1754*3117ece4Schristos unsigned char compressed[] = { 1755*3117ece4Schristos 0x28, 0xb5, 0x2f, 0xfd, 0x24, 0x3c, 0x35, 0x01, 0x00, 0xf0, 0x85, 0x08, 1756*3117ece4Schristos 0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x4c, 0x6b, 0xa9, 0x8b, 1757*3117ece4Schristos 0xbc, 0xc5, 0xb6, 0xd9, 0x7f, 0x4c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 1758*3117ece4Schristos 0x69, 0x94, 0x89, 0x1c, 0x03, 0x44, 0x0a, 0x07, 0x00, 0xb4, 0x04, 0x80, 1759*3117ece4Schristos 0x40, 0x0a, 0xa4 1760*3117ece4Schristos }; 1761*3117ece4Schristos unsigned int compressedSize = 51; 1762*3117ece4Schristos unsigned char decompressed[] = { 1763*3117ece4Schristos 0x85, 0x08, 0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x85, 0x08, 1764*3117ece4Schristos 0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x4c, 0x6b, 0xa9, 0x8b, 1765*3117ece4Schristos 0xbc, 0xc5, 0xb6, 0xd9, 0x7f, 0x4c, 0x4c, 0x6b, 0xa9, 0x8b, 0xbc, 0xc5, 1766*3117ece4Schristos 0xb6, 0xd9, 0x7f, 0x4c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 0x69, 0x94, 1767*3117ece4Schristos 0x89, 0x1c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 0x69, 0x94, 0x89, 0x1c 1768*3117ece4Schristos }; 1769*3117ece4Schristos unsigned int decompressedSize = 60; 1770*3117ece4Schristos 1771*3117ece4Schristos ZSTD_DStream* const zds = ZSTD_createDStream(); 1772*3117ece4Schristos if (zds==NULL) goto _output_error; 1773*3117ece4Schristos 1774*3117ece4Schristos CHECK_Z( ZSTD_initDStream(zds) ); 1775*3117ece4Schristos inBuff.src = compressed; 1776*3117ece4Schristos inBuff.size = compressedSize; 1777*3117ece4Schristos inBuff.pos = 0; 1778*3117ece4Schristos outBuff.dst = decodedBuffer; 1779*3117ece4Schristos outBuff.size = CNBufferSize; 1780*3117ece4Schristos outBuff.pos = 0; 1781*3117ece4Schristos 1782*3117ece4Schristos CHECK(ZSTD_decompressStream(zds, &outBuff, &inBuff) != 0, 1783*3117ece4Schristos "Decompress did not reach the end of frame"); 1784*3117ece4Schristos CHECK(inBuff.pos != inBuff.size, "Decompress did not fully consume input"); 1785*3117ece4Schristos CHECK(outBuff.pos != decompressedSize, "Decompressed size does not match"); 1786*3117ece4Schristos CHECK(memcmp(outBuff.dst, decompressed, decompressedSize) != 0, 1787*3117ece4Schristos "Decompressed data does not match"); 1788*3117ece4Schristos 1789*3117ece4Schristos ZSTD_freeDStream(zds); 1790*3117ece4Schristos } 1791*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1792*3117ece4Schristos 1793*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : raw block can be streamed: ", testNb++); 1794*3117ece4Schristos { size_t const inputSize = 10000; 1795*3117ece4Schristos size_t const compCapacity = ZSTD_compressBound(inputSize); 1796*3117ece4Schristos BYTE* const input = (BYTE*)malloc(inputSize); 1797*3117ece4Schristos BYTE* const comp = (BYTE*)malloc(compCapacity); 1798*3117ece4Schristos BYTE* const decomp = (BYTE*)malloc(inputSize); 1799*3117ece4Schristos 1800*3117ece4Schristos CHECK(input == NULL || comp == NULL || decomp == NULL, "failed to alloc buffers"); 1801*3117ece4Schristos 1802*3117ece4Schristos RDG_genBuffer(input, inputSize, 0.0, 0.0, seed); 1803*3117ece4Schristos { size_t const compSize = ZSTD_compress(comp, compCapacity, input, inputSize, -(int)inputSize); 1804*3117ece4Schristos ZSTD_inBuffer in = { comp, 0, 0 }; 1805*3117ece4Schristos ZSTD_outBuffer out = { decomp, 0, 0 }; 1806*3117ece4Schristos CHECK_Z(compSize); 1807*3117ece4Schristos CHECK_Z( ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters) ); 1808*3117ece4Schristos while (in.size < compSize) { 1809*3117ece4Schristos in.size = MIN(in.size + 100, compSize); 1810*3117ece4Schristos while (in.pos < in.size) { 1811*3117ece4Schristos size_t const outPos = out.pos; 1812*3117ece4Schristos if (out.pos == out.size) { 1813*3117ece4Schristos out.size = MIN(out.size + 10, inputSize); 1814*3117ece4Schristos } 1815*3117ece4Schristos CHECK_Z( ZSTD_decompressStream(zd, &out, &in) ); 1816*3117ece4Schristos CHECK(!(out.pos > outPos), "We are not streaming (no output generated)"); 1817*3117ece4Schristos } 1818*3117ece4Schristos } 1819*3117ece4Schristos CHECK(in.pos != compSize, "Not all input consumed!"); 1820*3117ece4Schristos CHECK(out.pos != inputSize, "Not all output produced!"); 1821*3117ece4Schristos } 1822*3117ece4Schristos CHECK(memcmp(input, decomp, inputSize), "round trip failed!"); 1823*3117ece4Schristos 1824*3117ece4Schristos free(input); 1825*3117ece4Schristos free(comp); 1826*3117ece4Schristos free(decomp); 1827*3117ece4Schristos } 1828*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1829*3117ece4Schristos 1830*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : dictionary + uncompressible block + reusing tables checks offset table validity: ", testNb++); 1831*3117ece4Schristos { ZSTD_CDict* const cdict = ZSTD_createCDict_advanced( 1832*3117ece4Schristos dictionary.start, dictionary.filled, 1833*3117ece4Schristos ZSTD_dlm_byRef, ZSTD_dct_fullDict, 1834*3117ece4Schristos ZSTD_getCParams(3, 0, dictionary.filled), 1835*3117ece4Schristos ZSTD_defaultCMem); 1836*3117ece4Schristos const size_t inbufsize = 2 * 128 * 1024; /* 2 blocks */ 1837*3117ece4Schristos const size_t outbufsize = ZSTD_compressBound(inbufsize); 1838*3117ece4Schristos size_t inbufpos = 0; 1839*3117ece4Schristos size_t cursegmentlen; 1840*3117ece4Schristos BYTE *inbuf = (BYTE *)malloc(inbufsize); 1841*3117ece4Schristos BYTE *outbuf = (BYTE *)malloc(outbufsize); 1842*3117ece4Schristos BYTE *checkbuf = (BYTE *)malloc(inbufsize); 1843*3117ece4Schristos size_t ret; 1844*3117ece4Schristos 1845*3117ece4Schristos CHECK(cdict == NULL, "failed to alloc cdict"); 1846*3117ece4Schristos CHECK(inbuf == NULL, "failed to alloc input buffer"); 1847*3117ece4Schristos 1848*3117ece4Schristos /* first block is uncompressible */ 1849*3117ece4Schristos cursegmentlen = 128 * 1024; 1850*3117ece4Schristos RDG_genBuffer(inbuf + inbufpos, cursegmentlen, 0., 0., seed); 1851*3117ece4Schristos inbufpos += cursegmentlen; 1852*3117ece4Schristos 1853*3117ece4Schristos /* second block is compressible */ 1854*3117ece4Schristos cursegmentlen = 128 * 1024 - 256; 1855*3117ece4Schristos RDG_genBuffer(inbuf + inbufpos, cursegmentlen, 0.05, 0., seed); 1856*3117ece4Schristos inbufpos += cursegmentlen; 1857*3117ece4Schristos 1858*3117ece4Schristos /* and includes a very long backref */ 1859*3117ece4Schristos cursegmentlen = 128; 1860*3117ece4Schristos memcpy(inbuf + inbufpos, (BYTE*)dictionary.start + 256, cursegmentlen); 1861*3117ece4Schristos inbufpos += cursegmentlen; 1862*3117ece4Schristos 1863*3117ece4Schristos /* and includes a very long backref */ 1864*3117ece4Schristos cursegmentlen = 128; 1865*3117ece4Schristos memcpy(inbuf + inbufpos, (BYTE*)dictionary.start + 128, cursegmentlen); 1866*3117ece4Schristos inbufpos += cursegmentlen; 1867*3117ece4Schristos 1868*3117ece4Schristos ret = ZSTD_compress_usingCDict(zc, outbuf, outbufsize, inbuf, inbufpos, cdict); 1869*3117ece4Schristos CHECK_Z(ret); 1870*3117ece4Schristos 1871*3117ece4Schristos ret = ZSTD_decompress_usingDict(zd, checkbuf, inbufsize, outbuf, ret, dictionary.start, dictionary.filled); 1872*3117ece4Schristos CHECK_Z(ret); 1873*3117ece4Schristos 1874*3117ece4Schristos CHECK(memcmp(inbuf, checkbuf, inbufpos), "start and finish buffers don't match"); 1875*3117ece4Schristos 1876*3117ece4Schristos ZSTD_freeCDict(cdict); 1877*3117ece4Schristos free(inbuf); 1878*3117ece4Schristos free(outbuf); 1879*3117ece4Schristos free(checkbuf); 1880*3117ece4Schristos } 1881*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1882*3117ece4Schristos 1883*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : dictionary + small blocks + reusing tables checks offset table validity: ", testNb++); 1884*3117ece4Schristos { ZSTD_CDict* const cdict = ZSTD_createCDict_advanced( 1885*3117ece4Schristos dictionary.start, dictionary.filled, 1886*3117ece4Schristos ZSTD_dlm_byRef, ZSTD_dct_fullDict, 1887*3117ece4Schristos ZSTD_getCParams(3, 0, dictionary.filled), 1888*3117ece4Schristos ZSTD_defaultCMem); 1889*3117ece4Schristos ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0}; 1890*3117ece4Schristos int remainingInput = 256 * 1024; 1891*3117ece4Schristos int offset; 1892*3117ece4Schristos 1893*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters)); 1894*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refCDict(zc, cdict)); 1895*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, 1)); 1896*3117ece4Schristos /* Write a bunch of 6 byte blocks */ 1897*3117ece4Schristos while (remainingInput > 0) { 1898*3117ece4Schristos char testBuffer[6] = "\xAA\xAA\xAA\xAA\xAA\xAA"; 1899*3117ece4Schristos const size_t kSmallBlockSize = sizeof(testBuffer); 1900*3117ece4Schristos ZSTD_inBuffer in = {testBuffer, kSmallBlockSize, 0}; 1901*3117ece4Schristos 1902*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_flush)); 1903*3117ece4Schristos CHECK(in.pos != in.size, "input not fully consumed"); 1904*3117ece4Schristos remainingInput -= kSmallBlockSize; 1905*3117ece4Schristos } 1906*3117ece4Schristos /* Write several very long offset matches into the dictionary */ 1907*3117ece4Schristos for (offset = 1024; offset >= 0; offset -= 128) { 1908*3117ece4Schristos ZSTD_inBuffer in = {(BYTE*)dictionary.start + offset, 128, 0}; 1909*3117ece4Schristos ZSTD_EndDirective flush = offset > 0 ? ZSTD_e_continue : ZSTD_e_end; 1910*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(zc, &out, &in, flush)); 1911*3117ece4Schristos CHECK(in.pos != in.size, "input not fully consumed"); 1912*3117ece4Schristos } 1913*3117ece4Schristos /* Ensure decompression works */ 1914*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(zd, decodedBuffer, CNBufferSize, out.dst, out.pos, dictionary.start, dictionary.filled)); 1915*3117ece4Schristos 1916*3117ece4Schristos ZSTD_freeCDict(cdict); 1917*3117ece4Schristos } 1918*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1919*3117ece4Schristos 1920*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Block-Level External Sequence Producer API: ", testNb++); 1921*3117ece4Schristos { 1922*3117ece4Schristos size_t const dstBufSize = ZSTD_compressBound(CNBufferSize); 1923*3117ece4Schristos BYTE* const dstBuf = (BYTE*)malloc(dstBufSize); 1924*3117ece4Schristos size_t const checkBufSize = CNBufferSize; 1925*3117ece4Schristos BYTE* const checkBuf = (BYTE*)malloc(checkBufSize); 1926*3117ece4Schristos int enableFallback; 1927*3117ece4Schristos EMF_testCase sequenceProducerState; 1928*3117ece4Schristos 1929*3117ece4Schristos CHECK(dstBuf == NULL || checkBuf == NULL, "allocation failed"); 1930*3117ece4Schristos 1931*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters)); 1932*3117ece4Schristos 1933*3117ece4Schristos /* Reference external matchfinder outside the test loop to 1934*3117ece4Schristos * check that the reference is preserved across compressions */ 1935*3117ece4Schristos ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer); 1936*3117ece4Schristos 1937*3117ece4Schristos for (enableFallback = 0; enableFallback <= 1; enableFallback++) { 1938*3117ece4Schristos size_t testCaseId; 1939*3117ece4Schristos size_t const numTestCases = 9; 1940*3117ece4Schristos 1941*3117ece4Schristos EMF_testCase const testCases[] = { 1942*3117ece4Schristos EMF_ONE_BIG_SEQ, 1943*3117ece4Schristos EMF_LOTS_OF_SEQS, 1944*3117ece4Schristos EMF_ZERO_SEQS, 1945*3117ece4Schristos EMF_BIG_ERROR, 1946*3117ece4Schristos EMF_SMALL_ERROR, 1947*3117ece4Schristos EMF_INVALID_OFFSET, 1948*3117ece4Schristos EMF_INVALID_MATCHLEN, 1949*3117ece4Schristos EMF_INVALID_LITLEN, 1950*3117ece4Schristos EMF_INVALID_LAST_LITS 1951*3117ece4Schristos }; 1952*3117ece4Schristos 1953*3117ece4Schristos ZSTD_ErrorCode const errorCodes[] = { 1954*3117ece4Schristos ZSTD_error_no_error, 1955*3117ece4Schristos ZSTD_error_no_error, 1956*3117ece4Schristos ZSTD_error_sequenceProducer_failed, 1957*3117ece4Schristos ZSTD_error_sequenceProducer_failed, 1958*3117ece4Schristos ZSTD_error_sequenceProducer_failed, 1959*3117ece4Schristos ZSTD_error_externalSequences_invalid, 1960*3117ece4Schristos ZSTD_error_externalSequences_invalid, 1961*3117ece4Schristos ZSTD_error_externalSequences_invalid, 1962*3117ece4Schristos ZSTD_error_externalSequences_invalid 1963*3117ece4Schristos }; 1964*3117ece4Schristos 1965*3117ece4Schristos for (testCaseId = 0; testCaseId < numTestCases; testCaseId++) { 1966*3117ece4Schristos size_t res; 1967*3117ece4Schristos 1968*3117ece4Schristos int const compressionShouldSucceed = ( 1969*3117ece4Schristos (errorCodes[testCaseId] == ZSTD_error_no_error) || 1970*3117ece4Schristos (enableFallback && errorCodes[testCaseId] == ZSTD_error_sequenceProducer_failed) 1971*3117ece4Schristos ); 1972*3117ece4Schristos 1973*3117ece4Schristos int const testWithSequenceValidation = ( 1974*3117ece4Schristos testCases[testCaseId] == EMF_INVALID_OFFSET 1975*3117ece4Schristos ); 1976*3117ece4Schristos 1977*3117ece4Schristos sequenceProducerState = testCases[testCaseId]; 1978*3117ece4Schristos 1979*3117ece4Schristos ZSTD_CCtx_reset(zc, ZSTD_reset_session_only); 1980*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_validateSequences, testWithSequenceValidation)); 1981*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, enableFallback)); 1982*3117ece4Schristos res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize); 1983*3117ece4Schristos 1984*3117ece4Schristos if (compressionShouldSucceed) { 1985*3117ece4Schristos CHECK(ZSTD_isError(res), "EMF: Compression error: %s", ZSTD_getErrorName(res)); 1986*3117ece4Schristos CHECK_Z(ZSTD_decompress(checkBuf, checkBufSize, dstBuf, res)); 1987*3117ece4Schristos CHECK(memcmp(CNBuffer, checkBuf, CNBufferSize) != 0, "EMF: Corruption!"); 1988*3117ece4Schristos } else { 1989*3117ece4Schristos CHECK(!ZSTD_isError(res), "EMF: Should have raised an error!"); 1990*3117ece4Schristos CHECK( 1991*3117ece4Schristos ZSTD_getErrorCode(res) != errorCodes[testCaseId], 1992*3117ece4Schristos "EMF: Wrong error code: %s", ZSTD_getErrorName(res) 1993*3117ece4Schristos ); 1994*3117ece4Schristos } 1995*3117ece4Schristos } 1996*3117ece4Schristos 1997*3117ece4Schristos /* Test compression with external matchfinder + empty src buffer */ 1998*3117ece4Schristos { 1999*3117ece4Schristos size_t res; 2000*3117ece4Schristos sequenceProducerState = EMF_ZERO_SEQS; 2001*3117ece4Schristos ZSTD_CCtx_reset(zc, ZSTD_reset_session_only); 2002*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, enableFallback)); 2003*3117ece4Schristos res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, 0); 2004*3117ece4Schristos CHECK(ZSTD_isError(res), "EMF: Compression error: %s", ZSTD_getErrorName(res)); 2005*3117ece4Schristos CHECK(ZSTD_decompress(checkBuf, checkBufSize, dstBuf, res) != 0, "EMF: Empty src round trip failed!"); 2006*3117ece4Schristos } 2007*3117ece4Schristos } 2008*3117ece4Schristos 2009*3117ece4Schristos /* Test that reset clears the external matchfinder */ 2010*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters)); 2011*3117ece4Schristos sequenceProducerState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder wasn't cleared */ 2012*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, 0)); 2013*3117ece4Schristos CHECK_Z(ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize)); 2014*3117ece4Schristos 2015*3117ece4Schristos /* Test that registering mFinder == NULL clears the external matchfinder */ 2016*3117ece4Schristos ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters); 2017*3117ece4Schristos ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer); 2018*3117ece4Schristos sequenceProducerState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder wasn't cleared */ 2019*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, 0)); 2020*3117ece4Schristos ZSTD_registerSequenceProducer(zc, NULL, NULL); /* clear the external matchfinder */ 2021*3117ece4Schristos CHECK_Z(ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize)); 2022*3117ece4Schristos 2023*3117ece4Schristos /* Test that external matchfinder doesn't interact with older APIs */ 2024*3117ece4Schristos ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters); 2025*3117ece4Schristos ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer); 2026*3117ece4Schristos sequenceProducerState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder is used */ 2027*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, 0)); 2028*3117ece4Schristos CHECK_Z(ZSTD_compressCCtx(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize, 3)); 2029*3117ece4Schristos 2030*3117ece4Schristos /* Test that compression returns the correct error with LDM */ 2031*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters)); 2032*3117ece4Schristos { 2033*3117ece4Schristos size_t res; 2034*3117ece4Schristos ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer); 2035*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)); 2036*3117ece4Schristos res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize); 2037*3117ece4Schristos CHECK(!ZSTD_isError(res), "EMF: Should have raised an error!"); 2038*3117ece4Schristos CHECK( 2039*3117ece4Schristos ZSTD_getErrorCode(res) != ZSTD_error_parameter_combination_unsupported, 2040*3117ece4Schristos "EMF: Wrong error code: %s", ZSTD_getErrorName(res) 2041*3117ece4Schristos ); 2042*3117ece4Schristos } 2043*3117ece4Schristos 2044*3117ece4Schristos #ifdef ZSTD_MULTITHREAD 2045*3117ece4Schristos /* Test that compression returns the correct error with nbWorkers > 0 */ 2046*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters)); 2047*3117ece4Schristos { 2048*3117ece4Schristos size_t res; 2049*3117ece4Schristos ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer); 2050*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_nbWorkers, 1)); 2051*3117ece4Schristos res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize); 2052*3117ece4Schristos CHECK(!ZSTD_isError(res), "EMF: Should have raised an error!"); 2053*3117ece4Schristos CHECK( 2054*3117ece4Schristos ZSTD_getErrorCode(res) != ZSTD_error_parameter_combination_unsupported, 2055*3117ece4Schristos "EMF: Wrong error code: %s", ZSTD_getErrorName(res) 2056*3117ece4Schristos ); 2057*3117ece4Schristos } 2058*3117ece4Schristos #endif 2059*3117ece4Schristos 2060*3117ece4Schristos free(dstBuf); 2061*3117ece4Schristos free(checkBuf); 2062*3117ece4Schristos } 2063*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2064*3117ece4Schristos 2065*3117ece4Schristos 2066*3117ece4Schristos /* Test maxBlockSize cctx param functionality */ 2067*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Testing maxBlockSize PR#3418: ", testNb++); 2068*3117ece4Schristos { 2069*3117ece4Schristos ZSTD_CCtx* cctx = ZSTD_createCCtx(); 2070*3117ece4Schristos 2071*3117ece4Schristos /* Quick test to make sure maxBlockSize bounds are enforced */ 2072*3117ece4Schristos assert(ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX_MIN - 1))); 2073*3117ece4Schristos assert(ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX + 1))); 2074*3117ece4Schristos 2075*3117ece4Schristos /* Test maxBlockSize < windowSize and windowSize < maxBlockSize*/ 2076*3117ece4Schristos { 2077*3117ece4Schristos size_t srcSize = 2 << 10; 2078*3117ece4Schristos void* const src = CNBuffer; 2079*3117ece4Schristos size_t dstSize = ZSTD_compressBound(srcSize); 2080*3117ece4Schristos void* const dst1 = compressedBuffer; 2081*3117ece4Schristos void* const dst2 = (BYTE*)compressedBuffer + dstSize; 2082*3117ece4Schristos size_t size1, size2; 2083*3117ece4Schristos void* const checkBuf = malloc(srcSize); 2084*3117ece4Schristos memset(src, 'x', srcSize); 2085*3117ece4Schristos 2086*3117ece4Schristos /* maxBlockSize = 1KB */ 2087*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 1u << 10)); 2088*3117ece4Schristos size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize); 2089*3117ece4Schristos 2090*3117ece4Schristos if (ZSTD_isError(size1)) goto _output_error; 2091*3117ece4Schristos CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1)); 2092*3117ece4Schristos CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!"); 2093*3117ece4Schristos 2094*3117ece4Schristos /* maxBlockSize = 3KB */ 2095*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 3u << 10)); 2096*3117ece4Schristos size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize); 2097*3117ece4Schristos 2098*3117ece4Schristos if (ZSTD_isError(size2)) goto _output_error; 2099*3117ece4Schristos CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2)); 2100*3117ece4Schristos CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!"); 2101*3117ece4Schristos 2102*3117ece4Schristos assert(size1 - size2 == 4); /* We add another RLE block with header + character */ 2103*3117ece4Schristos assert(memcmp(dst1, dst2, size2) != 0); /* Compressed output should not be equal */ 2104*3117ece4Schristos 2105*3117ece4Schristos /* maxBlockSize = 1KB, windowLog = 10 */ 2106*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 1u << 10)); 2107*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 10)); 2108*3117ece4Schristos size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize); 2109*3117ece4Schristos 2110*3117ece4Schristos if (ZSTD_isError(size1)) goto _output_error; 2111*3117ece4Schristos CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1)); 2112*3117ece4Schristos CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!"); 2113*3117ece4Schristos 2114*3117ece4Schristos /* maxBlockSize = 3KB, windowLog = 10 */ 2115*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 3u << 10)); 2116*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 10)); 2117*3117ece4Schristos size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize); 2118*3117ece4Schristos 2119*3117ece4Schristos if (ZSTD_isError(size2)) goto _output_error; 2120*3117ece4Schristos CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2)); 2121*3117ece4Schristos CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!"); 2122*3117ece4Schristos 2123*3117ece4Schristos assert(size1 == size2); 2124*3117ece4Schristos assert(memcmp(dst1, dst2, size1) == 0); /* Compressed output should be equal */ 2125*3117ece4Schristos 2126*3117ece4Schristos free(checkBuf); 2127*3117ece4Schristos } 2128*3117ece4Schristos 2129*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2130*3117ece4Schristos 2131*3117ece4Schristos /* Test maxBlockSize = 0 is valid */ 2132*3117ece4Schristos { size_t srcSize = 256 << 10; 2133*3117ece4Schristos void* const src = CNBuffer; 2134*3117ece4Schristos size_t dstSize = ZSTD_compressBound(srcSize); 2135*3117ece4Schristos void* const dst1 = compressedBuffer; 2136*3117ece4Schristos void* const dst2 = (BYTE*)compressedBuffer + dstSize; 2137*3117ece4Schristos size_t size1, size2; 2138*3117ece4Schristos void* const checkBuf = malloc(srcSize); 2139*3117ece4Schristos 2140*3117ece4Schristos /* maxBlockSize = 0 */ 2141*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 0)); 2142*3117ece4Schristos size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize); 2143*3117ece4Schristos 2144*3117ece4Schristos if (ZSTD_isError(size1)) goto _output_error; 2145*3117ece4Schristos CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1)); 2146*3117ece4Schristos CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!"); 2147*3117ece4Schristos 2148*3117ece4Schristos /* maxBlockSize = ZSTD_BLOCKSIZE_MAX */ 2149*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX)); 2150*3117ece4Schristos size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize); 2151*3117ece4Schristos 2152*3117ece4Schristos if (ZSTD_isError(size2)) goto _output_error; 2153*3117ece4Schristos CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2)); 2154*3117ece4Schristos CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!"); 2155*3117ece4Schristos 2156*3117ece4Schristos assert(size1 == size2); 2157*3117ece4Schristos assert(memcmp(dst1, dst2, size1) == 0); /* Compressed output should be equal */ 2158*3117ece4Schristos free(checkBuf); 2159*3117ece4Schristos } 2160*3117ece4Schristos ZSTD_freeCCtx(cctx); 2161*3117ece4Schristos } 2162*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2163*3117ece4Schristos 2164*3117ece4Schristos /* Test Sequence Validation */ 2165*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Testing sequence validation: ", testNb++); 2166*3117ece4Schristos { 2167*3117ece4Schristos ZSTD_CCtx* cctx = ZSTD_createCCtx(); 2168*3117ece4Schristos 2169*3117ece4Schristos /* Test minMatch >= 4, matchLength < 4 */ 2170*3117ece4Schristos { 2171*3117ece4Schristos size_t srcSize = 11; 2172*3117ece4Schristos void* const src = CNBuffer; 2173*3117ece4Schristos size_t dstSize = ZSTD_compressBound(srcSize); 2174*3117ece4Schristos void* const dst = compressedBuffer; 2175*3117ece4Schristos size_t const kNbSequences = 4; 2176*3117ece4Schristos ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences); 2177*3117ece4Schristos 2178*3117ece4Schristos memset(src, 'x', srcSize); 2179*3117ece4Schristos 2180*3117ece4Schristos sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0}; 2181*3117ece4Schristos sequences[1] = (ZSTD_Sequence) {1, 0, 3, 0}; 2182*3117ece4Schristos sequences[2] = (ZSTD_Sequence) {1, 0, 3, 0}; 2183*3117ece4Schristos sequences[3] = (ZSTD_Sequence) {0, 1, 0, 0}; 2184*3117ece4Schristos 2185*3117ece4Schristos /* Test with sequence validation */ 2186*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5)); 2187*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters)); 2188*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1)); 2189*3117ece4Schristos 2190*3117ece4Schristos cSize = ZSTD_compressSequences(cctx, dst, dstSize, 2191*3117ece4Schristos sequences, kNbSequences, 2192*3117ece4Schristos src, srcSize); 2193*3117ece4Schristos 2194*3117ece4Schristos CHECK(!ZSTD_isError(cSize), "Should throw an error"); /* maxNbSeq is too small and an assert will fail */ 2195*3117ece4Schristos CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, "Wrong error code: %s", ZSTD_getErrorName(cSize)); /* fails sequence validation */ 2196*3117ece4Schristos 2197*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2198*3117ece4Schristos 2199*3117ece4Schristos /* Test without sequence validation */ 2200*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5)); 2201*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters)); 2202*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 0)); 2203*3117ece4Schristos 2204*3117ece4Schristos cSize = ZSTD_compressSequences(cctx, dst, dstSize, 2205*3117ece4Schristos sequences, kNbSequences, 2206*3117ece4Schristos src, srcSize); 2207*3117ece4Schristos 2208*3117ece4Schristos CHECK(!ZSTD_isError(cSize), "Should throw an error"); /* maxNbSeq is too small and an assert will fail */ 2209*3117ece4Schristos CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, "Wrong error code: %s", ZSTD_getErrorName(cSize)); /* fails sequence validation */ 2210*3117ece4Schristos 2211*3117ece4Schristos free(sequences); 2212*3117ece4Schristos } 2213*3117ece4Schristos 2214*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2215*3117ece4Schristos 2216*3117ece4Schristos 2217*3117ece4Schristos /* Test with no block delim */ 2218*3117ece4Schristos { 2219*3117ece4Schristos size_t srcSize = 4; 2220*3117ece4Schristos void* const src = CNBuffer; 2221*3117ece4Schristos size_t dstSize = ZSTD_compressBound(srcSize); 2222*3117ece4Schristos void* const dst = compressedBuffer; 2223*3117ece4Schristos size_t const kNbSequences = 1; 2224*3117ece4Schristos ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences); 2225*3117ece4Schristos void* const checkBuf = malloc(srcSize); 2226*3117ece4Schristos 2227*3117ece4Schristos memset(src, 'x', srcSize); 2228*3117ece4Schristos 2229*3117ece4Schristos sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0}; 2230*3117ece4Schristos 2231*3117ece4Schristos /* Test with sequence validation */ 2232*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 3)); 2233*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_noBlockDelimiters)); 2234*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1)); 2235*3117ece4Schristos 2236*3117ece4Schristos cSize = ZSTD_compressSequences(cctx, dst, dstSize, 2237*3117ece4Schristos sequences, kNbSequences, 2238*3117ece4Schristos src, srcSize); 2239*3117ece4Schristos 2240*3117ece4Schristos CHECK(ZSTD_isError(cSize), "Should not throw an error"); 2241*3117ece4Schristos CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst, cSize)); 2242*3117ece4Schristos CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!"); 2243*3117ece4Schristos 2244*3117ece4Schristos free(sequences); 2245*3117ece4Schristos free(checkBuf); 2246*3117ece4Schristos } 2247*3117ece4Schristos 2248*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2249*3117ece4Schristos 2250*3117ece4Schristos { /* Test case with two additional sequences */ 2251*3117ece4Schristos size_t srcSize = 19; 2252*3117ece4Schristos void* const src = CNBuffer; 2253*3117ece4Schristos size_t dstSize = ZSTD_compressBound(srcSize); 2254*3117ece4Schristos void* const dst = compressedBuffer; 2255*3117ece4Schristos size_t const kNbSequences = 7; 2256*3117ece4Schristos ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences); 2257*3117ece4Schristos 2258*3117ece4Schristos memset(src, 'x', srcSize); 2259*3117ece4Schristos 2260*3117ece4Schristos sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0}; 2261*3117ece4Schristos sequences[1] = (ZSTD_Sequence) {1, 0, 3, 0}; 2262*3117ece4Schristos sequences[2] = (ZSTD_Sequence) {1, 0, 3, 0}; 2263*3117ece4Schristos sequences[3] = (ZSTD_Sequence) {1, 0, 3, 0}; 2264*3117ece4Schristos sequences[4] = (ZSTD_Sequence) {1, 0, 3, 0}; 2265*3117ece4Schristos sequences[5] = (ZSTD_Sequence) {1, 0, 3, 0}; 2266*3117ece4Schristos sequences[6] = (ZSTD_Sequence) {0, 0, 0, 0}; 2267*3117ece4Schristos 2268*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5)); 2269*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters)); 2270*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1)); 2271*3117ece4Schristos 2272*3117ece4Schristos cSize = ZSTD_compressSequences(cctx, dst, dstSize, 2273*3117ece4Schristos sequences, kNbSequences, 2274*3117ece4Schristos src, srcSize); 2275*3117ece4Schristos 2276*3117ece4Schristos CHECK(!ZSTD_isError(cSize), "Should throw an error"); /* maxNbSeq is too small and an assert will fail */ 2277*3117ece4Schristos CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, "Wrong error code: %s", ZSTD_getErrorName(cSize)); /* fails sequence validation */ 2278*3117ece4Schristos 2279*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2280*3117ece4Schristos 2281*3117ece4Schristos /* Test without sequence validation */ 2282*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5)); 2283*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters)); 2284*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 0)); 2285*3117ece4Schristos 2286*3117ece4Schristos cSize = ZSTD_compressSequences(cctx, dst, dstSize, 2287*3117ece4Schristos sequences, kNbSequences, 2288*3117ece4Schristos src, srcSize); 2289*3117ece4Schristos 2290*3117ece4Schristos CHECK(!ZSTD_isError(cSize), "Should throw an error"); /* maxNbSeq is too small and an assert will fail */ 2291*3117ece4Schristos CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, "Wrong error code: %s", ZSTD_getErrorName(cSize)); /* fails sequence validation */ 2292*3117ece4Schristos 2293*3117ece4Schristos free(sequences); 2294*3117ece4Schristos } 2295*3117ece4Schristos ZSTD_freeCCtx(cctx); 2296*3117ece4Schristos } 2297*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2298*3117ece4Schristos 2299*3117ece4Schristos 2300*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Testing large offset with small window size: ", testNb++); 2301*3117ece4Schristos { 2302*3117ece4Schristos ZSTD_CCtx* cctx = ZSTD_createCCtx(); 2303*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 2304*3117ece4Schristos 2305*3117ece4Schristos /* Test large offset, small window size*/ 2306*3117ece4Schristos { 2307*3117ece4Schristos size_t srcSize = 21; 2308*3117ece4Schristos void* const src = CNBuffer; 2309*3117ece4Schristos size_t dstSize = ZSTD_compressBound(srcSize); 2310*3117ece4Schristos void* const dst = compressedBuffer; 2311*3117ece4Schristos size_t const kNbSequences = 4; 2312*3117ece4Schristos ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences); 2313*3117ece4Schristos void* const checkBuf = malloc(srcSize); 2314*3117ece4Schristos const size_t largeDictSize = 1 << 25; 2315*3117ece4Schristos ZSTD_CDict* cdict = NULL; 2316*3117ece4Schristos ZSTD_DDict* ddict = NULL; 2317*3117ece4Schristos 2318*3117ece4Schristos /* Generate large dictionary */ 2319*3117ece4Schristos void* dictBuffer = calloc(largeDictSize, 1); 2320*3117ece4Schristos ZSTD_compressionParameters cParams = ZSTD_getCParams(1, srcSize, largeDictSize); 2321*3117ece4Schristos cParams.minMatch = ZSTD_MINMATCH_MIN; 2322*3117ece4Schristos cParams.hashLog = ZSTD_HASHLOG_MIN; 2323*3117ece4Schristos cParams.chainLog = ZSTD_CHAINLOG_MIN; 2324*3117ece4Schristos 2325*3117ece4Schristos cdict = ZSTD_createCDict_advanced(dictBuffer, largeDictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, cParams, ZSTD_defaultCMem); 2326*3117ece4Schristos ddict = ZSTD_createDDict_advanced(dictBuffer, largeDictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, ZSTD_defaultCMem); 2327*3117ece4Schristos 2328*3117ece4Schristos ZSTD_CCtx_refCDict(cctx, cdict); 2329*3117ece4Schristos ZSTD_DCtx_refDDict(dctx, ddict); 2330*3117ece4Schristos 2331*3117ece4Schristos sequences[0] = (ZSTD_Sequence) {3, 3, 3, 0}; 2332*3117ece4Schristos sequences[1] = (ZSTD_Sequence) {1 << 25, 0, 3, 0}; 2333*3117ece4Schristos sequences[2] = (ZSTD_Sequence) {1 << 25, 0, 9, 0}; 2334*3117ece4Schristos sequences[3] = (ZSTD_Sequence) {3, 0, 3, 0}; 2335*3117ece4Schristos 2336*3117ece4Schristos cSize = ZSTD_compressSequences(cctx, dst, dstSize, 2337*3117ece4Schristos sequences, kNbSequences, 2338*3117ece4Schristos src, srcSize); 2339*3117ece4Schristos 2340*3117ece4Schristos CHECK(ZSTD_isError(cSize), "Should not throw an error"); 2341*3117ece4Schristos 2342*3117ece4Schristos { 2343*3117ece4Schristos size_t dSize = ZSTD_decompressDCtx(dctx, checkBuf, srcSize, dst, cSize); 2344*3117ece4Schristos CHECK(ZSTD_isError(dSize), "Should not throw an error"); 2345*3117ece4Schristos CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!"); 2346*3117ece4Schristos } 2347*3117ece4Schristos 2348*3117ece4Schristos free(sequences); 2349*3117ece4Schristos free(checkBuf); 2350*3117ece4Schristos free(dictBuffer); 2351*3117ece4Schristos ZSTD_freeCDict(cdict); 2352*3117ece4Schristos ZSTD_freeDDict(ddict); 2353*3117ece4Schristos } 2354*3117ece4Schristos ZSTD_freeCCtx(cctx); 2355*3117ece4Schristos ZSTD_freeDCtx(dctx); 2356*3117ece4Schristos } 2357*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2358*3117ece4Schristos 2359*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Testing external sequence producer with static CCtx: ", testNb++); 2360*3117ece4Schristos { 2361*3117ece4Schristos size_t const dstBufSize = ZSTD_compressBound(CNBufferSize); 2362*3117ece4Schristos BYTE* const dstBuf = (BYTE*)malloc(dstBufSize); 2363*3117ece4Schristos size_t const checkBufSize = CNBufferSize; 2364*3117ece4Schristos BYTE* const checkBuf = (BYTE*)malloc(checkBufSize); 2365*3117ece4Schristos ZSTD_CCtx_params* params = ZSTD_createCCtxParams(); 2366*3117ece4Schristos ZSTD_CCtx* staticCCtx; 2367*3117ece4Schristos void* cctxBuf; 2368*3117ece4Schristos EMF_testCase seqProdState; 2369*3117ece4Schristos 2370*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_validateSequences, 1)); 2371*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_enableSeqProducerFallback, 0)); 2372*3117ece4Schristos ZSTD_CCtxParams_registerSequenceProducer(params, &seqProdState, zstreamSequenceProducer); 2373*3117ece4Schristos 2374*3117ece4Schristos { 2375*3117ece4Schristos size_t const cctxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); 2376*3117ece4Schristos cctxBuf = malloc(cctxSize); 2377*3117ece4Schristos staticCCtx = ZSTD_initStaticCCtx(cctxBuf, cctxSize); 2378*3117ece4Schristos ZSTD_CCtx_setParametersUsingCCtxParams(staticCCtx, params); 2379*3117ece4Schristos } 2380*3117ece4Schristos 2381*3117ece4Schristos // Check that compression with external sequence producer succeeds when expected 2382*3117ece4Schristos seqProdState = EMF_LOTS_OF_SEQS; 2383*3117ece4Schristos { 2384*3117ece4Schristos size_t dResult; 2385*3117ece4Schristos size_t const cResult = ZSTD_compress2(staticCCtx, dstBuf, dstBufSize, CNBuffer, CNBufferSize); 2386*3117ece4Schristos CHECK(ZSTD_isError(cResult), "EMF: Compression error: %s", ZSTD_getErrorName(cResult)); 2387*3117ece4Schristos dResult = ZSTD_decompress(checkBuf, checkBufSize, dstBuf, cResult); 2388*3117ece4Schristos CHECK(ZSTD_isError(dResult), "EMF: Decompression error: %s", ZSTD_getErrorName(dResult)); 2389*3117ece4Schristos CHECK(dResult != CNBufferSize, "EMF: Corruption!"); 2390*3117ece4Schristos CHECK(memcmp(CNBuffer, checkBuf, CNBufferSize) != 0, "EMF: Corruption!"); 2391*3117ece4Schristos } 2392*3117ece4Schristos 2393*3117ece4Schristos // Check that compression with external sequence producer fails when expected 2394*3117ece4Schristos seqProdState = EMF_BIG_ERROR; 2395*3117ece4Schristos { 2396*3117ece4Schristos size_t const cResult = ZSTD_compress2(staticCCtx, dstBuf, dstBufSize, CNBuffer, CNBufferSize); 2397*3117ece4Schristos CHECK(!ZSTD_isError(cResult), "EMF: Should have raised an error!"); 2398*3117ece4Schristos CHECK( 2399*3117ece4Schristos ZSTD_getErrorCode(cResult) != ZSTD_error_sequenceProducer_failed, 2400*3117ece4Schristos "EMF: Wrong error code: %s", ZSTD_getErrorName(cResult) 2401*3117ece4Schristos ); 2402*3117ece4Schristos } 2403*3117ece4Schristos 2404*3117ece4Schristos free(dstBuf); 2405*3117ece4Schristos free(checkBuf); 2406*3117ece4Schristos free(cctxBuf); 2407*3117ece4Schristos ZSTD_freeCCtxParams(params); 2408*3117ece4Schristos } 2409*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2410*3117ece4Schristos 2411*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Decoder should reject invalid frame header on legacy frames: ", testNb++); 2412*3117ece4Schristos { 2413*3117ece4Schristos const unsigned char compressed[] = { 0x26,0xb5,0x2f,0xfd,0x50,0x91,0xfd,0xd8,0xb5 }; 2414*3117ece4Schristos const size_t compressedSize = 9; 2415*3117ece4Schristos size_t const dSize = ZSTD_decompress(NULL, 0, compressed, compressedSize); 2416*3117ece4Schristos CHECK(!ZSTD_isError(dSize), "must reject when legacy frame header is invalid"); 2417*3117ece4Schristos } 2418*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2419*3117ece4Schristos 2420*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Test single-shot fallback for magicless mode: ", testNb++); 2421*3117ece4Schristos { 2422*3117ece4Schristos // Aquire resources 2423*3117ece4Schristos size_t const srcSize = COMPRESSIBLE_NOISE_LENGTH; 2424*3117ece4Schristos void* src = malloc(srcSize); 2425*3117ece4Schristos size_t const dstSize = ZSTD_compressBound(srcSize); 2426*3117ece4Schristos void* dst = malloc(dstSize); 2427*3117ece4Schristos size_t const valSize = srcSize; 2428*3117ece4Schristos void* val = malloc(valSize); 2429*3117ece4Schristos ZSTD_inBuffer inBuf = { dst, dstSize, 0 }; 2430*3117ece4Schristos ZSTD_outBuffer outBuf = { val, valSize, 0 }; 2431*3117ece4Schristos ZSTD_CCtx* cctx = ZSTD_createCCtx(); 2432*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 2433*3117ece4Schristos CHECK(!src || !dst || !val || !dctx || !cctx, "memory allocation failure"); 2434*3117ece4Schristos 2435*3117ece4Schristos // Write test data for decompression to dst 2436*3117ece4Schristos RDG_genBuffer(src, srcSize, compressibility, 0.0, 0xdeadbeef); 2437*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless)); 2438*3117ece4Schristos CHECK_Z(ZSTD_compress2(cctx, dst, dstSize, src, srcSize)); 2439*3117ece4Schristos 2440*3117ece4Schristos // Run decompression 2441*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless)); 2442*3117ece4Schristos CHECK_Z(ZSTD_decompressStream(dctx, &outBuf, &inBuf)); 2443*3117ece4Schristos 2444*3117ece4Schristos // Validate 2445*3117ece4Schristos CHECK(outBuf.pos != srcSize, "decompressed size must match"); 2446*3117ece4Schristos CHECK(memcmp(src, val, srcSize) != 0, "decompressed data must match"); 2447*3117ece4Schristos 2448*3117ece4Schristos // Cleanup 2449*3117ece4Schristos free(src); free(dst); free(val); 2450*3117ece4Schristos ZSTD_freeCCtx(cctx); 2451*3117ece4Schristos ZSTD_freeDCtx(dctx); 2452*3117ece4Schristos } 2453*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2454*3117ece4Schristos 2455*3117ece4Schristos _end: 2456*3117ece4Schristos FUZ_freeDictionary(dictionary); 2457*3117ece4Schristos ZSTD_freeCStream(zc); 2458*3117ece4Schristos ZSTD_freeDStream(zd); 2459*3117ece4Schristos ZSTD_freeCCtx(mtctx); 2460*3117ece4Schristos free(CNBuffer); 2461*3117ece4Schristos free(compressedBuffer); 2462*3117ece4Schristos free(decodedBuffer); 2463*3117ece4Schristos return testResult; 2464*3117ece4Schristos 2465*3117ece4Schristos _output_error: 2466*3117ece4Schristos testResult = 1; 2467*3117ece4Schristos DISPLAY("Error detected in Unit tests ! \n"); 2468*3117ece4Schristos goto _end; 2469*3117ece4Schristos } 2470*3117ece4Schristos 2471*3117ece4Schristos 2472*3117ece4Schristos /* ====== Fuzzer tests ====== */ 2473*3117ece4Schristos 2474*3117ece4Schristos static size_t findDiff(const void* buf1, const void* buf2, size_t max) 2475*3117ece4Schristos { 2476*3117ece4Schristos const BYTE* b1 = (const BYTE*)buf1; 2477*3117ece4Schristos const BYTE* b2 = (const BYTE*)buf2; 2478*3117ece4Schristos size_t u; 2479*3117ece4Schristos for (u=0; u<max; u++) { 2480*3117ece4Schristos if (b1[u] != b2[u]) break; 2481*3117ece4Schristos } 2482*3117ece4Schristos if (u==max) { 2483*3117ece4Schristos DISPLAY("=> No difference detected within %u bytes \n", (unsigned)max); 2484*3117ece4Schristos return u; 2485*3117ece4Schristos } 2486*3117ece4Schristos DISPLAY("Error at position %u / %u \n", (unsigned)u, (unsigned)max); 2487*3117ece4Schristos if (u>=3) 2488*3117ece4Schristos DISPLAY(" %02X %02X %02X ", 2489*3117ece4Schristos b1[u-3], b1[u-2], b1[u-1]); 2490*3117ece4Schristos DISPLAY(" :%02X: %02X %02X %02X %02X %02X \n", 2491*3117ece4Schristos b1[u], b1[u+1], b1[u+2], b1[u+3], b1[u+4], b1[u+5]); 2492*3117ece4Schristos if (u>=3) 2493*3117ece4Schristos DISPLAY(" %02X %02X %02X ", 2494*3117ece4Schristos b2[u-3], b2[u-2], b2[u-1]); 2495*3117ece4Schristos DISPLAY(" :%02X: %02X %02X %02X %02X %02X \n", 2496*3117ece4Schristos b2[u], b2[u+1], b2[u+2], b2[u+3], b2[u+4], b2[u+5]); 2497*3117ece4Schristos return u; 2498*3117ece4Schristos } 2499*3117ece4Schristos 2500*3117ece4Schristos static size_t FUZ_rLogLength(U32* seed, U32 logLength) 2501*3117ece4Schristos { 2502*3117ece4Schristos size_t const lengthMask = ((size_t)1 << logLength) - 1; 2503*3117ece4Schristos return (lengthMask+1) + (FUZ_rand(seed) & lengthMask); 2504*3117ece4Schristos } 2505*3117ece4Schristos 2506*3117ece4Schristos static size_t FUZ_randomLength(U32* seed, U32 maxLog) 2507*3117ece4Schristos { 2508*3117ece4Schristos U32 const logLength = FUZ_rand(seed) % maxLog; 2509*3117ece4Schristos return FUZ_rLogLength(seed, logLength); 2510*3117ece4Schristos } 2511*3117ece4Schristos 2512*3117ece4Schristos /* Return value in range minVal <= v <= maxVal */ 2513*3117ece4Schristos static U32 FUZ_randomClampedLength(U32* seed, U32 minVal, U32 maxVal) 2514*3117ece4Schristos { 2515*3117ece4Schristos U32 const mod = maxVal < minVal ? 1 : (maxVal + 1) - minVal; 2516*3117ece4Schristos return (U32)((FUZ_rand(seed) % mod) + minVal); 2517*3117ece4Schristos } 2518*3117ece4Schristos 2519*3117ece4Schristos static int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressibility, int bigTests) 2520*3117ece4Schristos { 2521*3117ece4Schristos U32 const maxSrcLog = bigTests ? 24 : 22; 2522*3117ece4Schristos static const U32 maxSampleLog = 19; 2523*3117ece4Schristos size_t const srcBufferSize = (size_t)1<<maxSrcLog; 2524*3117ece4Schristos BYTE* cNoiseBuffer[5]; 2525*3117ece4Schristos size_t const copyBufferSize = srcBufferSize + (1<<maxSampleLog); 2526*3117ece4Schristos BYTE* const copyBuffer = (BYTE*)malloc (copyBufferSize); 2527*3117ece4Schristos size_t const cBufferSize = ZSTD_compressBound(srcBufferSize); 2528*3117ece4Schristos BYTE* const cBuffer = (BYTE*)malloc (cBufferSize); 2529*3117ece4Schristos size_t const dstBufferSize = srcBufferSize; 2530*3117ece4Schristos BYTE* const dstBuffer = (BYTE*)malloc (dstBufferSize); 2531*3117ece4Schristos U32 result = 0; 2532*3117ece4Schristos unsigned testNb = 0; 2533*3117ece4Schristos U32 coreSeed = seed; 2534*3117ece4Schristos ZSTD_CStream* zc = ZSTD_createCStream(); /* will be re-created sometimes */ 2535*3117ece4Schristos ZSTD_DStream* zd = ZSTD_createDStream(); /* will be re-created sometimes */ 2536*3117ece4Schristos ZSTD_DStream* const zd_noise = ZSTD_createDStream(); 2537*3117ece4Schristos UTIL_time_t const startClock = UTIL_getTime(); 2538*3117ece4Schristos const BYTE* dict = NULL; /* can keep same dict on 2 consecutive tests */ 2539*3117ece4Schristos size_t dictSize = 0; 2540*3117ece4Schristos U32 oldTestLog = 0; 2541*3117ece4Schristos U32 const cLevelMax = bigTests ? (U32)ZSTD_maxCLevel() : g_cLevelMax_smallTests; 2542*3117ece4Schristos 2543*3117ece4Schristos /* allocations */ 2544*3117ece4Schristos cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize); 2545*3117ece4Schristos cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize); 2546*3117ece4Schristos cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize); 2547*3117ece4Schristos cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize); 2548*3117ece4Schristos cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize); 2549*3117ece4Schristos CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4] || 2550*3117ece4Schristos !copyBuffer || !dstBuffer || !cBuffer || !zc || !zd || !zd_noise , 2551*3117ece4Schristos "Not enough memory, fuzzer tests cancelled"); 2552*3117ece4Schristos 2553*3117ece4Schristos /* Create initial samples */ 2554*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed); /* pure noise */ 2555*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed); /* barely compressible */ 2556*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed); 2557*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */ 2558*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */ 2559*3117ece4Schristos memset(copyBuffer, 0x65, copyBufferSize); /* make copyBuffer considered initialized */ 2560*3117ece4Schristos ZSTD_initDStream_usingDict(zd, NULL, 0); /* ensure at least one init */ 2561*3117ece4Schristos 2562*3117ece4Schristos /* catch up testNb */ 2563*3117ece4Schristos for (testNb=1; testNb < startTest; testNb++) 2564*3117ece4Schristos FUZ_rand(&coreSeed); 2565*3117ece4Schristos 2566*3117ece4Schristos /* test loop */ 2567*3117ece4Schristos for ( ; (testNb <= nbTests) || (UTIL_clockSpanMicro(startClock) < g_clockTime) ; testNb++ ) { 2568*3117ece4Schristos U32 lseed; 2569*3117ece4Schristos const BYTE* srcBuffer; 2570*3117ece4Schristos size_t totalTestSize, totalGenSize, cSize; 2571*3117ece4Schristos XXH64_state_t xxhState; 2572*3117ece4Schristos U64 crcOrig; 2573*3117ece4Schristos U32 resetAllowed = 1; 2574*3117ece4Schristos size_t maxTestSize; 2575*3117ece4Schristos 2576*3117ece4Schristos /* init */ 2577*3117ece4Schristos FUZ_rand(&coreSeed); 2578*3117ece4Schristos lseed = coreSeed ^ prime32; 2579*3117ece4Schristos if (nbTests >= testNb) { 2580*3117ece4Schristos DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); 2581*3117ece4Schristos } else { 2582*3117ece4Schristos DISPLAYUPDATE(2, "\r%6u ", testNb); 2583*3117ece4Schristos } 2584*3117ece4Schristos 2585*3117ece4Schristos /* states full reset (deliberately not synchronized) */ 2586*3117ece4Schristos /* some issues can only happen when reusing states */ 2587*3117ece4Schristos if ((FUZ_rand(&lseed) & 0xFF) == 131) { 2588*3117ece4Schristos ZSTD_freeCStream(zc); 2589*3117ece4Schristos zc = ZSTD_createCStream(); 2590*3117ece4Schristos CHECK(zc==NULL, "ZSTD_createCStream : allocation error"); 2591*3117ece4Schristos resetAllowed=0; 2592*3117ece4Schristos } 2593*3117ece4Schristos if ((FUZ_rand(&lseed) & 0xFF) == 132) { 2594*3117ece4Schristos ZSTD_freeDStream(zd); 2595*3117ece4Schristos zd = ZSTD_createDStream(); 2596*3117ece4Schristos CHECK(zd==NULL, "ZSTD_createDStream : allocation error"); 2597*3117ece4Schristos CHECK_Z( ZSTD_initDStream_usingDict(zd, NULL, 0) ); /* ensure at least one init */ 2598*3117ece4Schristos } 2599*3117ece4Schristos 2600*3117ece4Schristos /* srcBuffer selection [0-4] */ 2601*3117ece4Schristos { U32 buffNb = FUZ_rand(&lseed) & 0x7F; 2602*3117ece4Schristos if (buffNb & 7) buffNb=2; /* most common : compressible (P) */ 2603*3117ece4Schristos else { 2604*3117ece4Schristos buffNb >>= 3; 2605*3117ece4Schristos if (buffNb & 7) { 2606*3117ece4Schristos const U32 tnb[2] = { 1, 3 }; /* barely/highly compressible */ 2607*3117ece4Schristos buffNb = tnb[buffNb >> 3]; 2608*3117ece4Schristos } else { 2609*3117ece4Schristos const U32 tnb[2] = { 0, 4 }; /* not compressible / sparse */ 2610*3117ece4Schristos buffNb = tnb[buffNb >> 3]; 2611*3117ece4Schristos } } 2612*3117ece4Schristos srcBuffer = cNoiseBuffer[buffNb]; 2613*3117ece4Schristos } 2614*3117ece4Schristos 2615*3117ece4Schristos /* compression init */ 2616*3117ece4Schristos if ((FUZ_rand(&lseed)&1) /* at beginning, to keep same nb of rand */ 2617*3117ece4Schristos && oldTestLog /* at least one test happened */ && resetAllowed) { 2618*3117ece4Schristos maxTestSize = FUZ_randomLength(&lseed, oldTestLog+2); 2619*3117ece4Schristos maxTestSize = MIN(maxTestSize, srcBufferSize-16); 2620*3117ece4Schristos { U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? ZSTD_CONTENTSIZE_UNKNOWN : maxTestSize; 2621*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 2622*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) ); 2623*3117ece4Schristos } 2624*3117ece4Schristos } else { 2625*3117ece4Schristos U32 const testLog = FUZ_rand(&lseed) % maxSrcLog; 2626*3117ece4Schristos U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog; 2627*3117ece4Schristos U32 const cLevelCandidate = ( FUZ_rand(&lseed) % 2628*3117ece4Schristos (ZSTD_maxCLevel() - 2629*3117ece4Schristos (MAX(testLog, dictLog) / 3))) 2630*3117ece4Schristos + 1; 2631*3117ece4Schristos U32 const cLevel = MIN(cLevelCandidate, cLevelMax); 2632*3117ece4Schristos maxTestSize = FUZ_rLogLength(&lseed, testLog); 2633*3117ece4Schristos oldTestLog = testLog; 2634*3117ece4Schristos /* random dictionary selection */ 2635*3117ece4Schristos dictSize = ((FUZ_rand(&lseed)&7)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0; 2636*3117ece4Schristos { size_t const dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize); 2637*3117ece4Schristos dict = srcBuffer + dictStart; 2638*3117ece4Schristos } 2639*3117ece4Schristos { U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? ZSTD_CONTENTSIZE_UNKNOWN : maxTestSize; 2640*3117ece4Schristos CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) ); 2641*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, cLevel) ); 2642*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, FUZ_rand(&lseed) & 1) ); 2643*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_contentSizeFlag, FUZ_rand(&lseed) & 1) ); 2644*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_dictIDFlag, FUZ_rand(&lseed) & 1) ); 2645*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) ); 2646*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dict, dictSize) ); 2647*3117ece4Schristos } } 2648*3117ece4Schristos 2649*3117ece4Schristos /* multi-segments compression test */ 2650*3117ece4Schristos XXH64_reset(&xxhState, 0); 2651*3117ece4Schristos { ZSTD_outBuffer outBuff = { cBuffer, cBufferSize, 0 } ; 2652*3117ece4Schristos cSize=0; 2653*3117ece4Schristos totalTestSize=0; 2654*3117ece4Schristos while(totalTestSize < maxTestSize) { 2655*3117ece4Schristos /* compress random chunks into randomly sized dst buffers */ 2656*3117ece4Schristos { size_t const randomSrcSize = FUZ_randomLength(&lseed, maxSampleLog); 2657*3117ece4Schristos size_t const srcSize = MIN(maxTestSize-totalTestSize, randomSrcSize); 2658*3117ece4Schristos size_t const srcStart = FUZ_rand(&lseed) % (srcBufferSize - srcSize); 2659*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog); 2660*3117ece4Schristos size_t const dstBuffSize = MIN(cBufferSize - cSize, randomDstSize); 2661*3117ece4Schristos ZSTD_inBuffer inBuff = { srcBuffer+srcStart, srcSize, 0 }; 2662*3117ece4Schristos outBuff.size = outBuff.pos + dstBuffSize; 2663*3117ece4Schristos 2664*3117ece4Schristos CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); 2665*3117ece4Schristos 2666*3117ece4Schristos XXH64_update(&xxhState, srcBuffer+srcStart, inBuff.pos); 2667*3117ece4Schristos memcpy(copyBuffer+totalTestSize, srcBuffer+srcStart, inBuff.pos); 2668*3117ece4Schristos totalTestSize += inBuff.pos; 2669*3117ece4Schristos } 2670*3117ece4Schristos 2671*3117ece4Schristos /* random flush operation, to mess around */ 2672*3117ece4Schristos if ((FUZ_rand(&lseed) & 15) == 0) { 2673*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog); 2674*3117ece4Schristos size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize); 2675*3117ece4Schristos outBuff.size = outBuff.pos + adjustedDstSize; 2676*3117ece4Schristos CHECK_Z( ZSTD_flushStream(zc, &outBuff) ); 2677*3117ece4Schristos } } 2678*3117ece4Schristos 2679*3117ece4Schristos /* final frame epilogue */ 2680*3117ece4Schristos { size_t remainingToFlush = (size_t)(-1); 2681*3117ece4Schristos while (remainingToFlush) { 2682*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog); 2683*3117ece4Schristos size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize); 2684*3117ece4Schristos outBuff.size = outBuff.pos + adjustedDstSize; 2685*3117ece4Schristos remainingToFlush = ZSTD_endStream(zc, &outBuff); 2686*3117ece4Schristos CHECK (ZSTD_isError(remainingToFlush), "end error : %s", ZSTD_getErrorName(remainingToFlush)); 2687*3117ece4Schristos } } 2688*3117ece4Schristos crcOrig = XXH64_digest(&xxhState); 2689*3117ece4Schristos cSize = outBuff.pos; 2690*3117ece4Schristos } 2691*3117ece4Schristos 2692*3117ece4Schristos /* multi - fragments decompression test */ 2693*3117ece4Schristos if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) { 2694*3117ece4Schristos CHECK_Z ( ZSTD_resetDStream(zd) ); 2695*3117ece4Schristos } else { 2696*3117ece4Schristos CHECK_Z ( ZSTD_initDStream_usingDict(zd, dict, dictSize) ); 2697*3117ece4Schristos } 2698*3117ece4Schristos { size_t decompressionResult = 1; 2699*3117ece4Schristos ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 }; 2700*3117ece4Schristos ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 }; 2701*3117ece4Schristos for (totalGenSize = 0 ; decompressionResult ; ) { 2702*3117ece4Schristos size_t const readCSrcSize = FUZ_randomLength(&lseed, maxSampleLog); 2703*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog); 2704*3117ece4Schristos size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize); 2705*3117ece4Schristos inBuff.size = inBuff.pos + readCSrcSize; 2706*3117ece4Schristos outBuff.size = outBuff.pos + dstBuffSize; 2707*3117ece4Schristos decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff); 2708*3117ece4Schristos if (ZSTD_getErrorCode(decompressionResult) == ZSTD_error_checksum_wrong) { 2709*3117ece4Schristos DISPLAY("checksum error : \n"); 2710*3117ece4Schristos findDiff(copyBuffer, dstBuffer, totalTestSize); 2711*3117ece4Schristos } 2712*3117ece4Schristos CHECK( ZSTD_isError(decompressionResult), "decompression error : %s", 2713*3117ece4Schristos ZSTD_getErrorName(decompressionResult) ); 2714*3117ece4Schristos } 2715*3117ece4Schristos CHECK (decompressionResult != 0, "frame not fully decoded"); 2716*3117ece4Schristos CHECK (outBuff.pos != totalTestSize, "decompressed data : wrong size (%u != %u)", 2717*3117ece4Schristos (unsigned)outBuff.pos, (unsigned)totalTestSize); 2718*3117ece4Schristos CHECK (inBuff.pos != cSize, "compressed data should be fully read") 2719*3117ece4Schristos { U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0); 2720*3117ece4Schristos if (crcDest!=crcOrig) findDiff(copyBuffer, dstBuffer, totalTestSize); 2721*3117ece4Schristos CHECK (crcDest!=crcOrig, "decompressed data corrupted"); 2722*3117ece4Schristos } } 2723*3117ece4Schristos 2724*3117ece4Schristos /*===== noisy/erroneous src decompression test =====*/ 2725*3117ece4Schristos 2726*3117ece4Schristos /* add some noise */ 2727*3117ece4Schristos { U32 const nbNoiseChunks = (FUZ_rand(&lseed) & 7) + 2; 2728*3117ece4Schristos U32 nn; for (nn=0; nn<nbNoiseChunks; nn++) { 2729*3117ece4Schristos size_t const randomNoiseSize = FUZ_randomLength(&lseed, maxSampleLog); 2730*3117ece4Schristos size_t const noiseSize = MIN((cSize/3) , randomNoiseSize); 2731*3117ece4Schristos size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseSize); 2732*3117ece4Schristos size_t const cStart = FUZ_rand(&lseed) % (cSize - noiseSize); 2733*3117ece4Schristos memcpy(cBuffer+cStart, srcBuffer+noiseStart, noiseSize); 2734*3117ece4Schristos } } 2735*3117ece4Schristos 2736*3117ece4Schristos /* try decompression on noisy data */ 2737*3117ece4Schristos CHECK_Z( ZSTD_initDStream(zd_noise) ); /* note : no dictionary */ 2738*3117ece4Schristos { ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 }; 2739*3117ece4Schristos ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 }; 2740*3117ece4Schristos while (outBuff.pos < dstBufferSize) { 2741*3117ece4Schristos size_t const randomCSrcSize = FUZ_randomLength(&lseed, maxSampleLog); 2742*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog); 2743*3117ece4Schristos size_t const adjustedDstSize = MIN(dstBufferSize - outBuff.pos, randomDstSize); 2744*3117ece4Schristos size_t const adjustedCSrcSize = MIN(cSize - inBuff.pos, randomCSrcSize); 2745*3117ece4Schristos outBuff.size = outBuff.pos + adjustedDstSize; 2746*3117ece4Schristos inBuff.size = inBuff.pos + adjustedCSrcSize; 2747*3117ece4Schristos { size_t const decompressError = ZSTD_decompressStream(zd, &outBuff, &inBuff); 2748*3117ece4Schristos if (ZSTD_isError(decompressError)) break; /* error correctly detected */ 2749*3117ece4Schristos /* No forward progress possible */ 2750*3117ece4Schristos if (outBuff.pos < outBuff.size && inBuff.pos == cSize) break; 2751*3117ece4Schristos } } } } 2752*3117ece4Schristos DISPLAY("\r%u fuzzer tests completed \n", testNb); 2753*3117ece4Schristos 2754*3117ece4Schristos _cleanup: 2755*3117ece4Schristos ZSTD_freeCStream(zc); 2756*3117ece4Schristos ZSTD_freeDStream(zd); 2757*3117ece4Schristos ZSTD_freeDStream(zd_noise); 2758*3117ece4Schristos free(cNoiseBuffer[0]); 2759*3117ece4Schristos free(cNoiseBuffer[1]); 2760*3117ece4Schristos free(cNoiseBuffer[2]); 2761*3117ece4Schristos free(cNoiseBuffer[3]); 2762*3117ece4Schristos free(cNoiseBuffer[4]); 2763*3117ece4Schristos free(copyBuffer); 2764*3117ece4Schristos free(cBuffer); 2765*3117ece4Schristos free(dstBuffer); 2766*3117ece4Schristos return result; 2767*3117ece4Schristos 2768*3117ece4Schristos _output_error: 2769*3117ece4Schristos result = 1; 2770*3117ece4Schristos goto _cleanup; 2771*3117ece4Schristos } 2772*3117ece4Schristos 2773*3117ece4Schristos /** If useOpaqueAPI, sets param in cctxParams. 2774*3117ece4Schristos * Otherwise, sets the param in zc. */ 2775*3117ece4Schristos static size_t setCCtxParameter(ZSTD_CCtx* zc, ZSTD_CCtx_params* cctxParams, 2776*3117ece4Schristos ZSTD_cParameter param, unsigned value, 2777*3117ece4Schristos int useOpaqueAPI) 2778*3117ece4Schristos { 2779*3117ece4Schristos if (useOpaqueAPI) { 2780*3117ece4Schristos return ZSTD_CCtxParams_setParameter(cctxParams, param, value); 2781*3117ece4Schristos } else { 2782*3117ece4Schristos return ZSTD_CCtx_setParameter(zc, param, value); 2783*3117ece4Schristos } 2784*3117ece4Schristos } 2785*3117ece4Schristos 2786*3117ece4Schristos /* Tests for ZSTD_compress_generic() API */ 2787*3117ece4Schristos static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest, 2788*3117ece4Schristos double compressibility, int bigTests) 2789*3117ece4Schristos { 2790*3117ece4Schristos U32 const maxSrcLog = bigTests ? 24 : 22; 2791*3117ece4Schristos static const U32 maxSampleLog = 19; 2792*3117ece4Schristos size_t const srcBufferSize = (size_t)1<<maxSrcLog; 2793*3117ece4Schristos BYTE* cNoiseBuffer[5]; 2794*3117ece4Schristos size_t const copyBufferSize= srcBufferSize + (1<<maxSampleLog); 2795*3117ece4Schristos BYTE* const copyBuffer = (BYTE*)malloc (copyBufferSize); 2796*3117ece4Schristos size_t const cBufferSize = ZSTD_compressBound(srcBufferSize); 2797*3117ece4Schristos BYTE* const cBuffer = (BYTE*)malloc (cBufferSize); 2798*3117ece4Schristos size_t const dstBufferSize = srcBufferSize; 2799*3117ece4Schristos BYTE* const dstBuffer = (BYTE*)malloc (dstBufferSize); 2800*3117ece4Schristos U32 result = 0; 2801*3117ece4Schristos int testNb = 0; 2802*3117ece4Schristos U32 coreSeed = seed; 2803*3117ece4Schristos ZSTD_CCtx* zc = ZSTD_createCCtx(); /* will be reset sometimes */ 2804*3117ece4Schristos ZSTD_DStream* zd = ZSTD_createDStream(); /* will be reset sometimes */ 2805*3117ece4Schristos ZSTD_DStream* const zd_noise = ZSTD_createDStream(); 2806*3117ece4Schristos UTIL_time_t const startClock = UTIL_getTime(); 2807*3117ece4Schristos const BYTE* dict = NULL; /* can keep same dict on 2 consecutive tests */ 2808*3117ece4Schristos size_t dictSize = 0; 2809*3117ece4Schristos U32 oldTestLog = 0; 2810*3117ece4Schristos U32 windowLogMalus = 0; /* can survive between 2 loops */ 2811*3117ece4Schristos U32 const cLevelMax = bigTests ? (U32)ZSTD_maxCLevel()-1 : g_cLevelMax_smallTests; 2812*3117ece4Schristos U32 const nbThreadsMax = bigTests ? 4 : 2; 2813*3117ece4Schristos ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams(); 2814*3117ece4Schristos 2815*3117ece4Schristos /* allocations */ 2816*3117ece4Schristos cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize); 2817*3117ece4Schristos cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize); 2818*3117ece4Schristos cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize); 2819*3117ece4Schristos cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize); 2820*3117ece4Schristos cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize); 2821*3117ece4Schristos CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4] || 2822*3117ece4Schristos !copyBuffer || !dstBuffer || !cBuffer || !zc || !zd || !zd_noise , 2823*3117ece4Schristos "Not enough memory, fuzzer tests cancelled"); 2824*3117ece4Schristos 2825*3117ece4Schristos /* Create initial samples */ 2826*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed); /* pure noise */ 2827*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed); /* barely compressible */ 2828*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed); 2829*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */ 2830*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */ 2831*3117ece4Schristos memset(copyBuffer, 0x65, copyBufferSize); /* make copyBuffer considered initialized */ 2832*3117ece4Schristos CHECK_Z( ZSTD_initDStream_usingDict(zd, NULL, 0) ); /* ensure at least one init */ 2833*3117ece4Schristos 2834*3117ece4Schristos /* catch up testNb */ 2835*3117ece4Schristos for (testNb=1; testNb < startTest; testNb++) 2836*3117ece4Schristos FUZ_rand(&coreSeed); 2837*3117ece4Schristos 2838*3117ece4Schristos /* test loop */ 2839*3117ece4Schristos for ( ; (testNb <= nbTests) || (UTIL_clockSpanMicro(startClock) < g_clockTime) ; testNb++ ) { 2840*3117ece4Schristos U32 lseed; 2841*3117ece4Schristos int opaqueAPI; 2842*3117ece4Schristos const BYTE* srcBuffer; 2843*3117ece4Schristos size_t totalTestSize, totalGenSize, cSize; 2844*3117ece4Schristos XXH64_state_t xxhState; 2845*3117ece4Schristos U64 crcOrig; 2846*3117ece4Schristos U32 resetAllowed = 1; 2847*3117ece4Schristos size_t maxTestSize; 2848*3117ece4Schristos ZSTD_parameters savedParams; 2849*3117ece4Schristos int isRefPrefix = 0; 2850*3117ece4Schristos U64 pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; 2851*3117ece4Schristos 2852*3117ece4Schristos /* init */ 2853*3117ece4Schristos if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); } 2854*3117ece4Schristos else { DISPLAYUPDATE(2, "\r%6u ", testNb); } 2855*3117ece4Schristos FUZ_rand(&coreSeed); 2856*3117ece4Schristos lseed = coreSeed ^ prime32; 2857*3117ece4Schristos DISPLAYLEVEL(5, " *** Test %u *** \n", testNb); 2858*3117ece4Schristos opaqueAPI = FUZ_rand(&lseed) & 1; 2859*3117ece4Schristos 2860*3117ece4Schristos /* states full reset (deliberately not synchronized) */ 2861*3117ece4Schristos /* some issues can only happen when reusing states */ 2862*3117ece4Schristos if ((FUZ_rand(&lseed) & 0xFF) == 131) { 2863*3117ece4Schristos DISPLAYLEVEL(5, "Creating new context \n"); 2864*3117ece4Schristos ZSTD_freeCCtx(zc); 2865*3117ece4Schristos zc = ZSTD_createCCtx(); 2866*3117ece4Schristos CHECK(zc == NULL, "ZSTD_createCCtx allocation error"); 2867*3117ece4Schristos resetAllowed = 0; 2868*3117ece4Schristos } 2869*3117ece4Schristos if ((FUZ_rand(&lseed) & 0xFF) == 132) { 2870*3117ece4Schristos ZSTD_freeDStream(zd); 2871*3117ece4Schristos zd = ZSTD_createDStream(); 2872*3117ece4Schristos CHECK(zd == NULL, "ZSTD_createDStream allocation error"); 2873*3117ece4Schristos ZSTD_initDStream_usingDict(zd, NULL, 0); /* ensure at least one init */ 2874*3117ece4Schristos } 2875*3117ece4Schristos 2876*3117ece4Schristos /* srcBuffer selection [0-4] */ 2877*3117ece4Schristos { U32 buffNb = FUZ_rand(&lseed) & 0x7F; 2878*3117ece4Schristos if (buffNb & 7) buffNb=2; /* most common : compressible (P) */ 2879*3117ece4Schristos else { 2880*3117ece4Schristos buffNb >>= 3; 2881*3117ece4Schristos if (buffNb & 7) { 2882*3117ece4Schristos const U32 tnb[2] = { 1, 3 }; /* barely/highly compressible */ 2883*3117ece4Schristos buffNb = tnb[buffNb >> 3]; 2884*3117ece4Schristos } else { 2885*3117ece4Schristos const U32 tnb[2] = { 0, 4 }; /* not compressible / sparse */ 2886*3117ece4Schristos buffNb = tnb[buffNb >> 3]; 2887*3117ece4Schristos } } 2888*3117ece4Schristos srcBuffer = cNoiseBuffer[buffNb]; 2889*3117ece4Schristos } 2890*3117ece4Schristos 2891*3117ece4Schristos /* compression init */ 2892*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(zc, NULL, 0) ); /* cancel previous dict /*/ 2893*3117ece4Schristos if ((FUZ_rand(&lseed)&1) /* at beginning, to keep same nb of rand */ 2894*3117ece4Schristos && oldTestLog /* at least one test happened */ 2895*3117ece4Schristos && resetAllowed) { 2896*3117ece4Schristos /* just set a compression level */ 2897*3117ece4Schristos maxTestSize = FUZ_randomLength(&lseed, oldTestLog+2); 2898*3117ece4Schristos if (maxTestSize >= srcBufferSize) maxTestSize = srcBufferSize-1; 2899*3117ece4Schristos { int const compressionLevel = (FUZ_rand(&lseed) % 5) + 1; 2900*3117ece4Schristos DISPLAYLEVEL(5, "t%u : compression level : %i \n", testNb, compressionLevel); 2901*3117ece4Schristos CHECK_Z (setCCtxParameter(zc, cctxParams, ZSTD_c_compressionLevel, compressionLevel, opaqueAPI) ); 2902*3117ece4Schristos } 2903*3117ece4Schristos } else { 2904*3117ece4Schristos U32 const testLog = FUZ_rand(&lseed) % maxSrcLog; 2905*3117ece4Schristos U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog; 2906*3117ece4Schristos U32 const cLevelCandidate = (FUZ_rand(&lseed) % 2907*3117ece4Schristos (ZSTD_maxCLevel() - 2908*3117ece4Schristos (MAX(testLog, dictLog) / 2))) + 2909*3117ece4Schristos 1; 2910*3117ece4Schristos int const cLevel = MIN(cLevelCandidate, cLevelMax); 2911*3117ece4Schristos DISPLAYLEVEL(5, "t%i: base cLevel : %u \n", testNb, cLevel); 2912*3117ece4Schristos maxTestSize = FUZ_rLogLength(&lseed, testLog); 2913*3117ece4Schristos DISPLAYLEVEL(5, "t%i: maxTestSize : %u \n", testNb, (unsigned)maxTestSize); 2914*3117ece4Schristos oldTestLog = testLog; 2915*3117ece4Schristos /* random dictionary selection */ 2916*3117ece4Schristos dictSize = ((FUZ_rand(&lseed)&63)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0; 2917*3117ece4Schristos { size_t const dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize); 2918*3117ece4Schristos dict = srcBuffer + dictStart; 2919*3117ece4Schristos if (!dictSize) dict=NULL; 2920*3117ece4Schristos } 2921*3117ece4Schristos pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? ZSTD_CONTENTSIZE_UNKNOWN : maxTestSize; 2922*3117ece4Schristos { ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, pledgedSrcSize, dictSize); 2923*3117ece4Schristos const U32 windowLogMax = bigTests ? 24 : 20; 2924*3117ece4Schristos const U32 searchLogMax = bigTests ? 15 : 13; 2925*3117ece4Schristos if (dictSize) 2926*3117ece4Schristos DISPLAYLEVEL(5, "t%u: with dictionary of size : %zu \n", testNb, dictSize); 2927*3117ece4Schristos 2928*3117ece4Schristos /* mess with compression parameters */ 2929*3117ece4Schristos cParams.windowLog += (FUZ_rand(&lseed) & 3) - 1; 2930*3117ece4Schristos cParams.windowLog = MIN(windowLogMax, cParams.windowLog); 2931*3117ece4Schristos cParams.hashLog += (FUZ_rand(&lseed) & 3) - 1; 2932*3117ece4Schristos cParams.chainLog += (FUZ_rand(&lseed) & 3) - 1; 2933*3117ece4Schristos cParams.searchLog += (FUZ_rand(&lseed) & 3) - 1; 2934*3117ece4Schristos cParams.searchLog = MIN(searchLogMax, cParams.searchLog); 2935*3117ece4Schristos cParams.minMatch += (FUZ_rand(&lseed) & 3) - 1; 2936*3117ece4Schristos cParams.targetLength = (U32)((cParams.targetLength + 1 ) * (0.5 + ((double)(FUZ_rand(&lseed) & 127) / 128))); 2937*3117ece4Schristos cParams = ZSTD_adjustCParams(cParams, pledgedSrcSize, dictSize); 2938*3117ece4Schristos 2939*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 2940*3117ece4Schristos DISPLAYLEVEL(5, "t%u: windowLog : %u \n", testNb, cParams.windowLog); 2941*3117ece4Schristos CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_windowLog, cParams.windowLog, opaqueAPI) ); 2942*3117ece4Schristos assert(cParams.windowLog >= ZSTD_WINDOWLOG_MIN); /* guaranteed by ZSTD_adjustCParams() */ 2943*3117ece4Schristos windowLogMalus = (cParams.windowLog - ZSTD_WINDOWLOG_MIN) / 5; 2944*3117ece4Schristos } 2945*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 2946*3117ece4Schristos DISPLAYLEVEL(5, "t%u: hashLog : %u \n", testNb, cParams.hashLog); 2947*3117ece4Schristos CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_hashLog, cParams.hashLog, opaqueAPI) ); 2948*3117ece4Schristos } 2949*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 2950*3117ece4Schristos DISPLAYLEVEL(5, "t%u: chainLog : %u \n", testNb, cParams.chainLog); 2951*3117ece4Schristos CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_chainLog, cParams.chainLog, opaqueAPI) ); 2952*3117ece4Schristos } 2953*3117ece4Schristos if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_searchLog, cParams.searchLog, opaqueAPI) ); 2954*3117ece4Schristos if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_minMatch, cParams.minMatch, opaqueAPI) ); 2955*3117ece4Schristos if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_targetLength, cParams.targetLength, opaqueAPI) ); 2956*3117ece4Schristos 2957*3117ece4Schristos /* mess with long distance matching parameters */ 2958*3117ece4Schristos if (bigTests) { 2959*3117ece4Schristos if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_enableLongDistanceMatching, FUZ_randomClampedLength(&lseed, ZSTD_ps_auto, ZSTD_ps_disable), opaqueAPI) ); 2960*3117ece4Schristos if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmHashLog, FUZ_randomClampedLength(&lseed, ZSTD_HASHLOG_MIN, 23), opaqueAPI) ); 2961*3117ece4Schristos if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmMinMatch, FUZ_randomClampedLength(&lseed, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX), opaqueAPI) ); 2962*3117ece4Schristos if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmBucketSizeLog, FUZ_randomClampedLength(&lseed, ZSTD_LDM_BUCKETSIZELOG_MIN, ZSTD_LDM_BUCKETSIZELOG_MAX), opaqueAPI) ); 2963*3117ece4Schristos if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmHashRateLog, FUZ_randomClampedLength(&lseed, ZSTD_LDM_HASHRATELOG_MIN, ZSTD_LDM_HASHRATELOG_MAX), opaqueAPI) ); 2964*3117ece4Schristos if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_srcSizeHint, FUZ_randomClampedLength(&lseed, ZSTD_SRCSIZEHINT_MIN, ZSTD_SRCSIZEHINT_MAX), opaqueAPI) ); 2965*3117ece4Schristos } 2966*3117ece4Schristos 2967*3117ece4Schristos /* mess with frame parameters */ 2968*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 2969*3117ece4Schristos int const checksumFlag = FUZ_rand(&lseed) & 1; 2970*3117ece4Schristos DISPLAYLEVEL(5, "t%u: frame checksum : %u \n", testNb, checksumFlag); 2971*3117ece4Schristos CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_checksumFlag, checksumFlag, opaqueAPI) ); 2972*3117ece4Schristos } 2973*3117ece4Schristos if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_dictIDFlag, FUZ_rand(&lseed) & 1, opaqueAPI) ); 2974*3117ece4Schristos if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_contentSizeFlag, FUZ_rand(&lseed) & 1, opaqueAPI) ); 2975*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 2976*3117ece4Schristos DISPLAYLEVEL(5, "t%u: pledgedSrcSize : %u \n", testNb, (unsigned)pledgedSrcSize); 2977*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) ); 2978*3117ece4Schristos } else { 2979*3117ece4Schristos pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; 2980*3117ece4Schristos } 2981*3117ece4Schristos 2982*3117ece4Schristos /* multi-threading parameters. Only adjust occasionally for small tests. */ 2983*3117ece4Schristos if (bigTests || (FUZ_rand(&lseed) & 0xF) == 0xF) { 2984*3117ece4Schristos U32 const nbThreadsCandidate = (FUZ_rand(&lseed) & 4) + 1; 2985*3117ece4Schristos U32 const nbThreadsAdjusted = (windowLogMalus < nbThreadsCandidate) ? nbThreadsCandidate - windowLogMalus : 1; 2986*3117ece4Schristos int const nbThreads = MIN(nbThreadsAdjusted, nbThreadsMax); 2987*3117ece4Schristos DISPLAYLEVEL(5, "t%i: nbThreads : %u \n", testNb, nbThreads); 2988*3117ece4Schristos CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_nbWorkers, nbThreads, opaqueAPI) ); 2989*3117ece4Schristos if (nbThreads > 1) { 2990*3117ece4Schristos U32 const jobLog = FUZ_rand(&lseed) % (testLog+1); 2991*3117ece4Schristos CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_overlapLog, FUZ_rand(&lseed) % 10, opaqueAPI) ); 2992*3117ece4Schristos CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_jobSize, (U32)FUZ_rLogLength(&lseed, jobLog), opaqueAPI) ); 2993*3117ece4Schristos } 2994*3117ece4Schristos } 2995*3117ece4Schristos /* Enable rsyncable mode 1 in 4 times. */ 2996*3117ece4Schristos { 2997*3117ece4Schristos int const rsyncable = (FUZ_rand(&lseed) % 4 == 0); 2998*3117ece4Schristos DISPLAYLEVEL(5, "t%u: rsyncable : %d \n", testNb, rsyncable); 2999*3117ece4Schristos setCCtxParameter(zc, cctxParams, ZSTD_c_rsyncable, rsyncable, opaqueAPI); 3000*3117ece4Schristos } 3001*3117ece4Schristos 3002*3117ece4Schristos if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_forceMaxWindow, FUZ_rand(&lseed) & 1, opaqueAPI) ); 3003*3117ece4Schristos if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_deterministicRefPrefix, FUZ_rand(&lseed) & 1, opaqueAPI) ); 3004*3117ece4Schristos 3005*3117ece4Schristos /* Set max block size parameters */ 3006*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 3007*3117ece4Schristos int maxBlockSize = (int)(FUZ_rand(&lseed) % ZSTD_BLOCKSIZE_MAX); 3008*3117ece4Schristos maxBlockSize = MAX(1024, maxBlockSize); 3009*3117ece4Schristos CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_maxBlockSize, maxBlockSize, opaqueAPI) ); 3010*3117ece4Schristos } 3011*3117ece4Schristos 3012*3117ece4Schristos /* Apply parameters */ 3013*3117ece4Schristos if (opaqueAPI) { 3014*3117ece4Schristos DISPLAYLEVEL(5, "t%u: applying CCtxParams \n", testNb); 3015*3117ece4Schristos CHECK_Z (ZSTD_CCtx_setParametersUsingCCtxParams(zc, cctxParams) ); 3016*3117ece4Schristos } 3017*3117ece4Schristos 3018*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 3019*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 3020*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dict, dictSize) ); 3021*3117ece4Schristos } else { 3022*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary_byReference(zc, dict, dictSize) ); 3023*3117ece4Schristos } 3024*3117ece4Schristos } else { 3025*3117ece4Schristos isRefPrefix = 1; 3026*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refPrefix(zc, dict, dictSize) ); 3027*3117ece4Schristos } 3028*3117ece4Schristos } } 3029*3117ece4Schristos 3030*3117ece4Schristos CHECK_Z(getCCtxParams(zc, &savedParams)); 3031*3117ece4Schristos 3032*3117ece4Schristos /* multi-segments compression test */ 3033*3117ece4Schristos { int iter; 3034*3117ece4Schristos int const startSeed = lseed; 3035*3117ece4Schristos XXH64_hash_t compressedCrcs[2]; 3036*3117ece4Schristos for (iter = 0; iter < 2; ++iter, lseed = startSeed) { 3037*3117ece4Schristos ZSTD_outBuffer outBuff = { cBuffer, cBufferSize, 0 } ; 3038*3117ece4Schristos int const singlePass = (FUZ_rand(&lseed) & 3) == 0; 3039*3117ece4Schristos int nbWorkers; 3040*3117ece4Schristos 3041*3117ece4Schristos XXH64_reset(&xxhState, 0); 3042*3117ece4Schristos 3043*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) ); 3044*3117ece4Schristos if (isRefPrefix) { 3045*3117ece4Schristos DISPLAYLEVEL(6, "t%u: Reloading prefix\n", testNb); 3046*3117ece4Schristos /* Need to reload the prefix because it gets dropped after one compression */ 3047*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refPrefix(zc, dict, dictSize) ); 3048*3117ece4Schristos } 3049*3117ece4Schristos 3050*3117ece4Schristos /* Adjust number of workers occasionally - result must be deterministic independent of nbWorkers */ 3051*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers)); 3052*3117ece4Schristos if (nbWorkers > 0 && (FUZ_rand(&lseed) & 7) == 0) { 3053*3117ece4Schristos DISPLAYLEVEL(6, "t%u: Modify nbWorkers: %d -> %d \n", testNb, nbWorkers, nbWorkers + iter); 3054*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_nbWorkers, nbWorkers + iter)); 3055*3117ece4Schristos } 3056*3117ece4Schristos 3057*3117ece4Schristos if (singlePass) { 3058*3117ece4Schristos ZSTD_inBuffer inBuff = { srcBuffer, maxTestSize, 0 }; 3059*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end)); 3060*3117ece4Schristos DISPLAYLEVEL(6, "t%u: Single pass compression: consumed %u bytes ; produced %u bytes \n", 3061*3117ece4Schristos testNb, (unsigned)inBuff.pos, (unsigned)outBuff.pos); 3062*3117ece4Schristos CHECK(inBuff.pos != inBuff.size, "Input not consumed!"); 3063*3117ece4Schristos crcOrig = XXH64(srcBuffer, maxTestSize, 0); 3064*3117ece4Schristos totalTestSize = maxTestSize; 3065*3117ece4Schristos } else { 3066*3117ece4Schristos outBuff.size = 0; 3067*3117ece4Schristos for (totalTestSize=0 ; (totalTestSize < maxTestSize) ; ) { 3068*3117ece4Schristos /* compress random chunks into randomly sized dst buffers */ 3069*3117ece4Schristos size_t const randomSrcSize = FUZ_randomLength(&lseed, maxSampleLog); 3070*3117ece4Schristos size_t const srcSize = MIN(maxTestSize-totalTestSize, randomSrcSize); 3071*3117ece4Schristos size_t const srcStart = FUZ_rand(&lseed) % (srcBufferSize - srcSize); 3072*3117ece4Schristos ZSTD_EndDirective const flush = (FUZ_rand(&lseed) & 15) ? ZSTD_e_continue : ZSTD_e_flush; 3073*3117ece4Schristos ZSTD_inBuffer inBuff = { srcBuffer+srcStart, srcSize, 0 }; 3074*3117ece4Schristos int forwardProgress; 3075*3117ece4Schristos do { 3076*3117ece4Schristos size_t const ipos = inBuff.pos; 3077*3117ece4Schristos size_t const opos = outBuff.pos; 3078*3117ece4Schristos size_t ret; 3079*3117ece4Schristos if (outBuff.pos == outBuff.size) { 3080*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog+1); 3081*3117ece4Schristos size_t const dstBuffSize = MIN(cBufferSize - outBuff.pos, randomDstSize); 3082*3117ece4Schristos outBuff.size = outBuff.pos + dstBuffSize; 3083*3117ece4Schristos } 3084*3117ece4Schristos CHECK_Z( ret = ZSTD_compressStream2(zc, &outBuff, &inBuff, flush) ); 3085*3117ece4Schristos DISPLAYLEVEL(6, "t%u: compress consumed %u bytes (total : %u) ; flush: %u (total : %u) \n", 3086*3117ece4Schristos testNb, (unsigned)inBuff.pos, (unsigned)(totalTestSize + inBuff.pos), (unsigned)flush, (unsigned)outBuff.pos); 3087*3117ece4Schristos 3088*3117ece4Schristos /* We've completed the flush */ 3089*3117ece4Schristos if (flush == ZSTD_e_flush && ret == 0) 3090*3117ece4Schristos break; 3091*3117ece4Schristos 3092*3117ece4Schristos /* Ensure maximal forward progress for determinism */ 3093*3117ece4Schristos forwardProgress = (inBuff.pos != ipos) || (outBuff.pos != opos); 3094*3117ece4Schristos } while (forwardProgress); 3095*3117ece4Schristos assert(inBuff.pos == inBuff.size); 3096*3117ece4Schristos 3097*3117ece4Schristos XXH64_update(&xxhState, srcBuffer+srcStart, inBuff.pos); 3098*3117ece4Schristos memcpy(copyBuffer+totalTestSize, srcBuffer+srcStart, inBuff.pos); 3099*3117ece4Schristos totalTestSize += inBuff.pos; 3100*3117ece4Schristos } 3101*3117ece4Schristos 3102*3117ece4Schristos /* final frame epilogue */ 3103*3117ece4Schristos { size_t remainingToFlush = 1; 3104*3117ece4Schristos while (remainingToFlush) { 3105*3117ece4Schristos ZSTD_inBuffer inBuff = { NULL, 0, 0 }; 3106*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog+1); 3107*3117ece4Schristos size_t const adjustedDstSize = MIN(cBufferSize - outBuff.pos, randomDstSize); 3108*3117ece4Schristos outBuff.size = outBuff.pos + adjustedDstSize; 3109*3117ece4Schristos DISPLAYLEVEL(6, "t%u: End-flush into dst buffer of size %u \n", testNb, (unsigned)adjustedDstSize); 3110*3117ece4Schristos /* ZSTD_e_end guarantees maximal forward progress */ 3111*3117ece4Schristos remainingToFlush = ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end); 3112*3117ece4Schristos DISPLAYLEVEL(6, "t%u: Total flushed so far : %u bytes \n", testNb, (unsigned)outBuff.pos); 3113*3117ece4Schristos CHECK( ZSTD_isError(remainingToFlush), 3114*3117ece4Schristos "ZSTD_compressStream2 w/ ZSTD_e_end error : %s", 3115*3117ece4Schristos ZSTD_getErrorName(remainingToFlush) ); 3116*3117ece4Schristos } } 3117*3117ece4Schristos crcOrig = XXH64_digest(&xxhState); 3118*3117ece4Schristos } 3119*3117ece4Schristos cSize = outBuff.pos; 3120*3117ece4Schristos compressedCrcs[iter] = XXH64(cBuffer, cSize, 0); 3121*3117ece4Schristos DISPLAYLEVEL(5, "Frame completed : %zu bytes \n", cSize); 3122*3117ece4Schristos } 3123*3117ece4Schristos CHECK(!(compressedCrcs[0] == compressedCrcs[1]), "Compression is not deterministic!"); 3124*3117ece4Schristos } 3125*3117ece4Schristos 3126*3117ece4Schristos CHECK(badParameters(zc, savedParams), "CCtx params are wrong"); 3127*3117ece4Schristos 3128*3117ece4Schristos /* multi - fragments decompression test */ 3129*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 3130*3117ece4Schristos CHECK_Z(ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters)); 3131*3117ece4Schristos } 3132*3117ece4Schristos if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) { 3133*3117ece4Schristos DISPLAYLEVEL(5, "resetting DCtx (dict:%p) \n", (void const*)dict); 3134*3117ece4Schristos CHECK_Z( ZSTD_resetDStream(zd) ); 3135*3117ece4Schristos } else { 3136*3117ece4Schristos if (dictSize) 3137*3117ece4Schristos DISPLAYLEVEL(5, "using dictionary of size %zu \n", dictSize); 3138*3117ece4Schristos CHECK_Z( ZSTD_initDStream_usingDict(zd, dict, dictSize) ); 3139*3117ece4Schristos } 3140*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 3141*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1)); 3142*3117ece4Schristos } 3143*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 3144*3117ece4Schristos int maxBlockSize; 3145*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_maxBlockSize, &maxBlockSize)); 3146*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_maxBlockSize, maxBlockSize)); 3147*3117ece4Schristos } else { 3148*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_maxBlockSize, 0)); 3149*3117ece4Schristos } 3150*3117ece4Schristos { size_t decompressionResult = 1; 3151*3117ece4Schristos ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 }; 3152*3117ece4Schristos ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 }; 3153*3117ece4Schristos for (totalGenSize = 0 ; decompressionResult ; ) { 3154*3117ece4Schristos size_t const readCSrcSize = FUZ_randomLength(&lseed, maxSampleLog); 3155*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog); 3156*3117ece4Schristos size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize); 3157*3117ece4Schristos inBuff.size = inBuff.pos + readCSrcSize; 3158*3117ece4Schristos outBuff.size = outBuff.pos + dstBuffSize; 3159*3117ece4Schristos DISPLAYLEVEL(6, "decompression presented %u new bytes (pos:%u/%u)\n", 3160*3117ece4Schristos (unsigned)readCSrcSize, (unsigned)inBuff.pos, (unsigned)cSize); 3161*3117ece4Schristos decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff); 3162*3117ece4Schristos DISPLAYLEVEL(6, "so far: consumed = %u, produced = %u \n", 3163*3117ece4Schristos (unsigned)inBuff.pos, (unsigned)outBuff.pos); 3164*3117ece4Schristos if (ZSTD_isError(decompressionResult)) { 3165*3117ece4Schristos DISPLAY("ZSTD_decompressStream error : %s \n", ZSTD_getErrorName(decompressionResult)); 3166*3117ece4Schristos findDiff(copyBuffer, dstBuffer, totalTestSize); 3167*3117ece4Schristos } 3168*3117ece4Schristos CHECK (ZSTD_isError(decompressionResult), "decompression error : %s", ZSTD_getErrorName(decompressionResult)); 3169*3117ece4Schristos CHECK (inBuff.pos > cSize, "ZSTD_decompressStream consumes too much input : %u > %u ", (unsigned)inBuff.pos, (unsigned)cSize); 3170*3117ece4Schristos } 3171*3117ece4Schristos CHECK (inBuff.pos != cSize, "compressed data should be fully read (%u != %u)", (unsigned)inBuff.pos, (unsigned)cSize); 3172*3117ece4Schristos CHECK (outBuff.pos != totalTestSize, "decompressed data : wrong size (%u != %u)", (unsigned)outBuff.pos, (unsigned)totalTestSize); 3173*3117ece4Schristos { U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0); 3174*3117ece4Schristos if (crcDest!=crcOrig) findDiff(copyBuffer, dstBuffer, totalTestSize); 3175*3117ece4Schristos CHECK (crcDest!=crcOrig, "decompressed data corrupted"); 3176*3117ece4Schristos } } 3177*3117ece4Schristos 3178*3117ece4Schristos /*===== noisy/erroneous src decompression test =====*/ 3179*3117ece4Schristos 3180*3117ece4Schristos /* add some noise */ 3181*3117ece4Schristos { U32 const nbNoiseChunks = (FUZ_rand(&lseed) & 7) + 2; 3182*3117ece4Schristos U32 nn; for (nn=0; nn<nbNoiseChunks; nn++) { 3183*3117ece4Schristos size_t const randomNoiseSize = FUZ_randomLength(&lseed, maxSampleLog); 3184*3117ece4Schristos size_t const noiseSize = MIN((cSize/3) , randomNoiseSize); 3185*3117ece4Schristos size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseSize); 3186*3117ece4Schristos size_t const cStart = FUZ_rand(&lseed) % (cSize - noiseSize); 3187*3117ece4Schristos memcpy(cBuffer+cStart, srcBuffer+noiseStart, noiseSize); 3188*3117ece4Schristos } } 3189*3117ece4Schristos 3190*3117ece4Schristos /* try decompression on noisy data */ 3191*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 3192*3117ece4Schristos CHECK_Z(ZSTD_DCtx_reset(zd_noise, ZSTD_reset_session_and_parameters)); 3193*3117ece4Schristos } else { 3194*3117ece4Schristos CHECK_Z(ZSTD_DCtx_reset(zd_noise, ZSTD_reset_session_only)); 3195*3117ece4Schristos } 3196*3117ece4Schristos if (FUZ_rand(&lseed) & 1) { 3197*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(zd_noise, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1)); 3198*3117ece4Schristos } 3199*3117ece4Schristos { ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 }; 3200*3117ece4Schristos ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 }; 3201*3117ece4Schristos while (outBuff.pos < dstBufferSize) { 3202*3117ece4Schristos size_t const randomCSrcSize = FUZ_randomLength(&lseed, maxSampleLog); 3203*3117ece4Schristos size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog); 3204*3117ece4Schristos size_t const adjustedDstSize = MIN(dstBufferSize - outBuff.pos, randomDstSize); 3205*3117ece4Schristos size_t const adjustedCSrcSize = MIN(cSize - inBuff.pos, randomCSrcSize); 3206*3117ece4Schristos outBuff.size = outBuff.pos + adjustedDstSize; 3207*3117ece4Schristos inBuff.size = inBuff.pos + adjustedCSrcSize; 3208*3117ece4Schristos { size_t const decompressError = ZSTD_decompressStream(zd, &outBuff, &inBuff); 3209*3117ece4Schristos if (ZSTD_isError(decompressError)) break; /* error correctly detected */ 3210*3117ece4Schristos /* Good so far, but no more progress possible */ 3211*3117ece4Schristos if (outBuff.pos < outBuff.size && inBuff.pos == cSize) break; 3212*3117ece4Schristos } } } } 3213*3117ece4Schristos DISPLAY("\r%u fuzzer tests completed \n", testNb-1); 3214*3117ece4Schristos 3215*3117ece4Schristos _cleanup: 3216*3117ece4Schristos ZSTD_freeCCtx(zc); 3217*3117ece4Schristos ZSTD_freeDStream(zd); 3218*3117ece4Schristos ZSTD_freeDStream(zd_noise); 3219*3117ece4Schristos ZSTD_freeCCtxParams(cctxParams); 3220*3117ece4Schristos free(cNoiseBuffer[0]); 3221*3117ece4Schristos free(cNoiseBuffer[1]); 3222*3117ece4Schristos free(cNoiseBuffer[2]); 3223*3117ece4Schristos free(cNoiseBuffer[3]); 3224*3117ece4Schristos free(cNoiseBuffer[4]); 3225*3117ece4Schristos free(copyBuffer); 3226*3117ece4Schristos free(cBuffer); 3227*3117ece4Schristos free(dstBuffer); 3228*3117ece4Schristos return result; 3229*3117ece4Schristos 3230*3117ece4Schristos _output_error: 3231*3117ece4Schristos result = 1; 3232*3117ece4Schristos goto _cleanup; 3233*3117ece4Schristos } 3234*3117ece4Schristos 3235*3117ece4Schristos /*-******************************************************* 3236*3117ece4Schristos * Command line 3237*3117ece4Schristos *********************************************************/ 3238*3117ece4Schristos static int FUZ_usage(const char* programName) 3239*3117ece4Schristos { 3240*3117ece4Schristos DISPLAY( "Usage :\n"); 3241*3117ece4Schristos DISPLAY( " %s [args]\n", programName); 3242*3117ece4Schristos DISPLAY( "\n"); 3243*3117ece4Schristos DISPLAY( "Arguments :\n"); 3244*3117ece4Schristos DISPLAY( " -i# : Number of tests (default:%u)\n", nbTestsDefault); 3245*3117ece4Schristos DISPLAY( " -T# : Max duration to run for. Overrides number of tests. (e.g. -T1m or -T60s for one minute)\n"); 3246*3117ece4Schristos DISPLAY( " -s# : Select seed (default:prompt user)\n"); 3247*3117ece4Schristos DISPLAY( " -t# : Select starting test number (default:0)\n"); 3248*3117ece4Schristos DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT); 3249*3117ece4Schristos DISPLAY( " -v : verbose\n"); 3250*3117ece4Schristos DISPLAY( " -p : pause at the end\n"); 3251*3117ece4Schristos DISPLAY( " -h : display help and exit\n"); 3252*3117ece4Schristos return 0; 3253*3117ece4Schristos } 3254*3117ece4Schristos 3255*3117ece4Schristos typedef enum { simple_api, advanced_api } e_api; 3256*3117ece4Schristos 3257*3117ece4Schristos int main(int argc, const char** argv) 3258*3117ece4Schristos { 3259*3117ece4Schristos U32 seed = 0; 3260*3117ece4Schristos int seedset = 0; 3261*3117ece4Schristos int nbTests = nbTestsDefault; 3262*3117ece4Schristos int testNb = 0; 3263*3117ece4Schristos int proba = FUZ_COMPRESSIBILITY_DEFAULT; 3264*3117ece4Schristos int result = 0; 3265*3117ece4Schristos int mainPause = 0; 3266*3117ece4Schristos int bigTests = (sizeof(size_t) == 8); 3267*3117ece4Schristos e_api selected_api = simple_api; 3268*3117ece4Schristos const char* const programName = argv[0]; 3269*3117ece4Schristos int argNb; 3270*3117ece4Schristos 3271*3117ece4Schristos /* Check command line */ 3272*3117ece4Schristos for(argNb=1; argNb<argc; argNb++) { 3273*3117ece4Schristos const char* argument = argv[argNb]; 3274*3117ece4Schristos assert(argument != NULL); 3275*3117ece4Schristos 3276*3117ece4Schristos /* Parsing commands. Aggregated commands are allowed */ 3277*3117ece4Schristos if (argument[0]=='-') { 3278*3117ece4Schristos 3279*3117ece4Schristos if (!strcmp(argument, "--newapi")) { selected_api=advanced_api; testNb += !testNb; continue; } 3280*3117ece4Schristos if (!strcmp(argument, "--no-big-tests")) { bigTests=0; continue; } 3281*3117ece4Schristos if (!strcmp(argument, "--big-tests")) { bigTests=1; continue; } 3282*3117ece4Schristos 3283*3117ece4Schristos argument++; 3284*3117ece4Schristos while (*argument!=0) { 3285*3117ece4Schristos switch(*argument) 3286*3117ece4Schristos { 3287*3117ece4Schristos case 'h': 3288*3117ece4Schristos return FUZ_usage(programName); 3289*3117ece4Schristos 3290*3117ece4Schristos case 'v': 3291*3117ece4Schristos argument++; 3292*3117ece4Schristos g_displayLevel++; 3293*3117ece4Schristos break; 3294*3117ece4Schristos 3295*3117ece4Schristos case 'q': 3296*3117ece4Schristos argument++; 3297*3117ece4Schristos g_displayLevel--; 3298*3117ece4Schristos break; 3299*3117ece4Schristos 3300*3117ece4Schristos case 'p': /* pause at the end */ 3301*3117ece4Schristos argument++; 3302*3117ece4Schristos mainPause = 1; 3303*3117ece4Schristos break; 3304*3117ece4Schristos 3305*3117ece4Schristos case 'i': /* limit tests by nb of iterations (default) */ 3306*3117ece4Schristos argument++; 3307*3117ece4Schristos nbTests=0; g_clockTime=0; 3308*3117ece4Schristos while ((*argument>='0') && (*argument<='9')) { 3309*3117ece4Schristos nbTests *= 10; 3310*3117ece4Schristos nbTests += *argument - '0'; 3311*3117ece4Schristos argument++; 3312*3117ece4Schristos } 3313*3117ece4Schristos break; 3314*3117ece4Schristos 3315*3117ece4Schristos case 'T': /* limit tests by time */ 3316*3117ece4Schristos argument++; 3317*3117ece4Schristos nbTests=0; g_clockTime=0; 3318*3117ece4Schristos while ((*argument>='0') && (*argument<='9')) { 3319*3117ece4Schristos g_clockTime *= 10; 3320*3117ece4Schristos g_clockTime += *argument - '0'; 3321*3117ece4Schristos argument++; 3322*3117ece4Schristos } 3323*3117ece4Schristos if (*argument=='m') { /* -T1m == -T60 */ 3324*3117ece4Schristos g_clockTime *=60, argument++; 3325*3117ece4Schristos if (*argument=='n') argument++; /* -T1mn == -T60 */ 3326*3117ece4Schristos } else if (*argument=='s') argument++; /* -T10s == -T10 */ 3327*3117ece4Schristos g_clockTime *= SEC_TO_MICRO; 3328*3117ece4Schristos break; 3329*3117ece4Schristos 3330*3117ece4Schristos case 's': /* manually select seed */ 3331*3117ece4Schristos argument++; 3332*3117ece4Schristos seedset=1; 3333*3117ece4Schristos seed=0; 3334*3117ece4Schristos while ((*argument>='0') && (*argument<='9')) { 3335*3117ece4Schristos seed *= 10; 3336*3117ece4Schristos seed += *argument - '0'; 3337*3117ece4Schristos argument++; 3338*3117ece4Schristos } 3339*3117ece4Schristos break; 3340*3117ece4Schristos 3341*3117ece4Schristos case 't': /* select starting test number */ 3342*3117ece4Schristos argument++; 3343*3117ece4Schristos testNb=0; 3344*3117ece4Schristos while ((*argument>='0') && (*argument<='9')) { 3345*3117ece4Schristos testNb *= 10; 3346*3117ece4Schristos testNb += *argument - '0'; 3347*3117ece4Schristos argument++; 3348*3117ece4Schristos } 3349*3117ece4Schristos break; 3350*3117ece4Schristos 3351*3117ece4Schristos case 'P': /* compressibility % */ 3352*3117ece4Schristos argument++; 3353*3117ece4Schristos proba=0; 3354*3117ece4Schristos while ((*argument>='0') && (*argument<='9')) { 3355*3117ece4Schristos proba *= 10; 3356*3117ece4Schristos proba += *argument - '0'; 3357*3117ece4Schristos argument++; 3358*3117ece4Schristos } 3359*3117ece4Schristos if (proba<0) proba=0; 3360*3117ece4Schristos if (proba>100) proba=100; 3361*3117ece4Schristos break; 3362*3117ece4Schristos 3363*3117ece4Schristos default: 3364*3117ece4Schristos return FUZ_usage(programName); 3365*3117ece4Schristos } 3366*3117ece4Schristos } } } /* for(argNb=1; argNb<argc; argNb++) */ 3367*3117ece4Schristos 3368*3117ece4Schristos /* Get Seed */ 3369*3117ece4Schristos DISPLAY("Starting zstream tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION_STRING); 3370*3117ece4Schristos 3371*3117ece4Schristos if (!seedset) { 3372*3117ece4Schristos time_t const t = time(NULL); 3373*3117ece4Schristos U32 const h = XXH32(&t, sizeof(t), 1); 3374*3117ece4Schristos seed = h % 10000; 3375*3117ece4Schristos } 3376*3117ece4Schristos 3377*3117ece4Schristos DISPLAY("Seed = %u\n", (unsigned)seed); 3378*3117ece4Schristos if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) DISPLAY("Compressibility : %i%%\n", proba); 3379*3117ece4Schristos 3380*3117ece4Schristos if (nbTests<=0) nbTests=1; 3381*3117ece4Schristos 3382*3117ece4Schristos if (testNb==0) { 3383*3117ece4Schristos result = basicUnitTests(0, ((double)proba) / 100, bigTests); /* constant seed for predictability */ 3384*3117ece4Schristos } 3385*3117ece4Schristos 3386*3117ece4Schristos if (!result) { 3387*3117ece4Schristos switch(selected_api) 3388*3117ece4Schristos { 3389*3117ece4Schristos case simple_api : 3390*3117ece4Schristos result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100, bigTests); 3391*3117ece4Schristos break; 3392*3117ece4Schristos case advanced_api : 3393*3117ece4Schristos result = fuzzerTests_newAPI(seed, nbTests, testNb, ((double)proba) / 100, bigTests); 3394*3117ece4Schristos break; 3395*3117ece4Schristos default : 3396*3117ece4Schristos assert(0); /* impossible */ 3397*3117ece4Schristos } 3398*3117ece4Schristos } 3399*3117ece4Schristos 3400*3117ece4Schristos if (mainPause) { 3401*3117ece4Schristos int unused; 3402*3117ece4Schristos DISPLAY("Press Enter \n"); 3403*3117ece4Schristos unused = getchar(); 3404*3117ece4Schristos (void)unused; 3405*3117ece4Schristos } 3406*3117ece4Schristos return result; 3407*3117ece4Schristos } 3408