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 : 4204) /* disable: C4204: non-constant aggregate initializer */ 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(), time_t */ 29*3117ece4Schristos #undef NDEBUG /* always enable assert() */ 30*3117ece4Schristos #include <assert.h> 31*3117ece4Schristos #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressContinue, ZSTD_compressBlock */ 32*3117ece4Schristos #include "debug.h" /* DEBUG_STATIC_ASSERT */ 33*3117ece4Schristos #include "fse.h" 34*3117ece4Schristos #define ZSTD_DISABLE_DEPRECATE_WARNINGS /* No deprecation warnings, we still test some deprecated functions */ 35*3117ece4Schristos #include "zstd.h" /* ZSTD_VERSION_STRING */ 36*3117ece4Schristos #include "zstd_errors.h" /* ZSTD_getErrorCode */ 37*3117ece4Schristos #define ZDICT_STATIC_LINKING_ONLY 38*3117ece4Schristos #include "zdict.h" /* ZDICT_trainFromBuffer */ 39*3117ece4Schristos #include "mem.h" 40*3117ece4Schristos #include "datagen.h" /* RDG_genBuffer */ 41*3117ece4Schristos #define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ 42*3117ece4Schristos #include "xxhash.h" /* XXH64 */ 43*3117ece4Schristos #include "util.h" 44*3117ece4Schristos #include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */ 45*3117ece4Schristos /* must be included after util.h, due to ERROR macro redefinition issue on Visual Studio */ 46*3117ece4Schristos #include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */ 47*3117ece4Schristos #include "threading.h" /* ZSTD_pthread_create, ZSTD_pthread_join */ 48*3117ece4Schristos 49*3117ece4Schristos 50*3117ece4Schristos /*-************************************ 51*3117ece4Schristos * Constants 52*3117ece4Schristos **************************************/ 53*3117ece4Schristos #define GB *(1U<<30) 54*3117ece4Schristos 55*3117ece4Schristos static const int FUZ_compressibility_default = 50; 56*3117ece4Schristos static const int nbTestsDefault = 30000; 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) { DISPLAY(__VA_ARGS__); } 64*3117ece4Schristos static U32 g_displayLevel = 2; 65*3117ece4Schristos 66*3117ece4Schristos static const U64 g_refreshRate = SEC_TO_MICRO / 6; 67*3117ece4Schristos static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; 68*3117ece4Schristos 69*3117ece4Schristos #define DISPLAYUPDATE(l, ...) \ 70*3117ece4Schristos if (g_displayLevel>=l) { \ 71*3117ece4Schristos if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \ 72*3117ece4Schristos { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ 73*3117ece4Schristos if (g_displayLevel>=4) fflush(stderr); } \ 74*3117ece4Schristos } 75*3117ece4Schristos 76*3117ece4Schristos 77*3117ece4Schristos /*-******************************************************* 78*3117ece4Schristos * Compile time test 79*3117ece4Schristos *********************************************************/ 80*3117ece4Schristos #undef MIN 81*3117ece4Schristos #undef MAX 82*3117ece4Schristos /* Declaring the function, to avoid -Wmissing-prototype */ 83*3117ece4Schristos void FUZ_bug976(void); 84*3117ece4Schristos void FUZ_bug976(void) 85*3117ece4Schristos { /* these constants shall not depend on MIN() macro */ 86*3117ece4Schristos DEBUG_STATIC_ASSERT(ZSTD_HASHLOG_MAX < 31); 87*3117ece4Schristos DEBUG_STATIC_ASSERT(ZSTD_CHAINLOG_MAX < 31); 88*3117ece4Schristos } 89*3117ece4Schristos 90*3117ece4Schristos 91*3117ece4Schristos /*-******************************************************* 92*3117ece4Schristos * Internal functions 93*3117ece4Schristos *********************************************************/ 94*3117ece4Schristos #define MIN(a,b) ((a)<(b)?(a):(b)) 95*3117ece4Schristos #define MAX(a,b) ((a)>(b)?(a):(b)) 96*3117ece4Schristos 97*3117ece4Schristos #define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r))) 98*3117ece4Schristos static U32 FUZ_rand(U32* src) 99*3117ece4Schristos { 100*3117ece4Schristos static const U32 prime1 = 2654435761U; 101*3117ece4Schristos static const U32 prime2 = 2246822519U; 102*3117ece4Schristos U32 rand32 = *src; 103*3117ece4Schristos rand32 *= prime1; 104*3117ece4Schristos rand32 += prime2; 105*3117ece4Schristos rand32 = FUZ_rotl32(rand32, 13); 106*3117ece4Schristos *src = rand32; 107*3117ece4Schristos return rand32 >> 5; 108*3117ece4Schristos } 109*3117ece4Schristos 110*3117ece4Schristos static U32 FUZ_highbit32(U32 v32) 111*3117ece4Schristos { 112*3117ece4Schristos unsigned nbBits = 0; 113*3117ece4Schristos if (v32==0) return 0; 114*3117ece4Schristos while (v32) v32 >>= 1, nbBits++; 115*3117ece4Schristos return nbBits; 116*3117ece4Schristos } 117*3117ece4Schristos 118*3117ece4Schristos 119*3117ece4Schristos /*============================================= 120*3117ece4Schristos * Test macros 121*3117ece4Schristos =============================================*/ 122*3117ece4Schristos #define CHECK(fn) { if(!(fn)) { DISPLAYLEVEL(1, "Error : test (%s) failed \n", #fn); exit(1); } } 123*3117ece4Schristos 124*3117ece4Schristos #define CHECK_Z(f) { \ 125*3117ece4Schristos size_t const err = f; \ 126*3117ece4Schristos if (ZSTD_isError(err)) { \ 127*3117ece4Schristos DISPLAY("Error => %s : %s ", \ 128*3117ece4Schristos #f, ZSTD_getErrorName(err)); \ 129*3117ece4Schristos exit(1); \ 130*3117ece4Schristos } } 131*3117ece4Schristos 132*3117ece4Schristos #define CHECK_VAR(var, fn) var = fn; if (ZSTD_isError(var)) { DISPLAYLEVEL(1, "%s : fails : %s \n", #fn, ZSTD_getErrorName(var)); exit(1); } 133*3117ece4Schristos #define CHECK_NEWV(var, fn) size_t const CHECK_VAR(var, fn) 134*3117ece4Schristos #define CHECKPLUS(var, fn, more) { CHECK_NEWV(var, fn); more; } 135*3117ece4Schristos 136*3117ece4Schristos #define CHECK_OP(op, lhs, rhs) { \ 137*3117ece4Schristos if (!((lhs) op (rhs))) { \ 138*3117ece4Schristos DISPLAY("Error L%u => FAILED %s %s %s ", __LINE__, #lhs, #op, #rhs); \ 139*3117ece4Schristos exit(1); \ 140*3117ece4Schristos } \ 141*3117ece4Schristos } 142*3117ece4Schristos #define CHECK_EQ(lhs, rhs) CHECK_OP(==, lhs, rhs) 143*3117ece4Schristos #define CHECK_LT(lhs, rhs) CHECK_OP(<, lhs, rhs) 144*3117ece4Schristos 145*3117ece4Schristos 146*3117ece4Schristos /*============================================= 147*3117ece4Schristos * Memory Tests 148*3117ece4Schristos =============================================*/ 149*3117ece4Schristos #if defined(__APPLE__) && defined(__MACH__) 150*3117ece4Schristos 151*3117ece4Schristos #include <malloc/malloc.h> /* malloc_size */ 152*3117ece4Schristos 153*3117ece4Schristos typedef struct { 154*3117ece4Schristos unsigned long long totalMalloc; 155*3117ece4Schristos size_t currentMalloc; 156*3117ece4Schristos size_t peakMalloc; 157*3117ece4Schristos unsigned nbMalloc; 158*3117ece4Schristos unsigned nbFree; 159*3117ece4Schristos } mallocCounter_t; 160*3117ece4Schristos 161*3117ece4Schristos static const mallocCounter_t INIT_MALLOC_COUNTER = { 0, 0, 0, 0, 0 }; 162*3117ece4Schristos 163*3117ece4Schristos static void* FUZ_mallocDebug(void* counter, size_t size) 164*3117ece4Schristos { 165*3117ece4Schristos mallocCounter_t* const mcPtr = (mallocCounter_t*)counter; 166*3117ece4Schristos void* const ptr = malloc(size); 167*3117ece4Schristos if (ptr==NULL) return NULL; 168*3117ece4Schristos DISPLAYLEVEL(4, "allocating %u KB => effectively %u KB \n", 169*3117ece4Schristos (unsigned)(size >> 10), (unsigned)(malloc_size(ptr) >> 10)); /* OS-X specific */ 170*3117ece4Schristos mcPtr->totalMalloc += size; 171*3117ece4Schristos mcPtr->currentMalloc += size; 172*3117ece4Schristos if (mcPtr->currentMalloc > mcPtr->peakMalloc) 173*3117ece4Schristos mcPtr->peakMalloc = mcPtr->currentMalloc; 174*3117ece4Schristos mcPtr->nbMalloc += 1; 175*3117ece4Schristos return ptr; 176*3117ece4Schristos } 177*3117ece4Schristos 178*3117ece4Schristos static void FUZ_freeDebug(void* counter, void* address) 179*3117ece4Schristos { 180*3117ece4Schristos mallocCounter_t* const mcPtr = (mallocCounter_t*)counter; 181*3117ece4Schristos DISPLAYLEVEL(4, "freeing %u KB \n", (unsigned)(malloc_size(address) >> 10)); 182*3117ece4Schristos mcPtr->nbFree += 1; 183*3117ece4Schristos mcPtr->currentMalloc -= malloc_size(address); /* OS-X specific */ 184*3117ece4Schristos free(address); 185*3117ece4Schristos } 186*3117ece4Schristos 187*3117ece4Schristos static void FUZ_displayMallocStats(mallocCounter_t count) 188*3117ece4Schristos { 189*3117ece4Schristos DISPLAYLEVEL(3, "peak:%6u KB, nbMallocs:%2u, total:%6u KB \n", 190*3117ece4Schristos (unsigned)(count.peakMalloc >> 10), 191*3117ece4Schristos count.nbMalloc, 192*3117ece4Schristos (unsigned)(count.totalMalloc >> 10)); 193*3117ece4Schristos } 194*3117ece4Schristos 195*3117ece4Schristos static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsigned part, 196*3117ece4Schristos void* inBuffer, size_t inSize, void* outBuffer, size_t outSize) 197*3117ece4Schristos { 198*3117ece4Schristos /* test only played in verbose mode, as they are long */ 199*3117ece4Schristos if (g_displayLevel<3) return 0; 200*3117ece4Schristos 201*3117ece4Schristos /* Create compressible noise */ 202*3117ece4Schristos if (!inBuffer || !outBuffer) { 203*3117ece4Schristos DISPLAY("Not enough memory, aborting\n"); 204*3117ece4Schristos exit(1); 205*3117ece4Schristos } 206*3117ece4Schristos RDG_genBuffer(inBuffer, inSize, compressibility, 0. /*auto*/, seed); 207*3117ece4Schristos 208*3117ece4Schristos /* simple compression tests */ 209*3117ece4Schristos if (part <= 1) 210*3117ece4Schristos { int compressionLevel; 211*3117ece4Schristos for (compressionLevel=1; compressionLevel<=6; compressionLevel++) { 212*3117ece4Schristos mallocCounter_t malcount = INIT_MALLOC_COUNTER; 213*3117ece4Schristos ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount }; 214*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem); 215*3117ece4Schristos CHECK_Z( ZSTD_compressCCtx(cctx, outBuffer, outSize, inBuffer, inSize, compressionLevel) ); 216*3117ece4Schristos ZSTD_freeCCtx(cctx); 217*3117ece4Schristos DISPLAYLEVEL(3, "compressCCtx level %i : ", compressionLevel); 218*3117ece4Schristos FUZ_displayMallocStats(malcount); 219*3117ece4Schristos } } 220*3117ece4Schristos 221*3117ece4Schristos /* streaming compression tests */ 222*3117ece4Schristos if (part <= 2) 223*3117ece4Schristos { int compressionLevel; 224*3117ece4Schristos for (compressionLevel=1; compressionLevel<=6; compressionLevel++) { 225*3117ece4Schristos mallocCounter_t malcount = INIT_MALLOC_COUNTER; 226*3117ece4Schristos ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount }; 227*3117ece4Schristos ZSTD_CCtx* const cstream = ZSTD_createCStream_advanced(cMem); 228*3117ece4Schristos ZSTD_outBuffer out = { outBuffer, outSize, 0 }; 229*3117ece4Schristos ZSTD_inBuffer in = { inBuffer, inSize, 0 }; 230*3117ece4Schristos CHECK_Z( ZSTD_initCStream(cstream, compressionLevel) ); 231*3117ece4Schristos CHECK_Z( ZSTD_compressStream(cstream, &out, &in) ); 232*3117ece4Schristos CHECK_Z( ZSTD_endStream(cstream, &out) ); 233*3117ece4Schristos ZSTD_freeCStream(cstream); 234*3117ece4Schristos DISPLAYLEVEL(3, "compressStream level %i : ", compressionLevel); 235*3117ece4Schristos FUZ_displayMallocStats(malcount); 236*3117ece4Schristos } } 237*3117ece4Schristos 238*3117ece4Schristos /* advanced MT API test */ 239*3117ece4Schristos if (part <= 3) 240*3117ece4Schristos { int nbThreads; 241*3117ece4Schristos for (nbThreads=1; nbThreads<=4; nbThreads++) { 242*3117ece4Schristos int compressionLevel; 243*3117ece4Schristos for (compressionLevel=1; compressionLevel<=6; compressionLevel++) { 244*3117ece4Schristos mallocCounter_t malcount = INIT_MALLOC_COUNTER; 245*3117ece4Schristos ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount }; 246*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem); 247*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) ); 248*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads) ); 249*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, outBuffer, outSize, inBuffer, inSize) ); 250*3117ece4Schristos ZSTD_freeCCtx(cctx); 251*3117ece4Schristos DISPLAYLEVEL(3, "compress_generic,-T%i,end level %i : ", 252*3117ece4Schristos nbThreads, compressionLevel); 253*3117ece4Schristos FUZ_displayMallocStats(malcount); 254*3117ece4Schristos } } } 255*3117ece4Schristos 256*3117ece4Schristos /* advanced MT streaming API test */ 257*3117ece4Schristos if (part <= 4) 258*3117ece4Schristos { int nbThreads; 259*3117ece4Schristos for (nbThreads=1; nbThreads<=4; nbThreads++) { 260*3117ece4Schristos int compressionLevel; 261*3117ece4Schristos for (compressionLevel=1; compressionLevel<=6; compressionLevel++) { 262*3117ece4Schristos mallocCounter_t malcount = INIT_MALLOC_COUNTER; 263*3117ece4Schristos ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount }; 264*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem); 265*3117ece4Schristos ZSTD_outBuffer out = { outBuffer, outSize, 0 }; 266*3117ece4Schristos ZSTD_inBuffer in = { inBuffer, inSize, 0 }; 267*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) ); 268*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads) ); 269*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue) ); 270*3117ece4Schristos while ( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) ) {} 271*3117ece4Schristos ZSTD_freeCCtx(cctx); 272*3117ece4Schristos DISPLAYLEVEL(3, "compress_generic,-T%i,continue level %i : ", 273*3117ece4Schristos nbThreads, compressionLevel); 274*3117ece4Schristos FUZ_displayMallocStats(malcount); 275*3117ece4Schristos } } } 276*3117ece4Schristos 277*3117ece4Schristos return 0; 278*3117ece4Schristos } 279*3117ece4Schristos 280*3117ece4Schristos static int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part) 281*3117ece4Schristos { 282*3117ece4Schristos size_t const inSize = 64 MB + 16 MB + 4 MB + 1 MB + 256 KB + 64 KB; /* 85.3 MB */ 283*3117ece4Schristos size_t const outSize = ZSTD_compressBound(inSize); 284*3117ece4Schristos void* const inBuffer = malloc(inSize); 285*3117ece4Schristos void* const outBuffer = malloc(outSize); 286*3117ece4Schristos int result; 287*3117ece4Schristos 288*3117ece4Schristos /* Create compressible noise */ 289*3117ece4Schristos if (!inBuffer || !outBuffer) { 290*3117ece4Schristos DISPLAY("Not enough memory, aborting \n"); 291*3117ece4Schristos exit(1); 292*3117ece4Schristos } 293*3117ece4Schristos 294*3117ece4Schristos result = FUZ_mallocTests_internal(seed, compressibility, part, 295*3117ece4Schristos inBuffer, inSize, outBuffer, outSize); 296*3117ece4Schristos 297*3117ece4Schristos free(inBuffer); 298*3117ece4Schristos free(outBuffer); 299*3117ece4Schristos return result; 300*3117ece4Schristos } 301*3117ece4Schristos 302*3117ece4Schristos #else 303*3117ece4Schristos 304*3117ece4Schristos static int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part) 305*3117ece4Schristos { 306*3117ece4Schristos (void)seed; (void)compressibility; (void)part; 307*3117ece4Schristos return 0; 308*3117ece4Schristos } 309*3117ece4Schristos 310*3117ece4Schristos #endif 311*3117ece4Schristos 312*3117ece4Schristos static void FUZ_decodeSequences(BYTE* dst, ZSTD_Sequence* seqs, size_t seqsSize, 313*3117ece4Schristos BYTE* src, size_t size, ZSTD_sequenceFormat_e format) 314*3117ece4Schristos { 315*3117ece4Schristos size_t i; 316*3117ece4Schristos size_t j; 317*3117ece4Schristos for(i = 0; i < seqsSize; ++i) { 318*3117ece4Schristos assert(dst + seqs[i].litLength + seqs[i].matchLength <= dst + size); 319*3117ece4Schristos assert(src + seqs[i].litLength + seqs[i].matchLength <= src + size); 320*3117ece4Schristos if (format == ZSTD_sf_noBlockDelimiters) { 321*3117ece4Schristos assert(seqs[i].matchLength != 0 || seqs[i].offset != 0); 322*3117ece4Schristos } 323*3117ece4Schristos 324*3117ece4Schristos memcpy(dst, src, seqs[i].litLength); 325*3117ece4Schristos dst += seqs[i].litLength; 326*3117ece4Schristos src += seqs[i].litLength; 327*3117ece4Schristos size -= seqs[i].litLength; 328*3117ece4Schristos 329*3117ece4Schristos if (seqs[i].offset != 0) { 330*3117ece4Schristos for (j = 0; j < seqs[i].matchLength; ++j) 331*3117ece4Schristos dst[j] = dst[(ptrdiff_t)(j - seqs[i].offset)]; 332*3117ece4Schristos dst += seqs[i].matchLength; 333*3117ece4Schristos src += seqs[i].matchLength; 334*3117ece4Schristos size -= seqs[i].matchLength; 335*3117ece4Schristos } 336*3117ece4Schristos } 337*3117ece4Schristos if (format == ZSTD_sf_noBlockDelimiters) { 338*3117ece4Schristos memcpy(dst, src, size); 339*3117ece4Schristos } 340*3117ece4Schristos } 341*3117ece4Schristos 342*3117ece4Schristos #ifdef ZSTD_MULTITHREAD 343*3117ece4Schristos 344*3117ece4Schristos typedef struct { 345*3117ece4Schristos ZSTD_CCtx* cctx; 346*3117ece4Schristos ZSTD_threadPool* pool; 347*3117ece4Schristos void* CNBuffer; 348*3117ece4Schristos size_t CNBuffSize; 349*3117ece4Schristos void* compressedBuffer; 350*3117ece4Schristos size_t compressedBufferSize; 351*3117ece4Schristos void* decodedBuffer; 352*3117ece4Schristos int err; 353*3117ece4Schristos } threadPoolTests_compressionJob_payload; 354*3117ece4Schristos 355*3117ece4Schristos static void* threadPoolTests_compressionJob(void* payload) { 356*3117ece4Schristos threadPoolTests_compressionJob_payload* args = (threadPoolTests_compressionJob_payload*)payload; 357*3117ece4Schristos size_t cSize; 358*3117ece4Schristos if (ZSTD_isError(ZSTD_CCtx_refThreadPool(args->cctx, args->pool))) args->err = 1; 359*3117ece4Schristos cSize = ZSTD_compress2(args->cctx, args->compressedBuffer, args->compressedBufferSize, args->CNBuffer, args->CNBuffSize); 360*3117ece4Schristos if (ZSTD_isError(cSize)) args->err = 1; 361*3117ece4Schristos if (ZSTD_isError(ZSTD_decompress(args->decodedBuffer, args->CNBuffSize, args->compressedBuffer, cSize))) args->err = 1; 362*3117ece4Schristos return payload; 363*3117ece4Schristos } 364*3117ece4Schristos 365*3117ece4Schristos static int threadPoolTests(void) { 366*3117ece4Schristos int testResult = 0; 367*3117ece4Schristos size_t err; 368*3117ece4Schristos 369*3117ece4Schristos size_t const CNBuffSize = 5 MB; 370*3117ece4Schristos void* const CNBuffer = malloc(CNBuffSize); 371*3117ece4Schristos size_t const compressedBufferSize = ZSTD_compressBound(CNBuffSize); 372*3117ece4Schristos void* const compressedBuffer = malloc(compressedBufferSize); 373*3117ece4Schristos void* const decodedBuffer = malloc(CNBuffSize); 374*3117ece4Schristos 375*3117ece4Schristos size_t const kPoolNumThreads = 8; 376*3117ece4Schristos 377*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, 0.5, 0.5, 0); 378*3117ece4Schristos 379*3117ece4Schristos DISPLAYLEVEL(3, "thread pool test : threadPool reuse roundtrips: "); 380*3117ece4Schristos { 381*3117ece4Schristos ZSTD_CCtx* cctx = ZSTD_createCCtx(); 382*3117ece4Schristos ZSTD_threadPool* pool = ZSTD_createThreadPool(kPoolNumThreads); 383*3117ece4Schristos 384*3117ece4Schristos size_t nbThreads = 1; 385*3117ece4Schristos for (; nbThreads <= kPoolNumThreads; ++nbThreads) { 386*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 387*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, (int)nbThreads); 388*3117ece4Schristos err = ZSTD_CCtx_refThreadPool(cctx, pool); 389*3117ece4Schristos if (ZSTD_isError(err)) { 390*3117ece4Schristos DISPLAYLEVEL(3, "refThreadPool error!\n"); 391*3117ece4Schristos ZSTD_freeCCtx(cctx); 392*3117ece4Schristos goto _output_error; 393*3117ece4Schristos } 394*3117ece4Schristos err = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 395*3117ece4Schristos if (ZSTD_isError(err)) { 396*3117ece4Schristos DISPLAYLEVEL(3, "Compression error!\n"); 397*3117ece4Schristos ZSTD_freeCCtx(cctx); 398*3117ece4Schristos goto _output_error; 399*3117ece4Schristos } 400*3117ece4Schristos err = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, err); 401*3117ece4Schristos if (ZSTD_isError(err)) { 402*3117ece4Schristos DISPLAYLEVEL(3, "Decompression error!\n"); 403*3117ece4Schristos ZSTD_freeCCtx(cctx); 404*3117ece4Schristos goto _output_error; 405*3117ece4Schristos } 406*3117ece4Schristos } 407*3117ece4Schristos 408*3117ece4Schristos ZSTD_freeCCtx(cctx); 409*3117ece4Schristos ZSTD_freeThreadPool(pool); 410*3117ece4Schristos } 411*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 412*3117ece4Schristos 413*3117ece4Schristos DISPLAYLEVEL(3, "thread pool test : threadPool simultaneous usage: "); 414*3117ece4Schristos { 415*3117ece4Schristos void* const decodedBuffer2 = malloc(CNBuffSize); 416*3117ece4Schristos void* const compressedBuffer2 = malloc(compressedBufferSize); 417*3117ece4Schristos ZSTD_threadPool* pool = ZSTD_createThreadPool(kPoolNumThreads); 418*3117ece4Schristos ZSTD_CCtx* cctx1 = ZSTD_createCCtx(); 419*3117ece4Schristos ZSTD_CCtx* cctx2 = ZSTD_createCCtx(); 420*3117ece4Schristos 421*3117ece4Schristos ZSTD_pthread_t t1; 422*3117ece4Schristos ZSTD_pthread_t t2; 423*3117ece4Schristos threadPoolTests_compressionJob_payload p1 = {cctx1, pool, CNBuffer, CNBuffSize, 424*3117ece4Schristos compressedBuffer, compressedBufferSize, decodedBuffer, 0 /* err */}; 425*3117ece4Schristos threadPoolTests_compressionJob_payload p2 = {cctx2, pool, CNBuffer, CNBuffSize, 426*3117ece4Schristos compressedBuffer2, compressedBufferSize, decodedBuffer2, 0 /* err */}; 427*3117ece4Schristos 428*3117ece4Schristos ZSTD_CCtx_setParameter(cctx1, ZSTD_c_nbWorkers, 2); 429*3117ece4Schristos ZSTD_CCtx_setParameter(cctx2, ZSTD_c_nbWorkers, 2); 430*3117ece4Schristos ZSTD_CCtx_refThreadPool(cctx1, pool); 431*3117ece4Schristos ZSTD_CCtx_refThreadPool(cctx2, pool); 432*3117ece4Schristos 433*3117ece4Schristos ZSTD_pthread_create(&t1, NULL, threadPoolTests_compressionJob, &p1); 434*3117ece4Schristos ZSTD_pthread_create(&t2, NULL, threadPoolTests_compressionJob, &p2); 435*3117ece4Schristos ZSTD_pthread_join(t1); 436*3117ece4Schristos ZSTD_pthread_join(t2); 437*3117ece4Schristos 438*3117ece4Schristos assert(!memcmp(decodedBuffer, decodedBuffer2, CNBuffSize)); 439*3117ece4Schristos free(decodedBuffer2); 440*3117ece4Schristos free(compressedBuffer2); 441*3117ece4Schristos 442*3117ece4Schristos ZSTD_freeThreadPool(pool); 443*3117ece4Schristos ZSTD_freeCCtx(cctx1); 444*3117ece4Schristos ZSTD_freeCCtx(cctx2); 445*3117ece4Schristos 446*3117ece4Schristos if (p1.err || p2.err) goto _output_error; 447*3117ece4Schristos } 448*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 449*3117ece4Schristos 450*3117ece4Schristos _end: 451*3117ece4Schristos free(CNBuffer); 452*3117ece4Schristos free(compressedBuffer); 453*3117ece4Schristos free(decodedBuffer); 454*3117ece4Schristos return testResult; 455*3117ece4Schristos 456*3117ece4Schristos _output_error: 457*3117ece4Schristos testResult = 1; 458*3117ece4Schristos DISPLAY("Error detected in Unit tests ! \n"); 459*3117ece4Schristos goto _end; 460*3117ece4Schristos } 461*3117ece4Schristos #endif /* ZSTD_MULTITHREAD */ 462*3117ece4Schristos 463*3117ece4Schristos /*============================================= 464*3117ece4Schristos * Unit tests 465*3117ece4Schristos =============================================*/ 466*3117ece4Schristos 467*3117ece4Schristos static void test_compressBound(unsigned tnb) 468*3117ece4Schristos { 469*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : compressBound : ", tnb); 470*3117ece4Schristos 471*3117ece4Schristos /* check ZSTD_compressBound == ZSTD_COMPRESSBOUND 472*3117ece4Schristos * for a large range of known valid values */ 473*3117ece4Schristos DEBUG_STATIC_ASSERT(sizeof(size_t) >= 4); 474*3117ece4Schristos { int s; 475*3117ece4Schristos for (s=0; s<30; s++) { 476*3117ece4Schristos size_t const w = (size_t)1 << s; 477*3117ece4Schristos CHECK_EQ(ZSTD_compressBound(w), ZSTD_COMPRESSBOUND(w)); 478*3117ece4Schristos } } 479*3117ece4Schristos 480*3117ece4Schristos /* Ensure error if srcSize too big */ 481*3117ece4Schristos { size_t const w = ZSTD_MAX_INPUT_SIZE + 1; 482*3117ece4Schristos CHECK(ZSTD_isError(ZSTD_compressBound(w))); /* must fail */ 483*3117ece4Schristos CHECK_EQ(ZSTD_COMPRESSBOUND(w), 0); 484*3117ece4Schristos } 485*3117ece4Schristos 486*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 487*3117ece4Schristos } 488*3117ece4Schristos 489*3117ece4Schristos static void test_decompressBound(unsigned tnb) 490*3117ece4Schristos { 491*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : decompressBound : ", tnb); 492*3117ece4Schristos 493*3117ece4Schristos /* Simple compression, with size : should provide size; */ 494*3117ece4Schristos { const char example[] = "abcd"; 495*3117ece4Schristos char cBuffer[ZSTD_COMPRESSBOUND(sizeof(example))]; 496*3117ece4Schristos size_t const cSize = ZSTD_compress(cBuffer, sizeof(cBuffer), example, sizeof(example), 0); 497*3117ece4Schristos CHECK_Z(cSize); 498*3117ece4Schristos CHECK_EQ(ZSTD_decompressBound(cBuffer, cSize), (unsigned long long)sizeof(example)); 499*3117ece4Schristos } 500*3117ece4Schristos 501*3117ece4Schristos /* Simple small compression without size : should provide 1 block size */ 502*3117ece4Schristos { char cBuffer[ZSTD_COMPRESSBOUND(0)]; 503*3117ece4Schristos ZSTD_outBuffer out = { cBuffer, sizeof(cBuffer), 0 }; 504*3117ece4Schristos ZSTD_inBuffer in = { NULL, 0, 0 }; 505*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 506*3117ece4Schristos assert(cctx); 507*3117ece4Schristos CHECK_Z( ZSTD_initCStream(cctx, 0) ); 508*3117ece4Schristos CHECK_Z( ZSTD_compressStream(cctx, &out, &in) ); 509*3117ece4Schristos CHECK_EQ( ZSTD_endStream(cctx, &out), 0 ); 510*3117ece4Schristos CHECK_EQ( ZSTD_decompressBound(cBuffer, out.pos), ZSTD_BLOCKSIZE_MAX ); 511*3117ece4Schristos ZSTD_freeCCtx(cctx); 512*3117ece4Schristos } 513*3117ece4Schristos 514*3117ece4Schristos /* Attempt to overflow 32-bit intermediate multiplication result 515*3117ece4Schristos * This requires dBound >= 4 GB, aka 2^32. 516*3117ece4Schristos * This requires 2^32 / 2^17 = 2^15 blocks 517*3117ece4Schristos * => create 2^15 blocks (can be empty, or just 1 byte). */ 518*3117ece4Schristos { const char input[] = "a"; 519*3117ece4Schristos size_t const nbBlocks = (1 << 15) + 1; 520*3117ece4Schristos size_t blockNb; 521*3117ece4Schristos size_t const outCapacity = 1 << 18; /* large margin */ 522*3117ece4Schristos char* const outBuffer = malloc (outCapacity); 523*3117ece4Schristos ZSTD_outBuffer out = { outBuffer, outCapacity, 0 }; 524*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 525*3117ece4Schristos assert(cctx); 526*3117ece4Schristos assert(outBuffer); 527*3117ece4Schristos CHECK_Z( ZSTD_initCStream(cctx, 0) ); 528*3117ece4Schristos for (blockNb=0; blockNb<nbBlocks; blockNb++) { 529*3117ece4Schristos ZSTD_inBuffer in = { input, sizeof(input), 0 }; 530*3117ece4Schristos CHECK_Z( ZSTD_compressStream(cctx, &out, &in) ); 531*3117ece4Schristos CHECK_EQ( ZSTD_flushStream(cctx, &out), 0 ); 532*3117ece4Schristos } 533*3117ece4Schristos CHECK_EQ( ZSTD_endStream(cctx, &out), 0 ); 534*3117ece4Schristos CHECK( ZSTD_decompressBound(outBuffer, out.pos) > 0x100000000ULL /* 4 GB */ ); 535*3117ece4Schristos ZSTD_freeCCtx(cctx); 536*3117ece4Schristos free(outBuffer); 537*3117ece4Schristos } 538*3117ece4Schristos 539*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 540*3117ece4Schristos } 541*3117ece4Schristos 542*3117ece4Schristos static void test_setCParams(unsigned tnb) 543*3117ece4Schristos { 544*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 545*3117ece4Schristos ZSTD_compressionParameters cparams; 546*3117ece4Schristos assert(cctx); 547*3117ece4Schristos 548*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : ZSTD_CCtx_setCParams : ", tnb); 549*3117ece4Schristos 550*3117ece4Schristos /* valid cparams */ 551*3117ece4Schristos cparams = ZSTD_getCParams(1, 0, 0); 552*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setCParams(cctx, cparams)); 553*3117ece4Schristos 554*3117ece4Schristos /* invalid cparams (must fail) */ 555*3117ece4Schristos cparams.windowLog = 99; 556*3117ece4Schristos CHECK(ZSTD_isError(ZSTD_CCtx_setCParams(cctx, cparams))); 557*3117ece4Schristos 558*3117ece4Schristos free(cctx); 559*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 560*3117ece4Schristos } 561*3117ece4Schristos 562*3117ece4Schristos static int basicUnitTests(U32 const seed, double compressibility) 563*3117ece4Schristos { 564*3117ece4Schristos size_t const CNBuffSize = 5 MB; 565*3117ece4Schristos void* const CNBuffer = malloc(CNBuffSize); 566*3117ece4Schristos size_t const compressedBufferSize = ZSTD_compressBound(CNBuffSize); 567*3117ece4Schristos void* const compressedBuffer = malloc(compressedBufferSize); 568*3117ece4Schristos void* const decodedBuffer = malloc(CNBuffSize); 569*3117ece4Schristos int testResult = 0; 570*3117ece4Schristos unsigned testNb=0; 571*3117ece4Schristos size_t cSize; 572*3117ece4Schristos 573*3117ece4Schristos /* Create compressible noise */ 574*3117ece4Schristos if (!CNBuffer || !compressedBuffer || !decodedBuffer) { 575*3117ece4Schristos DISPLAY("Not enough memory, aborting\n"); 576*3117ece4Schristos testResult = 1; 577*3117ece4Schristos goto _end; 578*3117ece4Schristos } 579*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed); 580*3117ece4Schristos 581*3117ece4Schristos /* Basic tests */ 582*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : ZSTD_getErrorName : ", testNb++); 583*3117ece4Schristos { const char* errorString = ZSTD_getErrorName(0); 584*3117ece4Schristos DISPLAYLEVEL(3, "OK : %s \n", errorString); 585*3117ece4Schristos } 586*3117ece4Schristos 587*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : ZSTD_getErrorName with wrong value : ", testNb++); 588*3117ece4Schristos { const char* errorString = ZSTD_getErrorName(499); 589*3117ece4Schristos DISPLAYLEVEL(3, "OK : %s \n", errorString); 590*3117ece4Schristos } 591*3117ece4Schristos 592*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : min compression level : ", testNb++); 593*3117ece4Schristos { int const mcl = ZSTD_minCLevel(); 594*3117ece4Schristos DISPLAYLEVEL(3, "%i (OK) \n", mcl); 595*3117ece4Schristos } 596*3117ece4Schristos 597*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : default compression level : ", testNb++); 598*3117ece4Schristos { int const defaultCLevel = ZSTD_defaultCLevel(); 599*3117ece4Schristos if (defaultCLevel != ZSTD_CLEVEL_DEFAULT) goto _output_error; 600*3117ece4Schristos DISPLAYLEVEL(3, "%i (OK) \n", defaultCLevel); 601*3117ece4Schristos } 602*3117ece4Schristos 603*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : ZSTD_versionNumber : ", testNb++); 604*3117ece4Schristos { unsigned const vn = ZSTD_versionNumber(); 605*3117ece4Schristos DISPLAYLEVEL(3, "%u (OK) \n", vn); 606*3117ece4Schristos } 607*3117ece4Schristos 608*3117ece4Schristos test_compressBound(testNb++); 609*3117ece4Schristos 610*3117ece4Schristos test_decompressBound(testNb++); 611*3117ece4Schristos 612*3117ece4Schristos test_setCParams(testNb++); 613*3117ece4Schristos 614*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : ZSTD_adjustCParams : ", testNb++); 615*3117ece4Schristos { 616*3117ece4Schristos ZSTD_compressionParameters params; 617*3117ece4Schristos memset(¶ms, 0, sizeof(params)); 618*3117ece4Schristos params.windowLog = 10; 619*3117ece4Schristos params.hashLog = 19; 620*3117ece4Schristos params.chainLog = 19; 621*3117ece4Schristos params = ZSTD_adjustCParams(params, 1000, 100000); 622*3117ece4Schristos if (params.hashLog != 18) goto _output_error; 623*3117ece4Schristos if (params.chainLog != 17) goto _output_error; 624*3117ece4Schristos } 625*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 626*3117ece4Schristos 627*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : compress %u bytes : ", testNb++, (unsigned)CNBuffSize); 628*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 629*3117ece4Schristos if (cctx==NULL) goto _output_error; 630*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressCCtx(cctx, 631*3117ece4Schristos compressedBuffer, compressedBufferSize, 632*3117ece4Schristos CNBuffer, CNBuffSize, 1) ); 633*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 634*3117ece4Schristos 635*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : size of cctx for level 1 : ", testNb++); 636*3117ece4Schristos { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx); 637*3117ece4Schristos DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cctxSize); 638*3117ece4Schristos } 639*3117ece4Schristos ZSTD_freeCCtx(cctx); 640*3117ece4Schristos } 641*3117ece4Schristos 642*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress skippable frame -8 size : ", testNb++); 643*3117ece4Schristos { 644*3117ece4Schristos char const skippable8[] = "\x50\x2a\x4d\x18\xf8\xff\xff\xff"; 645*3117ece4Schristos size_t const size = ZSTD_decompress(NULL, 0, skippable8, 8); 646*3117ece4Schristos if (!ZSTD_isError(size)) goto _output_error; 647*3117ece4Schristos } 648*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 649*3117ece4Schristos 650*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameContentSize test : ", testNb++); 651*3117ece4Schristos { unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize); 652*3117ece4Schristos if (rSize != CNBuffSize) goto _output_error; 653*3117ece4Schristos } 654*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 655*3117ece4Schristos 656*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_getDecompressedSize test : ", testNb++); 657*3117ece4Schristos { unsigned long long const rSize = ZSTD_getDecompressedSize(compressedBuffer, cSize); 658*3117ece4Schristos if (rSize != CNBuffSize) goto _output_error; 659*3117ece4Schristos } 660*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 661*3117ece4Schristos 662*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_findDecompressedSize test : ", testNb++); 663*3117ece4Schristos { unsigned long long const rSize = ZSTD_findDecompressedSize(compressedBuffer, cSize); 664*3117ece4Schristos if (rSize != CNBuffSize) goto _output_error; 665*3117ece4Schristos } 666*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 667*3117ece4Schristos 668*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : tight ZSTD_decompressBound test : ", testNb++); 669*3117ece4Schristos { 670*3117ece4Schristos unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize); 671*3117ece4Schristos if (bound != CNBuffSize) goto _output_error; 672*3117ece4Schristos } 673*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 674*3117ece4Schristos 675*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with invalid srcSize : ", testNb++); 676*3117ece4Schristos { 677*3117ece4Schristos unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize - 1); 678*3117ece4Schristos if (bound != ZSTD_CONTENTSIZE_ERROR) goto _output_error; 679*3117ece4Schristos } 680*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 681*3117ece4Schristos 682*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize); 683*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); 684*3117ece4Schristos if (r != CNBuffSize) goto _output_error; } 685*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 686*3117ece4Schristos 687*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress %u bytes with Huffman assembly disabled : ", testNb++, (unsigned)CNBuffSize); 688*3117ece4Schristos { 689*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 690*3117ece4Schristos size_t r; 691*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_disableHuffmanAssembly, 1)); 692*3117ece4Schristos r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); 693*3117ece4Schristos if (r != CNBuffSize || memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error; 694*3117ece4Schristos ZSTD_freeDCtx(dctx); 695*3117ece4Schristos } 696*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 697*3117ece4Schristos 698*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++); 699*3117ece4Schristos { size_t u; 700*3117ece4Schristos for (u=0; u<CNBuffSize; u++) { 701*3117ece4Schristos if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error; 702*3117ece4Schristos } } 703*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 704*3117ece4Schristos 705*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : invalid endDirective : ", testNb++); 706*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 707*3117ece4Schristos ZSTD_inBuffer inb = { CNBuffer, CNBuffSize, 0 }; 708*3117ece4Schristos ZSTD_outBuffer outb = { compressedBuffer, compressedBufferSize, 0 }; 709*3117ece4Schristos if (cctx==NULL) goto _output_error; 710*3117ece4Schristos CHECK( ZSTD_isError( ZSTD_compressStream2(cctx, &outb, &inb, (ZSTD_EndDirective) 3) ) ); /* must fail */ 711*3117ece4Schristos CHECK( ZSTD_isError( ZSTD_compressStream2(cctx, &outb, &inb, (ZSTD_EndDirective)-1) ) ); /* must fail */ 712*3117ece4Schristos ZSTD_freeCCtx(cctx); 713*3117ece4Schristos } 714*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 715*3117ece4Schristos 716*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_checkCParams : ", testNb++); 717*3117ece4Schristos { 718*3117ece4Schristos ZSTD_parameters params = ZSTD_getParams(3, 0, 0); 719*3117ece4Schristos assert(!ZSTD_checkCParams(params.cParams)); 720*3117ece4Schristos } 721*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 722*3117ece4Schristos 723*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_createDCtx_advanced and ZSTD_sizeof_DCtx: ", testNb++); 724*3117ece4Schristos { 725*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(ZSTD_defaultCMem); 726*3117ece4Schristos assert(dctx != NULL); 727*3117ece4Schristos assert(ZSTD_sizeof_DCtx(dctx) != 0); 728*3117ece4Schristos ZSTD_freeDCtx(dctx); 729*3117ece4Schristos } 730*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 731*3117ece4Schristos 732*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : misc unaccounted for zstd symbols : ", testNb++); 733*3117ece4Schristos { 734*3117ece4Schristos /* %p takes a void*. In ISO C, it's illegal to cast a function pointer 735*3117ece4Schristos * to a data pointer. (Although in POSIX you're required to be allowed 736*3117ece4Schristos * to do it...) So we have to fall back to our trusty friend memcpy. */ 737*3117ece4Schristos unsigned (* const funcptr_getDictID)(const ZSTD_DDict* ddict) = 738*3117ece4Schristos ZSTD_getDictID_fromDDict; 739*3117ece4Schristos ZSTD_DStream* (* const funcptr_createDStream)( 740*3117ece4Schristos ZSTD_customMem customMem) = ZSTD_createDStream_advanced; 741*3117ece4Schristos void (* const funcptr_copyDCtx)( 742*3117ece4Schristos ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx) = ZSTD_copyDCtx; 743*3117ece4Schristos ZSTD_nextInputType_e (* const funcptr_nextInputType)(ZSTD_DCtx* dctx) = 744*3117ece4Schristos ZSTD_nextInputType; 745*3117ece4Schristos const void *voidptr_getDictID; 746*3117ece4Schristos const void *voidptr_createDStream; 747*3117ece4Schristos const void *voidptr_copyDCtx; 748*3117ece4Schristos const void *voidptr_nextInputType; 749*3117ece4Schristos DEBUG_STATIC_ASSERT(sizeof(funcptr_getDictID) == sizeof(voidptr_getDictID)); 750*3117ece4Schristos memcpy( 751*3117ece4Schristos (void*)&voidptr_getDictID, 752*3117ece4Schristos (const void*)&funcptr_getDictID, 753*3117ece4Schristos sizeof(void*)); 754*3117ece4Schristos memcpy( 755*3117ece4Schristos (void*)&voidptr_createDStream, 756*3117ece4Schristos (const void*)&funcptr_createDStream, 757*3117ece4Schristos sizeof(void*)); 758*3117ece4Schristos memcpy( 759*3117ece4Schristos (void*)&voidptr_copyDCtx, 760*3117ece4Schristos (const void*)&funcptr_copyDCtx, 761*3117ece4Schristos sizeof(void*)); 762*3117ece4Schristos memcpy( 763*3117ece4Schristos (void*)&voidptr_nextInputType, 764*3117ece4Schristos (const void*)&funcptr_nextInputType, 765*3117ece4Schristos sizeof(void*)); 766*3117ece4Schristos DISPLAYLEVEL(3, "%p ", voidptr_getDictID); 767*3117ece4Schristos DISPLAYLEVEL(3, "%p ", voidptr_createDStream); 768*3117ece4Schristos DISPLAYLEVEL(3, "%p ", voidptr_copyDCtx); 769*3117ece4Schristos DISPLAYLEVEL(3, "%p ", voidptr_nextInputType); 770*3117ece4Schristos } 771*3117ece4Schristos DISPLAYLEVEL(3, ": OK \n"); 772*3117ece4Schristos 773*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress with null dict : ", testNb++); 774*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); 775*3117ece4Schristos { size_t const r = ZSTD_decompress_usingDict(dctx, 776*3117ece4Schristos decodedBuffer, CNBuffSize, 777*3117ece4Schristos compressedBuffer, cSize, 778*3117ece4Schristos NULL, 0); 779*3117ece4Schristos if (r != CNBuffSize) goto _output_error; 780*3117ece4Schristos } 781*3117ece4Schristos ZSTD_freeDCtx(dctx); 782*3117ece4Schristos } 783*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 784*3117ece4Schristos 785*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress with null DDict : ", testNb++); 786*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); 787*3117ece4Schristos { size_t const r = ZSTD_decompress_usingDDict(dctx, 788*3117ece4Schristos decodedBuffer, CNBuffSize, 789*3117ece4Schristos compressedBuffer, cSize, 790*3117ece4Schristos NULL); 791*3117ece4Schristos if (r != CNBuffSize) goto _output_error; 792*3117ece4Schristos } 793*3117ece4Schristos ZSTD_freeDCtx(dctx); 794*3117ece4Schristos } 795*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 796*3117ece4Schristos 797*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress with 1 missing byte : ", testNb++); 798*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize-1); 799*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 800*3117ece4Schristos if (ZSTD_getErrorCode((size_t)r) != ZSTD_error_srcSize_wrong) goto _output_error; } 801*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 802*3117ece4Schristos 803*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress with 1 too much byte : ", testNb++); 804*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize+1); 805*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 806*3117ece4Schristos if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; } 807*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 808*3117ece4Schristos 809*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress too large input : ", testNb++); 810*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, compressedBufferSize); 811*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 812*3117ece4Schristos if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; } 813*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 814*3117ece4Schristos 815*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress into NULL buffer : ", testNb++); 816*3117ece4Schristos { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, compressedBufferSize); 817*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 818*3117ece4Schristos if (ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall) goto _output_error; } 819*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 820*3117ece4Schristos 821*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress with corrupted checksum : ", testNb++); 822*3117ece4Schristos { /* create compressed buffer with checksumming enabled */ 823*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 824*3117ece4Schristos if (!cctx) { 825*3117ece4Schristos DISPLAY("Not enough memory, aborting\n"); 826*3117ece4Schristos testResult = 1; 827*3117ece4Schristos goto _end; 828*3117ece4Schristos } 829*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) ); 830*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compress2(cctx, 831*3117ece4Schristos compressedBuffer, compressedBufferSize, 832*3117ece4Schristos CNBuffer, CNBuffSize) ); 833*3117ece4Schristos ZSTD_freeCCtx(cctx); 834*3117ece4Schristos } 835*3117ece4Schristos { /* copy the compressed buffer and corrupt the checksum */ 836*3117ece4Schristos size_t r; 837*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 838*3117ece4Schristos if (!dctx) { 839*3117ece4Schristos DISPLAY("Not enough memory, aborting\n"); 840*3117ece4Schristos testResult = 1; 841*3117ece4Schristos goto _end; 842*3117ece4Schristos } 843*3117ece4Schristos 844*3117ece4Schristos ((char*)compressedBuffer)[cSize-1] += 1; 845*3117ece4Schristos r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); 846*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 847*3117ece4Schristos if (ZSTD_getErrorCode(r) != ZSTD_error_checksum_wrong) goto _output_error; 848*3117ece4Schristos 849*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_forceIgnoreChecksum, ZSTD_d_ignoreChecksum)); 850*3117ece4Schristos r = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize-1); 851*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; /* wrong checksum size should still throw error */ 852*3117ece4Schristos r = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); 853*3117ece4Schristos if (ZSTD_isError(r)) goto _output_error; 854*3117ece4Schristos 855*3117ece4Schristos ZSTD_freeDCtx(dctx); 856*3117ece4Schristos } 857*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 858*3117ece4Schristos 859*3117ece4Schristos 860*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with content size missing : ", testNb++); 861*3117ece4Schristos { /* create compressed buffer with content size missing */ 862*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 863*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0) ); 864*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compress2(cctx, 865*3117ece4Schristos compressedBuffer, compressedBufferSize, 866*3117ece4Schristos CNBuffer, CNBuffSize) ); 867*3117ece4Schristos ZSTD_freeCCtx(cctx); 868*3117ece4Schristos } 869*3117ece4Schristos { /* ensure frame content size is missing */ 870*3117ece4Schristos ZSTD_frameHeader zfh; 871*3117ece4Schristos size_t const ret = ZSTD_getFrameHeader(&zfh, compressedBuffer, compressedBufferSize); 872*3117ece4Schristos if (ret != 0 || zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error; 873*3117ece4Schristos } 874*3117ece4Schristos { /* ensure CNBuffSize <= decompressBound */ 875*3117ece4Schristos unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, compressedBufferSize); 876*3117ece4Schristos if (CNBuffSize > bound) goto _output_error; 877*3117ece4Schristos } 878*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 879*3117ece4Schristos 880*3117ece4Schristos DISPLAYLEVEL(3, "test%3d: check DCtx size is reduced after many oversized calls : ", testNb++); 881*3117ece4Schristos { 882*3117ece4Schristos size_t const largeFrameSrcSize = 200; 883*3117ece4Schristos size_t const smallFrameSrcSize = 10; 884*3117ece4Schristos size_t const nbFrames = 256; 885*3117ece4Schristos 886*3117ece4Schristos size_t i = 0, consumed = 0, produced = 0, prevDCtxSize = 0; 887*3117ece4Schristos int sizeReduced = 0; 888*3117ece4Schristos 889*3117ece4Schristos BYTE* const dst = (BYTE*)compressedBuffer; 890*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 891*3117ece4Schristos 892*3117ece4Schristos /* create a large frame and then a bunch of small frames */ 893*3117ece4Schristos size_t srcSize = ZSTD_compress((void*)dst, 894*3117ece4Schristos compressedBufferSize, CNBuffer, largeFrameSrcSize, 3); 895*3117ece4Schristos for (i = 0; i < nbFrames; i++) 896*3117ece4Schristos srcSize += ZSTD_compress((void*)(dst + srcSize), 897*3117ece4Schristos compressedBufferSize - srcSize, CNBuffer, 898*3117ece4Schristos smallFrameSrcSize, 3); 899*3117ece4Schristos 900*3117ece4Schristos /* decompressStream and make sure that dctx size was reduced at least once */ 901*3117ece4Schristos while (consumed < srcSize) { 902*3117ece4Schristos ZSTD_inBuffer in = {(void*)(dst + consumed), MIN(1, srcSize - consumed), 0}; 903*3117ece4Schristos ZSTD_outBuffer out = {(BYTE*)CNBuffer + produced, CNBuffSize - produced, 0}; 904*3117ece4Schristos ZSTD_decompressStream(dctx, &out, &in); 905*3117ece4Schristos consumed += in.pos; 906*3117ece4Schristos produced += out.pos; 907*3117ece4Schristos 908*3117ece4Schristos /* success! size was reduced from the previous frame */ 909*3117ece4Schristos if (prevDCtxSize > ZSTD_sizeof_DCtx(dctx)) 910*3117ece4Schristos sizeReduced = 1; 911*3117ece4Schristos 912*3117ece4Schristos prevDCtxSize = ZSTD_sizeof_DCtx(dctx); 913*3117ece4Schristos } 914*3117ece4Schristos 915*3117ece4Schristos assert(sizeReduced); 916*3117ece4Schristos 917*3117ece4Schristos ZSTD_freeDCtx(dctx); 918*3117ece4Schristos } 919*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 920*3117ece4Schristos 921*3117ece4Schristos { 922*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 923*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, 100, 1); 924*3117ece4Schristos ZSTD_parameters const params = ZSTD_getParams(1, 0, 0); 925*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) ); 926*3117ece4Schristos 927*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compressCCtx() doesn't use advanced parameters", testNb++); 928*3117ece4Schristos CHECK_Z(ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 1)); 929*3117ece4Schristos if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error; 930*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 931*3117ece4Schristos 932*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compress_usingDict() doesn't use advanced parameters: ", testNb++); 933*3117ece4Schristos CHECK_Z(ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize, NULL, 0, NULL, 0, 1)); 934*3117ece4Schristos if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error; 935*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 936*3117ece4Schristos 937*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compress_usingCDict() doesn't use advanced parameters: ", testNb++); 938*3117ece4Schristos CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, NULL, 0, cdict)); 939*3117ece4Schristos if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error; 940*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 941*3117ece4Schristos 942*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compress_advanced() doesn't use advanced parameters: ", testNb++); 943*3117ece4Schristos CHECK_Z(ZSTD_compress_advanced(cctx, compressedBuffer, compressedBufferSize, NULL, 0, NULL, 0, params)); 944*3117ece4Schristos if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error; 945*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 946*3117ece4Schristos 947*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compress_usingCDict_advanced() doesn't use advanced parameters: ", testNb++); 948*3117ece4Schristos CHECK_Z(ZSTD_compress_usingCDict_advanced(cctx, compressedBuffer, compressedBufferSize, NULL, 0, cdict, params.fParams)); 949*3117ece4Schristos if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error; 950*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 951*3117ece4Schristos 952*3117ece4Schristos ZSTD_freeCDict(cdict); 953*3117ece4Schristos ZSTD_freeCCtx(cctx); 954*3117ece4Schristos } 955*3117ece4Schristos 956*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : maxBlockSize = 2K", testNb++); 957*3117ece4Schristos { 958*3117ece4Schristos ZSTD_CCtx* cctx = ZSTD_createCCtx(); 959*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 960*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 961*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 2048)); 962*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 2048)); 963*3117ece4Schristos 964*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 965*3117ece4Schristos CHECK_Z(cSize); 966*3117ece4Schristos CHECK_Z(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize)); 967*3117ece4Schristos 968*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 1024)); 969*3117ece4Schristos CHECK(ZSTD_isError(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize))); 970*3117ece4Schristos 971*3117ece4Schristos ZSTD_freeDCtx(dctx); 972*3117ece4Schristos ZSTD_freeCCtx(cctx); 973*3117ece4Schristos } 974*3117ece4Schristos 975*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ldm fill dict out-of-bounds check", testNb++); 976*3117ece4Schristos { 977*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 978*3117ece4Schristos 979*3117ece4Schristos size_t const size = (1U << 10); 980*3117ece4Schristos size_t const dstCapacity = ZSTD_compressBound(size); 981*3117ece4Schristos void* dict = (void*)malloc(size); 982*3117ece4Schristos void* src = (void*)malloc(size); 983*3117ece4Schristos void* dst = (void*)malloc(dstCapacity); 984*3117ece4Schristos 985*3117ece4Schristos RDG_genBuffer(dict, size, 0.5, 0.5, seed); 986*3117ece4Schristos RDG_genBuffer(src, size, 0.5, 0.5, seed); 987*3117ece4Schristos 988*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)); 989*3117ece4Schristos assert(!ZSTD_isError(ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, size, dict, size, 3))); 990*3117ece4Schristos 991*3117ece4Schristos ZSTD_freeCCtx(cctx); 992*3117ece4Schristos free(dict); 993*3117ece4Schristos free(src); 994*3117ece4Schristos free(dst); 995*3117ece4Schristos } 996*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 997*3117ece4Schristos 998*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing dict compression with enableLdm and forceMaxWindow : ", testNb++); 999*3117ece4Schristos { 1000*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1001*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 1002*3117ece4Schristos void* dict = (void*)malloc(CNBuffSize); 1003*3117ece4Schristos int nbWorkers; 1004*3117ece4Schristos 1005*3117ece4Schristos for (nbWorkers = 0; nbWorkers < 3; ++nbWorkers) { 1006*3117ece4Schristos RDG_genBuffer(dict, CNBuffSize, 0.5, 0.5, seed); 1007*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, 0.6, 0.6, seed); 1008*3117ece4Schristos 1009*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbWorkers)); 1010*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 1011*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceMaxWindow, 1)); 1012*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)); 1013*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, CNBuffSize)); 1014*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 1015*3117ece4Schristos CHECK_Z(cSize); 1016*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, CNBuffSize)); 1017*3117ece4Schristos } 1018*3117ece4Schristos 1019*3117ece4Schristos ZSTD_freeCCtx(cctx); 1020*3117ece4Schristos ZSTD_freeDCtx(dctx); 1021*3117ece4Schristos free(dict); 1022*3117ece4Schristos } 1023*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1024*3117ece4Schristos 1025*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing dict compression for determinism : ", testNb++); 1026*3117ece4Schristos { 1027*3117ece4Schristos size_t const testSize = 1024; 1028*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1029*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 1030*3117ece4Schristos char* dict = (char*)malloc(2 * testSize); 1031*3117ece4Schristos int ldmEnabled, level; 1032*3117ece4Schristos 1033*3117ece4Schristos RDG_genBuffer(dict, testSize, 0.5, 0.5, seed); 1034*3117ece4Schristos RDG_genBuffer(CNBuffer, testSize, 0.6, 0.6, seed); 1035*3117ece4Schristos memcpy(dict + testSize, CNBuffer, testSize); 1036*3117ece4Schristos for (level = 1; level <= 5; ++level) { 1037*3117ece4Schristos for (ldmEnabled = ZSTD_ps_enable; ldmEnabled <= ZSTD_ps_disable; ++ldmEnabled) { 1038*3117ece4Schristos size_t cSize0; 1039*3117ece4Schristos XXH64_hash_t compressedChecksum0; 1040*3117ece4Schristos 1041*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 1042*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, level)); 1043*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ldmEnabled)); 1044*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_deterministicRefPrefix, 1)); 1045*3117ece4Schristos 1046*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, testSize)); 1047*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, testSize); 1048*3117ece4Schristos CHECK_Z(cSize); 1049*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, testSize, compressedBuffer, cSize, dict, testSize)); 1050*3117ece4Schristos 1051*3117ece4Schristos cSize0 = cSize; 1052*3117ece4Schristos compressedChecksum0 = XXH64(compressedBuffer, cSize, 0); 1053*3117ece4Schristos 1054*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, testSize)); 1055*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, dict + testSize, testSize); 1056*3117ece4Schristos CHECK_Z(cSize); 1057*3117ece4Schristos 1058*3117ece4Schristos if (cSize != cSize0) goto _output_error; 1059*3117ece4Schristos if (XXH64(compressedBuffer, cSize, 0) != compressedChecksum0) goto _output_error; 1060*3117ece4Schristos } 1061*3117ece4Schristos } 1062*3117ece4Schristos 1063*3117ece4Schristos ZSTD_freeCCtx(cctx); 1064*3117ece4Schristos ZSTD_freeDCtx(dctx); 1065*3117ece4Schristos free(dict); 1066*3117ece4Schristos } 1067*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1068*3117ece4Schristos 1069*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : LDM + opt parser with small uncompressible block ", testNb++); 1070*3117ece4Schristos { ZSTD_CCtx* cctx = ZSTD_createCCtx(); 1071*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 1072*3117ece4Schristos size_t const srcSize = 300 KB; 1073*3117ece4Schristos size_t const flushSize = 128 KB + 5; 1074*3117ece4Schristos size_t const dstSize = ZSTD_compressBound(srcSize); 1075*3117ece4Schristos char* src = (char*)CNBuffer; 1076*3117ece4Schristos char* dst = (char*)compressedBuffer; 1077*3117ece4Schristos 1078*3117ece4Schristos ZSTD_outBuffer out = { dst, dstSize, 0 }; 1079*3117ece4Schristos ZSTD_inBuffer in = { src, flushSize, 0 }; 1080*3117ece4Schristos 1081*3117ece4Schristos if (!cctx || !dctx) { 1082*3117ece4Schristos DISPLAY("Not enough memory, aborting\n"); 1083*3117ece4Schristos testResult = 1; 1084*3117ece4Schristos goto _end; 1085*3117ece4Schristos } 1086*3117ece4Schristos 1087*3117ece4Schristos RDG_genBuffer(src, srcSize, 0.5, 0.5, seed); 1088*3117ece4Schristos /* Force an LDM to exist that crosses block boundary into uncompressible block */ 1089*3117ece4Schristos memcpy(src + 125 KB, src, 3 KB + 5); 1090*3117ece4Schristos 1091*3117ece4Schristos /* Enable MT, LDM, and opt parser */ 1092*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1)); 1093*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)); 1094*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 1095*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19)); 1096*3117ece4Schristos 1097*3117ece4Schristos /* Flushes a block of 128 KB and block of 5 bytes */ 1098*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)); 1099*3117ece4Schristos 1100*3117ece4Schristos /* Compress the rest */ 1101*3117ece4Schristos in.size = 300 KB; 1102*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 1103*3117ece4Schristos 1104*3117ece4Schristos CHECK_Z(ZSTD_decompress(decodedBuffer, CNBuffSize, dst, out.pos)); 1105*3117ece4Schristos 1106*3117ece4Schristos ZSTD_freeCCtx(cctx); 1107*3117ece4Schristos ZSTD_freeDCtx(dctx); 1108*3117ece4Schristos } 1109*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1110*3117ece4Schristos 1111*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing ldm dictionary gets invalidated : ", testNb++); 1112*3117ece4Schristos { 1113*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1114*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 1115*3117ece4Schristos void* dict = (void*)malloc(CNBuffSize); 1116*3117ece4Schristos size_t const kWindowLog = 10; 1117*3117ece4Schristos size_t const kWindowSize = (size_t)1 << kWindowLog; 1118*3117ece4Schristos size_t const dictSize = kWindowSize * 10; 1119*3117ece4Schristos size_t const srcSize1 = kWindowSize / 2; 1120*3117ece4Schristos size_t const srcSize2 = kWindowSize * 10; 1121*3117ece4Schristos 1122*3117ece4Schristos CHECK(cctx!=NULL); 1123*3117ece4Schristos CHECK(dctx!=NULL); 1124*3117ece4Schristos CHECK(dict!=NULL); 1125*3117ece4Schristos if (CNBuffSize < dictSize) goto _output_error; 1126*3117ece4Schristos 1127*3117ece4Schristos RDG_genBuffer(dict, dictSize, 0.5, 0.5, seed); 1128*3117ece4Schristos RDG_genBuffer(CNBuffer, srcSize1 + srcSize2, 0.5, 0.5, seed); 1129*3117ece4Schristos 1130*3117ece4Schristos /* Enable checksum to verify round trip. */ 1131*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 1132*3117ece4Schristos /* Disable content size to skip single-pass decompression. */ 1133*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0)); 1134*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)kWindowLog)); 1135*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)); 1136*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmMinMatch, 32)); 1137*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashRateLog, 1)); 1138*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashLog, 16)); 1139*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmBucketSizeLog, 3)); 1140*3117ece4Schristos 1141*3117ece4Schristos /* Round trip once with a dictionary. */ 1142*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize)); 1143*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize1); 1144*3117ece4Schristos CHECK_Z(cSize); 1145*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize)); 1146*3117ece4Schristos 1147*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize2); 1148*3117ece4Schristos /* Streaming decompression to catch out of bounds offsets. */ 1149*3117ece4Schristos { 1150*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1151*3117ece4Schristos ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0}; 1152*3117ece4Schristos size_t const dSize = ZSTD_decompressStream(dctx, &out, &in); 1153*3117ece4Schristos CHECK_Z(dSize); 1154*3117ece4Schristos if (dSize != 0) goto _output_error; 1155*3117ece4Schristos } 1156*3117ece4Schristos 1157*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2)); 1158*3117ece4Schristos /* Round trip once with a dictionary. */ 1159*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize)); 1160*3117ece4Schristos { ZSTD_inBuffer in = {CNBuffer, srcSize1, 0}; 1161*3117ece4Schristos ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0}; 1162*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)); 1163*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 1164*3117ece4Schristos cSize = out.pos; 1165*3117ece4Schristos } 1166*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize)); 1167*3117ece4Schristos 1168*3117ece4Schristos { ZSTD_inBuffer in = {CNBuffer, srcSize2, 0}; 1169*3117ece4Schristos ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0}; 1170*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)); 1171*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 1172*3117ece4Schristos cSize = out.pos; 1173*3117ece4Schristos } 1174*3117ece4Schristos /* Streaming decompression to catch out of bounds offsets. */ 1175*3117ece4Schristos { ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 1176*3117ece4Schristos ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0}; 1177*3117ece4Schristos size_t const dSize = ZSTD_decompressStream(dctx, &out, &in); 1178*3117ece4Schristos CHECK_Z(dSize); 1179*3117ece4Schristos if (dSize != 0) goto _output_error; 1180*3117ece4Schristos } 1181*3117ece4Schristos 1182*3117ece4Schristos ZSTD_freeCCtx(cctx); 1183*3117ece4Schristos ZSTD_freeDCtx(dctx); 1184*3117ece4Schristos free(dict); 1185*3117ece4Schristos } 1186*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1187*3117ece4Schristos 1188*3117ece4Schristos /* Note: this test takes 0.5 seconds to run */ 1189*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing refPrefx vs refPrefx + ldm (size comparison) : ", testNb++); 1190*3117ece4Schristos { 1191*3117ece4Schristos /* test a big buffer so that ldm can take effect */ 1192*3117ece4Schristos size_t const size = 100 MB; 1193*3117ece4Schristos int const windowLog = 27; 1194*3117ece4Schristos size_t const dstSize = ZSTD_compressBound(size); 1195*3117ece4Schristos 1196*3117ece4Schristos void* dict = (void*)malloc(size); 1197*3117ece4Schristos void* src = (void*)malloc(size); 1198*3117ece4Schristos void* dst = (void*)malloc(dstSize); 1199*3117ece4Schristos void* recon = (void*)malloc(size); 1200*3117ece4Schristos 1201*3117ece4Schristos size_t refPrefixCompressedSize = 0; 1202*3117ece4Schristos size_t refPrefixLdmCompressedSize = 0; 1203*3117ece4Schristos size_t reconSize = 0; 1204*3117ece4Schristos 1205*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1206*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 1207*3117ece4Schristos 1208*3117ece4Schristos /* make dict and src the same uncompressible data */ 1209*3117ece4Schristos RDG_genBuffer(src, size, 0, 0, seed); 1210*3117ece4Schristos memcpy(dict, src, size); 1211*3117ece4Schristos assert(!memcmp(dict, src, size)); 1212*3117ece4Schristos 1213*3117ece4Schristos /* set level 1 and windowLog to cover src */ 1214*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1)); 1215*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, windowLog)); 1216*3117ece4Schristos 1217*3117ece4Schristos /* compress on level 1 using just refPrefix and no ldm */ 1218*3117ece4Schristos ZSTD_CCtx_refPrefix(cctx, dict, size); 1219*3117ece4Schristos refPrefixCompressedSize = ZSTD_compress2(cctx, dst, dstSize, src, size); 1220*3117ece4Schristos assert(!ZSTD_isError(refPrefixCompressedSize)); 1221*3117ece4Schristos 1222*3117ece4Schristos /* test round trip just refPrefix */ 1223*3117ece4Schristos ZSTD_DCtx_refPrefix(dctx, dict, size); 1224*3117ece4Schristos reconSize = ZSTD_decompressDCtx(dctx, recon, size, dst, refPrefixCompressedSize); 1225*3117ece4Schristos assert(!ZSTD_isError(reconSize)); 1226*3117ece4Schristos assert(reconSize == size); 1227*3117ece4Schristos assert(!memcmp(recon, src, size)); 1228*3117ece4Schristos 1229*3117ece4Schristos /* compress on level 1 using refPrefix and ldm */ 1230*3117ece4Schristos ZSTD_CCtx_refPrefix(cctx, dict, size);; 1231*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)) 1232*3117ece4Schristos refPrefixLdmCompressedSize = ZSTD_compress2(cctx, dst, dstSize, src, size); 1233*3117ece4Schristos assert(!ZSTD_isError(refPrefixLdmCompressedSize)); 1234*3117ece4Schristos 1235*3117ece4Schristos /* test round trip refPrefix + ldm*/ 1236*3117ece4Schristos ZSTD_DCtx_refPrefix(dctx, dict, size); 1237*3117ece4Schristos reconSize = ZSTD_decompressDCtx(dctx, recon, size, dst, refPrefixLdmCompressedSize); 1238*3117ece4Schristos assert(!ZSTD_isError(reconSize)); 1239*3117ece4Schristos assert(reconSize == size); 1240*3117ece4Schristos assert(!memcmp(recon, src, size)); 1241*3117ece4Schristos 1242*3117ece4Schristos /* make sure that refPrefixCompressedSize is significantly greater */ 1243*3117ece4Schristos assert(refPrefixCompressedSize > 10 * refPrefixLdmCompressedSize); 1244*3117ece4Schristos /* make sure the ldm compressed size is less than 1% of original */ 1245*3117ece4Schristos assert((double)refPrefixLdmCompressedSize / (double)size < 0.01); 1246*3117ece4Schristos 1247*3117ece4Schristos ZSTD_freeDCtx(dctx); 1248*3117ece4Schristos ZSTD_freeCCtx(cctx); 1249*3117ece4Schristos free(recon); 1250*3117ece4Schristos free(dict); 1251*3117ece4Schristos free(src); 1252*3117ece4Schristos free(dst); 1253*3117ece4Schristos } 1254*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1255*3117ece4Schristos 1256*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : in-place decompression : ", testNb++); 1257*3117ece4Schristos cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, -ZSTD_BLOCKSIZE_MAX); 1258*3117ece4Schristos CHECK_Z(cSize); 1259*3117ece4Schristos CHECK_LT(CNBuffSize, cSize); 1260*3117ece4Schristos { 1261*3117ece4Schristos size_t const margin = ZSTD_decompressionMargin(compressedBuffer, cSize); 1262*3117ece4Schristos size_t const outputSize = (CNBuffSize + margin); 1263*3117ece4Schristos char* output = malloc(outputSize); 1264*3117ece4Schristos char* input = output + outputSize - cSize; 1265*3117ece4Schristos CHECK_LT(cSize, CNBuffSize + margin); 1266*3117ece4Schristos CHECK(output != NULL); 1267*3117ece4Schristos CHECK_Z(margin); 1268*3117ece4Schristos CHECK(margin <= ZSTD_DECOMPRESSION_MARGIN(CNBuffSize, ZSTD_BLOCKSIZE_MAX)); 1269*3117ece4Schristos memcpy(input, compressedBuffer, cSize); 1270*3117ece4Schristos 1271*3117ece4Schristos { 1272*3117ece4Schristos size_t const dSize = ZSTD_decompress(output, outputSize, input, cSize); 1273*3117ece4Schristos CHECK_Z(dSize); 1274*3117ece4Schristos CHECK_EQ(dSize, CNBuffSize); 1275*3117ece4Schristos } 1276*3117ece4Schristos CHECK(!memcmp(output, CNBuffer, CNBuffSize)); 1277*3117ece4Schristos free(output); 1278*3117ece4Schristos } 1279*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1280*3117ece4Schristos 1281*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : in-place decompression with 2 frames : ", testNb++); 1282*3117ece4Schristos cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize / 3, -ZSTD_BLOCKSIZE_MAX); 1283*3117ece4Schristos CHECK_Z(cSize); 1284*3117ece4Schristos { 1285*3117ece4Schristos size_t const cSize2 = ZSTD_compress((char*)compressedBuffer + cSize, compressedBufferSize - cSize, (char const*)CNBuffer + (CNBuffSize / 3), CNBuffSize / 3, -ZSTD_BLOCKSIZE_MAX); 1286*3117ece4Schristos CHECK_Z(cSize2); 1287*3117ece4Schristos cSize += cSize2; 1288*3117ece4Schristos } 1289*3117ece4Schristos { 1290*3117ece4Schristos size_t const srcSize = (CNBuffSize / 3) * 2; 1291*3117ece4Schristos size_t const margin = ZSTD_decompressionMargin(compressedBuffer, cSize); 1292*3117ece4Schristos size_t const outputSize = (CNBuffSize + margin); 1293*3117ece4Schristos char* output = malloc(outputSize); 1294*3117ece4Schristos char* input = output + outputSize - cSize; 1295*3117ece4Schristos CHECK_LT(cSize, CNBuffSize + margin); 1296*3117ece4Schristos CHECK(output != NULL); 1297*3117ece4Schristos CHECK_Z(margin); 1298*3117ece4Schristos memcpy(input, compressedBuffer, cSize); 1299*3117ece4Schristos 1300*3117ece4Schristos { 1301*3117ece4Schristos size_t const dSize = ZSTD_decompress(output, outputSize, input, cSize); 1302*3117ece4Schristos CHECK_Z(dSize); 1303*3117ece4Schristos CHECK_EQ(dSize, srcSize); 1304*3117ece4Schristos } 1305*3117ece4Schristos CHECK(!memcmp(output, CNBuffer, srcSize)); 1306*3117ece4Schristos free(output); 1307*3117ece4Schristos } 1308*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1309*3117ece4Schristos 1310*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Check block splitter with 64K literal length : ", testNb++); 1311*3117ece4Schristos { ZSTD_CCtx* cctx = ZSTD_createCCtx(); 1312*3117ece4Schristos size_t const srcSize = 256 * 1024; 1313*3117ece4Schristos U32 const compressibleLenU32 = 32 * 1024 / 4; 1314*3117ece4Schristos U32 const blockSizeU32 = 128 * 1024 / 4; 1315*3117ece4Schristos U32 const litLenU32 = 64 * 1024 / 4; 1316*3117ece4Schristos U32* data = (U32*)malloc(srcSize); 1317*3117ece4Schristos size_t dSize; 1318*3117ece4Schristos 1319*3117ece4Schristos if (data == NULL || cctx == NULL) goto _output_error; 1320*3117ece4Schristos 1321*3117ece4Schristos /* Generate data without any matches */ 1322*3117ece4Schristos RDG_genBuffer(data, srcSize, 0.0, 0.01, 2654435761U); 1323*3117ece4Schristos /* Generate 32K of compressible data */ 1324*3117ece4Schristos RDG_genBuffer(data, compressibleLenU32 * 4, 0.5, 0.5, 0xcafebabe); 1325*3117ece4Schristos 1326*3117ece4Schristos /* Add a match of offset=12, length=8 at idx=16, 32, 48, 64 */ 1327*3117ece4Schristos data[compressibleLenU32 + 0] = 0xFFFFFFFF; 1328*3117ece4Schristos data[compressibleLenU32 + 1] = 0xEEEEEEEE; 1329*3117ece4Schristos data[compressibleLenU32 + 4] = 0xFFFFFFFF; 1330*3117ece4Schristos data[compressibleLenU32 + 5] = 0xEEEEEEEE; 1331*3117ece4Schristos 1332*3117ece4Schristos /* Add a match of offset=16, length=8 at idx=64K + 64. 1333*3117ece4Schristos * This generates a sequence with llen=64K, and repeat code 1. 1334*3117ece4Schristos * The block splitter thought this was ll0, and corrupted the 1335*3117ece4Schristos * repeat offset history. 1336*3117ece4Schristos */ 1337*3117ece4Schristos data[compressibleLenU32 + litLenU32 + 2 + 0] = 0xDDDDDDDD; 1338*3117ece4Schristos data[compressibleLenU32 + litLenU32 + 2 + 1] = 0xCCCCCCCC; 1339*3117ece4Schristos data[compressibleLenU32 + litLenU32 + 2 + 4] = 0xDDDDDDDD; 1340*3117ece4Schristos data[compressibleLenU32 + litLenU32 + 2 + 5] = 0xCCCCCCCC; 1341*3117ece4Schristos 1342*3117ece4Schristos /* Add a match of offset=16, length=8 at idx=128K + 16. 1343*3117ece4Schristos * This should generate a sequence with repeat code = 1. 1344*3117ece4Schristos * But the block splitters mistake caused zstd to generate 1345*3117ece4Schristos * repeat code = 2, corrupting the data. 1346*3117ece4Schristos */ 1347*3117ece4Schristos data[blockSizeU32] = 0xBBBBBBBB; 1348*3117ece4Schristos data[blockSizeU32 + 1] = 0xAAAAAAAA; 1349*3117ece4Schristos data[blockSizeU32 + 4] = 0xBBBBBBBB; 1350*3117ece4Schristos data[blockSizeU32 + 5] = 0xAAAAAAAA; 1351*3117ece4Schristos 1352*3117ece4Schristos /* Generate a golden file from this data in case datagen changes and 1353*3117ece4Schristos * doesn't generate the exact same data. We will also test this golden file. 1354*3117ece4Schristos */ 1355*3117ece4Schristos if (0) { 1356*3117ece4Schristos FILE* f = fopen("golden-compression/PR-3517-block-splitter-corruption-test", "wb"); 1357*3117ece4Schristos fwrite(data, 1, srcSize, f); 1358*3117ece4Schristos fclose(f); 1359*3117ece4Schristos } 1360*3117ece4Schristos 1361*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19)); 1362*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 7)); 1363*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_useBlockSplitter, ZSTD_ps_enable)); 1364*3117ece4Schristos 1365*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, data, srcSize); 1366*3117ece4Schristos CHECK_Z(cSize); 1367*3117ece4Schristos dSize = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); 1368*3117ece4Schristos CHECK_Z(dSize); 1369*3117ece4Schristos CHECK_EQ(dSize, srcSize); 1370*3117ece4Schristos CHECK(!memcmp(decodedBuffer, data, srcSize)); 1371*3117ece4Schristos 1372*3117ece4Schristos free(data); 1373*3117ece4Schristos ZSTD_freeCCtx(cctx); 1374*3117ece4Schristos } 1375*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1376*3117ece4Schristos 1377*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : superblock uncompressible data: too many nocompress superblocks : ", testNb++); 1378*3117ece4Schristos { 1379*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1380*3117ece4Schristos const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer; 1381*3117ece4Schristos size_t srcSize = 321656; size_t dstCapacity = ZSTD_compressBound(srcSize); 1382*3117ece4Schristos 1383*3117ece4Schristos /* This is the number of bytes to stream before ending. This value 1384*3117ece4Schristos * was obtained by trial and error :/. */ 1385*3117ece4Schristos 1386*3117ece4Schristos const size_t streamCompressThreshold = 161792; 1387*3117ece4Schristos const size_t streamCompressDelta = 1024; 1388*3117ece4Schristos 1389*3117ece4Schristos /* The first 1/5 of the buffer is compressible and the last 4/5 is 1390*3117ece4Schristos * uncompressible. This is an approximation of the type of data 1391*3117ece4Schristos * the fuzzer generated to catch this bug. Streams like this were making 1392*3117ece4Schristos * zstd generate noCompress superblocks (which are larger than the src 1393*3117ece4Schristos * they come from). Do this enough times, and we'll run out of room 1394*3117ece4Schristos * and throw a dstSize_tooSmall error. */ 1395*3117ece4Schristos 1396*3117ece4Schristos const size_t compressiblePartSize = srcSize/5; 1397*3117ece4Schristos const size_t uncompressiblePartSize = srcSize-compressiblePartSize; 1398*3117ece4Schristos RDG_genBuffer(CNBuffer, compressiblePartSize, 0.5, 0.5, seed); 1399*3117ece4Schristos RDG_genBuffer((BYTE*)CNBuffer+compressiblePartSize, uncompressiblePartSize, 0, 0, seed); 1400*3117ece4Schristos 1401*3117ece4Schristos /* Setting target block size so that superblock is used */ 1402*3117ece4Schristos 1403*3117ece4Schristos assert(cctx != NULL); 1404*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 81); 1405*3117ece4Schristos 1406*3117ece4Schristos { size_t read; 1407*3117ece4Schristos for (read = 0; read < streamCompressThreshold; read += streamCompressDelta) { 1408*3117ece4Schristos ZSTD_inBuffer in = {src, streamCompressDelta, 0}; 1409*3117ece4Schristos ZSTD_outBuffer out = {dst, dstCapacity, 0}; 1410*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue)); 1411*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 1412*3117ece4Schristos src += streamCompressDelta; srcSize -= streamCompressDelta; 1413*3117ece4Schristos dst += out.pos; dstCapacity -= out.pos; 1414*3117ece4Schristos } } 1415*3117ece4Schristos 1416*3117ece4Schristos /* This is trying to catch a dstSize_tooSmall error */ 1417*3117ece4Schristos 1418*3117ece4Schristos { ZSTD_inBuffer in = {src, srcSize, 0}; 1419*3117ece4Schristos ZSTD_outBuffer out = {dst, dstCapacity, 0}; 1420*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 1421*3117ece4Schristos } 1422*3117ece4Schristos ZSTD_freeCCtx(cctx); 1423*3117ece4Schristos } 1424*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1425*3117ece4Schristos 1426*3117ece4Schristos DISPLAYLEVEL(3, "test%3d: superblock with no literals : ", testNb++); 1427*3117ece4Schristos /* Generate the same data 20 times over */ 1428*3117ece4Schristos { size_t const avgChunkSize = CNBuffSize / 20; 1429*3117ece4Schristos size_t b; 1430*3117ece4Schristos for (b = 0; b < CNBuffSize; b += avgChunkSize) { 1431*3117ece4Schristos size_t const chunkSize = MIN(CNBuffSize - b, avgChunkSize); 1432*3117ece4Schristos RDG_genBuffer((char*)CNBuffer + b, chunkSize, compressibility, 0. /* auto */, seed); 1433*3117ece4Schristos } } 1434*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1435*3117ece4Schristos size_t const normalCSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 1436*3117ece4Schristos size_t const allowedExpansion = (CNBuffSize * 3 / 1000); 1437*3117ece4Schristos size_t superCSize; 1438*3117ece4Schristos CHECK_Z(normalCSize); 1439*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19); 1440*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 1000); 1441*3117ece4Schristos superCSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 1442*3117ece4Schristos CHECK_Z(superCSize); 1443*3117ece4Schristos if (superCSize > normalCSize + allowedExpansion) { 1444*3117ece4Schristos DISPLAYLEVEL(1, "Superblock too big: %u > %u + %u \n", (U32)superCSize, (U32)normalCSize, (U32)allowedExpansion); 1445*3117ece4Schristos goto _output_error; 1446*3117ece4Schristos } 1447*3117ece4Schristos ZSTD_freeCCtx(cctx); 1448*3117ece4Schristos } 1449*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1450*3117ece4Schristos 1451*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0. /*auto*/, seed); 1452*3117ece4Schristos DISPLAYLEVEL(3, "test%3d: superblock enough room for checksum : ", testNb++) 1453*3117ece4Schristos /* This tests whether or not we leave enough room for the checksum at the end 1454*3117ece4Schristos * of the dst buffer. The bug that motivated this test was found by the 1455*3117ece4Schristos * stream_round_trip fuzzer but this crashes for the same reason and is 1456*3117ece4Schristos * far more compact than re-creating the stream_round_trip fuzzer's code path */ 1457*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1458*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 64); 1459*3117ece4Schristos assert(!ZSTD_isError(ZSTD_compress2(cctx, compressedBuffer, 1339, CNBuffer, 1278))); 1460*3117ece4Schristos ZSTD_freeCCtx(cctx); 1461*3117ece4Schristos } 1462*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1463*3117ece4Schristos 1464*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress a NULL input with each level : ", testNb++); 1465*3117ece4Schristos { int level = -1; 1466*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1467*3117ece4Schristos if (!cctx) goto _output_error; 1468*3117ece4Schristos for (level = -1; level <= ZSTD_maxCLevel(); ++level) { 1469*3117ece4Schristos CHECK_Z( ZSTD_compress(compressedBuffer, compressedBufferSize, NULL, 0, level) ); 1470*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, level) ); 1471*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, NULL, 0) ); 1472*3117ece4Schristos } 1473*3117ece4Schristos ZSTD_freeCCtx(cctx); 1474*3117ece4Schristos } 1475*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1476*3117ece4Schristos 1477*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : check CCtx size after compressing empty input : ", testNb++); 1478*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1479*3117ece4Schristos size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19); 1480*3117ece4Schristos if (ZSTD_isError(r)) goto _output_error; 1481*3117ece4Schristos if (ZSTD_sizeof_CCtx(cctx) > (1U << 20)) goto _output_error; 1482*3117ece4Schristos ZSTD_freeCCtx(cctx); 1483*3117ece4Schristos cSize = r; 1484*3117ece4Schristos } 1485*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1486*3117ece4Schristos 1487*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : decompress empty frame into NULL : ", testNb++); 1488*3117ece4Schristos { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, cSize); 1489*3117ece4Schristos if (ZSTD_isError(r)) goto _output_error; 1490*3117ece4Schristos if (r != 0) goto _output_error; 1491*3117ece4Schristos } 1492*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1493*3117ece4Schristos ZSTD_outBuffer output; 1494*3117ece4Schristos if (cctx==NULL) goto _output_error; 1495*3117ece4Schristos output.dst = compressedBuffer; 1496*3117ece4Schristos output.size = compressedBufferSize; 1497*3117ece4Schristos output.pos = 0; 1498*3117ece4Schristos CHECK_Z( ZSTD_initCStream(cctx, 1) ); /* content size unknown */ 1499*3117ece4Schristos CHECK_Z( ZSTD_flushStream(cctx, &output) ); /* ensure no possibility to "concatenate" and determine the content size */ 1500*3117ece4Schristos CHECK_Z( ZSTD_endStream(cctx, &output) ); 1501*3117ece4Schristos ZSTD_freeCCtx(cctx); 1502*3117ece4Schristos /* single scan decompression */ 1503*3117ece4Schristos { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, output.pos); 1504*3117ece4Schristos if (ZSTD_isError(r)) goto _output_error; 1505*3117ece4Schristos if (r != 0) goto _output_error; 1506*3117ece4Schristos } 1507*3117ece4Schristos /* streaming decompression */ 1508*3117ece4Schristos { ZSTD_DCtx* const dstream = ZSTD_createDStream(); 1509*3117ece4Schristos ZSTD_inBuffer dinput; 1510*3117ece4Schristos ZSTD_outBuffer doutput; 1511*3117ece4Schristos size_t ipos; 1512*3117ece4Schristos if (dstream==NULL) goto _output_error; 1513*3117ece4Schristos dinput.src = compressedBuffer; 1514*3117ece4Schristos dinput.size = 0; 1515*3117ece4Schristos dinput.pos = 0; 1516*3117ece4Schristos doutput.dst = NULL; 1517*3117ece4Schristos doutput.size = 0; 1518*3117ece4Schristos doutput.pos = 0; 1519*3117ece4Schristos CHECK_Z ( ZSTD_initDStream(dstream) ); 1520*3117ece4Schristos for (ipos=1; ipos<=output.pos; ipos++) { 1521*3117ece4Schristos dinput.size = ipos; 1522*3117ece4Schristos CHECK_Z ( ZSTD_decompressStream(dstream, &doutput, &dinput) ); 1523*3117ece4Schristos } 1524*3117ece4Schristos if (doutput.pos != 0) goto _output_error; 1525*3117ece4Schristos ZSTD_freeDStream(dstream); 1526*3117ece4Schristos } 1527*3117ece4Schristos } 1528*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1529*3117ece4Schristos 1530*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : reuse CCtx with expanding block size : ", testNb++); 1531*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1532*3117ece4Schristos ZSTD_parameters const params = ZSTD_getParams(1, ZSTD_CONTENTSIZE_UNKNOWN, 0); 1533*3117ece4Schristos assert(params.fParams.contentSizeFlag == 1); /* block size will be adapted if pledgedSrcSize is enabled */ 1534*3117ece4Schristos CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, 1 /*pledgedSrcSize*/) ); 1535*3117ece4Schristos CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, compressedBufferSize, CNBuffer, 1) ); /* creates a block size of 1 */ 1536*3117ece4Schristos 1537*3117ece4Schristos CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN) ); /* reuse same parameters */ 1538*3117ece4Schristos { size_t const inSize = 2* 128 KB; 1539*3117ece4Schristos size_t const outSize = ZSTD_compressBound(inSize); 1540*3117ece4Schristos CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, outSize, CNBuffer, inSize) ); 1541*3117ece4Schristos /* will fail if blockSize is not resized */ 1542*3117ece4Schristos } 1543*3117ece4Schristos ZSTD_freeCCtx(cctx); 1544*3117ece4Schristos } 1545*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1546*3117ece4Schristos 1547*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : re-using a CCtx should compress the same : ", testNb++); 1548*3117ece4Schristos { size_t const sampleSize = 30; 1549*3117ece4Schristos int i; 1550*3117ece4Schristos for (i=0; i<20; i++) 1551*3117ece4Schristos ((char*)CNBuffer)[i] = (char)i; /* ensure no match during initial section */ 1552*3117ece4Schristos memcpy((char*)CNBuffer + 20, CNBuffer, 10); /* create one match, starting from beginning of sample, which is the difficult case (see #1241) */ 1553*3117ece4Schristos for (i=1; i<=19; i++) { 1554*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1555*3117ece4Schristos size_t size1, size2; 1556*3117ece4Schristos DISPLAYLEVEL(5, "l%i ", i); 1557*3117ece4Schristos size1 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i); 1558*3117ece4Schristos CHECK_Z(size1); 1559*3117ece4Schristos 1560*3117ece4Schristos size2 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i); 1561*3117ece4Schristos CHECK_Z(size2); 1562*3117ece4Schristos CHECK_EQ(size1, size2); 1563*3117ece4Schristos 1564*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, i) ); 1565*3117ece4Schristos size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize); 1566*3117ece4Schristos CHECK_Z(size2); 1567*3117ece4Schristos CHECK_EQ(size1, size2); 1568*3117ece4Schristos 1569*3117ece4Schristos size2 = ZSTD_compress2(cctx, compressedBuffer, ZSTD_compressBound(sampleSize) - 1, CNBuffer, sampleSize); /* force streaming, as output buffer is not large enough to guarantee success */ 1570*3117ece4Schristos CHECK_Z(size2); 1571*3117ece4Schristos CHECK_EQ(size1, size2); 1572*3117ece4Schristos 1573*3117ece4Schristos { ZSTD_inBuffer inb; 1574*3117ece4Schristos ZSTD_outBuffer outb; 1575*3117ece4Schristos inb.src = CNBuffer; 1576*3117ece4Schristos inb.pos = 0; 1577*3117ece4Schristos inb.size = sampleSize; 1578*3117ece4Schristos outb.dst = compressedBuffer; 1579*3117ece4Schristos outb.pos = 0; 1580*3117ece4Schristos outb.size = ZSTD_compressBound(sampleSize) - 1; /* force streaming, as output buffer is not large enough to guarantee success */ 1581*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) ); 1582*3117ece4Schristos assert(inb.pos == inb.size); 1583*3117ece4Schristos CHECK_EQ(size1, outb.pos); 1584*3117ece4Schristos } 1585*3117ece4Schristos 1586*3117ece4Schristos ZSTD_freeCCtx(cctx); 1587*3117ece4Schristos } 1588*3117ece4Schristos } 1589*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1590*3117ece4Schristos 1591*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : btultra2 & 1st block : ", testNb++); 1592*3117ece4Schristos { size_t const sampleSize = 1024; 1593*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1594*3117ece4Schristos ZSTD_inBuffer inb; 1595*3117ece4Schristos ZSTD_outBuffer outb; 1596*3117ece4Schristos inb.src = CNBuffer; 1597*3117ece4Schristos inb.pos = 0; 1598*3117ece4Schristos inb.size = 0; 1599*3117ece4Schristos outb.dst = compressedBuffer; 1600*3117ece4Schristos outb.pos = 0; 1601*3117ece4Schristos outb.size = compressedBufferSize; 1602*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, ZSTD_maxCLevel()) ); 1603*3117ece4Schristos 1604*3117ece4Schristos inb.size = sampleSize; /* start with something, so that context is already used */ 1605*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) ); /* will break internal assert if stats_init is not disabled */ 1606*3117ece4Schristos assert(inb.pos == inb.size); 1607*3117ece4Schristos outb.pos = 0; /* cancel output */ 1608*3117ece4Schristos 1609*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(cctx, sampleSize) ); 1610*3117ece4Schristos inb.size = 4; /* too small size : compression will be skipped */ 1611*3117ece4Schristos inb.pos = 0; 1612*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) ); 1613*3117ece4Schristos assert(inb.pos == inb.size); 1614*3117ece4Schristos 1615*3117ece4Schristos inb.size += 5; /* too small size : compression will be skipped */ 1616*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) ); 1617*3117ece4Schristos assert(inb.pos == inb.size); 1618*3117ece4Schristos 1619*3117ece4Schristos inb.size += 11; /* small enough to attempt compression */ 1620*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) ); 1621*3117ece4Schristos assert(inb.pos == inb.size); 1622*3117ece4Schristos 1623*3117ece4Schristos assert(inb.pos < sampleSize); 1624*3117ece4Schristos inb.size = sampleSize; /* large enough to trigger stats_init, but no longer at beginning */ 1625*3117ece4Schristos CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) ); /* will break internal assert if stats_init is not disabled */ 1626*3117ece4Schristos assert(inb.pos == inb.size); 1627*3117ece4Schristos ZSTD_freeCCtx(cctx); 1628*3117ece4Schristos } 1629*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1630*3117ece4Schristos 1631*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : ZSTD_CCtx_getParameter() : ", testNb++); 1632*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1633*3117ece4Schristos ZSTD_outBuffer out = {NULL, 0, 0}; 1634*3117ece4Schristos ZSTD_inBuffer in = {NULL, 0, 0}; 1635*3117ece4Schristos int value; 1636*3117ece4Schristos 1637*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); 1638*3117ece4Schristos CHECK_EQ(value, 3); 1639*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1640*3117ece4Schristos CHECK_EQ(value, 0); 1641*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, ZSTD_HASHLOG_MIN)); 1642*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); 1643*3117ece4Schristos CHECK_EQ(value, 3); 1644*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1645*3117ece4Schristos CHECK_EQ(value, ZSTD_HASHLOG_MIN); 1646*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7)); 1647*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); 1648*3117ece4Schristos CHECK_EQ(value, 7); 1649*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1650*3117ece4Schristos CHECK_EQ(value, ZSTD_HASHLOG_MIN); 1651*3117ece4Schristos /* Start a compression job */ 1652*3117ece4Schristos ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue); 1653*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); 1654*3117ece4Schristos CHECK_EQ(value, 7); 1655*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1656*3117ece4Schristos CHECK_EQ(value, ZSTD_HASHLOG_MIN); 1657*3117ece4Schristos /* Reset the CCtx */ 1658*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); 1659*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); 1660*3117ece4Schristos CHECK_EQ(value, 7); 1661*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1662*3117ece4Schristos CHECK_EQ(value, ZSTD_HASHLOG_MIN); 1663*3117ece4Schristos /* Reset the parameters */ 1664*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters); 1665*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); 1666*3117ece4Schristos CHECK_EQ(value, 3); 1667*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1668*3117ece4Schristos CHECK_EQ(value, 0); 1669*3117ece4Schristos 1670*3117ece4Schristos ZSTD_freeCCtx(cctx); 1671*3117ece4Schristos } 1672*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1673*3117ece4Schristos 1674*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : ZSTD_CCtx_setCParams() : ", testNb++); 1675*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1676*3117ece4Schristos int value; 1677*3117ece4Schristos ZSTD_compressionParameters cparams = ZSTD_getCParams(1, 0, 0); 1678*3117ece4Schristos cparams.strategy = -1; 1679*3117ece4Schristos /* Set invalid cParams == no change. */ 1680*3117ece4Schristos CHECK(ZSTD_isError(ZSTD_CCtx_setCParams(cctx, cparams))); 1681*3117ece4Schristos 1682*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); 1683*3117ece4Schristos CHECK_EQ(value, 0); 1684*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value)); 1685*3117ece4Schristos CHECK_EQ(value, 0); 1686*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1687*3117ece4Schristos CHECK_EQ(value, 0); 1688*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_searchLog, &value)); 1689*3117ece4Schristos CHECK_EQ(value, 0); 1690*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_minMatch, &value)); 1691*3117ece4Schristos CHECK_EQ(value, 0); 1692*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetLength, &value)); 1693*3117ece4Schristos CHECK_EQ(value, 0); 1694*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_strategy, &value)); 1695*3117ece4Schristos CHECK_EQ(value, 0); 1696*3117ece4Schristos 1697*3117ece4Schristos cparams = ZSTD_getCParams(12, 0, 0); 1698*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setCParams(cctx, cparams)); 1699*3117ece4Schristos 1700*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); 1701*3117ece4Schristos CHECK_EQ(value, (int)cparams.windowLog); 1702*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value)); 1703*3117ece4Schristos CHECK_EQ(value, (int)cparams.chainLog); 1704*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1705*3117ece4Schristos CHECK_EQ(value, (int)cparams.hashLog); 1706*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_searchLog, &value)); 1707*3117ece4Schristos CHECK_EQ(value, (int)cparams.searchLog); 1708*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_minMatch, &value)); 1709*3117ece4Schristos CHECK_EQ(value, (int)cparams.minMatch); 1710*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetLength, &value)); 1711*3117ece4Schristos CHECK_EQ(value, (int)cparams.targetLength); 1712*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_strategy, &value)); 1713*3117ece4Schristos CHECK_EQ(value, (int)cparams.strategy); 1714*3117ece4Schristos 1715*3117ece4Schristos ZSTD_freeCCtx(cctx); 1716*3117ece4Schristos } 1717*3117ece4Schristos 1718*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : ZSTD_CCtx_setFParams() : ", testNb++); 1719*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1720*3117ece4Schristos int value; 1721*3117ece4Schristos ZSTD_frameParameters fparams = {0, 1, 1}; 1722*3117ece4Schristos 1723*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_contentSizeFlag, &value)); 1724*3117ece4Schristos CHECK_EQ(value, 1); 1725*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_checksumFlag, &value)); 1726*3117ece4Schristos CHECK_EQ(value, 0); 1727*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_dictIDFlag, &value)); 1728*3117ece4Schristos CHECK_EQ(value, 1); 1729*3117ece4Schristos 1730*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setFParams(cctx, fparams)); 1731*3117ece4Schristos 1732*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_contentSizeFlag, &value)); 1733*3117ece4Schristos CHECK_EQ(value, fparams.contentSizeFlag); 1734*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_checksumFlag, &value)); 1735*3117ece4Schristos CHECK_EQ(value, fparams.checksumFlag); 1736*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_dictIDFlag, &value)); 1737*3117ece4Schristos CHECK_EQ(value, !fparams.noDictIDFlag); 1738*3117ece4Schristos 1739*3117ece4Schristos ZSTD_freeCCtx(cctx); 1740*3117ece4Schristos } 1741*3117ece4Schristos 1742*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : ZSTD_CCtx_setCarams() : ", testNb++); 1743*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1744*3117ece4Schristos int value; 1745*3117ece4Schristos ZSTD_parameters params = ZSTD_getParams(1, 0, 0); 1746*3117ece4Schristos params.cParams.strategy = -1; 1747*3117ece4Schristos /* Set invalid params == no change. */ 1748*3117ece4Schristos CHECK(ZSTD_isError(ZSTD_CCtx_setParams(cctx, params))); 1749*3117ece4Schristos 1750*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); 1751*3117ece4Schristos CHECK_EQ(value, 0); 1752*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value)); 1753*3117ece4Schristos CHECK_EQ(value, 0); 1754*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1755*3117ece4Schristos CHECK_EQ(value, 0); 1756*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_searchLog, &value)); 1757*3117ece4Schristos CHECK_EQ(value, 0); 1758*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_minMatch, &value)); 1759*3117ece4Schristos CHECK_EQ(value, 0); 1760*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetLength, &value)); 1761*3117ece4Schristos CHECK_EQ(value, 0); 1762*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_strategy, &value)); 1763*3117ece4Schristos CHECK_EQ(value, 0); 1764*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_contentSizeFlag, &value)); 1765*3117ece4Schristos CHECK_EQ(value, 1); 1766*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_checksumFlag, &value)); 1767*3117ece4Schristos CHECK_EQ(value, 0); 1768*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_dictIDFlag, &value)); 1769*3117ece4Schristos CHECK_EQ(value, 1); 1770*3117ece4Schristos 1771*3117ece4Schristos params = ZSTD_getParams(12, 0, 0); 1772*3117ece4Schristos params.fParams.contentSizeFlag = 0; 1773*3117ece4Schristos params.fParams.checksumFlag = 1; 1774*3117ece4Schristos params.fParams.noDictIDFlag = 1; 1775*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParams(cctx, params)); 1776*3117ece4Schristos 1777*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); 1778*3117ece4Schristos CHECK_EQ(value, (int)params.cParams.windowLog); 1779*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value)); 1780*3117ece4Schristos CHECK_EQ(value, (int)params.cParams.chainLog); 1781*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); 1782*3117ece4Schristos CHECK_EQ(value, (int)params.cParams.hashLog); 1783*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_searchLog, &value)); 1784*3117ece4Schristos CHECK_EQ(value, (int)params.cParams.searchLog); 1785*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_minMatch, &value)); 1786*3117ece4Schristos CHECK_EQ(value, (int)params.cParams.minMatch); 1787*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetLength, &value)); 1788*3117ece4Schristos CHECK_EQ(value, (int)params.cParams.targetLength); 1789*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_strategy, &value)); 1790*3117ece4Schristos CHECK_EQ(value, (int)params.cParams.strategy); 1791*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_contentSizeFlag, &value)); 1792*3117ece4Schristos CHECK_EQ(value, params.fParams.contentSizeFlag); 1793*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_checksumFlag, &value)); 1794*3117ece4Schristos CHECK_EQ(value, params.fParams.checksumFlag); 1795*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_dictIDFlag, &value)); 1796*3117ece4Schristos CHECK_EQ(value, !params.fParams.noDictIDFlag); 1797*3117ece4Schristos 1798*3117ece4Schristos ZSTD_freeCCtx(cctx); 1799*3117ece4Schristos } 1800*3117ece4Schristos 1801*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : ldm conditionally enabled by default doesn't change cctx params: ", testNb++); 1802*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1803*3117ece4Schristos ZSTD_outBuffer out = {NULL, 0, 0}; 1804*3117ece4Schristos ZSTD_inBuffer in = {NULL, 0, 0}; 1805*3117ece4Schristos int value; 1806*3117ece4Schristos 1807*3117ece4Schristos /* Even if LDM will be enabled by default in the applied params (since wlog >= 27 and strategy >= btopt), 1808*3117ece4Schristos * we should not modify the actual parameter specified by the user within the CCtx 1809*3117ece4Schristos */ 1810*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 27)); 1811*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, ZSTD_btopt)); 1812*3117ece4Schristos 1813*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue)); 1814*3117ece4Schristos CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_enableLongDistanceMatching, &value)); 1815*3117ece4Schristos CHECK_EQ(value, 0); 1816*3117ece4Schristos 1817*3117ece4Schristos ZSTD_freeCCtx(cctx); 1818*3117ece4Schristos } 1819*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1820*3117ece4Schristos 1821*3117ece4Schristos /* this test is really too long, and should be made faster */ 1822*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : overflow protection with large windowLog : ", testNb++); 1823*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 1824*3117ece4Schristos ZSTD_parameters params = ZSTD_getParams(-999, ZSTD_CONTENTSIZE_UNKNOWN, 0); 1825*3117ece4Schristos size_t const nbCompressions = ((1U << 31) / CNBuffSize) + 2; /* ensure U32 overflow protection is triggered */ 1826*3117ece4Schristos size_t cnb; 1827*3117ece4Schristos assert(cctx != NULL); 1828*3117ece4Schristos params.fParams.contentSizeFlag = 0; 1829*3117ece4Schristos params.cParams.windowLog = ZSTD_WINDOWLOG_MAX; 1830*3117ece4Schristos for (cnb = 0; cnb < nbCompressions; ++cnb) { 1831*3117ece4Schristos DISPLAYLEVEL(6, "run %zu / %zu \n", cnb, nbCompressions); 1832*3117ece4Schristos CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN) ); /* reuse same parameters */ 1833*3117ece4Schristos CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize) ); 1834*3117ece4Schristos } 1835*3117ece4Schristos ZSTD_freeCCtx(cctx); 1836*3117ece4Schristos } 1837*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1838*3117ece4Schristos 1839*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : size down context : ", testNb++); 1840*3117ece4Schristos { ZSTD_CCtx* const largeCCtx = ZSTD_createCCtx(); 1841*3117ece4Schristos assert(largeCCtx != NULL); 1842*3117ece4Schristos CHECK_Z( ZSTD_compressBegin(largeCCtx, 19) ); /* streaming implies ZSTD_CONTENTSIZE_UNKNOWN, which maximizes memory usage */ 1843*3117ece4Schristos CHECK_Z( ZSTD_compressEnd(largeCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1) ); 1844*3117ece4Schristos { size_t const largeCCtxSize = ZSTD_sizeof_CCtx(largeCCtx); /* size of context must be measured after compression */ 1845*3117ece4Schristos { ZSTD_CCtx* const smallCCtx = ZSTD_createCCtx(); 1846*3117ece4Schristos assert(smallCCtx != NULL); 1847*3117ece4Schristos CHECK_Z(ZSTD_compressCCtx(smallCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1, 1)); 1848*3117ece4Schristos { size_t const smallCCtxSize = ZSTD_sizeof_CCtx(smallCCtx); 1849*3117ece4Schristos DISPLAYLEVEL(5, "(large) %zuKB > 32*%zuKB (small) : ", 1850*3117ece4Schristos largeCCtxSize>>10, smallCCtxSize>>10); 1851*3117ece4Schristos assert(largeCCtxSize > 32* smallCCtxSize); /* note : "too large" definition is handled within zstd_compress.c . 1852*3117ece4Schristos * make this test case extreme, so that it doesn't depend on a possibly fluctuating definition */ 1853*3117ece4Schristos } 1854*3117ece4Schristos ZSTD_freeCCtx(smallCCtx); 1855*3117ece4Schristos } 1856*3117ece4Schristos { U32 const maxNbAttempts = 1100; /* nb of usages before triggering size down is handled within zstd_compress.c. 1857*3117ece4Schristos * currently defined as 128x, but could be adjusted in the future. 1858*3117ece4Schristos * make this test long enough so that it's not too much tied to the current definition within zstd_compress.c */ 1859*3117ece4Schristos unsigned u; 1860*3117ece4Schristos for (u=0; u<maxNbAttempts; u++) { 1861*3117ece4Schristos CHECK_Z(ZSTD_compressCCtx(largeCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1, 1)); 1862*3117ece4Schristos if (ZSTD_sizeof_CCtx(largeCCtx) < largeCCtxSize) break; /* sized down */ 1863*3117ece4Schristos } 1864*3117ece4Schristos DISPLAYLEVEL(5, "size down after %u attempts : ", u); 1865*3117ece4Schristos if (u==maxNbAttempts) goto _output_error; /* no sizedown happened */ 1866*3117ece4Schristos } 1867*3117ece4Schristos } 1868*3117ece4Schristos ZSTD_freeCCtx(largeCCtx); 1869*3117ece4Schristos } 1870*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1871*3117ece4Schristos 1872*3117ece4Schristos /* Static CCtx tests */ 1873*3117ece4Schristos #define STATIC_CCTX_LEVEL 4 1874*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : create static CCtx for level %u : ", testNb++, STATIC_CCTX_LEVEL); 1875*3117ece4Schristos { size_t const staticCStreamSize = ZSTD_estimateCStreamSize(STATIC_CCTX_LEVEL); 1876*3117ece4Schristos void* const staticCCtxBuffer = malloc(staticCStreamSize); 1877*3117ece4Schristos size_t const staticDCtxSize = ZSTD_estimateDCtxSize(); 1878*3117ece4Schristos void* const staticDCtxBuffer = malloc(staticDCtxSize); 1879*3117ece4Schristos DISPLAYLEVEL(4, "CStream size = %u, ", (U32)staticCStreamSize); 1880*3117ece4Schristos if (staticCCtxBuffer==NULL || staticDCtxBuffer==NULL) { 1881*3117ece4Schristos free(staticCCtxBuffer); 1882*3117ece4Schristos free(staticDCtxBuffer); 1883*3117ece4Schristos DISPLAY("Not enough memory, aborting\n"); 1884*3117ece4Schristos testResult = 1; 1885*3117ece4Schristos goto _end; 1886*3117ece4Schristos } 1887*3117ece4Schristos { size_t const smallInSize = 32 KB; 1888*3117ece4Schristos ZSTD_compressionParameters const cparams_small = ZSTD_getCParams(STATIC_CCTX_LEVEL, smallInSize, 0); 1889*3117ece4Schristos size_t const smallCCtxSize = ZSTD_estimateCCtxSize_usingCParams(cparams_small); 1890*3117ece4Schristos size_t const staticCCtxSize = ZSTD_estimateCCtxSize(STATIC_CCTX_LEVEL); 1891*3117ece4Schristos ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, smallCCtxSize); 1892*3117ece4Schristos ZSTD_DCtx* const staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize); 1893*3117ece4Schristos DISPLAYLEVEL(4, "Full CCtx size = %u, ", (U32)staticCCtxSize); 1894*3117ece4Schristos DISPLAYLEVEL(4, "CCtx for 32 KB = %u, ", (U32)smallCCtxSize); 1895*3117ece4Schristos if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error; 1896*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1897*3117ece4Schristos 1898*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress small input with small static CCtx : ", testNb++); 1899*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, 1900*3117ece4Schristos compressedBuffer, compressedBufferSize, 1901*3117ece4Schristos CNBuffer, smallInSize, STATIC_CCTX_LEVEL) ); 1902*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", 1903*3117ece4Schristos (unsigned)cSize, (double)cSize/smallInSize*100); 1904*3117ece4Schristos 1905*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress large input with small static CCtx (must fail) : ", testNb++); 1906*3117ece4Schristos { size_t const r = ZSTD_compressCCtx(staticCCtx, 1907*3117ece4Schristos compressedBuffer, compressedBufferSize, 1908*3117ece4Schristos CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL); 1909*3117ece4Schristos if (ZSTD_getErrorCode((size_t)r) != ZSTD_error_memory_allocation) goto _output_error; 1910*3117ece4Schristos } 1911*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1912*3117ece4Schristos 1913*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : resize context to full CCtx size : ", testNb++); 1914*3117ece4Schristos staticCCtx = ZSTD_initStaticCStream(staticCCtxBuffer, staticCCtxSize); 1915*3117ece4Schristos DISPLAYLEVEL(4, "staticCCtxBuffer = %p, staticCCtx = %p , ", staticCCtxBuffer, (void*)staticCCtx); 1916*3117ece4Schristos if (staticCCtx == NULL) goto _output_error; 1917*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1918*3117ece4Schristos 1919*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress large input with static CCtx : ", testNb++); 1920*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, 1921*3117ece4Schristos compressedBuffer, compressedBufferSize, 1922*3117ece4Schristos CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) ); 1923*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", 1924*3117ece4Schristos (unsigned)cSize, (double)cSize/CNBuffSize*100); 1925*3117ece4Schristos 1926*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress small input often enough to trigger context reduce : ", testNb++); 1927*3117ece4Schristos { int nbc; 1928*3117ece4Schristos assert(staticCCtxSize > smallCCtxSize * ZSTD_WORKSPACETOOLARGE_FACTOR); /* ensure size down scenario */ 1929*3117ece4Schristos assert(CNBuffSize > smallInSize + ZSTD_WORKSPACETOOLARGE_MAXDURATION + 3); 1930*3117ece4Schristos for (nbc=0; nbc<ZSTD_WORKSPACETOOLARGE_MAXDURATION+2; nbc++) { 1931*3117ece4Schristos CHECK_Z(ZSTD_compressCCtx(staticCCtx, 1932*3117ece4Schristos compressedBuffer, compressedBufferSize, 1933*3117ece4Schristos (char*)CNBuffer + nbc, smallInSize, 1934*3117ece4Schristos STATIC_CCTX_LEVEL) ); 1935*3117ece4Schristos } } 1936*3117ece4Schristos DISPLAYLEVEL(3, "OK \n") 1937*3117ece4Schristos 1938*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : init CCtx for level %u : ", testNb++, STATIC_CCTX_LEVEL); 1939*3117ece4Schristos CHECK_Z( ZSTD_compressBegin(staticCCtx, STATIC_CCTX_LEVEL) ); 1940*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1941*3117ece4Schristos 1942*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compression again with static CCtx : ", testNb++); 1943*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, 1944*3117ece4Schristos compressedBuffer, compressedBufferSize, 1945*3117ece4Schristos CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) ); 1946*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", 1947*3117ece4Schristos (unsigned)cSize, (double)cSize/CNBuffSize*100); 1948*3117ece4Schristos 1949*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : simple decompression test with static DCtx : ", testNb++); 1950*3117ece4Schristos { size_t const r = ZSTD_decompressDCtx(staticDCtx, 1951*3117ece4Schristos decodedBuffer, CNBuffSize, 1952*3117ece4Schristos compressedBuffer, cSize); 1953*3117ece4Schristos if (r != CNBuffSize) goto _output_error; } 1954*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1955*3117ece4Schristos 1956*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++); 1957*3117ece4Schristos if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error; 1958*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1959*3117ece4Schristos 1960*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : init CCtx for too large level (must fail) : ", testNb++); 1961*3117ece4Schristos { size_t const r = ZSTD_compressBegin(staticCCtx, ZSTD_maxCLevel()); 1962*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; } 1963*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1964*3117ece4Schristos 1965*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : init CCtx for small level %u (should work again) : ", testNb++, 1); 1966*3117ece4Schristos CHECK_Z( ZSTD_compressBegin(staticCCtx, 1) ); 1967*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1968*3117ece4Schristos 1969*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : use CStream on CCtx-sized static context (should fail) : ", testNb++); 1970*3117ece4Schristos CHECK_Z( ZSTD_initCStream(staticCCtx, STATIC_CCTX_LEVEL) ); /* note : doesn't allocate */ 1971*3117ece4Schristos { ZSTD_outBuffer output = { compressedBuffer, compressedBufferSize, 0 }; 1972*3117ece4Schristos ZSTD_inBuffer input = { CNBuffer, CNBuffSize, 0 }; 1973*3117ece4Schristos size_t const r = ZSTD_compressStream(staticCCtx, &output, &input); /* now allocates, should fail */ 1974*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 1975*3117ece4Schristos } 1976*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1977*3117ece4Schristos 1978*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : resize context to CStream size, then stream compress : ", testNb++); 1979*3117ece4Schristos staticCCtx = ZSTD_initStaticCStream(staticCCtxBuffer, staticCStreamSize); 1980*3117ece4Schristos assert(staticCCtx != NULL); 1981*3117ece4Schristos CHECK_Z( ZSTD_initCStream(staticCCtx, STATIC_CCTX_LEVEL) ); /* note : doesn't allocate */ 1982*3117ece4Schristos { ZSTD_outBuffer output = { compressedBuffer, compressedBufferSize, 0 }; 1983*3117ece4Schristos ZSTD_inBuffer input = { CNBuffer, CNBuffSize, 0 }; 1984*3117ece4Schristos CHECK_Z( ZSTD_compressStream(staticCCtx, &output, &input) ); 1985*3117ece4Schristos } 1986*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1987*3117ece4Schristos 1988*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : CStream for small level %u : ", testNb++, 1); 1989*3117ece4Schristos CHECK_Z( ZSTD_initCStream(staticCCtx, 1) ); /* note : doesn't allocate */ 1990*3117ece4Schristos { ZSTD_outBuffer output = { compressedBuffer, compressedBufferSize, 0 }; 1991*3117ece4Schristos ZSTD_inBuffer input = { CNBuffer, CNBuffSize, 0 }; 1992*3117ece4Schristos CHECK_Z( ZSTD_compressStream(staticCCtx, &output, &input) ); 1993*3117ece4Schristos } 1994*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 1995*3117ece4Schristos 1996*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : init static CStream with dictionary (should fail) : ", testNb++); 1997*3117ece4Schristos { size_t const r = ZSTD_initCStream_usingDict(staticCCtx, CNBuffer, 64 KB, 1); 1998*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; } 1999*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2000*3117ece4Schristos 2001*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : use DStream on DCtx-sized static context (should fail) : ", testNb++); 2002*3117ece4Schristos CHECK_Z( ZSTD_initDStream(staticDCtx) ); 2003*3117ece4Schristos { ZSTD_outBuffer output = { decodedBuffer, CNBuffSize, 0 }; 2004*3117ece4Schristos ZSTD_inBuffer input = { compressedBuffer, ZSTD_FRAMEHEADERSIZE_MAX+1, 0 }; 2005*3117ece4Schristos size_t const r = ZSTD_decompressStream(staticDCtx, &output, &input); 2006*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 2007*3117ece4Schristos } 2008*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2009*3117ece4Schristos 2010*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : test estimation functions with default cctx params : ", testNb++); 2011*3117ece4Schristos { 2012*3117ece4Schristos // Test ZSTD_estimateCCtxSize_usingCCtxParams 2013*3117ece4Schristos { 2014*3117ece4Schristos ZSTD_CCtx_params* params = ZSTD_createCCtxParams(); 2015*3117ece4Schristos size_t const cctxSizeDefault = ZSTD_estimateCCtxSize_usingCCtxParams(params); 2016*3117ece4Schristos staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, cctxSizeDefault); 2017*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, 2018*3117ece4Schristos compressedBuffer, compressedBufferSize, 2019*3117ece4Schristos CNBuffer, CNBuffSize, 3)); 2020*3117ece4Schristos 2021*3117ece4Schristos { 2022*3117ece4Schristos size_t const r = ZSTD_decompressDCtx(staticDCtx, 2023*3117ece4Schristos decodedBuffer, CNBuffSize, 2024*3117ece4Schristos compressedBuffer, cSize); 2025*3117ece4Schristos if (r != CNBuffSize) goto _output_error; 2026*3117ece4Schristos if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error; 2027*3117ece4Schristos } 2028*3117ece4Schristos ZSTD_freeCCtxParams(params); 2029*3117ece4Schristos } 2030*3117ece4Schristos 2031*3117ece4Schristos // Test ZSTD_estimateCStreamSize_usingCCtxParams 2032*3117ece4Schristos { 2033*3117ece4Schristos ZSTD_CCtx_params* params = ZSTD_createCCtxParams(); 2034*3117ece4Schristos size_t const cctxSizeDefault = ZSTD_estimateCStreamSize_usingCCtxParams(params); 2035*3117ece4Schristos staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, cctxSizeDefault); 2036*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, 2037*3117ece4Schristos compressedBuffer, compressedBufferSize, 2038*3117ece4Schristos CNBuffer, CNBuffSize, 3) ); 2039*3117ece4Schristos 2040*3117ece4Schristos { 2041*3117ece4Schristos size_t const r = ZSTD_decompressDCtx(staticDCtx, 2042*3117ece4Schristos decodedBuffer, CNBuffSize, 2043*3117ece4Schristos compressedBuffer, cSize); 2044*3117ece4Schristos if (r != CNBuffSize) goto _output_error; 2045*3117ece4Schristos if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error; 2046*3117ece4Schristos } 2047*3117ece4Schristos ZSTD_freeCCtxParams(params); 2048*3117ece4Schristos } 2049*3117ece4Schristos } 2050*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2051*3117ece4Schristos 2052*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : test estimation functions with maxBlockSize = 0 : ", testNb++); 2053*3117ece4Schristos { 2054*3117ece4Schristos // Test ZSTD_estimateCCtxSize_usingCCtxParams 2055*3117ece4Schristos { 2056*3117ece4Schristos ZSTD_CCtx_params* params = ZSTD_createCCtxParams(); 2057*3117ece4Schristos size_t cctxSizeDefault; 2058*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_maxBlockSize, 0)); 2059*3117ece4Schristos cctxSizeDefault = ZSTD_estimateCCtxSize_usingCCtxParams(params); 2060*3117ece4Schristos staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, cctxSizeDefault); 2061*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, 2062*3117ece4Schristos compressedBuffer, compressedBufferSize, 2063*3117ece4Schristos CNBuffer, CNBuffSize, 3) ); 2064*3117ece4Schristos 2065*3117ece4Schristos { 2066*3117ece4Schristos size_t const r = ZSTD_decompressDCtx(staticDCtx, 2067*3117ece4Schristos decodedBuffer, CNBuffSize, 2068*3117ece4Schristos compressedBuffer, cSize); 2069*3117ece4Schristos if (r != CNBuffSize) goto _output_error; 2070*3117ece4Schristos if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error; 2071*3117ece4Schristos } 2072*3117ece4Schristos ZSTD_freeCCtxParams(params); 2073*3117ece4Schristos } 2074*3117ece4Schristos 2075*3117ece4Schristos // Test ZSTD_estimateCStreamSize_usingCCtxParams 2076*3117ece4Schristos { 2077*3117ece4Schristos ZSTD_CCtx_params* params = ZSTD_createCCtxParams(); 2078*3117ece4Schristos size_t cctxSizeDefault; 2079*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_maxBlockSize, 0)); 2080*3117ece4Schristos cctxSizeDefault = ZSTD_estimateCStreamSize_usingCCtxParams(params); 2081*3117ece4Schristos staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, cctxSizeDefault); 2082*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, 2083*3117ece4Schristos compressedBuffer, compressedBufferSize, 2084*3117ece4Schristos CNBuffer, CNBuffSize, 3) ); 2085*3117ece4Schristos 2086*3117ece4Schristos { 2087*3117ece4Schristos size_t const r = ZSTD_decompressDCtx(staticDCtx, 2088*3117ece4Schristos decodedBuffer, CNBuffSize, 2089*3117ece4Schristos compressedBuffer, cSize); 2090*3117ece4Schristos if (r != CNBuffSize) goto _output_error; 2091*3117ece4Schristos if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error; 2092*3117ece4Schristos } 2093*3117ece4Schristos ZSTD_freeCCtxParams(params); 2094*3117ece4Schristos } 2095*3117ece4Schristos } 2096*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2097*3117ece4Schristos } 2098*3117ece4Schristos free(staticCCtxBuffer); 2099*3117ece4Schristos free(staticDCtxBuffer); 2100*3117ece4Schristos } 2101*3117ece4Schristos 2102*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Static context sizes for negative levels : ", testNb++); 2103*3117ece4Schristos { size_t const cctxSizeN1 = ZSTD_estimateCCtxSize(-1); 2104*3117ece4Schristos size_t const cctxSizeP1 = ZSTD_estimateCCtxSize(1); 2105*3117ece4Schristos size_t const cstreamSizeN1 = ZSTD_estimateCStreamSize(-1); 2106*3117ece4Schristos size_t const cstreamSizeP1 = ZSTD_estimateCStreamSize(1); 2107*3117ece4Schristos 2108*3117ece4Schristos if (!(0 < cctxSizeN1 && cctxSizeN1 <= cctxSizeP1)) goto _output_error; 2109*3117ece4Schristos if (!(0 < cstreamSizeN1 && cstreamSizeN1 <= cstreamSizeP1)) goto _output_error; 2110*3117ece4Schristos } 2111*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2112*3117ece4Schristos 2113*3117ece4Schristos 2114*3117ece4Schristos /* ZSTDMT simple MT compression test */ 2115*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : create ZSTDMT CCtx : ", testNb++); 2116*3117ece4Schristos { ZSTD_CCtx* const mtctx = ZSTD_createCCtx(); 2117*3117ece4Schristos if (mtctx==NULL) { 2118*3117ece4Schristos DISPLAY("mtctx : not enough memory, aborting \n"); 2119*3117ece4Schristos testResult = 1; 2120*3117ece4Schristos goto _end; 2121*3117ece4Schristos } 2122*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_nbWorkers, 2) ); 2123*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_compressionLevel, 1) ); 2124*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2125*3117ece4Schristos 2126*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : compress %u bytes with 2 threads : ", testNb++, (unsigned)CNBuffSize); 2127*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compress2(mtctx, 2128*3117ece4Schristos compressedBuffer, compressedBufferSize, 2129*3117ece4Schristos CNBuffer, CNBuffSize) ); 2130*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2131*3117ece4Schristos 2132*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompressed size test : ", testNb++); 2133*3117ece4Schristos { unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize); 2134*3117ece4Schristos if (rSize != CNBuffSize) { 2135*3117ece4Schristos DISPLAY("ZSTD_getFrameContentSize incorrect : %u != %u \n", (unsigned)rSize, (unsigned)CNBuffSize); 2136*3117ece4Schristos goto _output_error; 2137*3117ece4Schristos } } 2138*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2139*3117ece4Schristos 2140*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize); 2141*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); 2142*3117ece4Schristos if (r != CNBuffSize) goto _output_error; } 2143*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2144*3117ece4Schristos 2145*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++); 2146*3117ece4Schristos { size_t u; 2147*3117ece4Schristos for (u=0; u<CNBuffSize; u++) { 2148*3117ece4Schristos if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error; 2149*3117ece4Schristos } } 2150*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2151*3117ece4Schristos 2152*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress -T2 with checksum : ", testNb++); 2153*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_checksumFlag, 1) ); 2154*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_contentSizeFlag, 1) ); 2155*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_overlapLog, 3) ); 2156*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compress2(mtctx, 2157*3117ece4Schristos compressedBuffer, compressedBufferSize, 2158*3117ece4Schristos CNBuffer, CNBuffSize) ); 2159*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2160*3117ece4Schristos 2161*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize); 2162*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); 2163*3117ece4Schristos if (r != CNBuffSize) goto _output_error; } 2164*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2165*3117ece4Schristos 2166*3117ece4Schristos ZSTD_freeCCtx(mtctx); 2167*3117ece4Schristos } 2168*3117ece4Schristos 2169*3117ece4Schristos DISPLAYLEVEL(3, "test%3u : compress empty string and decompress with small window log : ", testNb++); 2170*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 2171*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 2172*3117ece4Schristos char out[32]; 2173*3117ece4Schristos if (cctx == NULL || dctx == NULL) goto _output_error; 2174*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0) ); 2175*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compress2(cctx, out, sizeof(out), NULL, 0) ); 2176*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes)\n", (unsigned)cSize); 2177*3117ece4Schristos 2178*3117ece4Schristos CHECK_Z( ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 10) ); 2179*3117ece4Schristos { char const* outPtr = out; 2180*3117ece4Schristos ZSTD_inBuffer inBuffer = { outPtr, cSize, 0 }; 2181*3117ece4Schristos ZSTD_outBuffer outBuffer = { NULL, 0, 0 }; 2182*3117ece4Schristos size_t dSize; 2183*3117ece4Schristos CHECK_VAR(dSize, ZSTD_decompressStream(dctx, &outBuffer, &inBuffer) ); 2184*3117ece4Schristos if (dSize != 0) goto _output_error; 2185*3117ece4Schristos } 2186*3117ece4Schristos 2187*3117ece4Schristos ZSTD_freeDCtx(dctx); 2188*3117ece4Schristos ZSTD_freeCCtx(cctx); 2189*3117ece4Schristos } 2190*3117ece4Schristos 2191*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress with block splitting : ", testNb++) 2192*3117ece4Schristos { ZSTD_CCtx* cctx = ZSTD_createCCtx(); 2193*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_useBlockSplitter, ZSTD_ps_enable) ); 2194*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 2195*3117ece4Schristos CHECK_Z(cSize); 2196*3117ece4Schristos ZSTD_freeCCtx(cctx); 2197*3117ece4Schristos } 2198*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2199*3117ece4Schristos 2200*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress -T2 with/without literals compression : ", testNb++) 2201*3117ece4Schristos { ZSTD_CCtx* cctx = ZSTD_createCCtx(); 2202*3117ece4Schristos size_t cSize1, cSize2; 2203*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) ); 2204*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2) ); 2205*3117ece4Schristos cSize1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 2206*3117ece4Schristos CHECK_Z(cSize1); 2207*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_literalCompressionMode, ZSTD_ps_disable) ); 2208*3117ece4Schristos cSize2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 2209*3117ece4Schristos CHECK_Z(cSize2); 2210*3117ece4Schristos CHECK_LT(cSize1, cSize2); 2211*3117ece4Schristos ZSTD_freeCCtx(cctx); 2212*3117ece4Schristos } 2213*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2214*3117ece4Schristos 2215*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Multithreaded ZSTD_compress2() with rsyncable : ", testNb++) 2216*3117ece4Schristos { ZSTD_CCtx* cctx = ZSTD_createCCtx(); 2217*3117ece4Schristos /* Set rsyncable and don't give the ZSTD_compressBound(CNBuffSize) so 2218*3117ece4Schristos * ZSTDMT is forced to not take the shortcut. 2219*3117ece4Schristos */ 2220*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) ); 2221*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1) ); 2222*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_rsyncable, 1) ); 2223*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize - 1, CNBuffer, CNBuffSize) ); 2224*3117ece4Schristos ZSTD_freeCCtx(cctx); 2225*3117ece4Schristos } 2226*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2227*3117ece4Schristos 2228*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : setting multithreaded parameters : ", testNb++) 2229*3117ece4Schristos { ZSTD_CCtx_params* params = ZSTD_createCCtxParams(); 2230*3117ece4Schristos int const jobSize = 512 KB; 2231*3117ece4Schristos int value; 2232*3117ece4Schristos /* Check that the overlap log and job size are unset. */ 2233*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) ); 2234*3117ece4Schristos CHECK_EQ(value, 0); 2235*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) ); 2236*3117ece4Schristos CHECK_EQ(value, 0); 2237*3117ece4Schristos /* Set and check the overlap log and job size. */ 2238*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, 5) ); 2239*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, jobSize) ); 2240*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) ); 2241*3117ece4Schristos CHECK_EQ(value, 5); 2242*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) ); 2243*3117ece4Schristos CHECK_EQ(value, jobSize); 2244*3117ece4Schristos /* Set the number of workers and check the overlap log and job size. */ 2245*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, 2) ); 2246*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) ); 2247*3117ece4Schristos CHECK_EQ(value, 5); 2248*3117ece4Schristos CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) ); 2249*3117ece4Schristos CHECK_EQ(value, jobSize); 2250*3117ece4Schristos ZSTD_freeCCtxParams(params); 2251*3117ece4Schristos } 2252*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2253*3117ece4Schristos 2254*3117ece4Schristos /* Simple API multiframe test */ 2255*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress multiple frames : ", testNb++); 2256*3117ece4Schristos { size_t off = 0; 2257*3117ece4Schristos int i; 2258*3117ece4Schristos int const segs = 4; 2259*3117ece4Schristos /* only use the first half so we don't push against size limit of compressedBuffer */ 2260*3117ece4Schristos size_t const segSize = (CNBuffSize / 2) / segs; 2261*3117ece4Schristos 2262*3117ece4Schristos const U32 skipLen = 129 KB; 2263*3117ece4Schristos char* const skipBuff = (char*)malloc(skipLen); 2264*3117ece4Schristos assert(skipBuff != NULL); 2265*3117ece4Schristos memset(skipBuff, 0, skipLen); 2266*3117ece4Schristos for (i = 0; i < segs; i++) { 2267*3117ece4Schristos CHECK_NEWV(r, ZSTD_compress( 2268*3117ece4Schristos (BYTE*)compressedBuffer + off, CNBuffSize - off, 2269*3117ece4Schristos (BYTE*)CNBuffer + segSize * (size_t)i, segSize, 2270*3117ece4Schristos 5) ); 2271*3117ece4Schristos off += r; 2272*3117ece4Schristos if (i == segs/2) { 2273*3117ece4Schristos /* insert skippable frame */ 2274*3117ece4Schristos size_t const skippableSize = 2275*3117ece4Schristos ZSTD_writeSkippableFrame((BYTE*)compressedBuffer + off, compressedBufferSize, 2276*3117ece4Schristos skipBuff, skipLen, seed % 15); 2277*3117ece4Schristos CHECK_Z(skippableSize); 2278*3117ece4Schristos off += skippableSize; 2279*3117ece4Schristos } 2280*3117ece4Schristos } 2281*3117ece4Schristos cSize = off; 2282*3117ece4Schristos free(skipBuff); 2283*3117ece4Schristos } 2284*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2285*3117ece4Schristos 2286*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : get decompressed size of multiple frames : ", testNb++); 2287*3117ece4Schristos { unsigned long long const r = ZSTD_findDecompressedSize(compressedBuffer, cSize); 2288*3117ece4Schristos if (r != CNBuffSize / 2) goto _output_error; } 2289*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2290*3117ece4Schristos 2291*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : get tight decompressed bound of multiple frames : ", testNb++); 2292*3117ece4Schristos { unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, cSize); 2293*3117ece4Schristos if (bound != CNBuffSize / 2) goto _output_error; } 2294*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2295*3117ece4Schristos 2296*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress multiple frames : ", testNb++); 2297*3117ece4Schristos { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize)); 2298*3117ece4Schristos if (r != CNBuffSize / 2) goto _output_error; } 2299*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2300*3117ece4Schristos 2301*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++); 2302*3117ece4Schristos if (memcmp(decodedBuffer, CNBuffer, CNBuffSize / 2) != 0) goto _output_error; 2303*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2304*3117ece4Schristos 2305*3117ece4Schristos /* Simple API skippable frame test */ 2306*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : read/write a skippable frame : ", testNb++); 2307*3117ece4Schristos { U32 i; 2308*3117ece4Schristos unsigned readMagic; 2309*3117ece4Schristos unsigned long long receivedSize; 2310*3117ece4Schristos size_t skippableSize; 2311*3117ece4Schristos const U32 skipLen = 129 KB; 2312*3117ece4Schristos char* const skipBuff = (char*)malloc(skipLen); 2313*3117ece4Schristos assert(skipBuff != NULL); 2314*3117ece4Schristos for (i = 0; i < skipLen; i++) 2315*3117ece4Schristos skipBuff[i] = (char) ((seed + i) % 256); 2316*3117ece4Schristos skippableSize = ZSTD_writeSkippableFrame( 2317*3117ece4Schristos compressedBuffer, compressedBufferSize, 2318*3117ece4Schristos skipBuff, skipLen, seed % 15); 2319*3117ece4Schristos CHECK_Z(skippableSize); 2320*3117ece4Schristos CHECK_EQ(1, ZSTD_isSkippableFrame(compressedBuffer, skippableSize)); 2321*3117ece4Schristos receivedSize = ZSTD_readSkippableFrame(decodedBuffer, CNBuffSize, &readMagic, compressedBuffer, skippableSize); 2322*3117ece4Schristos CHECK_EQ(skippableSize, receivedSize + ZSTD_SKIPPABLEHEADERSIZE); 2323*3117ece4Schristos CHECK_EQ(seed % 15, readMagic); 2324*3117ece4Schristos if (memcmp(decodedBuffer, skipBuff, skipLen) != 0) goto _output_error; 2325*3117ece4Schristos 2326*3117ece4Schristos free(skipBuff); 2327*3117ece4Schristos } 2328*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2329*3117ece4Schristos 2330*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : read/write an empty skippable frame : ", testNb++); 2331*3117ece4Schristos { 2332*3117ece4Schristos unsigned readMagic; 2333*3117ece4Schristos unsigned long long receivedSize; 2334*3117ece4Schristos size_t skippableSize; 2335*3117ece4Schristos skippableSize = ZSTD_writeSkippableFrame( 2336*3117ece4Schristos compressedBuffer, compressedBufferSize, 2337*3117ece4Schristos CNBuffer, 0, seed % 15); 2338*3117ece4Schristos CHECK_EQ(ZSTD_SKIPPABLEHEADERSIZE, skippableSize); 2339*3117ece4Schristos CHECK_EQ(1, ZSTD_isSkippableFrame(compressedBuffer, skippableSize)); 2340*3117ece4Schristos receivedSize = ZSTD_readSkippableFrame(NULL, 0, &readMagic, compressedBuffer, skippableSize); 2341*3117ece4Schristos CHECK_EQ(skippableSize, receivedSize + ZSTD_SKIPPABLEHEADERSIZE); 2342*3117ece4Schristos CHECK_EQ(seed % 15, readMagic); 2343*3117ece4Schristos } 2344*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2345*3117ece4Schristos 2346*3117ece4Schristos /* Dictionary and CCtx Duplication tests */ 2347*3117ece4Schristos { ZSTD_CCtx* const ctxOrig = ZSTD_createCCtx(); 2348*3117ece4Schristos ZSTD_CCtx* const ctxDuplicated = ZSTD_createCCtx(); 2349*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 2350*3117ece4Schristos static const size_t dictSize = 551; 2351*3117ece4Schristos assert(dctx != NULL); assert(ctxOrig != NULL); assert(ctxDuplicated != NULL); 2352*3117ece4Schristos 2353*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : copy context too soon : ", testNb++); 2354*3117ece4Schristos { size_t const copyResult = ZSTD_copyCCtx(ctxDuplicated, ctxOrig, 0); 2355*3117ece4Schristos if (!ZSTD_isError(copyResult)) goto _output_error; } /* error must be detected */ 2356*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2357*3117ece4Schristos 2358*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : load dictionary into context : ", testNb++); 2359*3117ece4Schristos CHECK_Z( ZSTD_compressBegin_usingDict(ctxOrig, CNBuffer, dictSize, 2) ); 2360*3117ece4Schristos CHECK_Z( ZSTD_copyCCtx(ctxDuplicated, ctxOrig, 0) ); /* Begin_usingDict implies unknown srcSize, so match that */ 2361*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2362*3117ece4Schristos 2363*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress with flat dictionary : ", testNb++); 2364*3117ece4Schristos cSize = 0; 2365*3117ece4Schristos CHECKPLUS(r, ZSTD_compressEnd(ctxOrig, 2366*3117ece4Schristos compressedBuffer, compressedBufferSize, 2367*3117ece4Schristos (const char*)CNBuffer + dictSize, CNBuffSize - dictSize), 2368*3117ece4Schristos cSize += r); 2369*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2370*3117ece4Schristos 2371*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : frame built with flat dictionary should be decompressible : ", testNb++); 2372*3117ece4Schristos CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, 2373*3117ece4Schristos decodedBuffer, CNBuffSize, 2374*3117ece4Schristos compressedBuffer, cSize, 2375*3117ece4Schristos CNBuffer, dictSize), 2376*3117ece4Schristos if (r != CNBuffSize - dictSize) goto _output_error); 2377*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2378*3117ece4Schristos 2379*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress with duplicated context : ", testNb++); 2380*3117ece4Schristos { size_t const cSizeOrig = cSize; 2381*3117ece4Schristos cSize = 0; 2382*3117ece4Schristos CHECKPLUS(r, ZSTD_compressEnd(ctxDuplicated, 2383*3117ece4Schristos compressedBuffer, compressedBufferSize, 2384*3117ece4Schristos (const char*)CNBuffer + dictSize, CNBuffSize - dictSize), 2385*3117ece4Schristos cSize += r); 2386*3117ece4Schristos if (cSize != cSizeOrig) goto _output_error; /* should be identical ==> same size */ 2387*3117ece4Schristos } 2388*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2389*3117ece4Schristos 2390*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : frame built with duplicated context should be decompressible : ", testNb++); 2391*3117ece4Schristos CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, 2392*3117ece4Schristos decodedBuffer, CNBuffSize, 2393*3117ece4Schristos compressedBuffer, cSize, 2394*3117ece4Schristos CNBuffer, dictSize), 2395*3117ece4Schristos if (r != CNBuffSize - dictSize) goto _output_error); 2396*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2397*3117ece4Schristos 2398*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress with DDict : ", testNb++); 2399*3117ece4Schristos { ZSTD_DDict* const ddict = ZSTD_createDDict(CNBuffer, dictSize); 2400*3117ece4Schristos size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, ddict); 2401*3117ece4Schristos if (r != CNBuffSize - dictSize) goto _output_error; 2402*3117ece4Schristos DISPLAYLEVEL(3, "OK (size of DDict : %u) \n", (unsigned)ZSTD_sizeof_DDict(ddict)); 2403*3117ece4Schristos ZSTD_freeDDict(ddict); 2404*3117ece4Schristos } 2405*3117ece4Schristos 2406*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress with static DDict : ", testNb++); 2407*3117ece4Schristos { size_t const ddictBufferSize = ZSTD_estimateDDictSize(dictSize, ZSTD_dlm_byCopy); 2408*3117ece4Schristos void* const ddictBuffer = malloc(ddictBufferSize); 2409*3117ece4Schristos if (ddictBuffer == NULL) goto _output_error; 2410*3117ece4Schristos { const ZSTD_DDict* const ddict = ZSTD_initStaticDDict(ddictBuffer, ddictBufferSize, CNBuffer, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto); 2411*3117ece4Schristos size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, ddict); 2412*3117ece4Schristos if (r != CNBuffSize - dictSize) goto _output_error; 2413*3117ece4Schristos } 2414*3117ece4Schristos free(ddictBuffer); 2415*3117ece4Schristos DISPLAYLEVEL(3, "OK (size of static DDict : %u) \n", (unsigned)ddictBufferSize); 2416*3117ece4Schristos } 2417*3117ece4Schristos 2418*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check content size on duplicated context : ", testNb++); 2419*3117ece4Schristos { size_t const testSize = CNBuffSize / 3; 2420*3117ece4Schristos CHECK_Z( ZSTD_compressBegin(ctxOrig, ZSTD_defaultCLevel()) ); 2421*3117ece4Schristos CHECK_Z( ZSTD_copyCCtx(ctxDuplicated, ctxOrig, testSize) ); 2422*3117ece4Schristos 2423*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressEnd(ctxDuplicated, compressedBuffer, ZSTD_compressBound(testSize), 2424*3117ece4Schristos (const char*)CNBuffer + dictSize, testSize) ); 2425*3117ece4Schristos { ZSTD_frameHeader zfh; 2426*3117ece4Schristos if (ZSTD_getFrameHeader(&zfh, compressedBuffer, cSize)) goto _output_error; 2427*3117ece4Schristos if ((zfh.frameContentSize != testSize) && (zfh.frameContentSize != 0)) goto _output_error; 2428*3117ece4Schristos } } 2429*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2430*3117ece4Schristos 2431*3117ece4Schristos #if !defined(ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR) \ 2432*3117ece4Schristos && !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \ 2433*3117ece4Schristos && !defined(ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR) \ 2434*3117ece4Schristos && !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \ 2435*3117ece4Schristos && !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \ 2436*3117ece4Schristos && !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \ 2437*3117ece4Schristos && !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \ 2438*3117ece4Schristos && !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR) 2439*3117ece4Schristos /* Note : these tests should be replaced by proper regression tests, 2440*3117ece4Schristos * but existing ones do not focus on small data + dictionary + all levels. 2441*3117ece4Schristos */ 2442*3117ece4Schristos if ((int)(compressibility * 100 + 0.1) == FUZ_compressibility_default) { /* test only valid with known input */ 2443*3117ece4Schristos size_t const flatdictSize = 22 KB; 2444*3117ece4Schristos size_t const contentSize = 9 KB; 2445*3117ece4Schristos const void* const dict = (const char*)CNBuffer; 2446*3117ece4Schristos const void* const contentStart = (const char*)dict + flatdictSize; 2447*3117ece4Schristos /* These upper bounds are generally within a few bytes of the compressed size */ 2448*3117ece4Schristos size_t target_nodict_cSize[22+1] = { 3840, 3770, 3870, 3830, 3770, 2449*3117ece4Schristos 3770, 3770, 3770, 3750, 3750, 2450*3117ece4Schristos 3742, 3675, 3674, 3665, 3664, 2451*3117ece4Schristos 3663, 3662, 3661, 3660, 3660, 2452*3117ece4Schristos 3660, 3660, 3660 }; 2453*3117ece4Schristos size_t const target_wdict_cSize[22+1] = { 2830, 2896, 2893, 2820, 2940, 2454*3117ece4Schristos 2950, 2950, 2925, 2900, 2892, 2455*3117ece4Schristos 2910, 2910, 2910, 2780, 2775, 2456*3117ece4Schristos 2765, 2760, 2755, 2754, 2753, 2457*3117ece4Schristos 2753, 2753, 2753 }; 2458*3117ece4Schristos int l = 1; 2459*3117ece4Schristos int const maxLevel = ZSTD_maxCLevel(); 2460*3117ece4Schristos /* clevels with strategies that support rowhash on small inputs */ 2461*3117ece4Schristos int rowLevel = 4; 2462*3117ece4Schristos int const rowLevelEnd = 8; 2463*3117ece4Schristos 2464*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : flat-dictionary efficiency test : \n", testNb++); 2465*3117ece4Schristos assert(maxLevel == 22); 2466*3117ece4Schristos RDG_genBuffer(CNBuffer, flatdictSize + contentSize, compressibility, 0., seed); 2467*3117ece4Schristos DISPLAYLEVEL(4, "content hash : %016llx; dict hash : %016llx \n", 2468*3117ece4Schristos (unsigned long long)XXH64(contentStart, contentSize, 0), 2469*3117ece4Schristos (unsigned long long)XXH64(dict, flatdictSize, 0)); 2470*3117ece4Schristos 2471*3117ece4Schristos for ( ; l <= maxLevel; l++) { 2472*3117ece4Schristos size_t const nodict_cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, 2473*3117ece4Schristos contentStart, contentSize, l); 2474*3117ece4Schristos if (nodict_cSize > target_nodict_cSize[l]) { 2475*3117ece4Schristos DISPLAYLEVEL(1, "error : compression at level %i worse than expected (%u > %u) \n", 2476*3117ece4Schristos l, (unsigned)nodict_cSize, (unsigned)target_nodict_cSize[l]); 2477*3117ece4Schristos goto _output_error; 2478*3117ece4Schristos } 2479*3117ece4Schristos DISPLAYLEVEL(4, "level %i : max expected %u >= reached %u \n", 2480*3117ece4Schristos l, (unsigned)target_nodict_cSize[l], (unsigned)nodict_cSize); 2481*3117ece4Schristos } 2482*3117ece4Schristos for ( l=1 ; l <= maxLevel; l++) { 2483*3117ece4Schristos size_t const wdict_cSize = ZSTD_compress_usingDict(ctxOrig, 2484*3117ece4Schristos compressedBuffer, compressedBufferSize, 2485*3117ece4Schristos contentStart, contentSize, 2486*3117ece4Schristos dict, flatdictSize, 2487*3117ece4Schristos l); 2488*3117ece4Schristos if (wdict_cSize > target_wdict_cSize[l]) { 2489*3117ece4Schristos DISPLAYLEVEL(1, "error : compression with dictionary at level %i worse than expected (%u > %u) \n", 2490*3117ece4Schristos l, (unsigned)wdict_cSize, (unsigned)target_wdict_cSize[l]); 2491*3117ece4Schristos goto _output_error; 2492*3117ece4Schristos } 2493*3117ece4Schristos DISPLAYLEVEL(4, "level %i with dictionary : max expected %u >= reached %u \n", 2494*3117ece4Schristos l, (unsigned)target_wdict_cSize[l], (unsigned)wdict_cSize); 2495*3117ece4Schristos } 2496*3117ece4Schristos /* Compression with ZSTD_compress2 and row match finder force enabled. 2497*3117ece4Schristos * Give some slack for force-enabled row matchfinder since we're on a small input (9KB) 2498*3117ece4Schristos */ 2499*3117ece4Schristos for ( ; rowLevel <= rowLevelEnd; ++rowLevel) target_nodict_cSize[rowLevel] += 5; 2500*3117ece4Schristos for (l=1 ; l <= maxLevel; l++) { 2501*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 2502*3117ece4Schristos size_t nodict_cSize; 2503*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, l); 2504*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_useRowMatchFinder, ZSTD_ps_enable); 2505*3117ece4Schristos nodict_cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, 2506*3117ece4Schristos contentStart, contentSize); 2507*3117ece4Schristos if (nodict_cSize > target_nodict_cSize[l]) { 2508*3117ece4Schristos DISPLAYLEVEL(1, "error : compression with compress2 at level %i worse than expected (%u > %u) \n", 2509*3117ece4Schristos l, (unsigned)nodict_cSize, (unsigned)target_nodict_cSize[l]); 2510*3117ece4Schristos ZSTD_freeCCtx(cctx); 2511*3117ece4Schristos goto _output_error; 2512*3117ece4Schristos } 2513*3117ece4Schristos DISPLAYLEVEL(4, "level %i with compress2 : max expected %u >= reached %u \n", 2514*3117ece4Schristos l, (unsigned)target_nodict_cSize[l], (unsigned)nodict_cSize); 2515*3117ece4Schristos ZSTD_freeCCtx(cctx); 2516*3117ece4Schristos } 2517*3117ece4Schristos /* Dict compression with DMS */ 2518*3117ece4Schristos for ( l=1 ; l <= maxLevel; l++) { 2519*3117ece4Schristos size_t wdict_cSize; 2520*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(ctxOrig, dict, flatdictSize) ); 2521*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(ctxOrig, ZSTD_c_compressionLevel, l) ); 2522*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(ctxOrig, ZSTD_c_enableDedicatedDictSearch, 0) ); 2523*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(ctxOrig, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach) ); 2524*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(ctxOrig, ZSTD_c_prefetchCDictTables, seed % 3) ); 2525*3117ece4Schristos wdict_cSize = ZSTD_compress2(ctxOrig, compressedBuffer, compressedBufferSize, contentStart, contentSize); 2526*3117ece4Schristos if (wdict_cSize > target_wdict_cSize[l]) { 2527*3117ece4Schristos DISPLAYLEVEL(1, "error : compression with dictionary and compress2 at level %i worse than expected (%u > %u) \n", 2528*3117ece4Schristos l, (unsigned)wdict_cSize, (unsigned)target_wdict_cSize[l]); 2529*3117ece4Schristos goto _output_error; 2530*3117ece4Schristos } 2531*3117ece4Schristos DISPLAYLEVEL(4, "level %i with dictionary and compress2 : max expected %u >= reached %u \n", 2532*3117ece4Schristos l, (unsigned)target_wdict_cSize[l], (unsigned)wdict_cSize); 2533*3117ece4Schristos } 2534*3117ece4Schristos 2535*3117ece4Schristos DISPLAYLEVEL(4, "compression efficiency tests OK \n"); 2536*3117ece4Schristos } 2537*3117ece4Schristos #endif 2538*3117ece4Schristos 2539*3117ece4Schristos ZSTD_freeCCtx(ctxOrig); 2540*3117ece4Schristos ZSTD_freeCCtx(ctxDuplicated); 2541*3117ece4Schristos ZSTD_freeDCtx(dctx); 2542*3117ece4Schristos } 2543*3117ece4Schristos 2544*3117ece4Schristos /* Dictionary and dictBuilder tests */ 2545*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 2546*3117ece4Schristos size_t const dictBufferCapacity = 16 KB; 2547*3117ece4Schristos void* const dictBuffer = malloc(dictBufferCapacity); 2548*3117ece4Schristos size_t const totalSampleSize = 1 MB; 2549*3117ece4Schristos size_t const sampleUnitSize = 8 KB; 2550*3117ece4Schristos U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize); 2551*3117ece4Schristos size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t)); 2552*3117ece4Schristos size_t dictSize; 2553*3117ece4Schristos U32 dictID; 2554*3117ece4Schristos size_t dictHeaderSize; 2555*3117ece4Schristos size_t dictBufferFixedSize = 144; 2556*3117ece4Schristos unsigned char const dictBufferFixed[144] = {0x37, 0xa4, 0x30, 0xec, 0x63, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x1f, 2557*3117ece4Schristos 0x0f, 0x00, 0x28, 0xe5, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2558*3117ece4Schristos 0x00, 0x80, 0x0f, 0x9e, 0x0f, 0x00, 0x00, 0x24, 0x40, 0x80, 0x00, 0x01, 2559*3117ece4Schristos 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0xde, 0x08, 2560*3117ece4Schristos 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 2561*3117ece4Schristos 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 2562*3117ece4Schristos 0x08, 0x08, 0x08, 0x08, 0xbc, 0xe1, 0x4b, 0x92, 0x0e, 0xb4, 0x7b, 0x18, 2563*3117ece4Schristos 0x86, 0x61, 0x18, 0xc6, 0x18, 0x63, 0x8c, 0x31, 0xc6, 0x18, 0x63, 0x8c, 2564*3117ece4Schristos 0x31, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x04, 2565*3117ece4Schristos 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x73, 0x6f, 0x64, 0x61, 2566*3117ece4Schristos 0x6c, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x72, 0x74, 0x6f, 0x72, 0x20, 0x65, 2567*3117ece4Schristos 0x6c, 0x65, 0x69, 0x66, 0x65, 0x6e, 0x64, 0x2e, 0x20, 0x41, 0x6c, 0x69}; 2568*3117ece4Schristos 2569*3117ece4Schristos if (dictBuffer==NULL || samplesSizes==NULL) { 2570*3117ece4Schristos free(dictBuffer); 2571*3117ece4Schristos free(samplesSizes); 2572*3117ece4Schristos goto _output_error; 2573*3117ece4Schristos } 2574*3117ece4Schristos 2575*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : dictBuilder on cyclic data : ", testNb++); 2576*3117ece4Schristos assert(compressedBufferSize >= totalSampleSize); 2577*3117ece4Schristos { U32 u; for (u=0; u<totalSampleSize; u++) ((BYTE*)decodedBuffer)[u] = (BYTE)u; } 2578*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 2579*3117ece4Schristos { size_t const sDictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity, 2580*3117ece4Schristos decodedBuffer, samplesSizes, nbSamples); 2581*3117ece4Schristos if (ZDICT_isError(sDictSize)) goto _output_error; 2582*3117ece4Schristos DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)sDictSize); 2583*3117ece4Schristos } 2584*3117ece4Schristos 2585*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : dictBuilder : ", testNb++); 2586*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 2587*3117ece4Schristos dictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity, 2588*3117ece4Schristos CNBuffer, samplesSizes, nbSamples); 2589*3117ece4Schristos if (ZDICT_isError(dictSize)) goto _output_error; 2590*3117ece4Schristos DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); 2591*3117ece4Schristos 2592*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Multithreaded COVER dictBuilder : ", testNb++); 2593*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 2594*3117ece4Schristos { ZDICT_cover_params_t coverParams; 2595*3117ece4Schristos memset(&coverParams, 0, sizeof(coverParams)); 2596*3117ece4Schristos coverParams.steps = 8; 2597*3117ece4Schristos coverParams.nbThreads = 4; 2598*3117ece4Schristos dictSize = ZDICT_optimizeTrainFromBuffer_cover( 2599*3117ece4Schristos dictBuffer, dictBufferCapacity, 2600*3117ece4Schristos CNBuffer, samplesSizes, nbSamples/8, /* less samples for faster tests */ 2601*3117ece4Schristos &coverParams); 2602*3117ece4Schristos if (ZDICT_isError(dictSize)) goto _output_error; 2603*3117ece4Schristos } 2604*3117ece4Schristos DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); 2605*3117ece4Schristos 2606*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : COVER dictBuilder with shrinkDict: ", testNb++); 2607*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 2608*3117ece4Schristos { ZDICT_cover_params_t coverParams; 2609*3117ece4Schristos memset(&coverParams, 0, sizeof(coverParams)); 2610*3117ece4Schristos coverParams.steps = 8; 2611*3117ece4Schristos coverParams.nbThreads = 4; 2612*3117ece4Schristos coverParams.shrinkDict = 1; 2613*3117ece4Schristos coverParams.shrinkDictMaxRegression = 1; 2614*3117ece4Schristos dictSize = ZDICT_optimizeTrainFromBuffer_cover( 2615*3117ece4Schristos dictBuffer, dictBufferCapacity, 2616*3117ece4Schristos CNBuffer, samplesSizes, nbSamples/8, /* less samples for faster tests */ 2617*3117ece4Schristos &coverParams); 2618*3117ece4Schristos if (ZDICT_isError(dictSize)) goto _output_error; 2619*3117ece4Schristos } 2620*3117ece4Schristos DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); 2621*3117ece4Schristos 2622*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Multithreaded FASTCOVER dictBuilder : ", testNb++); 2623*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 2624*3117ece4Schristos { ZDICT_fastCover_params_t fastCoverParams; 2625*3117ece4Schristos memset(&fastCoverParams, 0, sizeof(fastCoverParams)); 2626*3117ece4Schristos fastCoverParams.steps = 8; 2627*3117ece4Schristos fastCoverParams.nbThreads = 4; 2628*3117ece4Schristos dictSize = ZDICT_optimizeTrainFromBuffer_fastCover( 2629*3117ece4Schristos dictBuffer, dictBufferCapacity, 2630*3117ece4Schristos CNBuffer, samplesSizes, nbSamples, 2631*3117ece4Schristos &fastCoverParams); 2632*3117ece4Schristos if (ZDICT_isError(dictSize)) goto _output_error; 2633*3117ece4Schristos } 2634*3117ece4Schristos DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); 2635*3117ece4Schristos 2636*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : FASTCOVER dictBuilder with shrinkDict: ", testNb++); 2637*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 2638*3117ece4Schristos { ZDICT_fastCover_params_t fastCoverParams; 2639*3117ece4Schristos memset(&fastCoverParams, 0, sizeof(fastCoverParams)); 2640*3117ece4Schristos fastCoverParams.steps = 8; 2641*3117ece4Schristos fastCoverParams.nbThreads = 4; 2642*3117ece4Schristos fastCoverParams.shrinkDict = 1; 2643*3117ece4Schristos fastCoverParams.shrinkDictMaxRegression = 1; 2644*3117ece4Schristos dictSize = ZDICT_optimizeTrainFromBuffer_fastCover( 2645*3117ece4Schristos dictBuffer, dictBufferCapacity, 2646*3117ece4Schristos CNBuffer, samplesSizes, nbSamples, 2647*3117ece4Schristos &fastCoverParams); 2648*3117ece4Schristos if (ZDICT_isError(dictSize)) goto _output_error; 2649*3117ece4Schristos } 2650*3117ece4Schristos DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); 2651*3117ece4Schristos 2652*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++); 2653*3117ece4Schristos dictID = ZDICT_getDictID(dictBuffer, dictSize); 2654*3117ece4Schristos if (dictID==0) goto _output_error; 2655*3117ece4Schristos DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID); 2656*3117ece4Schristos 2657*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check dict header size no error : ", testNb++); 2658*3117ece4Schristos dictHeaderSize = ZDICT_getDictHeaderSize(dictBuffer, dictSize); 2659*3117ece4Schristos if (dictHeaderSize==0) goto _output_error; 2660*3117ece4Schristos DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictHeaderSize); 2661*3117ece4Schristos 2662*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check dict header size correctness : ", testNb++); 2663*3117ece4Schristos { dictHeaderSize = ZDICT_getDictHeaderSize(dictBufferFixed, dictBufferFixedSize); 2664*3117ece4Schristos if (dictHeaderSize != 115) goto _output_error; 2665*3117ece4Schristos } 2666*3117ece4Schristos DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictHeaderSize); 2667*3117ece4Schristos 2668*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress with dictionary : ", testNb++); 2669*3117ece4Schristos cSize = ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize, 2670*3117ece4Schristos CNBuffer, CNBuffSize, 2671*3117ece4Schristos dictBuffer, dictSize, 4); 2672*3117ece4Schristos if (ZSTD_isError(cSize)) goto _output_error; 2673*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2674*3117ece4Schristos 2675*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : retrieve dictID from dictionary : ", testNb++); 2676*3117ece4Schristos { U32 const did = ZSTD_getDictID_fromDict(dictBuffer, dictSize); 2677*3117ece4Schristos if (did != dictID) goto _output_error; /* non-conformant (content-only) dictionary */ 2678*3117ece4Schristos } 2679*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2680*3117ece4Schristos 2681*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : retrieve dictID from frame : ", testNb++); 2682*3117ece4Schristos { U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize); 2683*3117ece4Schristos if (did != dictID) goto _output_error; /* non-conformant (content-only) dictionary */ 2684*3117ece4Schristos } 2685*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2686*3117ece4Schristos 2687*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : frame built with dictionary should be decompressible : ", testNb++); 2688*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); 2689*3117ece4Schristos CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, 2690*3117ece4Schristos decodedBuffer, CNBuffSize, 2691*3117ece4Schristos compressedBuffer, cSize, 2692*3117ece4Schristos dictBuffer, dictSize), 2693*3117ece4Schristos if (r != CNBuffSize) goto _output_error); 2694*3117ece4Schristos ZSTD_freeDCtx(dctx); 2695*3117ece4Schristos } 2696*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2697*3117ece4Schristos 2698*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : estimate CDict size : ", testNb++); 2699*3117ece4Schristos { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); 2700*3117ece4Schristos size_t const estimatedSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byRef); 2701*3117ece4Schristos DISPLAYLEVEL(3, "OK : %u \n", (unsigned)estimatedSize); 2702*3117ece4Schristos } 2703*3117ece4Schristos 2704*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress with CDict ", testNb++); 2705*3117ece4Schristos { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); 2706*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, 2707*3117ece4Schristos ZSTD_dlm_byRef, ZSTD_dct_auto, 2708*3117ece4Schristos cParams, ZSTD_defaultCMem); 2709*3117ece4Schristos assert(cdict != NULL); 2710*3117ece4Schristos DISPLAYLEVEL(3, "(size : %u) : ", (unsigned)ZSTD_sizeof_CDict(cdict)); 2711*3117ece4Schristos assert(ZSTD_getDictID_fromDict(dictBuffer, dictSize) == ZSTD_getDictID_fromCDict(cdict)); 2712*3117ece4Schristos cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, 2713*3117ece4Schristos CNBuffer, CNBuffSize, cdict); 2714*3117ece4Schristos ZSTD_freeCDict(cdict); 2715*3117ece4Schristos if (ZSTD_isError(cSize)) goto _output_error; 2716*3117ece4Schristos } 2717*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2718*3117ece4Schristos 2719*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : retrieve dictID from frame : ", testNb++); 2720*3117ece4Schristos { U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize); 2721*3117ece4Schristos if (did != dictID) goto _output_error; /* non-conformant (content-only) dictionary */ 2722*3117ece4Schristos } 2723*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2724*3117ece4Schristos 2725*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : frame built with dictionary should be decompressible : ", testNb++); 2726*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); 2727*3117ece4Schristos CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, 2728*3117ece4Schristos decodedBuffer, CNBuffSize, 2729*3117ece4Schristos compressedBuffer, cSize, 2730*3117ece4Schristos dictBuffer, dictSize), 2731*3117ece4Schristos if (r != CNBuffSize) goto _output_error); 2732*3117ece4Schristos ZSTD_freeDCtx(dctx); 2733*3117ece4Schristos } 2734*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2735*3117ece4Schristos 2736*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress with static CDict : ", testNb++); 2737*3117ece4Schristos { int const maxLevel = ZSTD_maxCLevel(); 2738*3117ece4Schristos int level; 2739*3117ece4Schristos for (level = 1; level <= maxLevel; ++level) { 2740*3117ece4Schristos ZSTD_compressionParameters const cParams = ZSTD_getCParams(level, CNBuffSize, dictSize); 2741*3117ece4Schristos size_t const cdictSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); 2742*3117ece4Schristos void* const cdictBuffer = malloc(cdictSize); 2743*3117ece4Schristos if (cdictBuffer==NULL) goto _output_error; 2744*3117ece4Schristos { const ZSTD_CDict* const cdict = ZSTD_initStaticCDict( 2745*3117ece4Schristos cdictBuffer, cdictSize, 2746*3117ece4Schristos dictBuffer, dictSize, 2747*3117ece4Schristos ZSTD_dlm_byCopy, ZSTD_dct_auto, 2748*3117ece4Schristos cParams); 2749*3117ece4Schristos if (cdict == NULL) { 2750*3117ece4Schristos DISPLAY("ZSTD_initStaticCDict failed "); 2751*3117ece4Schristos goto _output_error; 2752*3117ece4Schristos } 2753*3117ece4Schristos cSize = ZSTD_compress_usingCDict(cctx, 2754*3117ece4Schristos compressedBuffer, compressedBufferSize, 2755*3117ece4Schristos CNBuffer, MIN(10 KB, CNBuffSize), cdict); 2756*3117ece4Schristos if (ZSTD_isError(cSize)) { 2757*3117ece4Schristos DISPLAY("ZSTD_compress_usingCDict failed "); 2758*3117ece4Schristos goto _output_error; 2759*3117ece4Schristos } } 2760*3117ece4Schristos free(cdictBuffer); 2761*3117ece4Schristos } } 2762*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2763*3117ece4Schristos 2764*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compress_usingCDict_advanced, no contentSize, no dictID : ", testNb++); 2765*3117ece4Schristos { ZSTD_frameParameters const fParams = { 0 /* frameSize */, 1 /* checksum */, 1 /* noDictID*/ }; 2766*3117ece4Schristos ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); 2767*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); 2768*3117ece4Schristos assert(cdict != NULL); 2769*3117ece4Schristos cSize = ZSTD_compress_usingCDict_advanced(cctx, 2770*3117ece4Schristos compressedBuffer, compressedBufferSize, 2771*3117ece4Schristos CNBuffer, CNBuffSize, 2772*3117ece4Schristos cdict, fParams); 2773*3117ece4Schristos ZSTD_freeCDict(cdict); 2774*3117ece4Schristos if (ZSTD_isError(cSize)) goto _output_error; 2775*3117ece4Schristos } 2776*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2777*3117ece4Schristos 2778*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : try retrieving contentSize from frame : ", testNb++); 2779*3117ece4Schristos { U64 const contentSize = ZSTD_getFrameContentSize(compressedBuffer, cSize); 2780*3117ece4Schristos if (contentSize != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error; 2781*3117ece4Schristos } 2782*3117ece4Schristos DISPLAYLEVEL(3, "OK (unknown)\n"); 2783*3117ece4Schristos 2784*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : frame built without dictID should be decompressible : ", testNb++); 2785*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 2786*3117ece4Schristos assert(dctx != NULL); 2787*3117ece4Schristos CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, 2788*3117ece4Schristos decodedBuffer, CNBuffSize, 2789*3117ece4Schristos compressedBuffer, cSize, 2790*3117ece4Schristos dictBuffer, dictSize), 2791*3117ece4Schristos if (r != CNBuffSize) goto _output_error); 2792*3117ece4Schristos ZSTD_freeDCtx(dctx); 2793*3117ece4Schristos } 2794*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2795*3117ece4Schristos 2796*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_compress_advanced, no dictID : ", testNb++); 2797*3117ece4Schristos { ZSTD_parameters p = ZSTD_getParams(3, CNBuffSize, dictSize); 2798*3117ece4Schristos p.fParams.noDictIDFlag = 1; 2799*3117ece4Schristos cSize = ZSTD_compress_advanced(cctx, compressedBuffer, compressedBufferSize, 2800*3117ece4Schristos CNBuffer, CNBuffSize, 2801*3117ece4Schristos dictBuffer, dictSize, p); 2802*3117ece4Schristos if (ZSTD_isError(cSize)) goto _output_error; 2803*3117ece4Schristos } 2804*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); 2805*3117ece4Schristos 2806*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : frame built without dictID should be decompressible : ", testNb++); 2807*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); 2808*3117ece4Schristos CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, 2809*3117ece4Schristos decodedBuffer, CNBuffSize, 2810*3117ece4Schristos compressedBuffer, cSize, 2811*3117ece4Schristos dictBuffer, dictSize), 2812*3117ece4Schristos if (r != CNBuffSize) goto _output_error); 2813*3117ece4Schristos ZSTD_freeDCtx(dctx); 2814*3117ece4Schristos } 2815*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2816*3117ece4Schristos 2817*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : dictionary containing only header should return error : ", testNb++); 2818*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 2819*3117ece4Schristos assert(dctx != NULL); 2820*3117ece4Schristos { const size_t ret = ZSTD_decompress_usingDict( 2821*3117ece4Schristos dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, 2822*3117ece4Schristos "\x37\xa4\x30\xec\x11\x22\x33\x44", 8); 2823*3117ece4Schristos if (ZSTD_getErrorCode(ret) != ZSTD_error_dictionary_corrupted) 2824*3117ece4Schristos goto _output_error; 2825*3117ece4Schristos } 2826*3117ece4Schristos ZSTD_freeDCtx(dctx); 2827*3117ece4Schristos } 2828*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2829*3117ece4Schristos 2830*3117ece4Schristos DISPLAYLEVEL(3, "test%3d : bufferless api with cdict : ", testNb++); 2831*3117ece4Schristos { ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1); 2832*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 2833*3117ece4Schristos ZSTD_frameParameters const fParams = { 0, 1, 0 }; 2834*3117ece4Schristos size_t cBlockSize; 2835*3117ece4Schristos cSize = 0; 2836*3117ece4Schristos CHECK_Z(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN)); 2837*3117ece4Schristos cBlockSize = ZSTD_compressContinue(cctx, (char*)compressedBuffer + cSize, compressedBufferSize - cSize, CNBuffer, 1000); 2838*3117ece4Schristos CHECK_Z(cBlockSize); 2839*3117ece4Schristos cSize += cBlockSize; 2840*3117ece4Schristos cBlockSize = ZSTD_compressEnd(cctx, (char*)compressedBuffer + cSize, compressedBufferSize - cSize, (char const*)CNBuffer + 2000, 1000); 2841*3117ece4Schristos CHECK_Z(cBlockSize); 2842*3117ece4Schristos cSize += cBlockSize; 2843*3117ece4Schristos 2844*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dictBuffer, dictSize)); 2845*3117ece4Schristos 2846*3117ece4Schristos ZSTD_freeCDict(cdict); 2847*3117ece4Schristos ZSTD_freeDCtx(dctx); 2848*3117ece4Schristos } 2849*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2850*3117ece4Schristos 2851*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Building cdict w/ ZSTD_dct_fullDict on a good dictionary : ", testNb++); 2852*3117ece4Schristos { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); 2853*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem); 2854*3117ece4Schristos if (cdict==NULL) goto _output_error; 2855*3117ece4Schristos ZSTD_freeCDict(cdict); 2856*3117ece4Schristos } 2857*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2858*3117ece4Schristos 2859*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Building cdict w/ ZSTD_dct_fullDict on a rawContent (must fail) : ", testNb++); 2860*3117ece4Schristos { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); 2861*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict_advanced((const char*)dictBuffer+1, dictSize-1, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem); 2862*3117ece4Schristos if (cdict!=NULL) goto _output_error; 2863*3117ece4Schristos ZSTD_freeCDict(cdict); 2864*3117ece4Schristos } 2865*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2866*3117ece4Schristos 2867*3117ece4Schristos { char* rawDictBuffer = (char*)malloc(dictSize); 2868*3117ece4Schristos assert(rawDictBuffer); 2869*3117ece4Schristos memcpy(rawDictBuffer, (char*)dictBuffer + 2, dictSize - 2); 2870*3117ece4Schristos memset(rawDictBuffer + dictSize - 2, 0, 2); 2871*3117ece4Schristos MEM_writeLE32((char*)rawDictBuffer, ZSTD_MAGIC_DICTIONARY); 2872*3117ece4Schristos 2873*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading rawContent starting with dict header w/ ZSTD_dct_auto should fail : ", testNb++); 2874*3117ece4Schristos { 2875*3117ece4Schristos size_t ret; 2876*3117ece4Schristos /* Either operation is allowed to fail, but one must fail. */ 2877*3117ece4Schristos ret = ZSTD_CCtx_loadDictionary_advanced( 2878*3117ece4Schristos cctx, (const char*)rawDictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto); 2879*3117ece4Schristos if (!ZSTD_isError(ret)) { 2880*3117ece4Schristos ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)); 2881*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 2882*3117ece4Schristos } 2883*3117ece4Schristos } 2884*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2885*3117ece4Schristos 2886*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading rawContent starting with dict header w/ ZSTD_dct_rawContent should pass : ", testNb++); 2887*3117ece4Schristos { 2888*3117ece4Schristos size_t ret; 2889*3117ece4Schristos ret = ZSTD_CCtx_loadDictionary_advanced( 2890*3117ece4Schristos cctx, (const char*)rawDictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent); 2891*3117ece4Schristos if (ZSTD_isError(ret)) goto _output_error; 2892*3117ece4Schristos ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)); 2893*3117ece4Schristos if (ZSTD_isError(ret)) goto _output_error; 2894*3117ece4Schristos } 2895*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2896*3117ece4Schristos 2897*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Testing non-attached CDict with ZSTD_dct_rawContent : ", testNb++); 2898*3117ece4Schristos { size_t const srcSize = MIN(CNBuffSize, 100); 2899*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2900*3117ece4Schristos /* Force the dictionary to be reloaded in raw content mode */ 2901*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceLoad)); 2902*3117ece4Schristos CHECK_Z(ZSTD_CCtx_loadDictionary_advanced(cctx, rawDictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent)); 2903*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize); 2904*3117ece4Schristos CHECK_Z(cSize); 2905*3117ece4Schristos } 2906*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2907*3117ece4Schristos 2908*3117ece4Schristos free(rawDictBuffer); 2909*3117ece4Schristos } 2910*3117ece4Schristos 2911*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_CCtx_refCDict() then set parameters : ", testNb++); 2912*3117ece4Schristos { ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 1); 2913*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2914*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) ); 2915*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 )); 2916*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) ); 2917*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) ); 2918*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 )); 2919*3117ece4Schristos ZSTD_freeCDict(cdict); 2920*3117ece4Schristos } 2921*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2922*3117ece4Schristos 2923*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading dictionary before setting parameters is the same as loading after : ", testNb++); 2924*3117ece4Schristos { 2925*3117ece4Schristos size_t size1, size2; 2926*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2927*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) ); 2928*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) ); 2929*3117ece4Schristos size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB)); 2930*3117ece4Schristos if (ZSTD_isError(size1)) goto _output_error; 2931*3117ece4Schristos 2932*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 2933*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) ); 2934*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) ); 2935*3117ece4Schristos size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB)); 2936*3117ece4Schristos if (ZSTD_isError(size2)) goto _output_error; 2937*3117ece4Schristos 2938*3117ece4Schristos if (size1 != size2) goto _output_error; 2939*3117ece4Schristos } 2940*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2941*3117ece4Schristos 2942*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the prefix : ", testNb++); 2943*3117ece4Schristos { 2944*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) ); 2945*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) ); 2946*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) ); 2947*3117ece4Schristos } 2948*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2949*3117ece4Schristos 2950*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the cdict : ", testNb++); 2951*3117ece4Schristos { 2952*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1); 2953*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) ); 2954*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) ); 2955*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) ); 2956*3117ece4Schristos ZSTD_freeCDict(cdict); 2957*3117ece4Schristos } 2958*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2959*3117ece4Schristos 2960*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the prefix : ", testNb++); 2961*3117ece4Schristos { 2962*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1); 2963*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) ); 2964*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) ); 2965*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) ); 2966*3117ece4Schristos ZSTD_freeCDict(cdict); 2967*3117ece4Schristos } 2968*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2969*3117ece4Schristos 2970*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the dictionary : ", testNb++); 2971*3117ece4Schristos { 2972*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1); 2973*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) ); 2974*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) ); 2975*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) ); 2976*3117ece4Schristos ZSTD_freeCDict(cdict); 2977*3117ece4Schristos } 2978*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2979*3117ece4Schristos 2980*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the dictionary : ", testNb++); 2981*3117ece4Schristos { 2982*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) ); 2983*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) ); 2984*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) ); 2985*3117ece4Schristos } 2986*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2987*3117ece4Schristos 2988*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the cdict : ", testNb++); 2989*3117ece4Schristos { 2990*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1); 2991*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) ); 2992*3117ece4Schristos CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) ); 2993*3117ece4Schristos CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) ); 2994*3117ece4Schristos ZSTD_freeCDict(cdict); 2995*3117ece4Schristos } 2996*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 2997*3117ece4Schristos 2998*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loaded dictionary persists across reset session : ", testNb++); 2999*3117ece4Schristos { 3000*3117ece4Schristos size_t size1, size2; 3001*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 3002*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) ); 3003*3117ece4Schristos size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB)); 3004*3117ece4Schristos if (ZSTD_isError(size1)) goto _output_error; 3005*3117ece4Schristos 3006*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); 3007*3117ece4Schristos size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB)); 3008*3117ece4Schristos if (ZSTD_isError(size2)) goto _output_error; 3009*3117ece4Schristos 3010*3117ece4Schristos if (size1 != size2) goto _output_error; 3011*3117ece4Schristos } 3012*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3013*3117ece4Schristos 3014*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Loaded dictionary is cleared after resetting parameters : ", testNb++); 3015*3117ece4Schristos { 3016*3117ece4Schristos size_t size1, size2; 3017*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 3018*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) ); 3019*3117ece4Schristos size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB)); 3020*3117ece4Schristos if (ZSTD_isError(size1)) goto _output_error; 3021*3117ece4Schristos 3022*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 3023*3117ece4Schristos size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB)); 3024*3117ece4Schristos if (ZSTD_isError(size2)) goto _output_error; 3025*3117ece4Schristos 3026*3117ece4Schristos if (size1 == size2) goto _output_error; 3027*3117ece4Schristos } 3028*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3029*3117ece4Schristos 3030*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 3031*3117ece4Schristos CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, dictBuffer, dictSize) ); 3032*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB)); 3033*3117ece4Schristos CHECK_Z(cSize); 3034*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with dictionary : ", testNb++); 3035*3117ece4Schristos { 3036*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 3037*3117ece4Schristos size_t ret; 3038*3117ece4Schristos /* We should fail to decompress without a dictionary. */ 3039*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3040*3117ece4Schristos ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); 3041*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 3042*3117ece4Schristos /* We should succeed to decompress with the dictionary. */ 3043*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3044*3117ece4Schristos CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictSize) ); 3045*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) ); 3046*3117ece4Schristos /* The dictionary should persist across calls. */ 3047*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) ); 3048*3117ece4Schristos /* When we reset the context the dictionary is cleared. */ 3049*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3050*3117ece4Schristos ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); 3051*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 3052*3117ece4Schristos ZSTD_freeDCtx(dctx); 3053*3117ece4Schristos } 3054*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3055*3117ece4Schristos 3056*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with ddict : ", testNb++); 3057*3117ece4Schristos { 3058*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 3059*3117ece4Schristos ZSTD_DDict* ddict = ZSTD_createDDict(dictBuffer, dictSize); 3060*3117ece4Schristos size_t ret; 3061*3117ece4Schristos /* We should succeed to decompress with the ddict. */ 3062*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3063*3117ece4Schristos CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) ); 3064*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) ); 3065*3117ece4Schristos /* The ddict should persist across calls. */ 3066*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) ); 3067*3117ece4Schristos /* When we reset the context the ddict is cleared. */ 3068*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3069*3117ece4Schristos ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); 3070*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 3071*3117ece4Schristos ZSTD_freeDCtx(dctx); 3072*3117ece4Schristos ZSTD_freeDDict(ddict); 3073*3117ece4Schristos } 3074*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3075*3117ece4Schristos 3076*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with prefix : ", testNb++); 3077*3117ece4Schristos { 3078*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 3079*3117ece4Schristos size_t ret; 3080*3117ece4Schristos /* We should succeed to decompress with the prefix. */ 3081*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3082*3117ece4Schristos CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictBuffer, dictSize, ZSTD_dct_auto) ); 3083*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) ); 3084*3117ece4Schristos /* The prefix should be cleared after the first compression. */ 3085*3117ece4Schristos ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); 3086*3117ece4Schristos if (!ZSTD_isError(ret)) goto _output_error; 3087*3117ece4Schristos ZSTD_freeDCtx(dctx); 3088*3117ece4Schristos } 3089*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3090*3117ece4Schristos 3091*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_fast attach dictionary with hashLog = 25 and chainLog = 25 : ", testNb++); 3092*3117ece4Schristos { 3093*3117ece4Schristos ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams(); 3094*3117ece4Schristos ZSTD_customMem customMem = {NULL, NULL, NULL}; 3095*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 3096*3117ece4Schristos ZSTD_CDict* cdict; 3097*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_strategy, ZSTD_fast)); 3098*3117ece4Schristos /* Set windowLog to 25 so hash/chain logs don't get sized down */ 3099*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, 25)); 3100*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_hashLog, 25)); 3101*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_chainLog, 25)); 3102*3117ece4Schristos /* Set srcSizeHint to 2^25 so hash/chain logs don't get sized down */ 3103*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_srcSizeHint, 1u << 25)); 3104*3117ece4Schristos cdict = ZSTD_createCDict_advanced2(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cctxParams, customMem); 3105*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters)); 3106*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach)); 3107*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 3108*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict)); 3109*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 3110*3117ece4Schristos CHECK_Z(cSize); 3111*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dictBuffer, dictSize)); 3112*3117ece4Schristos ZSTD_freeCDict(cdict); 3113*3117ece4Schristos ZSTD_freeDCtx(dctx); 3114*3117ece4Schristos ZSTD_freeCCtxParams(cctxParams); 3115*3117ece4Schristos } 3116*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3117*3117ece4Schristos 3118*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_dfast attach dictionary with hashLog = 25 and chainLog = 25 : ", testNb++); 3119*3117ece4Schristos { 3120*3117ece4Schristos ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams(); 3121*3117ece4Schristos ZSTD_customMem customMem = {NULL, NULL, NULL}; 3122*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 3123*3117ece4Schristos ZSTD_CDict* cdict; 3124*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_strategy, ZSTD_dfast)); 3125*3117ece4Schristos /* Set windowLog to 25 so hash/chain logs don't get sized down */ 3126*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, 25)); 3127*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_hashLog, 25)); 3128*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_chainLog, 25)); 3129*3117ece4Schristos /* Set srcSizeHint to 2^25 so hash/chain logs don't get sized down */ 3130*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_srcSizeHint, 1u << 25)); 3131*3117ece4Schristos cdict = ZSTD_createCDict_advanced2(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cctxParams, customMem); 3132*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters)); 3133*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach)); 3134*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 3135*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict)); 3136*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 3137*3117ece4Schristos CHECK_Z(cSize); 3138*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dictBuffer, dictSize)); 3139*3117ece4Schristos ZSTD_freeCDict(cdict); 3140*3117ece4Schristos ZSTD_freeDCtx(dctx); 3141*3117ece4Schristos ZSTD_freeCCtxParams(cctxParams); 3142*3117ece4Schristos } 3143*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3144*3117ece4Schristos 3145*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_lazy attach dictionary with hashLog = 29 and searchLog = 4 : ", testNb++); 3146*3117ece4Schristos if (MEM_64bits()) { 3147*3117ece4Schristos ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams(); 3148*3117ece4Schristos ZSTD_customMem customMem = {NULL, NULL, NULL}; 3149*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 3150*3117ece4Schristos ZSTD_CDict* cdict; 3151*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_strategy, ZSTD_lazy)); 3152*3117ece4Schristos /* Force enable row based match finder, and disable dedicated dict search. */ 3153*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_useRowMatchFinder, ZSTD_ps_enable)); 3154*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_enableDedicatedDictSearch, 0)); 3155*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_searchLog, 4)); 3156*3117ece4Schristos /* Set windowLog to 29 so hash/chain logs don't get sized down */ 3157*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, 29)); 3158*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_hashLog, 29)); 3159*3117ece4Schristos /* Set srcSizeHint to 2^29 so hash/chain logs don't get sized down */ 3160*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_srcSizeHint, 1u << 29)); 3161*3117ece4Schristos cdict = ZSTD_createCDict_advanced2(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cctxParams, customMem); 3162*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters)); 3163*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach)); 3164*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 3165*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict)); 3166*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 3167*3117ece4Schristos CHECK_Z(cSize); 3168*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dictBuffer, dictSize)); 3169*3117ece4Schristos ZSTD_freeCDict(cdict); 3170*3117ece4Schristos ZSTD_freeDCtx(dctx); 3171*3117ece4Schristos ZSTD_freeCCtxParams(cctxParams); 3172*3117ece4Schristos } 3173*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3174*3117ece4Schristos 3175*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Dictionary with non-default repcodes : ", testNb++); 3176*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 3177*3117ece4Schristos dictSize = ZDICT_trainFromBuffer(dictBuffer, dictSize, 3178*3117ece4Schristos CNBuffer, samplesSizes, nbSamples); 3179*3117ece4Schristos if (ZDICT_isError(dictSize)) goto _output_error; 3180*3117ece4Schristos /* Set all the repcodes to non-default */ 3181*3117ece4Schristos { 3182*3117ece4Schristos BYTE* dictPtr = (BYTE*)dictBuffer; 3183*3117ece4Schristos BYTE* dictLimit = dictPtr + dictSize - 12; 3184*3117ece4Schristos /* Find the repcodes */ 3185*3117ece4Schristos while (dictPtr < dictLimit && 3186*3117ece4Schristos (MEM_readLE32(dictPtr) != 1 || MEM_readLE32(dictPtr + 4) != 4 || 3187*3117ece4Schristos MEM_readLE32(dictPtr + 8) != 8)) { 3188*3117ece4Schristos ++dictPtr; 3189*3117ece4Schristos } 3190*3117ece4Schristos if (dictPtr >= dictLimit) goto _output_error; 3191*3117ece4Schristos MEM_writeLE32(dictPtr + 0, 10); 3192*3117ece4Schristos MEM_writeLE32(dictPtr + 4, 10); 3193*3117ece4Schristos MEM_writeLE32(dictPtr + 8, 10); 3194*3117ece4Schristos /* Set the last 8 bytes to 'x' */ 3195*3117ece4Schristos memset((BYTE*)dictBuffer + dictSize - 8, 'x', 8); 3196*3117ece4Schristos } 3197*3117ece4Schristos /* The optimal parser checks all the repcodes. 3198*3117ece4Schristos * Make sure at least one is a match >= targetLength so that it is 3199*3117ece4Schristos * immediately chosen. This will make sure that the compressor and 3200*3117ece4Schristos * decompressor agree on at least one of the repcodes. 3201*3117ece4Schristos */ 3202*3117ece4Schristos { size_t dSize; 3203*3117ece4Schristos BYTE data[1024]; 3204*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 3205*3117ece4Schristos ZSTD_compressionParameters const cParams = ZSTD_getCParams(19, CNBuffSize, dictSize); 3206*3117ece4Schristos ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, 3207*3117ece4Schristos ZSTD_dlm_byRef, ZSTD_dct_auto, 3208*3117ece4Schristos cParams, ZSTD_defaultCMem); 3209*3117ece4Schristos assert(dctx != NULL); assert(cdict != NULL); 3210*3117ece4Schristos memset(data, 'x', sizeof(data)); 3211*3117ece4Schristos cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, 3212*3117ece4Schristos data, sizeof(data), cdict); 3213*3117ece4Schristos ZSTD_freeCDict(cdict); 3214*3117ece4Schristos if (ZSTD_isError(cSize)) { DISPLAYLEVEL(5, "Compression error %s : ", ZSTD_getErrorName(cSize)); goto _output_error; } 3215*3117ece4Schristos dSize = ZSTD_decompress_usingDict(dctx, decodedBuffer, sizeof(data), compressedBuffer, cSize, dictBuffer, dictSize); 3216*3117ece4Schristos if (ZSTD_isError(dSize)) { DISPLAYLEVEL(5, "Decompression error %s : ", ZSTD_getErrorName(dSize)); goto _output_error; } 3217*3117ece4Schristos if (memcmp(data, decodedBuffer, sizeof(data))) { DISPLAYLEVEL(5, "Data corruption : "); goto _output_error; } 3218*3117ece4Schristos ZSTD_freeDCtx(dctx); 3219*3117ece4Schristos } 3220*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3221*3117ece4Schristos 3222*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with multiple ddicts : ", testNb++); 3223*3117ece4Schristos { 3224*3117ece4Schristos const size_t numDicts = 128; 3225*3117ece4Schristos const size_t numFrames = 4; 3226*3117ece4Schristos size_t i; 3227*3117ece4Schristos ZSTD_DCtx* dctx = ZSTD_createDCtx(); 3228*3117ece4Schristos ZSTD_DDict** ddictTable = (ZSTD_DDict**)malloc(sizeof(ZSTD_DDict*)*numDicts); 3229*3117ece4Schristos ZSTD_CDict** cdictTable = (ZSTD_CDict**)malloc(sizeof(ZSTD_CDict*)*numDicts); 3230*3117ece4Schristos U32 dictIDSeed = seed; 3231*3117ece4Schristos /* Create new compressed buffer that will hold frames with differing dictIDs */ 3232*3117ece4Schristos char* dictBufferMulti = (char*)malloc(sizeof(char) * dictBufferFixedSize); /* Modifiable copy of fixed full dict buffer */ 3233*3117ece4Schristos 3234*3117ece4Schristos ZSTD_memcpy(dictBufferMulti, dictBufferFixed, dictBufferFixedSize); 3235*3117ece4Schristos /* Create a bunch of DDicts with random dict IDs */ 3236*3117ece4Schristos for (i = 0; i < numDicts; ++i) { 3237*3117ece4Schristos U32 currDictID = FUZ_rand(&dictIDSeed); 3238*3117ece4Schristos MEM_writeLE32(dictBufferMulti+ZSTD_FRAMEIDSIZE, currDictID); 3239*3117ece4Schristos ddictTable[i] = ZSTD_createDDict(dictBufferMulti, dictBufferFixedSize); 3240*3117ece4Schristos cdictTable[i] = ZSTD_createCDict(dictBufferMulti, dictBufferFixedSize, 3); 3241*3117ece4Schristos if (!ddictTable[i] || !cdictTable[i] || ZSTD_getDictID_fromCDict(cdictTable[i]) != ZSTD_getDictID_fromDDict(ddictTable[i])) { 3242*3117ece4Schristos goto _output_error; 3243*3117ece4Schristos } 3244*3117ece4Schristos } 3245*3117ece4Schristos /* Compress a few frames using random CDicts */ 3246*3117ece4Schristos { 3247*3117ece4Schristos size_t off = 0; 3248*3117ece4Schristos /* only use the first half so we don't push against size limit of compressedBuffer */ 3249*3117ece4Schristos size_t const segSize = (CNBuffSize / 2) / numFrames; 3250*3117ece4Schristos for (i = 0; i < numFrames; i++) { 3251*3117ece4Schristos size_t dictIdx = FUZ_rand(&dictIDSeed) % numDicts; 3252*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 3253*3117ece4Schristos { CHECK_NEWV(r, ZSTD_compress_usingCDict(cctx, 3254*3117ece4Schristos (BYTE*)compressedBuffer + off, CNBuffSize - off, 3255*3117ece4Schristos (BYTE*)CNBuffer + segSize * (size_t)i, segSize, 3256*3117ece4Schristos cdictTable[dictIdx])); 3257*3117ece4Schristos off += r; 3258*3117ece4Schristos } 3259*3117ece4Schristos } 3260*3117ece4Schristos cSize = off; 3261*3117ece4Schristos } 3262*3117ece4Schristos 3263*3117ece4Schristos /* We should succeed to decompression even though different dicts were used on different frames */ 3264*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3265*3117ece4Schristos ZSTD_DCtx_setParameter(dctx, ZSTD_d_refMultipleDDicts, ZSTD_rmd_refMultipleDDicts); 3266*3117ece4Schristos /* Reference every single ddict we made */ 3267*3117ece4Schristos for (i = 0; i < numDicts; ++i) { 3268*3117ece4Schristos CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddictTable[i])); 3269*3117ece4Schristos } 3270*3117ece4Schristos CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) ); 3271*3117ece4Schristos /* Streaming decompression should also work */ 3272*3117ece4Schristos { 3273*3117ece4Schristos ZSTD_inBuffer in = {compressedBuffer, cSize, 0}; 3274*3117ece4Schristos ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0}; 3275*3117ece4Schristos while (in.pos < in.size) { 3276*3117ece4Schristos CHECK_Z(ZSTD_decompressStream(dctx, &out, &in)); 3277*3117ece4Schristos } 3278*3117ece4Schristos } 3279*3117ece4Schristos ZSTD_freeDCtx(dctx); 3280*3117ece4Schristos for (i = 0; i < numDicts; ++i) { 3281*3117ece4Schristos ZSTD_freeCDict(cdictTable[i]); 3282*3117ece4Schristos ZSTD_freeDDict(ddictTable[i]); 3283*3117ece4Schristos } 3284*3117ece4Schristos free(dictBufferMulti); 3285*3117ece4Schristos free(ddictTable); 3286*3117ece4Schristos free(cdictTable); 3287*3117ece4Schristos } 3288*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3289*3117ece4Schristos 3290*3117ece4Schristos ZSTD_freeCCtx(cctx); 3291*3117ece4Schristos free(dictBuffer); 3292*3117ece4Schristos free(samplesSizes); 3293*3117ece4Schristos } 3294*3117ece4Schristos 3295*3117ece4Schristos /* COVER dictionary builder tests */ 3296*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3297*3117ece4Schristos size_t dictSize = 16 KB; 3298*3117ece4Schristos size_t optDictSize = dictSize; 3299*3117ece4Schristos void* dictBuffer = malloc(dictSize); 3300*3117ece4Schristos size_t const totalSampleSize = 1 MB; 3301*3117ece4Schristos size_t const sampleUnitSize = 8 KB; 3302*3117ece4Schristos U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize); 3303*3117ece4Schristos size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t)); 3304*3117ece4Schristos U32 seed32 = seed; 3305*3117ece4Schristos ZDICT_cover_params_t params; 3306*3117ece4Schristos U32 dictID; 3307*3117ece4Schristos 3308*3117ece4Schristos if (dictBuffer==NULL || samplesSizes==NULL) { 3309*3117ece4Schristos free(dictBuffer); 3310*3117ece4Schristos free(samplesSizes); 3311*3117ece4Schristos goto _output_error; 3312*3117ece4Schristos } 3313*3117ece4Schristos 3314*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZDICT_trainFromBuffer_cover : ", testNb++); 3315*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 3316*3117ece4Schristos memset(¶ms, 0, sizeof(params)); 3317*3117ece4Schristos params.d = 1 + (FUZ_rand(&seed32) % 16); 3318*3117ece4Schristos params.k = params.d + (FUZ_rand(&seed32) % 256); 3319*3117ece4Schristos dictSize = ZDICT_trainFromBuffer_cover(dictBuffer, dictSize, 3320*3117ece4Schristos CNBuffer, samplesSizes, nbSamples, 3321*3117ece4Schristos params); 3322*3117ece4Schristos if (ZDICT_isError(dictSize)) goto _output_error; 3323*3117ece4Schristos DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); 3324*3117ece4Schristos 3325*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++); 3326*3117ece4Schristos dictID = ZDICT_getDictID(dictBuffer, dictSize); 3327*3117ece4Schristos if (dictID==0) goto _output_error; 3328*3117ece4Schristos DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID); 3329*3117ece4Schristos 3330*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZDICT_optimizeTrainFromBuffer_cover : ", testNb++); 3331*3117ece4Schristos memset(¶ms, 0, sizeof(params)); 3332*3117ece4Schristos params.steps = 4; 3333*3117ece4Schristos optDictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, optDictSize, 3334*3117ece4Schristos CNBuffer, samplesSizes, 3335*3117ece4Schristos nbSamples / 4, ¶ms); 3336*3117ece4Schristos if (ZDICT_isError(optDictSize)) goto _output_error; 3337*3117ece4Schristos DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)optDictSize); 3338*3117ece4Schristos 3339*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++); 3340*3117ece4Schristos dictID = ZDICT_getDictID(dictBuffer, optDictSize); 3341*3117ece4Schristos if (dictID==0) goto _output_error; 3342*3117ece4Schristos DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID); 3343*3117ece4Schristos 3344*3117ece4Schristos ZSTD_freeCCtx(cctx); 3345*3117ece4Schristos free(dictBuffer); 3346*3117ece4Schristos free(samplesSizes); 3347*3117ece4Schristos } 3348*3117ece4Schristos 3349*3117ece4Schristos /* Decompression defense tests */ 3350*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Check input length for magic number : ", testNb++); 3351*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, CNBuffer, 3); /* too small input */ 3352*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; 3353*3117ece4Schristos if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; } 3354*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3355*3117ece4Schristos 3356*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Check magic Number : ", testNb++); 3357*3117ece4Schristos ((char*)(CNBuffer))[0] = 1; 3358*3117ece4Schristos { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, CNBuffer, 4); 3359*3117ece4Schristos if (!ZSTD_isError(r)) goto _output_error; } 3360*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3361*3117ece4Schristos 3362*3117ece4Schristos /* content size verification test */ 3363*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Content size verification : ", testNb++); 3364*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3365*3117ece4Schristos size_t const srcSize = 5000; 3366*3117ece4Schristos size_t const wrongSrcSize = (srcSize + 1000); 3367*3117ece4Schristos ZSTD_parameters params = ZSTD_getParams(1, wrongSrcSize, 0); 3368*3117ece4Schristos params.fParams.contentSizeFlag = 1; 3369*3117ece4Schristos CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, wrongSrcSize) ); 3370*3117ece4Schristos { size_t const result = ZSTD_compressEnd(cctx, decodedBuffer, CNBuffSize, CNBuffer, srcSize); 3371*3117ece4Schristos if (!ZSTD_isError(result)) goto _output_error; 3372*3117ece4Schristos if (ZSTD_getErrorCode(result) != ZSTD_error_srcSize_wrong) goto _output_error; 3373*3117ece4Schristos DISPLAYLEVEL(3, "OK : %s \n", ZSTD_getErrorName(result)); 3374*3117ece4Schristos } 3375*3117ece4Schristos ZSTD_freeCCtx(cctx); 3376*3117ece4Schristos } 3377*3117ece4Schristos 3378*3117ece4Schristos /* negative compression level test : ensure simple API and advanced API produce same result */ 3379*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : negative compression level : ", testNb++); 3380*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3381*3117ece4Schristos size_t const srcSize = CNBuffSize / 5; 3382*3117ece4Schristos int const compressionLevel = -1; 3383*3117ece4Schristos 3384*3117ece4Schristos assert(cctx != NULL); 3385*3117ece4Schristos { size_t const cSize_1pass = ZSTD_compress(compressedBuffer, compressedBufferSize, 3386*3117ece4Schristos CNBuffer, srcSize, compressionLevel); 3387*3117ece4Schristos if (ZSTD_isError(cSize_1pass)) goto _output_error; 3388*3117ece4Schristos 3389*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) ); 3390*3117ece4Schristos { size_t const compressionResult = ZSTD_compress2(cctx, 3391*3117ece4Schristos compressedBuffer, compressedBufferSize, 3392*3117ece4Schristos CNBuffer, srcSize); 3393*3117ece4Schristos DISPLAYLEVEL(5, "simple=%zu vs %zu=advanced : ", cSize_1pass, compressionResult); 3394*3117ece4Schristos if (ZSTD_isError(compressionResult)) goto _output_error; 3395*3117ece4Schristos if (compressionResult != cSize_1pass) goto _output_error; 3396*3117ece4Schristos } } 3397*3117ece4Schristos ZSTD_freeCCtx(cctx); 3398*3117ece4Schristos } 3399*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3400*3117ece4Schristos 3401*3117ece4Schristos /* parameters order test */ 3402*3117ece4Schristos { size_t const inputSize = CNBuffSize / 2; 3403*3117ece4Schristos U64 xxh64; 3404*3117ece4Schristos 3405*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3406*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : parameters in order : ", testNb++); 3407*3117ece4Schristos assert(cctx != NULL); 3408*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 2) ); 3409*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable) ); 3410*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18) ); 3411*3117ece4Schristos { size_t const compressedSize = ZSTD_compress2(cctx, 3412*3117ece4Schristos compressedBuffer, ZSTD_compressBound(inputSize), 3413*3117ece4Schristos CNBuffer, inputSize); 3414*3117ece4Schristos CHECK_Z(compressedSize); 3415*3117ece4Schristos cSize = compressedSize; 3416*3117ece4Schristos xxh64 = XXH64(compressedBuffer, compressedSize, 0); 3417*3117ece4Schristos } 3418*3117ece4Schristos DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)cSize); 3419*3117ece4Schristos ZSTD_freeCCtx(cctx); 3420*3117ece4Schristos } 3421*3117ece4Schristos 3422*3117ece4Schristos { ZSTD_CCtx* cctx = ZSTD_createCCtx(); 3423*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : parameters disordered : ", testNb++); 3424*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18) ); 3425*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable) ); 3426*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 2) ); 3427*3117ece4Schristos { size_t const result = ZSTD_compress2(cctx, 3428*3117ece4Schristos compressedBuffer, ZSTD_compressBound(inputSize), 3429*3117ece4Schristos CNBuffer, inputSize); 3430*3117ece4Schristos CHECK_Z(result); 3431*3117ece4Schristos if (result != cSize) goto _output_error; /* must result in same compressed result, hence same size */ 3432*3117ece4Schristos if (XXH64(compressedBuffer, result, 0) != xxh64) goto _output_error; /* must result in exactly same content, hence same hash */ 3433*3117ece4Schristos DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)result); 3434*3117ece4Schristos } 3435*3117ece4Schristos ZSTD_freeCCtx(cctx); 3436*3117ece4Schristos } 3437*3117ece4Schristos } 3438*3117ece4Schristos 3439*3117ece4Schristos /* advanced parameters for decompression */ 3440*3117ece4Schristos { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 3441*3117ece4Schristos assert(dctx != NULL); 3442*3117ece4Schristos 3443*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : get dParameter bounds ", testNb++); 3444*3117ece4Schristos { ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax); 3445*3117ece4Schristos CHECK_Z(bounds.error); 3446*3117ece4Schristos } 3447*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3448*3117ece4Schristos 3449*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : wrong dParameter : ", testNb++); 3450*3117ece4Schristos { size_t const sr = ZSTD_DCtx_setParameter(dctx, (ZSTD_dParameter)999999, 0); 3451*3117ece4Schristos if (!ZSTD_isError(sr)) goto _output_error; 3452*3117ece4Schristos } 3453*3117ece4Schristos { ZSTD_bounds const bounds = ZSTD_dParam_getBounds((ZSTD_dParameter)999998); 3454*3117ece4Schristos if (!ZSTD_isError(bounds.error)) goto _output_error; 3455*3117ece4Schristos } 3456*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3457*3117ece4Schristos 3458*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : out of bound dParameter : ", testNb++); 3459*3117ece4Schristos { size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 9999); 3460*3117ece4Schristos if (!ZSTD_isError(sr)) goto _output_error; 3461*3117ece4Schristos } 3462*3117ece4Schristos { size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (ZSTD_format_e)888); 3463*3117ece4Schristos if (!ZSTD_isError(sr)) goto _output_error; 3464*3117ece4Schristos } 3465*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3466*3117ece4Schristos 3467*3117ece4Schristos ZSTD_freeDCtx(dctx); 3468*3117ece4Schristos } 3469*3117ece4Schristos 3470*3117ece4Schristos 3471*3117ece4Schristos /* custom formats tests */ 3472*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3473*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 3474*3117ece4Schristos size_t const inputSize = CNBuffSize / 2; /* won't cause pb with small dict size */ 3475*3117ece4Schristos assert(dctx != NULL); assert(cctx != NULL); 3476*3117ece4Schristos 3477*3117ece4Schristos /* basic block compression */ 3478*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : magic-less format test : ", testNb++); 3479*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) ); 3480*3117ece4Schristos { ZSTD_inBuffer in = { CNBuffer, inputSize, 0 }; 3481*3117ece4Schristos ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(inputSize), 0 }; 3482*3117ece4Schristos size_t const result = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end); 3483*3117ece4Schristos if (result != 0) goto _output_error; 3484*3117ece4Schristos if (in.pos != in.size) goto _output_error; 3485*3117ece4Schristos cSize = out.pos; 3486*3117ece4Schristos } 3487*3117ece4Schristos DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)cSize); 3488*3117ece4Schristos 3489*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress normally (should fail) : ", testNb++); 3490*3117ece4Schristos { size_t const decodeResult = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); 3491*3117ece4Schristos if (ZSTD_getErrorCode(decodeResult) != ZSTD_error_prefix_unknown) goto _output_error; 3492*3117ece4Schristos DISPLAYLEVEL(3, "OK : %s \n", ZSTD_getErrorName(decodeResult)); 3493*3117ece4Schristos } 3494*3117ece4Schristos 3495*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress of magic-less frame : ", testNb++); 3496*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3497*3117ece4Schristos CHECK_Z( ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless) ); 3498*3117ece4Schristos { ZSTD_frameHeader zfh; 3499*3117ece4Schristos size_t const zfhrt = ZSTD_getFrameHeader_advanced(&zfh, compressedBuffer, cSize, ZSTD_f_zstd1_magicless); 3500*3117ece4Schristos if (zfhrt != 0) goto _output_error; 3501*3117ece4Schristos } 3502*3117ece4Schristos /* one shot */ 3503*3117ece4Schristos { size_t const result = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); 3504*3117ece4Schristos if (result != inputSize) goto _output_error; 3505*3117ece4Schristos DISPLAYLEVEL(3, "one-shot OK, "); 3506*3117ece4Schristos } 3507*3117ece4Schristos /* streaming */ 3508*3117ece4Schristos { ZSTD_inBuffer in = { compressedBuffer, cSize, 0 }; 3509*3117ece4Schristos ZSTD_outBuffer out = { decodedBuffer, CNBuffSize, 0 }; 3510*3117ece4Schristos size_t const result = ZSTD_decompressStream(dctx, &out, &in); 3511*3117ece4Schristos if (result != 0) goto _output_error; 3512*3117ece4Schristos if (in.pos != in.size) goto _output_error; 3513*3117ece4Schristos if (out.pos != inputSize) goto _output_error; 3514*3117ece4Schristos DISPLAYLEVEL(3, "streaming OK : regenerated %u bytes \n", (unsigned)out.pos); 3515*3117ece4Schristos } 3516*3117ece4Schristos 3517*3117ece4Schristos /* basic block compression */ 3518*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : empty magic-less format test : ", testNb++); 3519*3117ece4Schristos CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) ); 3520*3117ece4Schristos { ZSTD_inBuffer in = { CNBuffer, 0, 0 }; 3521*3117ece4Schristos ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(0), 0 }; 3522*3117ece4Schristos size_t const result = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end); 3523*3117ece4Schristos if (result != 0) goto _output_error; 3524*3117ece4Schristos if (in.pos != in.size) goto _output_error; 3525*3117ece4Schristos cSize = out.pos; 3526*3117ece4Schristos } 3527*3117ece4Schristos DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)0, (unsigned)cSize); 3528*3117ece4Schristos 3529*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress of empty magic-less frame : ", testNb++); 3530*3117ece4Schristos ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); 3531*3117ece4Schristos CHECK_Z( ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless) ); 3532*3117ece4Schristos /* one shot */ 3533*3117ece4Schristos { size_t const result = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); 3534*3117ece4Schristos if (result != 0) goto _output_error; 3535*3117ece4Schristos DISPLAYLEVEL(3, "one-shot OK, "); 3536*3117ece4Schristos } 3537*3117ece4Schristos /* streaming */ 3538*3117ece4Schristos { ZSTD_inBuffer in = { compressedBuffer, cSize, 0 }; 3539*3117ece4Schristos ZSTD_outBuffer out = { decodedBuffer, CNBuffSize, 0 }; 3540*3117ece4Schristos size_t const result = ZSTD_decompressStream(dctx, &out, &in); 3541*3117ece4Schristos if (result != 0) goto _output_error; 3542*3117ece4Schristos if (in.pos != in.size) goto _output_error; 3543*3117ece4Schristos if (out.pos != 0) goto _output_error; 3544*3117ece4Schristos DISPLAYLEVEL(3, "streaming OK : regenerated %u bytes \n", (unsigned)out.pos); 3545*3117ece4Schristos } 3546*3117ece4Schristos 3547*3117ece4Schristos ZSTD_freeCCtx(cctx); 3548*3117ece4Schristos ZSTD_freeDCtx(dctx); 3549*3117ece4Schristos } 3550*3117ece4Schristos 3551*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Decompression parameter reset test : ", testNb++); 3552*3117ece4Schristos { 3553*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 3554*3117ece4Schristos /* Attempt to future proof this to new parameters. */ 3555*3117ece4Schristos int const maxParam = 2000; 3556*3117ece4Schristos int param; 3557*3117ece4Schristos if (ZSTD_d_experimentalParam3 > maxParam) goto _output_error; 3558*3117ece4Schristos for (param = 0; param < maxParam; ++param) { 3559*3117ece4Schristos ZSTD_dParameter dParam = (ZSTD_dParameter)param; 3560*3117ece4Schristos ZSTD_bounds bounds = ZSTD_dParam_getBounds(dParam); 3561*3117ece4Schristos int value1; 3562*3117ece4Schristos int value2; 3563*3117ece4Schristos int check; 3564*3117ece4Schristos if (ZSTD_isError(bounds.error)) 3565*3117ece4Schristos continue; 3566*3117ece4Schristos CHECK_Z(ZSTD_DCtx_getParameter(dctx, dParam, &value1)); 3567*3117ece4Schristos value2 = (value1 != bounds.lowerBound) ? bounds.lowerBound : bounds.upperBound; 3568*3117ece4Schristos CHECK_Z(ZSTD_DCtx_setParameter(dctx, dParam, value2)); 3569*3117ece4Schristos CHECK_Z(ZSTD_DCtx_getParameter(dctx, dParam, &check)); 3570*3117ece4Schristos if (check != value2) goto _output_error; 3571*3117ece4Schristos CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_parameters)); 3572*3117ece4Schristos CHECK_Z(ZSTD_DCtx_getParameter(dctx, dParam, &check)); 3573*3117ece4Schristos if (check != value1) goto _output_error; 3574*3117ece4Schristos } 3575*3117ece4Schristos ZSTD_freeDCtx(dctx); 3576*3117ece4Schristos } 3577*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3578*3117ece4Schristos 3579*3117ece4Schristos /* block API tests */ 3580*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3581*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 3582*3117ece4Schristos static const size_t dictSize = 65 KB; 3583*3117ece4Schristos static const size_t blockSize = 100 KB; /* won't cause pb with small dict size */ 3584*3117ece4Schristos size_t cSize2; 3585*3117ece4Schristos assert(cctx != NULL); assert(dctx != NULL); 3586*3117ece4Schristos 3587*3117ece4Schristos /* basic block compression */ 3588*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Block compression test : ", testNb++); 3589*3117ece4Schristos CHECK_Z( ZSTD_compressBegin(cctx, 5) ); 3590*3117ece4Schristos CHECK_Z( ZSTD_getBlockSize(cctx) >= blockSize); 3591*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize) ); 3592*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3593*3117ece4Schristos 3594*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Block decompression test : ", testNb++); 3595*3117ece4Schristos CHECK_Z( ZSTD_decompressBegin(dctx) ); 3596*3117ece4Schristos { CHECK_NEWV(r, ZSTD_decompressBlock(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) ); 3597*3117ece4Schristos if (r != blockSize) goto _output_error; } 3598*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3599*3117ece4Schristos 3600*3117ece4Schristos /* very long stream of block compression */ 3601*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Huge block streaming compression test : ", testNb++); 3602*3117ece4Schristos CHECK_Z( ZSTD_compressBegin(cctx, -199) ); /* we just want to quickly overflow internal U32 index */ 3603*3117ece4Schristos CHECK_Z( ZSTD_getBlockSize(cctx) >= blockSize); 3604*3117ece4Schristos { U64 const toCompress = 5000000000ULL; /* > 4 GB */ 3605*3117ece4Schristos U64 compressed = 0; 3606*3117ece4Schristos while (compressed < toCompress) { 3607*3117ece4Schristos size_t const blockCSize = ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize); 3608*3117ece4Schristos assert(blockCSize != 0); 3609*3117ece4Schristos if (ZSTD_isError(blockCSize)) goto _output_error; 3610*3117ece4Schristos compressed += blockCSize; 3611*3117ece4Schristos } } 3612*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3613*3117ece4Schristos 3614*3117ece4Schristos /* dictionary block compression */ 3615*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Dictionary Block compression test : ", testNb++); 3616*3117ece4Schristos CHECK_Z( ZSTD_compressBegin_usingDict(cctx, CNBuffer, dictSize, 5) ); 3617*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize, blockSize)); 3618*3117ece4Schristos RDG_genBuffer((char*)CNBuffer+dictSize+blockSize, blockSize, 0.0, 0.0, seed); /* create a non-compressible second block */ 3619*3117ece4Schristos { CHECK_NEWV(r, ZSTD_compressBlock(cctx, (char*)compressedBuffer+cSize, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize+blockSize, blockSize) ); /* for cctx history consistency */ 3620*3117ece4Schristos assert(r == 0); /* non-compressible block */ } 3621*3117ece4Schristos memcpy((char*)compressedBuffer+cSize, (char*)CNBuffer+dictSize+blockSize, blockSize); /* send non-compressed block (without header) */ 3622*3117ece4Schristos CHECK_VAR(cSize2, ZSTD_compressBlock(cctx, (char*)compressedBuffer+cSize+blockSize, ZSTD_compressBound(blockSize), 3623*3117ece4Schristos (char*)CNBuffer+dictSize+2*blockSize, blockSize)); 3624*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3625*3117ece4Schristos 3626*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Dictionary Block decompression test : ", testNb++); 3627*3117ece4Schristos CHECK_Z( ZSTD_decompressBegin_usingDict(dctx, CNBuffer, dictSize) ); 3628*3117ece4Schristos { CHECK_NEWV( r, ZSTD_decompressBlock(dctx, decodedBuffer, blockSize, compressedBuffer, cSize) ); 3629*3117ece4Schristos if (r != blockSize) { 3630*3117ece4Schristos DISPLAYLEVEL(1, "ZSTD_decompressBlock() with _usingDict() fails : %u, instead of %u expected \n", (unsigned)r, (unsigned)blockSize); 3631*3117ece4Schristos goto _output_error; 3632*3117ece4Schristos } } 3633*3117ece4Schristos memcpy((char*)decodedBuffer+blockSize, (char*)compressedBuffer+cSize, blockSize); 3634*3117ece4Schristos ZSTD_insertBlock(dctx, (char*)decodedBuffer+blockSize, blockSize); /* insert non-compressed block into dctx history */ 3635*3117ece4Schristos { CHECK_NEWV( r, ZSTD_decompressBlock(dctx, (char*)decodedBuffer+2*blockSize, blockSize, (char*)compressedBuffer+cSize+blockSize, cSize2) ); 3636*3117ece4Schristos if (r != blockSize) { 3637*3117ece4Schristos DISPLAYLEVEL(1, "ZSTD_decompressBlock() with _usingDict() and after insertBlock() fails : %u, instead of %u expected \n", (unsigned)r, (unsigned)blockSize); 3638*3117ece4Schristos goto _output_error; 3639*3117ece4Schristos } } 3640*3117ece4Schristos assert(memcpy((char*)CNBuffer+dictSize, decodedBuffer, blockSize*3)); /* ensure regenerated content is identical to origin */ 3641*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3642*3117ece4Schristos 3643*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Block compression with CDict : ", testNb++); 3644*3117ece4Schristos { ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 3); 3645*3117ece4Schristos if (cdict==NULL) goto _output_error; 3646*3117ece4Schristos CHECK_Z( ZSTD_compressBegin_usingCDict(cctx, cdict) ); 3647*3117ece4Schristos CHECK_Z( ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize, blockSize) ); 3648*3117ece4Schristos ZSTD_freeCDict(cdict); 3649*3117ece4Schristos } 3650*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3651*3117ece4Schristos 3652*3117ece4Schristos ZSTD_freeCCtx(cctx); 3653*3117ece4Schristos ZSTD_freeDCtx(dctx); 3654*3117ece4Schristos } 3655*3117ece4Schristos 3656*3117ece4Schristos /* long rle test */ 3657*3117ece4Schristos { size_t sampleSize = 0; 3658*3117ece4Schristos size_t expectedCompressedSize = 39; /* block 1, 2: compressed, block 3: RLE, zstd 1.4.4 */ 3659*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : Long RLE test : ", testNb++); 3660*3117ece4Schristos memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1); 3661*3117ece4Schristos sampleSize += 256 KB - 1; 3662*3117ece4Schristos memset((char*)CNBuffer+sampleSize, 'A', 96 KB); 3663*3117ece4Schristos sampleSize += 96 KB; 3664*3117ece4Schristos cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize, 1); 3665*3117ece4Schristos if (ZSTD_isError(cSize) || cSize > expectedCompressedSize) goto _output_error; 3666*3117ece4Schristos { CHECK_NEWV(regenSize, ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize)); 3667*3117ece4Schristos if (regenSize!=sampleSize) goto _output_error; } 3668*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3669*3117ece4Schristos } 3670*3117ece4Schristos 3671*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_generateSequences decode from sequences test : ", testNb++); 3672*3117ece4Schristos { 3673*3117ece4Schristos size_t srcSize = 150 KB; 3674*3117ece4Schristos BYTE* src = (BYTE*)CNBuffer; 3675*3117ece4Schristos BYTE* decoded = (BYTE*)compressedBuffer; 3676*3117ece4Schristos 3677*3117ece4Schristos ZSTD_CCtx* cctx = ZSTD_createCCtx(); 3678*3117ece4Schristos ZSTD_Sequence* seqs = (ZSTD_Sequence*)malloc(srcSize * sizeof(ZSTD_Sequence)); 3679*3117ece4Schristos size_t seqsSize; 3680*3117ece4Schristos 3681*3117ece4Schristos if (seqs == NULL) goto _output_error; 3682*3117ece4Schristos assert(cctx != NULL); 3683*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19); 3684*3117ece4Schristos /* Populate src with random data */ 3685*3117ece4Schristos RDG_genBuffer(CNBuffer, srcSize, compressibility, 0.5, seed); 3686*3117ece4Schristos 3687*3117ece4Schristos /* Test with block delimiters roundtrip */ 3688*3117ece4Schristos seqsSize = ZSTD_generateSequences(cctx, seqs, srcSize, src, srcSize); 3689*3117ece4Schristos CHECK_Z(seqsSize); 3690*3117ece4Schristos FUZ_decodeSequences(decoded, seqs, seqsSize, src, srcSize, ZSTD_sf_explicitBlockDelimiters); 3691*3117ece4Schristos assert(!memcmp(CNBuffer, compressedBuffer, srcSize)); 3692*3117ece4Schristos 3693*3117ece4Schristos /* Test no block delimiters roundtrip */ 3694*3117ece4Schristos seqsSize = ZSTD_mergeBlockDelimiters(seqs, seqsSize); 3695*3117ece4Schristos CHECK_Z(seqsSize); 3696*3117ece4Schristos FUZ_decodeSequences(decoded, seqs, seqsSize, src, srcSize, ZSTD_sf_noBlockDelimiters); 3697*3117ece4Schristos assert(!memcmp(CNBuffer, compressedBuffer, srcSize)); 3698*3117ece4Schristos 3699*3117ece4Schristos ZSTD_freeCCtx(cctx); 3700*3117ece4Schristos free(seqs); 3701*3117ece4Schristos } 3702*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3703*3117ece4Schristos 3704*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_generateSequences too small output buffer : ", testNb++); 3705*3117ece4Schristos { 3706*3117ece4Schristos const size_t seqsCapacity = 10; 3707*3117ece4Schristos const size_t srcSize = 150 KB; 3708*3117ece4Schristos const BYTE* src = (BYTE*)CNBuffer; 3709*3117ece4Schristos 3710*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3711*3117ece4Schristos ZSTD_Sequence* const seqs = (ZSTD_Sequence*)malloc(seqsCapacity * sizeof(ZSTD_Sequence)); 3712*3117ece4Schristos 3713*3117ece4Schristos if (seqs == NULL) goto _output_error; 3714*3117ece4Schristos if (cctx == NULL) goto _output_error; 3715*3117ece4Schristos /* Populate src with random data */ 3716*3117ece4Schristos RDG_genBuffer(CNBuffer, srcSize, compressibility, 0.5, seed); 3717*3117ece4Schristos 3718*3117ece4Schristos /* Test with block delimiters roundtrip */ 3719*3117ece4Schristos { 3720*3117ece4Schristos size_t const seqsSize = ZSTD_generateSequences(cctx, seqs, seqsCapacity, src, srcSize); 3721*3117ece4Schristos if (!ZSTD_isError(seqsSize)) goto _output_error; 3722*3117ece4Schristos } 3723*3117ece4Schristos 3724*3117ece4Schristos ZSTD_freeCCtx(cctx); 3725*3117ece4Schristos free(seqs); 3726*3117ece4Schristos } 3727*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3728*3117ece4Schristos 3729*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_getSequences followed by ZSTD_compressSequences : ", testNb++); 3730*3117ece4Schristos { 3731*3117ece4Schristos const size_t srcSize = 500 KB; 3732*3117ece4Schristos const BYTE* const src = (BYTE*)CNBuffer; 3733*3117ece4Schristos BYTE* const dst = (BYTE*)compressedBuffer; 3734*3117ece4Schristos const size_t dstCapacity = ZSTD_compressBound(srcSize); 3735*3117ece4Schristos const size_t decompressSize = srcSize; 3736*3117ece4Schristos char* const decompressBuffer = (char*)malloc(decompressSize); 3737*3117ece4Schristos size_t compressedSize; 3738*3117ece4Schristos 3739*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3740*3117ece4Schristos ZSTD_Sequence* const seqs = (ZSTD_Sequence*)malloc(srcSize * sizeof(ZSTD_Sequence)); 3741*3117ece4Schristos size_t nbSeqs; 3742*3117ece4Schristos 3743*3117ece4Schristos if (seqs == NULL) goto _output_error; 3744*3117ece4Schristos assert(cctx != NULL); 3745*3117ece4Schristos 3746*3117ece4Schristos /* Populate src with random data */ 3747*3117ece4Schristos RDG_genBuffer(CNBuffer, srcSize, compressibility, 0., seed); 3748*3117ece4Schristos 3749*3117ece4Schristos /* Roundtrip Test with block delimiters generated by ZSTD_generateSequences() */ 3750*3117ece4Schristos nbSeqs = ZSTD_generateSequences(cctx, seqs, srcSize, src, srcSize); 3751*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 3752*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters); 3753*3117ece4Schristos compressedSize = ZSTD_compressSequences(cctx, dst, dstCapacity, seqs, nbSeqs, src, srcSize); 3754*3117ece4Schristos if (ZSTD_isError(compressedSize)) { 3755*3117ece4Schristos DISPLAY("Error in sequence compression with block delims\n"); 3756*3117ece4Schristos goto _output_error; 3757*3117ece4Schristos } 3758*3117ece4Schristos { size_t const dSize = ZSTD_decompress(decompressBuffer, decompressSize, dst, compressedSize); 3759*3117ece4Schristos if (ZSTD_isError(dSize)) { 3760*3117ece4Schristos DISPLAY("Error in sequence compression roundtrip with block delims\n"); 3761*3117ece4Schristos goto _output_error; 3762*3117ece4Schristos } } 3763*3117ece4Schristos assert(!memcmp(decompressBuffer, src, srcSize)); 3764*3117ece4Schristos 3765*3117ece4Schristos /* Roundtrip Test with no block delimiters */ 3766*3117ece4Schristos { size_t const nbSeqsAfterMerge = ZSTD_mergeBlockDelimiters(seqs, nbSeqs); 3767*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 3768*3117ece4Schristos ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_noBlockDelimiters); 3769*3117ece4Schristos compressedSize = ZSTD_compressSequences(cctx, dst, dstCapacity, seqs, nbSeqsAfterMerge, src, srcSize); 3770*3117ece4Schristos } 3771*3117ece4Schristos if (ZSTD_isError(compressedSize)) { 3772*3117ece4Schristos DISPLAY("Error in sequence compression with no block delims\n"); 3773*3117ece4Schristos goto _output_error; 3774*3117ece4Schristos } 3775*3117ece4Schristos { size_t const dSize = ZSTD_decompress(decompressBuffer, decompressSize, dst, compressedSize); 3776*3117ece4Schristos if (ZSTD_isError(dSize)) { 3777*3117ece4Schristos DISPLAY("Error in sequence compression roundtrip with no block delims\n"); 3778*3117ece4Schristos goto _output_error; 3779*3117ece4Schristos } } 3780*3117ece4Schristos assert(!memcmp(decompressBuffer, src, srcSize)); 3781*3117ece4Schristos 3782*3117ece4Schristos ZSTD_freeCCtx(cctx); 3783*3117ece4Schristos free(decompressBuffer); 3784*3117ece4Schristos free(seqs); 3785*3117ece4Schristos } 3786*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3787*3117ece4Schristos 3788*3117ece4Schristos /* Multiple blocks of zeros test */ 3789*3117ece4Schristos #define LONGZEROSLENGTH 1000000 /* 1MB of zeros */ 3790*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress %u zeroes : ", testNb++, LONGZEROSLENGTH); 3791*3117ece4Schristos memset(CNBuffer, 0, LONGZEROSLENGTH); 3792*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(LONGZEROSLENGTH), CNBuffer, LONGZEROSLENGTH, 1) ); 3793*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/LONGZEROSLENGTH*100); 3794*3117ece4Schristos 3795*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress %u zeroes : ", testNb++, LONGZEROSLENGTH); 3796*3117ece4Schristos { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, LONGZEROSLENGTH, compressedBuffer, cSize) ); 3797*3117ece4Schristos if (r != LONGZEROSLENGTH) goto _output_error; } 3798*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3799*3117ece4Schristos 3800*3117ece4Schristos /* All zeroes test (test bug #137) */ 3801*3117ece4Schristos #define ZEROESLENGTH 100 3802*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress %u zeroes : ", testNb++, ZEROESLENGTH); 3803*3117ece4Schristos memset(CNBuffer, 0, ZEROESLENGTH); 3804*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(ZEROESLENGTH), CNBuffer, ZEROESLENGTH, 1) ); 3805*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/ZEROESLENGTH*100); 3806*3117ece4Schristos 3807*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress %u zeroes : ", testNb++, ZEROESLENGTH); 3808*3117ece4Schristos { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, ZEROESLENGTH, compressedBuffer, cSize) ); 3809*3117ece4Schristos if (r != ZEROESLENGTH) goto _output_error; } 3810*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3811*3117ece4Schristos 3812*3117ece4Schristos /* nbSeq limit test */ 3813*3117ece4Schristos #define _3BYTESTESTLENGTH 131000 3814*3117ece4Schristos #define NB3BYTESSEQLOG 9 3815*3117ece4Schristos #define NB3BYTESSEQ (1 << NB3BYTESSEQLOG) 3816*3117ece4Schristos #define NB3BYTESSEQMASK (NB3BYTESSEQ-1) 3817*3117ece4Schristos /* creates a buffer full of 3-bytes sequences */ 3818*3117ece4Schristos { BYTE _3BytesSeqs[NB3BYTESSEQ][3]; 3819*3117ece4Schristos U32 rSeed = 1; 3820*3117ece4Schristos 3821*3117ece4Schristos /* create batch of 3-bytes sequences */ 3822*3117ece4Schristos { int i; 3823*3117ece4Schristos for (i=0; i < NB3BYTESSEQ; i++) { 3824*3117ece4Schristos _3BytesSeqs[i][0] = (BYTE)(FUZ_rand(&rSeed) & 255); 3825*3117ece4Schristos _3BytesSeqs[i][1] = (BYTE)(FUZ_rand(&rSeed) & 255); 3826*3117ece4Schristos _3BytesSeqs[i][2] = (BYTE)(FUZ_rand(&rSeed) & 255); 3827*3117ece4Schristos } } 3828*3117ece4Schristos 3829*3117ece4Schristos /* randomly fills CNBuffer with prepared 3-bytes sequences */ 3830*3117ece4Schristos { int i; 3831*3117ece4Schristos for (i=0; i < _3BYTESTESTLENGTH; i += 3) { /* note : CNBuffer size > _3BYTESTESTLENGTH+3 */ 3832*3117ece4Schristos U32 const id = FUZ_rand(&rSeed) & NB3BYTESSEQMASK; 3833*3117ece4Schristos ((BYTE*)CNBuffer)[i+0] = _3BytesSeqs[id][0]; 3834*3117ece4Schristos ((BYTE*)CNBuffer)[i+1] = _3BytesSeqs[id][1]; 3835*3117ece4Schristos ((BYTE*)CNBuffer)[i+2] = _3BytesSeqs[id][2]; 3836*3117ece4Schristos } } } 3837*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : growing nbSeq : ", testNb++); 3838*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3839*3117ece4Schristos size_t const maxNbSeq = _3BYTESTESTLENGTH / 3; 3840*3117ece4Schristos size_t const bound = ZSTD_compressBound(_3BYTESTESTLENGTH); 3841*3117ece4Schristos size_t nbSeq = 1; 3842*3117ece4Schristos while (nbSeq <= maxNbSeq) { 3843*3117ece4Schristos CHECK_Z(ZSTD_compressCCtx(cctx, compressedBuffer, bound, CNBuffer, nbSeq * 3, 19)); 3844*3117ece4Schristos /* Check every sequence for the first 100, then skip more rapidly. */ 3845*3117ece4Schristos if (nbSeq < 100) { 3846*3117ece4Schristos ++nbSeq; 3847*3117ece4Schristos } else { 3848*3117ece4Schristos nbSeq += (nbSeq >> 2); 3849*3117ece4Schristos } 3850*3117ece4Schristos } 3851*3117ece4Schristos ZSTD_freeCCtx(cctx); 3852*3117ece4Schristos } 3853*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3854*3117ece4Schristos 3855*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : compress lots 3-bytes sequences : ", testNb++); 3856*3117ece4Schristos CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(_3BYTESTESTLENGTH), 3857*3117ece4Schristos CNBuffer, _3BYTESTESTLENGTH, 19) ); 3858*3117ece4Schristos DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/_3BYTESTESTLENGTH*100); 3859*3117ece4Schristos 3860*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : decompress lots 3-bytes sequence : ", testNb++); 3861*3117ece4Schristos { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, _3BYTESTESTLENGTH, compressedBuffer, cSize) ); 3862*3117ece4Schristos if (r != _3BYTESTESTLENGTH) goto _output_error; } 3863*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3864*3117ece4Schristos 3865*3117ece4Schristos 3866*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : growing literals buffer : ", testNb++); 3867*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, 0.0, 0.1, seed); 3868*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3869*3117ece4Schristos size_t const bound = ZSTD_compressBound(CNBuffSize); 3870*3117ece4Schristos size_t size = 1; 3871*3117ece4Schristos while (size <= CNBuffSize) { 3872*3117ece4Schristos CHECK_Z(ZSTD_compressCCtx(cctx, compressedBuffer, bound, CNBuffer, size, 3)); 3873*3117ece4Schristos /* Check every size for the first 100, then skip more rapidly. */ 3874*3117ece4Schristos if (size < 100) { 3875*3117ece4Schristos ++size; 3876*3117ece4Schristos } else { 3877*3117ece4Schristos size += (size >> 2); 3878*3117ece4Schristos } 3879*3117ece4Schristos } 3880*3117ece4Schristos ZSTD_freeCCtx(cctx); 3881*3117ece4Schristos } 3882*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3883*3117ece4Schristos 3884*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : incompressible data and ill suited dictionary : ", testNb++); 3885*3117ece4Schristos { /* Train a dictionary on low characters */ 3886*3117ece4Schristos size_t dictSize = 16 KB; 3887*3117ece4Schristos void* const dictBuffer = malloc(dictSize); 3888*3117ece4Schristos size_t const totalSampleSize = 1 MB; 3889*3117ece4Schristos size_t const sampleUnitSize = 8 KB; 3890*3117ece4Schristos U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize); 3891*3117ece4Schristos size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t)); 3892*3117ece4Schristos if (!dictBuffer || !samplesSizes) goto _output_error; 3893*3117ece4Schristos { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } 3894*3117ece4Schristos dictSize = ZDICT_trainFromBuffer(dictBuffer, dictSize, CNBuffer, samplesSizes, nbSamples); 3895*3117ece4Schristos if (ZDICT_isError(dictSize)) goto _output_error; 3896*3117ece4Schristos /* Reverse the characters to make the dictionary ill suited */ 3897*3117ece4Schristos { U32 u; 3898*3117ece4Schristos for (u = 0; u < CNBuffSize; ++u) { 3899*3117ece4Schristos ((BYTE*)CNBuffer)[u] = 255 - ((BYTE*)CNBuffer)[u]; 3900*3117ece4Schristos } } 3901*3117ece4Schristos { /* Compress the data */ 3902*3117ece4Schristos size_t const inputSize = 500; 3903*3117ece4Schristos size_t const outputSize = ZSTD_compressBound(inputSize); 3904*3117ece4Schristos void* const outputBuffer = malloc(outputSize); 3905*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3906*3117ece4Schristos if (!outputBuffer || !cctx) goto _output_error; 3907*3117ece4Schristos CHECK_Z(ZSTD_compress_usingDict(cctx, outputBuffer, outputSize, CNBuffer, inputSize, dictBuffer, dictSize, 1)); 3908*3117ece4Schristos free(outputBuffer); 3909*3117ece4Schristos ZSTD_freeCCtx(cctx); 3910*3117ece4Schristos } 3911*3117ece4Schristos 3912*3117ece4Schristos free(dictBuffer); 3913*3117ece4Schristos free(samplesSizes); 3914*3117ece4Schristos } 3915*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3916*3117ece4Schristos 3917*3117ece4Schristos 3918*3117ece4Schristos /* findFrameCompressedSize on skippable frames */ 3919*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : frame compressed size of skippable frame : ", testNb++); 3920*3117ece4Schristos { const char* frame = "\x50\x2a\x4d\x18\x05\x0\x0\0abcde"; 3921*3117ece4Schristos size_t const frameSrcSize = 13; 3922*3117ece4Schristos if (ZSTD_findFrameCompressedSize(frame, frameSrcSize) != frameSrcSize) goto _output_error; } 3923*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3924*3117ece4Schristos 3925*3117ece4Schristos /* error string tests */ 3926*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing ZSTD error code strings : ", testNb++); 3927*3117ece4Schristos if (strcmp("No error detected", ZSTD_getErrorName((ZSTD_ErrorCode)(0-ZSTD_error_no_error))) != 0) goto _output_error; 3928*3117ece4Schristos if (strcmp("No error detected", ZSTD_getErrorString(ZSTD_error_no_error)) != 0) goto _output_error; 3929*3117ece4Schristos if (strcmp("Unspecified error code", ZSTD_getErrorString((ZSTD_ErrorCode)(0-ZSTD_error_GENERIC))) != 0) goto _output_error; 3930*3117ece4Schristos if (strcmp("Error (generic)", ZSTD_getErrorName((size_t)0-ZSTD_error_GENERIC)) != 0) goto _output_error; 3931*3117ece4Schristos if (strcmp("Error (generic)", ZSTD_getErrorString(ZSTD_error_GENERIC)) != 0) goto _output_error; 3932*3117ece4Schristos if (strcmp("No error detected", ZSTD_getErrorName(ZSTD_error_GENERIC)) != 0) goto _output_error; 3933*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3934*3117ece4Schristos 3935*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing ZSTD dictionary sizes : ", testNb++); 3936*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed); 3937*3117ece4Schristos { 3938*3117ece4Schristos size_t const size = MIN(128 KB, CNBuffSize); 3939*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 3940*3117ece4Schristos ZSTD_CDict* const lgCDict = ZSTD_createCDict(CNBuffer, size, 1); 3941*3117ece4Schristos ZSTD_CDict* const smCDict = ZSTD_createCDict(CNBuffer, 1 KB, 1); 3942*3117ece4Schristos ZSTD_frameHeader lgHeader; 3943*3117ece4Schristos ZSTD_frameHeader smHeader; 3944*3117ece4Schristos 3945*3117ece4Schristos CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, size, lgCDict)); 3946*3117ece4Schristos CHECK_Z(ZSTD_getFrameHeader(&lgHeader, compressedBuffer, compressedBufferSize)); 3947*3117ece4Schristos CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, size, smCDict)); 3948*3117ece4Schristos CHECK_Z(ZSTD_getFrameHeader(&smHeader, compressedBuffer, compressedBufferSize)); 3949*3117ece4Schristos 3950*3117ece4Schristos if (lgHeader.windowSize != smHeader.windowSize) goto _output_error; 3951*3117ece4Schristos 3952*3117ece4Schristos ZSTD_freeCDict(smCDict); 3953*3117ece4Schristos ZSTD_freeCDict(lgCDict); 3954*3117ece4Schristos ZSTD_freeCCtx(cctx); 3955*3117ece4Schristos } 3956*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3957*3117ece4Schristos 3958*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing FSE_normalizeCount() PR#1255: ", testNb++); 3959*3117ece4Schristos { 3960*3117ece4Schristos short norm[32]; 3961*3117ece4Schristos unsigned count[32]; 3962*3117ece4Schristos unsigned const tableLog = 5; 3963*3117ece4Schristos size_t const nbSeq = 32; 3964*3117ece4Schristos unsigned const maxSymbolValue = 31; 3965*3117ece4Schristos size_t i; 3966*3117ece4Schristos 3967*3117ece4Schristos for (i = 0; i < 32; ++i) 3968*3117ece4Schristos count[i] = 1; 3969*3117ece4Schristos /* Calling FSE_normalizeCount() on a uniform distribution should not 3970*3117ece4Schristos * cause a division by zero. 3971*3117ece4Schristos */ 3972*3117ece4Schristos FSE_normalizeCount(norm, tableLog, count, nbSeq, maxSymbolValue, /* useLowProbCount */ 1); 3973*3117ece4Schristos } 3974*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3975*3117ece4Schristos 3976*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing FSE_writeNCount() PR#2779: ", testNb++); 3977*3117ece4Schristos { 3978*3117ece4Schristos size_t const outBufSize = 9; 3979*3117ece4Schristos short const count[11] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 9, 18}; 3980*3117ece4Schristos unsigned const tableLog = 5; 3981*3117ece4Schristos unsigned const maxSymbolValue = 10; 3982*3117ece4Schristos BYTE* outBuf = (BYTE*)malloc(outBufSize*sizeof(BYTE)); 3983*3117ece4Schristos 3984*3117ece4Schristos /* Ensure that this write doesn't write out of bounds, and that 3985*3117ece4Schristos * FSE_writeNCount_generic() is *not* called with writeIsSafe == 1. 3986*3117ece4Schristos */ 3987*3117ece4Schristos FSE_writeNCount(outBuf, outBufSize, count, maxSymbolValue, tableLog); 3988*3117ece4Schristos free(outBuf); 3989*3117ece4Schristos } 3990*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 3991*3117ece4Schristos 3992*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : testing bitwise intrinsics PR#3045: ", testNb++); 3993*3117ece4Schristos { 3994*3117ece4Schristos U32 seed_copy = seed; /* need non-const seed to avoid compiler warning for FUZ_rand(&seed) */ 3995*3117ece4Schristos U32 rand32 = FUZ_rand(&seed_copy); 3996*3117ece4Schristos U64 rand64 = ((U64)FUZ_rand(&seed_copy) << 32) | FUZ_rand(&seed_copy); 3997*3117ece4Schristos U32 lowbit_only_32 = 1; 3998*3117ece4Schristos U64 lowbit_only_64 = 1; 3999*3117ece4Schristos U32 highbit_only_32 = (U32)1 << 31; 4000*3117ece4Schristos U64 highbit_only_64 = (U64)1 << 63; 4001*3117ece4Schristos U32 i; 4002*3117ece4Schristos if (rand32 == 0) rand32 = 1; /* CLZ and CTZ are undefined on 0 */ 4003*3117ece4Schristos if (rand64 == 0) rand64 = 1; /* CLZ and CTZ are undefined on 0 */ 4004*3117ece4Schristos 4005*3117ece4Schristos /* Test ZSTD_countTrailingZeros32 */ 4006*3117ece4Schristos CHECK_EQ(ZSTD_countTrailingZeros32(lowbit_only_32), 0u); 4007*3117ece4Schristos CHECK_EQ(ZSTD_countTrailingZeros32(highbit_only_32), 31u); 4008*3117ece4Schristos CHECK_EQ(ZSTD_countTrailingZeros32(rand32), ZSTD_countTrailingZeros32_fallback(rand32)); 4009*3117ece4Schristos 4010*3117ece4Schristos /* Test ZSTD_countLeadingZeros32 */ 4011*3117ece4Schristos CHECK_EQ(ZSTD_countLeadingZeros32(lowbit_only_32), 31u); 4012*3117ece4Schristos CHECK_EQ(ZSTD_countLeadingZeros32(highbit_only_32), 0u); 4013*3117ece4Schristos CHECK_EQ(ZSTD_countLeadingZeros32(rand32), ZSTD_countLeadingZeros32_fallback(rand32)); 4014*3117ece4Schristos 4015*3117ece4Schristos /* Test ZSTD_countTrailingZeros64 */ 4016*3117ece4Schristos CHECK_EQ(ZSTD_countTrailingZeros64(lowbit_only_64), 0u); 4017*3117ece4Schristos CHECK_EQ(ZSTD_countTrailingZeros64(highbit_only_64), 63u); 4018*3117ece4Schristos 4019*3117ece4Schristos /* Test ZSTD_countLeadingZeros64 */ 4020*3117ece4Schristos CHECK_EQ(ZSTD_countLeadingZeros64(lowbit_only_64), 63u); 4021*3117ece4Schristos CHECK_EQ(ZSTD_countLeadingZeros64(highbit_only_64), 0u); 4022*3117ece4Schristos 4023*3117ece4Schristos /* Test ZSTD_highbit32 */ 4024*3117ece4Schristos CHECK_EQ(ZSTD_highbit32(lowbit_only_32), 0u); 4025*3117ece4Schristos CHECK_EQ(ZSTD_highbit32(highbit_only_32), 31u); 4026*3117ece4Schristos 4027*3117ece4Schristos /* Test ZSTD_NbCommonBytes */ 4028*3117ece4Schristos if (MEM_isLittleEndian()) { 4029*3117ece4Schristos if (MEM_64bits()) { 4030*3117ece4Schristos CHECK_EQ(ZSTD_NbCommonBytes(lowbit_only_32), 0u); 4031*3117ece4Schristos CHECK_EQ(ZSTD_NbCommonBytes(highbit_only_32), 3u); 4032*3117ece4Schristos } else { 4033*3117ece4Schristos CHECK_EQ(ZSTD_NbCommonBytes(lowbit_only_32), 0u); 4034*3117ece4Schristos CHECK_EQ(ZSTD_NbCommonBytes(highbit_only_32), 3u); 4035*3117ece4Schristos } 4036*3117ece4Schristos } else { 4037*3117ece4Schristos if (MEM_64bits()) { 4038*3117ece4Schristos CHECK_EQ(ZSTD_NbCommonBytes(lowbit_only_32), 7u); 4039*3117ece4Schristos CHECK_EQ(ZSTD_NbCommonBytes(highbit_only_32), 4u); 4040*3117ece4Schristos } else { 4041*3117ece4Schristos CHECK_EQ(ZSTD_NbCommonBytes(lowbit_only_32), 3u); 4042*3117ece4Schristos CHECK_EQ(ZSTD_NbCommonBytes(highbit_only_32), 0u); 4043*3117ece4Schristos } 4044*3117ece4Schristos } 4045*3117ece4Schristos 4046*3117ece4Schristos /* Test MEM_ intrinsics */ 4047*3117ece4Schristos CHECK_EQ(MEM_swap32(rand32), MEM_swap32_fallback(rand32)); 4048*3117ece4Schristos CHECK_EQ(MEM_swap64(rand64), MEM_swap64_fallback(rand64)); 4049*3117ece4Schristos 4050*3117ece4Schristos /* Test fallbacks vs intrinsics on a range of small integers */ 4051*3117ece4Schristos for (i=1; i <= 1000; i++) { 4052*3117ece4Schristos CHECK_EQ(MEM_swap32(i), MEM_swap32_fallback(i)); 4053*3117ece4Schristos CHECK_EQ(MEM_swap64((U64)i), MEM_swap64_fallback((U64)i)); 4054*3117ece4Schristos CHECK_EQ(ZSTD_countTrailingZeros32(i), ZSTD_countTrailingZeros32_fallback(i)); 4055*3117ece4Schristos CHECK_EQ(ZSTD_countLeadingZeros32(i), ZSTD_countLeadingZeros32_fallback(i)); 4056*3117ece4Schristos } 4057*3117ece4Schristos } 4058*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4059*3117ece4Schristos 4060*3117ece4Schristos #ifdef ZSTD_MULTITHREAD 4061*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : passing wrong full dict should fail on compressStream2 refPrefix ", testNb++); 4062*3117ece4Schristos { ZSTD_CCtx* cctx = ZSTD_createCCtx(); 4063*3117ece4Schristos size_t const srcSize = 1 MB + 5; /* A little more than ZSTDMT_JOBSIZE_MIN */ 4064*3117ece4Schristos size_t const dstSize = ZSTD_compressBound(srcSize); 4065*3117ece4Schristos void* const src = CNBuffer; 4066*3117ece4Schristos void* const dst = compressedBuffer; 4067*3117ece4Schristos void* dict = (void*)malloc(srcSize); 4068*3117ece4Schristos 4069*3117ece4Schristos RDG_genBuffer(src, srcSize, compressibility, 0.5, seed); 4070*3117ece4Schristos RDG_genBuffer(dict, srcSize, compressibility, 0., seed); 4071*3117ece4Schristos 4072*3117ece4Schristos /* Make sure there is no ZSTD_MAGIC_NUMBER */ 4073*3117ece4Schristos memset(dict, 0, sizeof(U32)); 4074*3117ece4Schristos 4075*3117ece4Schristos /* something more than 1 */ 4076*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2)); 4077*3117ece4Schristos /* lie and claim this is a full dict */ 4078*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refPrefix_advanced(cctx, dict, srcSize, ZSTD_dct_fullDict)); 4079*3117ece4Schristos 4080*3117ece4Schristos { ZSTD_outBuffer out = {dst, dstSize, 0}; 4081*3117ece4Schristos ZSTD_inBuffer in = {src, srcSize, 0}; 4082*3117ece4Schristos /* should fail because its not a full dict like we said it was */ 4083*3117ece4Schristos assert(ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush))); 4084*3117ece4Schristos } 4085*3117ece4Schristos 4086*3117ece4Schristos ZSTD_freeCCtx(cctx); 4087*3117ece4Schristos free(dict); 4088*3117ece4Schristos } 4089*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4090*3117ece4Schristos 4091*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : small dictionary with multithreading and LDM ", testNb++); 4092*3117ece4Schristos { ZSTD_CCtx* cctx = ZSTD_createCCtx(); 4093*3117ece4Schristos size_t const srcSize = 1 MB + 5; /* A little more than ZSTDMT_JOBSIZE_MIN */ 4094*3117ece4Schristos size_t const dictSize = 10; 4095*3117ece4Schristos size_t const dstSize = ZSTD_compressBound(srcSize); 4096*3117ece4Schristos void* const src = CNBuffer; 4097*3117ece4Schristos void* const dst = compressedBuffer; 4098*3117ece4Schristos void* dict = (void*)malloc(dictSize); 4099*3117ece4Schristos 4100*3117ece4Schristos RDG_genBuffer(src, srcSize, compressibility, 0.5, seed); 4101*3117ece4Schristos RDG_genBuffer(dict, dictSize, compressibility, 0., seed); 4102*3117ece4Schristos 4103*3117ece4Schristos /* Make sure there is no ZSTD_MAGIC_NUMBER */ 4104*3117ece4Schristos memset(dict, 0, sizeof(U32)); 4105*3117ece4Schristos 4106*3117ece4Schristos /* Enable MT, LDM, and use refPrefix() for a small dict */ 4107*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2)); 4108*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)); 4109*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize)); 4110*3117ece4Schristos 4111*3117ece4Schristos CHECK_Z(ZSTD_compress2(cctx, dst, dstSize, src, srcSize)); 4112*3117ece4Schristos 4113*3117ece4Schristos ZSTD_freeCCtx(cctx); 4114*3117ece4Schristos free(dict); 4115*3117ece4Schristos } 4116*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4117*3117ece4Schristos 4118*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_getCParams() + dictionary ", testNb++); 4119*3117ece4Schristos { 4120*3117ece4Schristos ZSTD_compressionParameters const medium = ZSTD_getCParams(1, 16*1024-1, 0); 4121*3117ece4Schristos ZSTD_compressionParameters const large = ZSTD_getCParams(1, 128*1024-1, 0); 4122*3117ece4Schristos ZSTD_compressionParameters const smallDict = ZSTD_getCParams(1, 0, 400); 4123*3117ece4Schristos ZSTD_compressionParameters const mediumDict = ZSTD_getCParams(1, 0, 10000); 4124*3117ece4Schristos ZSTD_compressionParameters const largeDict = ZSTD_getCParams(1, 0, 100000); 4125*3117ece4Schristos 4126*3117ece4Schristos assert(!memcmp(&smallDict, &mediumDict, sizeof(smallDict))); 4127*3117ece4Schristos assert(!memcmp(&medium, &mediumDict, sizeof(medium))); 4128*3117ece4Schristos assert(!memcmp(&large, &largeDict, sizeof(large))); 4129*3117ece4Schristos } 4130*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4131*3117ece4Schristos 4132*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : ZSTD_adjustCParams() + dictionary ", testNb++); 4133*3117ece4Schristos { 4134*3117ece4Schristos ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, 0, 0); 4135*3117ece4Schristos ZSTD_compressionParameters const smallDict = ZSTD_adjustCParams(cParams, 0, 400); 4136*3117ece4Schristos ZSTD_compressionParameters const smallSrcAndDict = ZSTD_adjustCParams(cParams, 500, 400); 4137*3117ece4Schristos 4138*3117ece4Schristos assert(smallSrcAndDict.windowLog == 10); 4139*3117ece4Schristos assert(!memcmp(&cParams, &smallDict, sizeof(cParams))); 4140*3117ece4Schristos } 4141*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4142*3117ece4Schristos 4143*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check compression mem usage monotonicity over levels for estimateCCtxSize() : ", testNb++); 4144*3117ece4Schristos { 4145*3117ece4Schristos int level = 1; 4146*3117ece4Schristos size_t prevSize = 0; 4147*3117ece4Schristos for (; level < ZSTD_maxCLevel(); ++level) { 4148*3117ece4Schristos size_t const currSize = ZSTD_estimateCCtxSize(level); 4149*3117ece4Schristos if (prevSize > currSize) { 4150*3117ece4Schristos DISPLAYLEVEL(3, "Error! previous cctx size: %zu at level: %d is larger than current cctx size: %zu at level: %d", 4151*3117ece4Schristos prevSize, level-1, currSize, level); 4152*3117ece4Schristos goto _output_error; 4153*3117ece4Schristos } 4154*3117ece4Schristos prevSize = currSize; 4155*3117ece4Schristos } 4156*3117ece4Schristos } 4157*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4158*3117ece4Schristos 4159*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : check estimateCCtxSize() always larger or equal to ZSTD_estimateCCtxSize_usingCParams() : ", testNb++); 4160*3117ece4Schristos { 4161*3117ece4Schristos size_t const kSizeIncrement = 2 KB; 4162*3117ece4Schristos int level = -3; 4163*3117ece4Schristos 4164*3117ece4Schristos for (; level <= ZSTD_maxCLevel(); ++level) { 4165*3117ece4Schristos size_t dictSize = 0; 4166*3117ece4Schristos for (; dictSize <= 256 KB; dictSize += 8 * kSizeIncrement) { 4167*3117ece4Schristos size_t srcSize = 2 KB; 4168*3117ece4Schristos for (; srcSize < 300 KB; srcSize += kSizeIncrement) { 4169*3117ece4Schristos ZSTD_compressionParameters const cParams = ZSTD_getCParams(level, srcSize, dictSize); 4170*3117ece4Schristos size_t const cctxSizeUsingCParams = ZSTD_estimateCCtxSize_usingCParams(cParams); 4171*3117ece4Schristos size_t const cctxSizeUsingLevel = ZSTD_estimateCCtxSize(level); 4172*3117ece4Schristos if (cctxSizeUsingLevel < cctxSizeUsingCParams 4173*3117ece4Schristos || ZSTD_isError(cctxSizeUsingCParams) 4174*3117ece4Schristos || ZSTD_isError(cctxSizeUsingLevel)) { 4175*3117ece4Schristos DISPLAYLEVEL(3, "error! l: %d dict: %zu srcSize: %zu cctx size cpar: %zu, cctx size level: %zu\n", 4176*3117ece4Schristos level, dictSize, srcSize, cctxSizeUsingCParams, cctxSizeUsingLevel); 4177*3117ece4Schristos goto _output_error; 4178*3117ece4Schristos } } } } } 4179*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4180*3117ece4Schristos 4181*3117ece4Schristos DISPLAYLEVEL(3, "test%3i : thread pool API tests : \n", testNb++) 4182*3117ece4Schristos { 4183*3117ece4Schristos int const threadPoolTestResult = threadPoolTests(); 4184*3117ece4Schristos if (threadPoolTestResult) { 4185*3117ece4Schristos goto _output_error; 4186*3117ece4Schristos } 4187*3117ece4Schristos } 4188*3117ece4Schristos DISPLAYLEVEL(3, "thread pool tests OK \n"); 4189*3117ece4Schristos 4190*3117ece4Schristos #endif /* ZSTD_MULTITHREAD */ 4191*3117ece4Schristos 4192*3117ece4Schristos _end: 4193*3117ece4Schristos free(CNBuffer); 4194*3117ece4Schristos free(compressedBuffer); 4195*3117ece4Schristos free(decodedBuffer); 4196*3117ece4Schristos return testResult; 4197*3117ece4Schristos 4198*3117ece4Schristos _output_error: 4199*3117ece4Schristos testResult = 1; 4200*3117ece4Schristos DISPLAY("Error detected in Unit tests ! \n"); 4201*3117ece4Schristos goto _end; 4202*3117ece4Schristos } 4203*3117ece4Schristos 4204*3117ece4Schristos static int longUnitTests(U32 const seed, double compressibility) 4205*3117ece4Schristos { 4206*3117ece4Schristos size_t const CNBuffSize = 5 MB; 4207*3117ece4Schristos void* const CNBuffer = malloc(CNBuffSize); 4208*3117ece4Schristos size_t const compressedBufferSize = ZSTD_compressBound(CNBuffSize); 4209*3117ece4Schristos void* const compressedBuffer = malloc(compressedBufferSize); 4210*3117ece4Schristos void* const decodedBuffer = malloc(CNBuffSize); 4211*3117ece4Schristos int testResult = 0; 4212*3117ece4Schristos unsigned testNb=0; 4213*3117ece4Schristos size_t cSize; 4214*3117ece4Schristos 4215*3117ece4Schristos /* Create compressible noise */ 4216*3117ece4Schristos if (!CNBuffer || !compressedBuffer || !decodedBuffer) { 4217*3117ece4Schristos DISPLAY("Not enough memory, aborting\n"); 4218*3117ece4Schristos testResult = 1; 4219*3117ece4Schristos goto _end; 4220*3117ece4Schristos } 4221*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed); 4222*3117ece4Schristos 4223*3117ece4Schristos /* note : this test is rather long, it would be great to find a way to speed up its execution */ 4224*3117ece4Schristos DISPLAYLEVEL(3, "longtest%3i : table cleanliness through index reduction : ", testNb++); 4225*3117ece4Schristos { int cLevel; 4226*3117ece4Schristos size_t approxIndex = 0; 4227*3117ece4Schristos size_t maxIndex = ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX)); /* ZSTD_CURRENT_MAX from zstd_compress_internal.h */ 4228*3117ece4Schristos 4229*3117ece4Schristos /* Provision enough space in a static context so that we can do all 4230*3117ece4Schristos * this without ever reallocating, which would reset the indices. */ 4231*3117ece4Schristos size_t const staticCCtxSize = ZSTD_estimateCStreamSize(22); 4232*3117ece4Schristos void* const staticCCtxBuffer = malloc(staticCCtxSize); 4233*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize); 4234*3117ece4Schristos 4235*3117ece4Schristos /* bump the indices so the following compressions happen at high 4236*3117ece4Schristos * indices. */ 4237*3117ece4Schristos { ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 }; 4238*3117ece4Schristos ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 }; 4239*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 4240*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, -500)); 4241*3117ece4Schristos while (approxIndex <= (maxIndex / 4) * 3) { 4242*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)); 4243*3117ece4Schristos approxIndex += in.pos; 4244*3117ece4Schristos CHECK_Z(in.pos == in.size); 4245*3117ece4Schristos in.pos = 0; 4246*3117ece4Schristos out.pos = 0; 4247*3117ece4Schristos } 4248*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 4249*3117ece4Schristos } 4250*3117ece4Schristos 4251*3117ece4Schristos /* spew a bunch of stuff into the table area */ 4252*3117ece4Schristos for (cLevel = 1; cLevel <= 22; cLevel++) { 4253*3117ece4Schristos ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize / (unsigned)cLevel, 0 }; 4254*3117ece4Schristos ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 }; 4255*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 4256*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel)); 4257*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)); 4258*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 4259*3117ece4Schristos approxIndex += in.pos; 4260*3117ece4Schristos } 4261*3117ece4Schristos 4262*3117ece4Schristos /* now crank the indices so we overflow */ 4263*3117ece4Schristos { ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 }; 4264*3117ece4Schristos ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 }; 4265*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 4266*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, -500)); 4267*3117ece4Schristos while (approxIndex <= maxIndex) { 4268*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)); 4269*3117ece4Schristos approxIndex += in.pos; 4270*3117ece4Schristos CHECK_Z(in.pos == in.size); 4271*3117ece4Schristos in.pos = 0; 4272*3117ece4Schristos out.pos = 0; 4273*3117ece4Schristos } 4274*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 4275*3117ece4Schristos } 4276*3117ece4Schristos 4277*3117ece4Schristos /* do a bunch of compressions again in low indices and ensure we don't 4278*3117ece4Schristos * hit untracked invalid indices */ 4279*3117ece4Schristos for (cLevel = 1; cLevel <= 22; cLevel++) { 4280*3117ece4Schristos ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize / (unsigned)cLevel, 0 }; 4281*3117ece4Schristos ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 }; 4282*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 4283*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel)); 4284*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)); 4285*3117ece4Schristos CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); 4286*3117ece4Schristos approxIndex += in.pos; 4287*3117ece4Schristos } 4288*3117ece4Schristos 4289*3117ece4Schristos free(staticCCtxBuffer); 4290*3117ece4Schristos } 4291*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4292*3117ece4Schristos 4293*3117ece4Schristos DISPLAYLEVEL(3, "longtest%3i : testing ldm no regressions in size for opt parser : ", testNb++); 4294*3117ece4Schristos { size_t cSizeLdm; 4295*3117ece4Schristos size_t cSizeNoLdm; 4296*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 4297*3117ece4Schristos 4298*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, 0.5, 0.5, seed); 4299*3117ece4Schristos 4300*3117ece4Schristos /* Enable checksum to verify round trip. */ 4301*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 4302*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)); 4303*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19)); 4304*3117ece4Schristos 4305*3117ece4Schristos /* Round trip once with ldm. */ 4306*3117ece4Schristos cSizeLdm = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 4307*3117ece4Schristos CHECK_Z(cSizeLdm); 4308*3117ece4Schristos CHECK_Z(ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSizeLdm)); 4309*3117ece4Schristos 4310*3117ece4Schristos ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); 4311*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)); 4312*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_disable)); 4313*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19)); 4314*3117ece4Schristos 4315*3117ece4Schristos /* Round trip once without ldm. */ 4316*3117ece4Schristos cSizeNoLdm = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 4317*3117ece4Schristos CHECK_Z(cSizeNoLdm); 4318*3117ece4Schristos CHECK_Z(ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSizeNoLdm)); 4319*3117ece4Schristos 4320*3117ece4Schristos if (cSizeLdm > cSizeNoLdm) { 4321*3117ece4Schristos DISPLAY("Using long mode should not cause regressions for btopt+\n"); 4322*3117ece4Schristos testResult = 1; 4323*3117ece4Schristos goto _end; 4324*3117ece4Schristos } 4325*3117ece4Schristos 4326*3117ece4Schristos ZSTD_freeCCtx(cctx); 4327*3117ece4Schristos } 4328*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4329*3117ece4Schristos 4330*3117ece4Schristos DISPLAYLEVEL(3, "longtest%3i : testing cdict compression with different attachment strategies : ", testNb++); 4331*3117ece4Schristos { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 4332*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 4333*3117ece4Schristos size_t dictSize = CNBuffSize; 4334*3117ece4Schristos void* dict = (void*)malloc(dictSize); 4335*3117ece4Schristos ZSTD_CCtx_params* cctx_params = ZSTD_createCCtxParams(); 4336*3117ece4Schristos ZSTD_dictAttachPref_e const attachPrefs[] = { 4337*3117ece4Schristos ZSTD_dictDefaultAttach, 4338*3117ece4Schristos ZSTD_dictForceAttach, 4339*3117ece4Schristos ZSTD_dictForceCopy, 4340*3117ece4Schristos ZSTD_dictForceLoad, 4341*3117ece4Schristos ZSTD_dictDefaultAttach, 4342*3117ece4Schristos ZSTD_dictForceAttach, 4343*3117ece4Schristos ZSTD_dictForceCopy, 4344*3117ece4Schristos ZSTD_dictForceLoad 4345*3117ece4Schristos }; 4346*3117ece4Schristos int const enableDedicatedDictSearch[] = {0, 0, 0, 0, 1, 1, 1, 1}; 4347*3117ece4Schristos int cLevel; 4348*3117ece4Schristos int i; 4349*3117ece4Schristos 4350*3117ece4Schristos RDG_genBuffer(dict, dictSize, 0.5, 0.5, seed); 4351*3117ece4Schristos RDG_genBuffer(CNBuffer, CNBuffSize, 0.6, 0.6, seed); 4352*3117ece4Schristos 4353*3117ece4Schristos CHECK_Z(cctx_params != NULL); 4354*3117ece4Schristos 4355*3117ece4Schristos for (dictSize = CNBuffSize; dictSize; dictSize = dictSize >> 3) { 4356*3117ece4Schristos DISPLAYLEVEL(3, "\n Testing with dictSize %u ", (U32)dictSize); 4357*3117ece4Schristos for (cLevel = 4; cLevel < 13; cLevel++) { 4358*3117ece4Schristos for (i = 0; i < 8; ++i) { 4359*3117ece4Schristos ZSTD_dictAttachPref_e const attachPref = attachPrefs[i]; 4360*3117ece4Schristos int const enableDDS = enableDedicatedDictSearch[i]; 4361*3117ece4Schristos ZSTD_CDict* cdict; 4362*3117ece4Schristos 4363*3117ece4Schristos DISPLAYLEVEL(5, "\n dictSize %u cLevel %d iter %d ", (U32)dictSize, cLevel, i); 4364*3117ece4Schristos 4365*3117ece4Schristos ZSTD_CCtxParams_init(cctx_params, cLevel); 4366*3117ece4Schristos CHECK_Z(ZSTD_CCtxParams_setParameter(cctx_params, ZSTD_c_enableDedicatedDictSearch, enableDDS)); 4367*3117ece4Schristos 4368*3117ece4Schristos cdict = ZSTD_createCDict_advanced2(dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cctx_params, ZSTD_defaultCMem); 4369*3117ece4Schristos CHECK(cdict != NULL); 4370*3117ece4Schristos 4371*3117ece4Schristos CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict)); 4372*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, (int)attachPref)); 4373*3117ece4Schristos 4374*3117ece4Schristos cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); 4375*3117ece4Schristos CHECK_Z(cSize); 4376*3117ece4Schristos CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize)); 4377*3117ece4Schristos 4378*3117ece4Schristos DISPLAYLEVEL(5, "compressed to %u bytes ", (U32)cSize); 4379*3117ece4Schristos 4380*3117ece4Schristos CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters)); 4381*3117ece4Schristos ZSTD_freeCDict(cdict); 4382*3117ece4Schristos } } } 4383*3117ece4Schristos 4384*3117ece4Schristos ZSTD_freeCCtx(cctx); 4385*3117ece4Schristos ZSTD_freeDCtx(dctx); 4386*3117ece4Schristos ZSTD_freeCCtxParams(cctx_params); 4387*3117ece4Schristos free(dict); 4388*3117ece4Schristos } 4389*3117ece4Schristos DISPLAYLEVEL(3, "OK \n"); 4390*3117ece4Schristos 4391*3117ece4Schristos _end: 4392*3117ece4Schristos free(CNBuffer); 4393*3117ece4Schristos free(compressedBuffer); 4394*3117ece4Schristos free(decodedBuffer); 4395*3117ece4Schristos return testResult; 4396*3117ece4Schristos } 4397*3117ece4Schristos 4398*3117ece4Schristos 4399*3117ece4Schristos static size_t findDiff(const void* buf1, const void* buf2, size_t max) 4400*3117ece4Schristos { 4401*3117ece4Schristos const BYTE* b1 = (const BYTE*)buf1; 4402*3117ece4Schristos const BYTE* b2 = (const BYTE*)buf2; 4403*3117ece4Schristos size_t u; 4404*3117ece4Schristos for (u=0; u<max; u++) { 4405*3117ece4Schristos if (b1[u] != b2[u]) break; 4406*3117ece4Schristos } 4407*3117ece4Schristos return u; 4408*3117ece4Schristos } 4409*3117ece4Schristos 4410*3117ece4Schristos 4411*3117ece4Schristos static ZSTD_parameters FUZ_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams) 4412*3117ece4Schristos { 4413*3117ece4Schristos ZSTD_parameters params; 4414*3117ece4Schristos params.cParams = cParams; 4415*3117ece4Schristos params.fParams = fParams; 4416*3117ece4Schristos return params; 4417*3117ece4Schristos } 4418*3117ece4Schristos 4419*3117ece4Schristos static size_t FUZ_rLogLength(U32* seed, U32 logLength) 4420*3117ece4Schristos { 4421*3117ece4Schristos size_t const lengthMask = ((size_t)1 << logLength) - 1; 4422*3117ece4Schristos return (lengthMask+1) + (FUZ_rand(seed) & lengthMask); 4423*3117ece4Schristos } 4424*3117ece4Schristos 4425*3117ece4Schristos static size_t FUZ_randomLength(U32* seed, U32 maxLog) 4426*3117ece4Schristos { 4427*3117ece4Schristos U32 const logLength = FUZ_rand(seed) % maxLog; 4428*3117ece4Schristos return FUZ_rLogLength(seed, logLength); 4429*3117ece4Schristos } 4430*3117ece4Schristos 4431*3117ece4Schristos #undef CHECK 4432*3117ece4Schristos #define CHECK(cond, ...) { \ 4433*3117ece4Schristos if (cond) { \ 4434*3117ece4Schristos DISPLAY("Error => "); \ 4435*3117ece4Schristos DISPLAY(__VA_ARGS__); \ 4436*3117ece4Schristos DISPLAY(" (seed %u, test nb %u) \n", (unsigned)seed, testNb); \ 4437*3117ece4Schristos goto _output_error; \ 4438*3117ece4Schristos } } 4439*3117ece4Schristos 4440*3117ece4Schristos #undef CHECK_Z 4441*3117ece4Schristos #define CHECK_Z(f) { \ 4442*3117ece4Schristos size_t const err = f; \ 4443*3117ece4Schristos if (ZSTD_isError(err)) { \ 4444*3117ece4Schristos DISPLAY("Error => %s : %s ", \ 4445*3117ece4Schristos #f, ZSTD_getErrorName(err)); \ 4446*3117ece4Schristos DISPLAY(" (seed %u, test nb %u) \n", (unsigned)seed, testNb); \ 4447*3117ece4Schristos goto _output_error; \ 4448*3117ece4Schristos } } 4449*3117ece4Schristos 4450*3117ece4Schristos 4451*3117ece4Schristos static int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, U32 const maxDurationS, double compressibility, int bigTests) 4452*3117ece4Schristos { 4453*3117ece4Schristos static const U32 maxSrcLog = 23; 4454*3117ece4Schristos static const U32 maxSampleLog = 22; 4455*3117ece4Schristos size_t const srcBufferSize = (size_t)1<<maxSrcLog; 4456*3117ece4Schristos size_t const dstBufferSize = (size_t)1<<maxSampleLog; 4457*3117ece4Schristos size_t const cBufferSize = ZSTD_compressBound(dstBufferSize); 4458*3117ece4Schristos BYTE* cNoiseBuffer[5]; 4459*3117ece4Schristos BYTE* const cBuffer = (BYTE*) malloc (cBufferSize); 4460*3117ece4Schristos BYTE* const dstBuffer = (BYTE*) malloc (dstBufferSize); 4461*3117ece4Schristos BYTE* const mirrorBuffer = (BYTE*) malloc (dstBufferSize); 4462*3117ece4Schristos ZSTD_CCtx* const refCtx = ZSTD_createCCtx(); 4463*3117ece4Schristos ZSTD_CCtx* const ctx = ZSTD_createCCtx(); 4464*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 4465*3117ece4Schristos U32 result = 0; 4466*3117ece4Schristos unsigned testNb = 0; 4467*3117ece4Schristos U32 coreSeed = seed; 4468*3117ece4Schristos UTIL_time_t const startClock = UTIL_getTime(); 4469*3117ece4Schristos U64 const maxClockSpan = maxDurationS * SEC_TO_MICRO; 4470*3117ece4Schristos int const cLevelLimiter = bigTests ? 3 : 2; 4471*3117ece4Schristos 4472*3117ece4Schristos /* allocation */ 4473*3117ece4Schristos cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize); 4474*3117ece4Schristos cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize); 4475*3117ece4Schristos cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize); 4476*3117ece4Schristos cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize); 4477*3117ece4Schristos cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize); 4478*3117ece4Schristos CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4] 4479*3117ece4Schristos || !dstBuffer || !mirrorBuffer || !cBuffer || !refCtx || !ctx || !dctx, 4480*3117ece4Schristos "Not enough memory, fuzzer tests cancelled"); 4481*3117ece4Schristos 4482*3117ece4Schristos /* Create initial samples */ 4483*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed); /* pure noise */ 4484*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed); /* barely compressible */ 4485*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed); 4486*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */ 4487*3117ece4Schristos RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */ 4488*3117ece4Schristos 4489*3117ece4Schristos /* catch up testNb */ 4490*3117ece4Schristos for (testNb=1; testNb < startTest; testNb++) FUZ_rand(&coreSeed); 4491*3117ece4Schristos 4492*3117ece4Schristos /* main test loop */ 4493*3117ece4Schristos for ( ; (testNb <= nbTests) || (UTIL_clockSpanMicro(startClock) < maxClockSpan); testNb++ ) { 4494*3117ece4Schristos BYTE* srcBuffer; /* jumping pointer */ 4495*3117ece4Schristos U32 lseed; 4496*3117ece4Schristos size_t sampleSize, maxTestSize, totalTestSize; 4497*3117ece4Schristos size_t cSize, totalCSize, totalGenSize; 4498*3117ece4Schristos U64 crcOrig; 4499*3117ece4Schristos BYTE* sampleBuffer; 4500*3117ece4Schristos const BYTE* dict; 4501*3117ece4Schristos size_t dictSize; 4502*3117ece4Schristos 4503*3117ece4Schristos /* notification */ 4504*3117ece4Schristos if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); } 4505*3117ece4Schristos else { DISPLAYUPDATE(2, "\r%6u ", testNb); } 4506*3117ece4Schristos 4507*3117ece4Schristos FUZ_rand(&coreSeed); 4508*3117ece4Schristos { U32 const prime1 = 2654435761U; lseed = coreSeed ^ prime1; } 4509*3117ece4Schristos 4510*3117ece4Schristos /* srcBuffer selection [0-4] */ 4511*3117ece4Schristos { U32 buffNb = FUZ_rand(&lseed) & 0x7F; 4512*3117ece4Schristos if (buffNb & 7) buffNb=2; /* most common : compressible (P) */ 4513*3117ece4Schristos else { 4514*3117ece4Schristos buffNb >>= 3; 4515*3117ece4Schristos if (buffNb & 7) { 4516*3117ece4Schristos const U32 tnb[2] = { 1, 3 }; /* barely/highly compressible */ 4517*3117ece4Schristos buffNb = tnb[buffNb >> 3]; 4518*3117ece4Schristos } else { 4519*3117ece4Schristos const U32 tnb[2] = { 0, 4 }; /* not compressible / sparse */ 4520*3117ece4Schristos buffNb = tnb[buffNb >> 3]; 4521*3117ece4Schristos } } 4522*3117ece4Schristos srcBuffer = cNoiseBuffer[buffNb]; 4523*3117ece4Schristos } 4524*3117ece4Schristos 4525*3117ece4Schristos /* select src segment */ 4526*3117ece4Schristos sampleSize = FUZ_randomLength(&lseed, maxSampleLog); 4527*3117ece4Schristos 4528*3117ece4Schristos /* create sample buffer (to catch read error with valgrind & sanitizers) */ 4529*3117ece4Schristos sampleBuffer = (BYTE*)malloc(sampleSize); 4530*3117ece4Schristos CHECK(sampleBuffer==NULL, "not enough memory for sample buffer"); 4531*3117ece4Schristos { size_t const sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize); 4532*3117ece4Schristos memcpy(sampleBuffer, srcBuffer + sampleStart, sampleSize); } 4533*3117ece4Schristos crcOrig = XXH64(sampleBuffer, sampleSize, 0); 4534*3117ece4Schristos 4535*3117ece4Schristos /* compression tests */ 4536*3117ece4Schristos { int const cLevelPositive = (int) 4537*3117ece4Schristos ( FUZ_rand(&lseed) % 4538*3117ece4Schristos ((U32)ZSTD_maxCLevel() - (FUZ_highbit32((U32)sampleSize) / (U32)cLevelLimiter)) ) 4539*3117ece4Schristos + 1; 4540*3117ece4Schristos int const cLevel = ((FUZ_rand(&lseed) & 15) == 3) ? 4541*3117ece4Schristos - (int)((FUZ_rand(&lseed) & 7) + 1) : /* test negative cLevel */ 4542*3117ece4Schristos cLevelPositive; 4543*3117ece4Schristos DISPLAYLEVEL(5, "fuzzer t%u: Simple compression test (level %i) \n", testNb, cLevel); 4544*3117ece4Schristos cSize = ZSTD_compressCCtx(ctx, cBuffer, cBufferSize, sampleBuffer, sampleSize, cLevel); 4545*3117ece4Schristos CHECK(ZSTD_isError(cSize), "ZSTD_compressCCtx failed : %s", ZSTD_getErrorName(cSize)); 4546*3117ece4Schristos 4547*3117ece4Schristos /* compression failure test : too small dest buffer */ 4548*3117ece4Schristos assert(cSize > 3); 4549*3117ece4Schristos { const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; 4550*3117ece4Schristos const size_t tooSmallSize = cSize - missing; 4551*3117ece4Schristos const unsigned endMark = 0x4DC2B1A9; 4552*3117ece4Schristos memcpy(dstBuffer+tooSmallSize, &endMark, sizeof(endMark)); 4553*3117ece4Schristos DISPLAYLEVEL(5, "fuzzer t%u: compress into too small buffer of size %u (missing %u bytes) \n", 4554*3117ece4Schristos testNb, (unsigned)tooSmallSize, (unsigned)missing); 4555*3117ece4Schristos { size_t const errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, sampleBuffer, sampleSize, cLevel); 4556*3117ece4Schristos CHECK(ZSTD_getErrorCode(errorCode) != ZSTD_error_dstSize_tooSmall, "ZSTD_compressCCtx should have failed ! (buffer too small : %u < %u)", (unsigned)tooSmallSize, (unsigned)cSize); } 4557*3117ece4Schristos { unsigned endCheck; memcpy(&endCheck, dstBuffer+tooSmallSize, sizeof(endCheck)); 4558*3117ece4Schristos CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow (check.%08X != %08X.mark)", endCheck, endMark); } 4559*3117ece4Schristos } } 4560*3117ece4Schristos 4561*3117ece4Schristos /* frame header decompression test */ 4562*3117ece4Schristos { ZSTD_frameHeader zfh; 4563*3117ece4Schristos CHECK_Z( ZSTD_getFrameHeader(&zfh, cBuffer, cSize) ); 4564*3117ece4Schristos CHECK(zfh.frameContentSize != sampleSize, "Frame content size incorrect"); 4565*3117ece4Schristos } 4566*3117ece4Schristos 4567*3117ece4Schristos /* Decompressed size test */ 4568*3117ece4Schristos { unsigned long long const rSize = ZSTD_findDecompressedSize(cBuffer, cSize); 4569*3117ece4Schristos CHECK(rSize != sampleSize, "decompressed size incorrect"); 4570*3117ece4Schristos } 4571*3117ece4Schristos 4572*3117ece4Schristos /* successful decompression test */ 4573*3117ece4Schristos DISPLAYLEVEL(5, "fuzzer t%u: simple decompression test \n", testNb); 4574*3117ece4Schristos { size_t const margin = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1; 4575*3117ece4Schristos size_t const dSize = ZSTD_decompress(dstBuffer, sampleSize + margin, cBuffer, cSize); 4576*3117ece4Schristos CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (unsigned)sampleSize, (unsigned)cSize); 4577*3117ece4Schristos { U64 const crcDest = XXH64(dstBuffer, sampleSize, 0); 4578*3117ece4Schristos CHECK(crcOrig != crcDest, "decompression result corrupted (pos %u / %u)", (unsigned)findDiff(sampleBuffer, dstBuffer, sampleSize), (unsigned)sampleSize); 4579*3117ece4Schristos } } 4580*3117ece4Schristos 4581*3117ece4Schristos free(sampleBuffer); /* no longer useful after this point */ 4582*3117ece4Schristos 4583*3117ece4Schristos /* truncated src decompression test */ 4584*3117ece4Schristos DISPLAYLEVEL(5, "fuzzer t%u: decompression of truncated source \n", testNb); 4585*3117ece4Schristos { size_t const missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */ 4586*3117ece4Schristos size_t const tooSmallSize = cSize - missing; 4587*3117ece4Schristos void* cBufferTooSmall = malloc(tooSmallSize); /* valgrind will catch read overflows */ 4588*3117ece4Schristos CHECK(cBufferTooSmall == NULL, "not enough memory !"); 4589*3117ece4Schristos memcpy(cBufferTooSmall, cBuffer, tooSmallSize); 4590*3117ece4Schristos { size_t const errorCode = ZSTD_decompress(dstBuffer, dstBufferSize, cBufferTooSmall, tooSmallSize); 4591*3117ece4Schristos CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed ! (truncated src buffer)"); } 4592*3117ece4Schristos free(cBufferTooSmall); 4593*3117ece4Schristos } 4594*3117ece4Schristos 4595*3117ece4Schristos /* too small dst decompression test */ 4596*3117ece4Schristos DISPLAYLEVEL(5, "fuzzer t%u: decompress into too small dst buffer \n", testNb); 4597*3117ece4Schristos if (sampleSize > 3) { 4598*3117ece4Schristos size_t const missing = (FUZ_rand(&lseed) % (sampleSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */ 4599*3117ece4Schristos size_t const tooSmallSize = sampleSize - missing; 4600*3117ece4Schristos static const BYTE token = 0xA9; 4601*3117ece4Schristos dstBuffer[tooSmallSize] = token; 4602*3117ece4Schristos { size_t const errorCode = ZSTD_decompress(dstBuffer, tooSmallSize, cBuffer, cSize); 4603*3117ece4Schristos CHECK(ZSTD_getErrorCode(errorCode) != ZSTD_error_dstSize_tooSmall, "ZSTD_decompress should have failed : %u > %u (dst buffer too small)", (unsigned)errorCode, (unsigned)tooSmallSize); } 4604*3117ece4Schristos CHECK(dstBuffer[tooSmallSize] != token, "ZSTD_decompress : dst buffer overflow"); 4605*3117ece4Schristos } 4606*3117ece4Schristos 4607*3117ece4Schristos /* noisy src decompression test */ 4608*3117ece4Schristos if (cSize > 6) { 4609*3117ece4Schristos /* insert noise into src */ 4610*3117ece4Schristos { U32 const maxNbBits = FUZ_highbit32((U32)(cSize-4)); 4611*3117ece4Schristos size_t pos = 4; /* preserve magic number (too easy to detect) */ 4612*3117ece4Schristos for (;;) { 4613*3117ece4Schristos /* keep some original src */ 4614*3117ece4Schristos { U32 const nbBits = FUZ_rand(&lseed) % maxNbBits; 4615*3117ece4Schristos size_t const mask = (1<<nbBits) - 1; 4616*3117ece4Schristos size_t const skipLength = FUZ_rand(&lseed) & mask; 4617*3117ece4Schristos pos += skipLength; 4618*3117ece4Schristos } 4619*3117ece4Schristos if (pos >= cSize) break; 4620*3117ece4Schristos /* add noise */ 4621*3117ece4Schristos { U32 const nbBitsCodes = FUZ_rand(&lseed) % maxNbBits; 4622*3117ece4Schristos U32 const nbBits = nbBitsCodes ? nbBitsCodes-1 : 0; 4623*3117ece4Schristos size_t const mask = (1<<nbBits) - 1; 4624*3117ece4Schristos size_t const rNoiseLength = (FUZ_rand(&lseed) & mask) + 1; 4625*3117ece4Schristos size_t const noiseLength = MIN(rNoiseLength, cSize-pos); 4626*3117ece4Schristos size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseLength); 4627*3117ece4Schristos memcpy(cBuffer + pos, srcBuffer + noiseStart, noiseLength); 4628*3117ece4Schristos pos += noiseLength; 4629*3117ece4Schristos } } } 4630*3117ece4Schristos 4631*3117ece4Schristos /* decompress noisy source */ 4632*3117ece4Schristos DISPLAYLEVEL(5, "fuzzer t%u: decompress noisy source \n", testNb); 4633*3117ece4Schristos { U32 const endMark = 0xA9B1C3D6; 4634*3117ece4Schristos memcpy(dstBuffer+sampleSize, &endMark, 4); 4635*3117ece4Schristos { size_t const decompressResult = ZSTD_decompress(dstBuffer, sampleSize, cBuffer, cSize); 4636*3117ece4Schristos /* result *may* be an unlikely success, but even then, it must strictly respect dst buffer boundaries */ 4637*3117ece4Schristos CHECK((!ZSTD_isError(decompressResult)) && (decompressResult>sampleSize), 4638*3117ece4Schristos "ZSTD_decompress on noisy src : result is too large : %u > %u (dst buffer)", (unsigned)decompressResult, (unsigned)sampleSize); 4639*3117ece4Schristos } 4640*3117ece4Schristos { U32 endCheck; memcpy(&endCheck, dstBuffer+sampleSize, 4); 4641*3117ece4Schristos CHECK(endMark!=endCheck, "ZSTD_decompress on noisy src : dst buffer overflow"); 4642*3117ece4Schristos } } } /* noisy src decompression test */ 4643*3117ece4Schristos 4644*3117ece4Schristos /*===== Bufferless streaming compression test, scattered segments and dictionary =====*/ 4645*3117ece4Schristos DISPLAYLEVEL(5, "fuzzer t%u: Bufferless streaming compression test \n", testNb); 4646*3117ece4Schristos { U32 const testLog = FUZ_rand(&lseed) % maxSrcLog; 4647*3117ece4Schristos U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog; 4648*3117ece4Schristos int const cLevel = (int)(FUZ_rand(&lseed) % 4649*3117ece4Schristos ((U32)ZSTD_maxCLevel() - 4650*3117ece4Schristos (MAX(testLog, dictLog) / (U32)cLevelLimiter))) + 4651*3117ece4Schristos 1; 4652*3117ece4Schristos maxTestSize = FUZ_rLogLength(&lseed, testLog); 4653*3117ece4Schristos if (maxTestSize >= dstBufferSize) maxTestSize = dstBufferSize-1; 4654*3117ece4Schristos 4655*3117ece4Schristos dictSize = FUZ_rLogLength(&lseed, dictLog); /* needed also for decompression */ 4656*3117ece4Schristos dict = srcBuffer + (FUZ_rand(&lseed) % (srcBufferSize - dictSize)); 4657*3117ece4Schristos 4658*3117ece4Schristos DISPLAYLEVEL(6, "fuzzer t%u: Compressing up to <=%u bytes at level %i with dictionary size %u \n", 4659*3117ece4Schristos testNb, (unsigned)maxTestSize, cLevel, (unsigned)dictSize); 4660*3117ece4Schristos 4661*3117ece4Schristos if (FUZ_rand(&lseed) & 0xF) { 4662*3117ece4Schristos CHECK_Z ( ZSTD_compressBegin_usingDict(refCtx, dict, dictSize, cLevel) ); 4663*3117ece4Schristos } else { 4664*3117ece4Schristos ZSTD_compressionParameters const cPar = ZSTD_getCParams(cLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); 4665*3117ece4Schristos ZSTD_frameParameters const fPar = { FUZ_rand(&lseed)&1 /* contentSizeFlag */, 4666*3117ece4Schristos !(FUZ_rand(&lseed)&3) /* contentChecksumFlag*/, 4667*3117ece4Schristos 0 /*NodictID*/ }; /* note : since dictionary is fake, dictIDflag has no impact */ 4668*3117ece4Schristos ZSTD_parameters const p = FUZ_makeParams(cPar, fPar); 4669*3117ece4Schristos CHECK_Z ( ZSTD_compressBegin_advanced(refCtx, dict, dictSize, p, 0) ); 4670*3117ece4Schristos } 4671*3117ece4Schristos CHECK_Z( ZSTD_copyCCtx(ctx, refCtx, 0) ); 4672*3117ece4Schristos } 4673*3117ece4Schristos 4674*3117ece4Schristos { U32 const nbChunks = (FUZ_rand(&lseed) & 127) + 2; 4675*3117ece4Schristos U32 n; 4676*3117ece4Schristos XXH64_state_t xxhState; 4677*3117ece4Schristos XXH64_reset(&xxhState, 0); 4678*3117ece4Schristos for (totalTestSize=0, cSize=0, n=0 ; n<nbChunks ; n++) { 4679*3117ece4Schristos size_t const segmentSize = FUZ_randomLength(&lseed, maxSampleLog); 4680*3117ece4Schristos size_t const segmentStart = FUZ_rand(&lseed) % (srcBufferSize - segmentSize); 4681*3117ece4Schristos 4682*3117ece4Schristos if (cBufferSize-cSize < ZSTD_compressBound(segmentSize)) break; /* avoid invalid dstBufferTooSmall */ 4683*3117ece4Schristos if (totalTestSize+segmentSize > maxTestSize) break; 4684*3117ece4Schristos 4685*3117ece4Schristos { size_t const compressResult = ZSTD_compressContinue(ctx, cBuffer+cSize, cBufferSize-cSize, srcBuffer+segmentStart, segmentSize); 4686*3117ece4Schristos CHECK (ZSTD_isError(compressResult), "multi-segments compression error : %s", ZSTD_getErrorName(compressResult)); 4687*3117ece4Schristos cSize += compressResult; 4688*3117ece4Schristos } 4689*3117ece4Schristos XXH64_update(&xxhState, srcBuffer+segmentStart, segmentSize); 4690*3117ece4Schristos memcpy(mirrorBuffer + totalTestSize, srcBuffer+segmentStart, segmentSize); 4691*3117ece4Schristos totalTestSize += segmentSize; 4692*3117ece4Schristos } 4693*3117ece4Schristos 4694*3117ece4Schristos { size_t const flushResult = ZSTD_compressEnd(ctx, cBuffer+cSize, cBufferSize-cSize, NULL, 0); 4695*3117ece4Schristos CHECK (ZSTD_isError(flushResult), "multi-segments epilogue error : %s", ZSTD_getErrorName(flushResult)); 4696*3117ece4Schristos cSize += flushResult; 4697*3117ece4Schristos } 4698*3117ece4Schristos crcOrig = XXH64_digest(&xxhState); 4699*3117ece4Schristos } 4700*3117ece4Schristos 4701*3117ece4Schristos /* streaming decompression test */ 4702*3117ece4Schristos DISPLAYLEVEL(5, "fuzzer t%u: Bufferless streaming decompression test \n", testNb); 4703*3117ece4Schristos /* ensure memory requirement is good enough (should always be true) */ 4704*3117ece4Schristos { ZSTD_frameHeader zfh; 4705*3117ece4Schristos CHECK( ZSTD_getFrameHeader(&zfh, cBuffer, ZSTD_FRAMEHEADERSIZE_MAX), 4706*3117ece4Schristos "ZSTD_getFrameHeader(): error retrieving frame information"); 4707*3117ece4Schristos { size_t const roundBuffSize = ZSTD_decodingBufferSize_min(zfh.windowSize, zfh.frameContentSize); 4708*3117ece4Schristos CHECK_Z(roundBuffSize); 4709*3117ece4Schristos CHECK((roundBuffSize > totalTestSize) && (zfh.frameContentSize!=ZSTD_CONTENTSIZE_UNKNOWN), 4710*3117ece4Schristos "ZSTD_decodingBufferSize_min() requires more memory (%u) than necessary (%u)", 4711*3117ece4Schristos (unsigned)roundBuffSize, (unsigned)totalTestSize ); 4712*3117ece4Schristos } } 4713*3117ece4Schristos if (dictSize<8) dictSize=0, dict=NULL; /* disable dictionary */ 4714*3117ece4Schristos CHECK_Z( ZSTD_decompressBegin_usingDict(dctx, dict, dictSize) ); 4715*3117ece4Schristos totalCSize = 0; 4716*3117ece4Schristos totalGenSize = 0; 4717*3117ece4Schristos while (totalCSize < cSize) { 4718*3117ece4Schristos size_t const inSize = ZSTD_nextSrcSizeToDecompress(dctx); 4719*3117ece4Schristos size_t const genSize = ZSTD_decompressContinue(dctx, dstBuffer+totalGenSize, dstBufferSize-totalGenSize, cBuffer+totalCSize, inSize); 4720*3117ece4Schristos CHECK (ZSTD_isError(genSize), "ZSTD_decompressContinue error : %s", ZSTD_getErrorName(genSize)); 4721*3117ece4Schristos totalGenSize += genSize; 4722*3117ece4Schristos totalCSize += inSize; 4723*3117ece4Schristos } 4724*3117ece4Schristos CHECK (ZSTD_nextSrcSizeToDecompress(dctx) != 0, "frame not fully decoded"); 4725*3117ece4Schristos CHECK (totalGenSize != totalTestSize, "streaming decompressed data : wrong size") 4726*3117ece4Schristos CHECK (totalCSize != cSize, "compressed data should be fully read") 4727*3117ece4Schristos { U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0); 4728*3117ece4Schristos CHECK(crcOrig != crcDest, "streaming decompressed data corrupted (pos %u / %u)", 4729*3117ece4Schristos (unsigned)findDiff(mirrorBuffer, dstBuffer, totalTestSize), (unsigned)totalTestSize); 4730*3117ece4Schristos } 4731*3117ece4Schristos } /* for ( ; (testNb <= nbTests) */ 4732*3117ece4Schristos DISPLAY("\r%u fuzzer tests completed \n", testNb-1); 4733*3117ece4Schristos 4734*3117ece4Schristos _cleanup: 4735*3117ece4Schristos ZSTD_freeCCtx(refCtx); 4736*3117ece4Schristos ZSTD_freeCCtx(ctx); 4737*3117ece4Schristos ZSTD_freeDCtx(dctx); 4738*3117ece4Schristos free(cNoiseBuffer[0]); 4739*3117ece4Schristos free(cNoiseBuffer[1]); 4740*3117ece4Schristos free(cNoiseBuffer[2]); 4741*3117ece4Schristos free(cNoiseBuffer[3]); 4742*3117ece4Schristos free(cNoiseBuffer[4]); 4743*3117ece4Schristos free(cBuffer); 4744*3117ece4Schristos free(dstBuffer); 4745*3117ece4Schristos free(mirrorBuffer); 4746*3117ece4Schristos return (int)result; 4747*3117ece4Schristos 4748*3117ece4Schristos _output_error: 4749*3117ece4Schristos result = 1; 4750*3117ece4Schristos goto _cleanup; 4751*3117ece4Schristos } 4752*3117ece4Schristos 4753*3117ece4Schristos 4754*3117ece4Schristos /*_******************************************************* 4755*3117ece4Schristos * Command line 4756*3117ece4Schristos *********************************************************/ 4757*3117ece4Schristos static int FUZ_usage(const char* programName) 4758*3117ece4Schristos { 4759*3117ece4Schristos DISPLAY( "Usage :\n"); 4760*3117ece4Schristos DISPLAY( " %s [args]\n", programName); 4761*3117ece4Schristos DISPLAY( "\n"); 4762*3117ece4Schristos DISPLAY( "Arguments :\n"); 4763*3117ece4Schristos DISPLAY( " -i# : Number of tests (default:%i)\n", nbTestsDefault); 4764*3117ece4Schristos DISPLAY( " -T# : Max duration to run for. Overrides number of tests. (e.g. -T1m or -T60s for one minute)\n"); 4765*3117ece4Schristos DISPLAY( " -s# : Select seed (default:prompt user)\n"); 4766*3117ece4Schristos DISPLAY( " -t# : Select starting test number (default:0)\n"); 4767*3117ece4Schristos DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_compressibility_default); 4768*3117ece4Schristos DISPLAY( " -v : verbose\n"); 4769*3117ece4Schristos DISPLAY( " -p : pause at the end\n"); 4770*3117ece4Schristos DISPLAY( " -h : display help and exit\n"); 4771*3117ece4Schristos return 0; 4772*3117ece4Schristos } 4773*3117ece4Schristos 4774*3117ece4Schristos /*! readU32FromChar() : 4775*3117ece4Schristos @return : unsigned integer value read from input in `char` format 4776*3117ece4Schristos allows and interprets K, KB, KiB, M, MB and MiB suffix. 4777*3117ece4Schristos Will also modify `*stringPtr`, advancing it to position where it stopped reading. 4778*3117ece4Schristos Note : function result can overflow if digit string > MAX_UINT */ 4779*3117ece4Schristos static unsigned readU32FromChar(const char** stringPtr) 4780*3117ece4Schristos { 4781*3117ece4Schristos unsigned result = 0; 4782*3117ece4Schristos while ((**stringPtr >='0') && (**stringPtr <='9')) 4783*3117ece4Schristos result *= 10, result += (unsigned)(**stringPtr - '0'), (*stringPtr)++ ; 4784*3117ece4Schristos if ((**stringPtr=='K') || (**stringPtr=='M')) { 4785*3117ece4Schristos result <<= 10; 4786*3117ece4Schristos if (**stringPtr=='M') result <<= 10; 4787*3117ece4Schristos (*stringPtr)++ ; 4788*3117ece4Schristos if (**stringPtr=='i') (*stringPtr)++; 4789*3117ece4Schristos if (**stringPtr=='B') (*stringPtr)++; 4790*3117ece4Schristos } 4791*3117ece4Schristos return result; 4792*3117ece4Schristos } 4793*3117ece4Schristos 4794*3117ece4Schristos /** longCommandWArg() : 4795*3117ece4Schristos * check if *stringPtr is the same as longCommand. 4796*3117ece4Schristos * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand. 4797*3117ece4Schristos * @return 0 and doesn't modify *stringPtr otherwise. 4798*3117ece4Schristos */ 4799*3117ece4Schristos static int longCommandWArg(const char** stringPtr, const char* longCommand) 4800*3117ece4Schristos { 4801*3117ece4Schristos size_t const comSize = strlen(longCommand); 4802*3117ece4Schristos int const result = !strncmp(*stringPtr, longCommand, comSize); 4803*3117ece4Schristos if (result) *stringPtr += comSize; 4804*3117ece4Schristos return result; 4805*3117ece4Schristos } 4806*3117ece4Schristos 4807*3117ece4Schristos int main(int argc, const char** argv) 4808*3117ece4Schristos { 4809*3117ece4Schristos U32 seed = 0; 4810*3117ece4Schristos int seedset = 0; 4811*3117ece4Schristos int argNb; 4812*3117ece4Schristos int nbTests = nbTestsDefault; 4813*3117ece4Schristos int testNb = 0; 4814*3117ece4Schristos int proba = FUZ_compressibility_default; 4815*3117ece4Schristos double probfloat; 4816*3117ece4Schristos int result = 0; 4817*3117ece4Schristos U32 mainPause = 0; 4818*3117ece4Schristos U32 maxDuration = 0; 4819*3117ece4Schristos int bigTests = 1; 4820*3117ece4Schristos int longTests = 0; 4821*3117ece4Schristos U32 memTestsOnly = 0; 4822*3117ece4Schristos const char* const programName = argv[0]; 4823*3117ece4Schristos 4824*3117ece4Schristos /* Check command line */ 4825*3117ece4Schristos for (argNb=1; argNb<argc; argNb++) { 4826*3117ece4Schristos const char* argument = argv[argNb]; 4827*3117ece4Schristos if(!argument) continue; /* Protection if argument empty */ 4828*3117ece4Schristos 4829*3117ece4Schristos /* Handle commands. Aggregated commands are allowed */ 4830*3117ece4Schristos if (argument[0]=='-') { 4831*3117ece4Schristos 4832*3117ece4Schristos if (longCommandWArg(&argument, "--memtest=")) { memTestsOnly = readU32FromChar(&argument); continue; } 4833*3117ece4Schristos 4834*3117ece4Schristos if (!strcmp(argument, "--memtest")) { memTestsOnly=1; continue; } 4835*3117ece4Schristos if (!strcmp(argument, "--no-big-tests")) { bigTests=0; continue; } 4836*3117ece4Schristos if (!strcmp(argument, "--long-tests")) { longTests=1; continue; } 4837*3117ece4Schristos if (!strcmp(argument, "--no-long-tests")) { longTests=0; continue; } 4838*3117ece4Schristos 4839*3117ece4Schristos argument++; 4840*3117ece4Schristos while (*argument!=0) { 4841*3117ece4Schristos switch(*argument) 4842*3117ece4Schristos { 4843*3117ece4Schristos case 'h': 4844*3117ece4Schristos return FUZ_usage(programName); 4845*3117ece4Schristos 4846*3117ece4Schristos case 'v': 4847*3117ece4Schristos argument++; 4848*3117ece4Schristos g_displayLevel++; 4849*3117ece4Schristos break; 4850*3117ece4Schristos 4851*3117ece4Schristos case 'q': 4852*3117ece4Schristos argument++; 4853*3117ece4Schristos g_displayLevel--; 4854*3117ece4Schristos break; 4855*3117ece4Schristos 4856*3117ece4Schristos case 'p': /* pause at the end */ 4857*3117ece4Schristos argument++; 4858*3117ece4Schristos mainPause = 1; 4859*3117ece4Schristos break; 4860*3117ece4Schristos 4861*3117ece4Schristos case 'i': 4862*3117ece4Schristos argument++; maxDuration = 0; 4863*3117ece4Schristos nbTests = (int)readU32FromChar(&argument); 4864*3117ece4Schristos break; 4865*3117ece4Schristos 4866*3117ece4Schristos case 'T': 4867*3117ece4Schristos argument++; 4868*3117ece4Schristos nbTests = 0; 4869*3117ece4Schristos maxDuration = readU32FromChar(&argument); 4870*3117ece4Schristos if (*argument=='s') argument++; /* seconds */ 4871*3117ece4Schristos if (*argument=='m') maxDuration *= 60, argument++; /* minutes */ 4872*3117ece4Schristos if (*argument=='n') argument++; 4873*3117ece4Schristos break; 4874*3117ece4Schristos 4875*3117ece4Schristos case 's': 4876*3117ece4Schristos argument++; 4877*3117ece4Schristos seedset = 1; 4878*3117ece4Schristos seed = readU32FromChar(&argument); 4879*3117ece4Schristos break; 4880*3117ece4Schristos 4881*3117ece4Schristos case 't': 4882*3117ece4Schristos argument++; 4883*3117ece4Schristos testNb = (int)readU32FromChar(&argument); 4884*3117ece4Schristos break; 4885*3117ece4Schristos 4886*3117ece4Schristos case 'P': /* compressibility % */ 4887*3117ece4Schristos argument++; 4888*3117ece4Schristos proba = (int)readU32FromChar(&argument); 4889*3117ece4Schristos if (proba>100) proba = 100; 4890*3117ece4Schristos break; 4891*3117ece4Schristos 4892*3117ece4Schristos default: 4893*3117ece4Schristos return (FUZ_usage(programName), 1); 4894*3117ece4Schristos } } } } /* for (argNb=1; argNb<argc; argNb++) */ 4895*3117ece4Schristos 4896*3117ece4Schristos /* Get Seed */ 4897*3117ece4Schristos DISPLAY("Starting zstd tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION_STRING); 4898*3117ece4Schristos 4899*3117ece4Schristos if (!seedset) { 4900*3117ece4Schristos time_t const t = time(NULL); 4901*3117ece4Schristos U32 const h = XXH32(&t, sizeof(t), 1); 4902*3117ece4Schristos seed = h % 10000; 4903*3117ece4Schristos } 4904*3117ece4Schristos 4905*3117ece4Schristos DISPLAY("Seed = %u\n", (unsigned)seed); 4906*3117ece4Schristos if (proba!=FUZ_compressibility_default) DISPLAY("Compressibility : %i%%\n", proba); 4907*3117ece4Schristos 4908*3117ece4Schristos probfloat = ((double)proba) / 100; 4909*3117ece4Schristos 4910*3117ece4Schristos if (memTestsOnly) { 4911*3117ece4Schristos g_displayLevel = MAX(3, g_displayLevel); 4912*3117ece4Schristos return FUZ_mallocTests(seed, probfloat, memTestsOnly); 4913*3117ece4Schristos } 4914*3117ece4Schristos 4915*3117ece4Schristos if (nbTests < testNb) nbTests = testNb; 4916*3117ece4Schristos 4917*3117ece4Schristos if (testNb==0) { 4918*3117ece4Schristos result = basicUnitTests(0, probfloat); /* constant seed for predictability */ 4919*3117ece4Schristos 4920*3117ece4Schristos if (!result && longTests) { 4921*3117ece4Schristos result = longUnitTests(0, probfloat); 4922*3117ece4Schristos } 4923*3117ece4Schristos } 4924*3117ece4Schristos if (!result) 4925*3117ece4Schristos result = fuzzerTests(seed, (unsigned)nbTests, (unsigned)testNb, maxDuration, ((double)proba) / 100, bigTests); 4926*3117ece4Schristos if (mainPause) { 4927*3117ece4Schristos int unused; 4928*3117ece4Schristos DISPLAY("Press Enter \n"); 4929*3117ece4Schristos unused = getchar(); 4930*3117ece4Schristos (void)unused; 4931*3117ece4Schristos } 4932*3117ece4Schristos return result; 4933*3117ece4Schristos } 4934