2 * Copyright (c) 2015-present, Yann Collet, Facebook, Inc.
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
12 /*-************************************
14 **************************************/
15 #ifdef _MSC_VER /* Visual Studio */
16 # define _CRT_SECURE_NO_WARNINGS /* fgets */
17 # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
18 # pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
22 /*-************************************
24 **************************************/
25 #include <stdlib.h> /* free */
26 #include <stdio.h> /* fgets, sscanf */
27 #include <string.h> /* strcmp */
29 #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressContinue, ZSTD_compressBlock */
31 #include "zstd.h" /* ZSTD_VERSION_STRING */
32 #include "zstd_errors.h" /* ZSTD_getErrorCode */
33 #include "zstdmt_compress.h"
34 #define ZDICT_STATIC_LINKING_ONLY
35 #include "zdict.h" /* ZDICT_trainFromBuffer */
36 #include "datagen.h" /* RDG_genBuffer */
38 #define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
39 #include "xxhash.h" /* XXH64 */
41 #include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */
44 /*-************************************
46 **************************************/
51 static const int FUZ_compressibility_default = 50;
52 static const int nbTestsDefault = 30000;
55 /*-************************************
57 **************************************/
58 #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
59 #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
60 static U32 g_displayLevel = 2;
62 static const U64 g_refreshRate = SEC_TO_MICRO / 6;
63 static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
65 #define DISPLAYUPDATE(l, ...) \
66 if (g_displayLevel>=l) { \
67 if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \
68 { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \
69 if (g_displayLevel>=4) fflush(stderr); } \
73 /*-*******************************************************
75 *********************************************************/
78 /* Declaring the function, to avoid -Wmissing-prototype */
79 void FUZ_bug976(void);
81 { /* these constants shall not depend on MIN() macro */
82 assert(ZSTD_HASHLOG_MAX < 31);
83 assert(ZSTD_CHAINLOG_MAX < 31);
87 /*-*******************************************************
89 *********************************************************/
90 #define MIN(a,b) ((a)<(b)?(a):(b))
91 #define MAX(a,b) ((a)>(b)?(a):(b))
93 #define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
94 static U32 FUZ_rand(U32* src)
96 static const U32 prime1 = 2654435761U;
97 static const U32 prime2 = 2246822519U;
101 rand32 = FUZ_rotl32(rand32, 13);
106 static U32 FUZ_highbit32(U32 v32)
109 if (v32==0) return 0;
110 while (v32) v32 >>= 1, nbBits++;
115 /*=============================================
117 =============================================*/
118 #define CHECK_Z(f) { \
119 size_t const err = f; \
120 if (ZSTD_isError(err)) { \
121 DISPLAY("Error => %s : %s ", \
122 #f, ZSTD_getErrorName(err)); \
126 #define CHECK_VAR(var, fn) var = fn; if (ZSTD_isError(var)) { DISPLAYLEVEL(1, "%s : fails : %s \n", #fn, ZSTD_getErrorName(var)); goto _output_error; }
127 #define CHECK_NEWV(var, fn) size_t const CHECK_VAR(var, fn)
128 #define CHECK(fn) { CHECK_NEWV(err, fn); }
129 #define CHECKPLUS(var, fn, more) { CHECK_NEWV(var, fn); more; }
131 #define CHECK_OP(op, lhs, rhs) { \
132 if (!((lhs) op (rhs))) { \
133 DISPLAY("Error L%u => FAILED %s %s %s ", __LINE__, #lhs, #op, #rhs); \
134 goto _output_error; \
137 #define CHECK_EQ(lhs, rhs) CHECK_OP(==, lhs, rhs)
138 #define CHECK_LT(lhs, rhs) CHECK_OP(<, lhs, rhs)
141 /*=============================================
143 =============================================*/
144 #if defined(__APPLE__) && defined(__MACH__)
146 #include <malloc/malloc.h> /* malloc_size */
149 unsigned long long totalMalloc;
150 size_t currentMalloc;
156 static const mallocCounter_t INIT_MALLOC_COUNTER = { 0, 0, 0, 0, 0 };
158 static void* FUZ_mallocDebug(void* counter, size_t size)
160 mallocCounter_t* const mcPtr = (mallocCounter_t*)counter;
161 void* const ptr = malloc(size);
162 if (ptr==NULL) return NULL;
163 DISPLAYLEVEL(4, "allocating %u KB => effectively %u KB \n",
164 (unsigned)(size >> 10), (unsigned)(malloc_size(ptr) >> 10)); /* OS-X specific */
165 mcPtr->totalMalloc += size;
166 mcPtr->currentMalloc += size;
167 if (mcPtr->currentMalloc > mcPtr->peakMalloc)
168 mcPtr->peakMalloc = mcPtr->currentMalloc;
169 mcPtr->nbMalloc += 1;
173 static void FUZ_freeDebug(void* counter, void* address)
175 mallocCounter_t* const mcPtr = (mallocCounter_t*)counter;
176 DISPLAYLEVEL(4, "freeing %u KB \n", (unsigned)(malloc_size(address) >> 10));
178 mcPtr->currentMalloc -= malloc_size(address); /* OS-X specific */
182 static void FUZ_displayMallocStats(mallocCounter_t count)
184 DISPLAYLEVEL(3, "peak:%6u KB, nbMallocs:%2u, total:%6u KB \n",
185 (unsigned)(count.peakMalloc >> 10),
187 (unsigned)(count.totalMalloc >> 10));
190 static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsigned part,
191 void* inBuffer, size_t inSize, void* outBuffer, size_t outSize)
193 /* test only played in verbose mode, as they are long */
194 if (g_displayLevel<3) return 0;
196 /* Create compressible noise */
197 if (!inBuffer || !outBuffer) {
198 DISPLAY("Not enough memory, aborting\n");
201 RDG_genBuffer(inBuffer, inSize, compressibility, 0. /*auto*/, seed);
203 /* simple compression tests */
205 { int compressionLevel;
206 for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {
207 mallocCounter_t malcount = INIT_MALLOC_COUNTER;
208 ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount };
209 ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem);
210 CHECK_Z( ZSTD_compressCCtx(cctx, outBuffer, outSize, inBuffer, inSize, compressionLevel) );
212 DISPLAYLEVEL(3, "compressCCtx level %i : ", compressionLevel);
213 FUZ_displayMallocStats(malcount);
216 /* streaming compression tests */
218 { int compressionLevel;
219 for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {
220 mallocCounter_t malcount = INIT_MALLOC_COUNTER;
221 ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount };
222 ZSTD_CCtx* const cstream = ZSTD_createCStream_advanced(cMem);
223 ZSTD_outBuffer out = { outBuffer, outSize, 0 };
224 ZSTD_inBuffer in = { inBuffer, inSize, 0 };
225 CHECK_Z( ZSTD_initCStream(cstream, compressionLevel) );
226 CHECK_Z( ZSTD_compressStream(cstream, &out, &in) );
227 CHECK_Z( ZSTD_endStream(cstream, &out) );
228 ZSTD_freeCStream(cstream);
229 DISPLAYLEVEL(3, "compressStream level %i : ", compressionLevel);
230 FUZ_displayMallocStats(malcount);
233 /* advanced MT API test */
236 for (nbThreads=1; nbThreads<=4; nbThreads++) {
237 int compressionLevel;
238 for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {
239 mallocCounter_t malcount = INIT_MALLOC_COUNTER;
240 ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount };
241 ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem);
242 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) );
243 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads) );
244 CHECK_Z( ZSTD_compress2(cctx, outBuffer, outSize, inBuffer, inSize) );
246 DISPLAYLEVEL(3, "compress_generic,-T%i,end level %i : ",
247 nbThreads, compressionLevel);
248 FUZ_displayMallocStats(malcount);
251 /* advanced MT streaming API test */
254 for (nbThreads=1; nbThreads<=4; nbThreads++) {
255 int compressionLevel;
256 for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {
257 mallocCounter_t malcount = INIT_MALLOC_COUNTER;
258 ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount };
259 ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem);
260 ZSTD_outBuffer out = { outBuffer, outSize, 0 };
261 ZSTD_inBuffer in = { inBuffer, inSize, 0 };
262 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) );
263 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads) );
264 CHECK_Z( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue) );
265 while ( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) ) {}
267 DISPLAYLEVEL(3, "compress_generic,-T%i,continue level %i : ",
268 nbThreads, compressionLevel);
269 FUZ_displayMallocStats(malcount);
275 static int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part)
277 size_t const inSize = 64 MB + 16 MB + 4 MB + 1 MB + 256 KB + 64 KB; /* 85.3 MB */
278 size_t const outSize = ZSTD_compressBound(inSize);
279 void* const inBuffer = malloc(inSize);
280 void* const outBuffer = malloc(outSize);
283 /* Create compressible noise */
284 if (!inBuffer || !outBuffer) {
285 DISPLAY("Not enough memory, aborting \n");
289 result = FUZ_mallocTests_internal(seed, compressibility, part,
290 inBuffer, inSize, outBuffer, outSize);
299 static int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part)
301 (void)seed; (void)compressibility; (void)part;
307 static void FUZ_decodeSequences(BYTE* dst, ZSTD_Sequence* seqs, size_t seqsSize, BYTE* src, size_t size)
311 for(i = 0; i < seqsSize - 1; ++i) {
312 assert(dst + seqs[i].litLength + seqs[i].matchLength < dst + size);
313 assert(src + seqs[i].litLength + seqs[i].matchLength < src + size);
315 memcpy(dst, src, seqs[i].litLength);
316 dst += seqs[i].litLength;
317 src += seqs[i].litLength;
318 size -= seqs[i].litLength;
320 for (j = 0; j < seqs[i].matchLength; ++j)
321 dst[j] = dst[j - seqs[i].offset];
322 dst += seqs[i].matchLength;
323 src += seqs[i].matchLength;
324 size -= seqs[i].matchLength;
326 memcpy(dst, src, size);
329 /*=============================================
331 =============================================*/
333 static int basicUnitTests(U32 const seed, double compressibility)
335 size_t const CNBuffSize = 5 MB;
336 void* const CNBuffer = malloc(CNBuffSize);
337 size_t const compressedBufferSize = ZSTD_compressBound(CNBuffSize);
338 void* const compressedBuffer = malloc(compressedBufferSize);
339 void* const decodedBuffer = malloc(CNBuffSize);
344 /* Create compressible noise */
345 if (!CNBuffer || !compressedBuffer || !decodedBuffer) {
346 DISPLAY("Not enough memory, aborting\n");
350 RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed);
353 DISPLAYLEVEL(3, "test%3u : ZSTD_getErrorName : ", testNb++);
354 { const char* errorString = ZSTD_getErrorName(0);
355 DISPLAYLEVEL(3, "OK : %s \n", errorString);
358 DISPLAYLEVEL(3, "test%3u : ZSTD_getErrorName with wrong value : ", testNb++);
359 { const char* errorString = ZSTD_getErrorName(499);
360 DISPLAYLEVEL(3, "OK : %s \n", errorString);
363 DISPLAYLEVEL(3, "test%3u : min compression level : ", testNb++);
364 { int const mcl = ZSTD_minCLevel();
365 DISPLAYLEVEL(3, "%i (OK) \n", mcl);
368 DISPLAYLEVEL(3, "test%3u : compress %u bytes : ", testNb++, (unsigned)CNBuffSize);
369 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
370 if (cctx==NULL) goto _output_error;
371 CHECK_VAR(cSize, ZSTD_compressCCtx(cctx,
372 compressedBuffer, compressedBufferSize,
373 CNBuffer, CNBuffSize, 1) );
374 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
376 DISPLAYLEVEL(3, "test%3i : size of cctx for level 1 : ", testNb++);
377 { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx);
378 DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cctxSize);
383 DISPLAYLEVEL(3, "test%3i : decompress skippable frame -8 size : ", testNb++);
385 char const skippable8[] = "\x50\x2a\x4d\x18\xf8\xff\xff\xff";
386 size_t const size = ZSTD_decompress(NULL, 0, skippable8, 8);
387 if (!ZSTD_isError(size)) goto _output_error;
389 DISPLAYLEVEL(3, "OK \n");
392 DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameContentSize test : ", testNb++);
393 { unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize);
394 if (rSize != CNBuffSize) goto _output_error;
396 DISPLAYLEVEL(3, "OK \n");
398 DISPLAYLEVEL(3, "test%3i : ZSTD_findDecompressedSize test : ", testNb++);
399 { unsigned long long const rSize = ZSTD_findDecompressedSize(compressedBuffer, cSize);
400 if (rSize != CNBuffSize) goto _output_error;
402 DISPLAYLEVEL(3, "OK \n");
404 DISPLAYLEVEL(3, "test%3i : tight ZSTD_decompressBound test : ", testNb++);
406 unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize);
407 if (bound != CNBuffSize) goto _output_error;
409 DISPLAYLEVEL(3, "OK \n");
411 DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with invalid srcSize : ", testNb++);
413 unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize - 1);
414 if (bound != ZSTD_CONTENTSIZE_ERROR) goto _output_error;
416 DISPLAYLEVEL(3, "OK \n");
418 DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize);
419 { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);
420 if (r != CNBuffSize) goto _output_error; }
421 DISPLAYLEVEL(3, "OK \n");
423 DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
425 for (u=0; u<CNBuffSize; u++) {
426 if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;
428 DISPLAYLEVEL(3, "OK \n");
431 DISPLAYLEVEL(3, "test%3i : decompress with null dict : ", testNb++);
432 { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);
433 { size_t const r = ZSTD_decompress_usingDict(dctx,
434 decodedBuffer, CNBuffSize,
435 compressedBuffer, cSize,
437 if (r != CNBuffSize) goto _output_error;
441 DISPLAYLEVEL(3, "OK \n");
443 DISPLAYLEVEL(3, "test%3i : decompress with null DDict : ", testNb++);
444 { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);
445 { size_t const r = ZSTD_decompress_usingDDict(dctx,
446 decodedBuffer, CNBuffSize,
447 compressedBuffer, cSize,
449 if (r != CNBuffSize) goto _output_error;
453 DISPLAYLEVEL(3, "OK \n");
455 DISPLAYLEVEL(3, "test%3i : decompress with 1 missing byte : ", testNb++);
456 { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize-1);
457 if (!ZSTD_isError(r)) goto _output_error;
458 if (ZSTD_getErrorCode((size_t)r) != ZSTD_error_srcSize_wrong) goto _output_error; }
459 DISPLAYLEVEL(3, "OK \n");
461 DISPLAYLEVEL(3, "test%3i : decompress with 1 too much byte : ", testNb++);
462 { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize+1);
463 if (!ZSTD_isError(r)) goto _output_error;
464 if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }
465 DISPLAYLEVEL(3, "OK \n");
467 DISPLAYLEVEL(3, "test%3i : decompress too large input : ", testNb++);
468 { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, compressedBufferSize);
469 if (!ZSTD_isError(r)) goto _output_error;
470 if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }
471 DISPLAYLEVEL(3, "OK \n");
473 DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with content size missing : ", testNb++);
474 { /* create compressed buffer with content size missing */
475 ZSTD_CCtx* const cctx = ZSTD_createCCtx();
476 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0) );
477 CHECK_VAR(cSize, ZSTD_compress2(cctx,
478 compressedBuffer, compressedBufferSize,
479 CNBuffer, CNBuffSize) );
482 { /* ensure frame content size is missing */
483 ZSTD_frameHeader zfh;
484 size_t const ret = ZSTD_getFrameHeader(&zfh, compressedBuffer, compressedBufferSize);
485 if (ret != 0 || zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error;
487 { /* ensure CNBuffSize <= decompressBound */
488 unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, compressedBufferSize);
489 if (CNBuffSize > bound) goto _output_error;
491 DISPLAYLEVEL(3, "OK \n");
493 DISPLAYLEVEL(3, "test%3d : check CCtx size after compressing empty input : ", testNb++);
494 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
495 size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19);
496 if (ZSTD_isError(r)) goto _output_error;
497 if (ZSTD_sizeof_CCtx(cctx) > (1U << 20)) goto _output_error;
501 DISPLAYLEVEL(3, "OK \n");
503 DISPLAYLEVEL(3, "test%3d : decompress empty frame into NULL : ", testNb++);
504 { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, cSize);
505 if (ZSTD_isError(r)) goto _output_error;
506 if (r != 0) goto _output_error;
508 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
509 ZSTD_outBuffer output;
510 if (cctx==NULL) goto _output_error;
511 output.dst = compressedBuffer;
512 output.size = compressedBufferSize;
514 CHECK_Z( ZSTD_initCStream(cctx, 1) ); /* content size unknown */
515 CHECK_Z( ZSTD_flushStream(cctx, &output) ); /* ensure no possibility to "concatenate" and determine the content size */
516 CHECK_Z( ZSTD_endStream(cctx, &output) );
518 /* single scan decompression */
519 { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, output.pos);
520 if (ZSTD_isError(r)) goto _output_error;
521 if (r != 0) goto _output_error;
523 /* streaming decompression */
524 { ZSTD_DCtx* const dstream = ZSTD_createDStream();
525 ZSTD_inBuffer dinput;
526 ZSTD_outBuffer doutput;
528 if (dstream==NULL) goto _output_error;
529 dinput.src = compressedBuffer;
535 CHECK_Z ( ZSTD_initDStream(dstream) );
536 for (ipos=1; ipos<=output.pos; ipos++) {
538 CHECK_Z ( ZSTD_decompressStream(dstream, &doutput, &dinput) );
540 if (doutput.pos != 0) goto _output_error;
541 ZSTD_freeDStream(dstream);
544 DISPLAYLEVEL(3, "OK \n");
546 DISPLAYLEVEL(3, "test%3d : re-use CCtx with expanding block size : ", testNb++);
547 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
548 ZSTD_parameters const params = ZSTD_getParams(1, ZSTD_CONTENTSIZE_UNKNOWN, 0);
549 assert(params.fParams.contentSizeFlag == 1); /* block size will be adapted if pledgedSrcSize is enabled */
550 CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, 1 /*pledgedSrcSize*/) );
551 CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, compressedBufferSize, CNBuffer, 1) ); /* creates a block size of 1 */
553 CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN) ); /* re-use same parameters */
554 { size_t const inSize = 2* 128 KB;
555 size_t const outSize = ZSTD_compressBound(inSize);
556 CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, outSize, CNBuffer, inSize) );
557 /* will fail if blockSize is not resized */
561 DISPLAYLEVEL(3, "OK \n");
563 DISPLAYLEVEL(3, "test%3d : re-using a CCtx should compress the same : ", testNb++);
564 { size_t const sampleSize = 30;
567 ((char*)CNBuffer)[i] = (char)i; /* ensure no match during initial section */
568 memcpy((char*)CNBuffer + 20, CNBuffer, 10); /* create one match, starting from beginning of sample, which is the difficult case (see #1241) */
569 for (i=1; i<=19; i++) {
570 ZSTD_CCtx* const cctx = ZSTD_createCCtx();
572 DISPLAYLEVEL(5, "l%i ", i);
573 size1 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i);
576 size2 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i);
578 CHECK_EQ(size1, size2);
580 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, i) );
581 size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize);
583 CHECK_EQ(size1, size2);
585 size2 = ZSTD_compress2(cctx, compressedBuffer, ZSTD_compressBound(sampleSize) - 1, CNBuffer, sampleSize); /* force streaming, as output buffer is not large enough to guarantee success */
587 CHECK_EQ(size1, size2);
593 inb.size = sampleSize;
594 outb.dst = compressedBuffer;
596 outb.size = ZSTD_compressBound(sampleSize) - 1; /* force streaming, as output buffer is not large enough to guarantee success */
597 CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) );
598 assert(inb.pos == inb.size);
599 CHECK_EQ(size1, outb.pos);
605 DISPLAYLEVEL(3, "OK \n");
607 DISPLAYLEVEL(3, "test%3d : btultra2 & 1st block : ", testNb++);
608 { size_t const sampleSize = 1024;
609 ZSTD_CCtx* const cctx = ZSTD_createCCtx();
615 outb.dst = compressedBuffer;
617 outb.size = compressedBufferSize;
618 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, ZSTD_maxCLevel()) );
620 inb.size = sampleSize; /* start with something, so that context is already used */
621 CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) ); /* will break internal assert if stats_init is not disabled */
622 assert(inb.pos == inb.size);
623 outb.pos = 0; /* cancel output */
625 CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(cctx, sampleSize) );
626 inb.size = 4; /* too small size : compression will be skipped */
628 CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) );
629 assert(inb.pos == inb.size);
631 inb.size += 5; /* too small size : compression will be skipped */
632 CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) );
633 assert(inb.pos == inb.size);
635 inb.size += 11; /* small enough to attempt compression */
636 CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) );
637 assert(inb.pos == inb.size);
639 assert(inb.pos < sampleSize);
640 inb.size = sampleSize; /* large enough to trigger stats_init, but no longer at beginning */
641 CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) ); /* will break internal assert if stats_init is not disabled */
642 assert(inb.pos == inb.size);
645 DISPLAYLEVEL(3, "OK \n");
647 DISPLAYLEVEL(3, "test%3d : ZSTD_CCtx_getParameter() : ", testNb++);
648 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
649 ZSTD_outBuffer out = {NULL, 0, 0};
650 ZSTD_inBuffer in = {NULL, 0, 0};
653 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
655 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
657 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, ZSTD_HASHLOG_MIN));
658 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
660 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
661 CHECK_EQ(value, ZSTD_HASHLOG_MIN);
662 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7));
663 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
665 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
666 CHECK_EQ(value, ZSTD_HASHLOG_MIN);
667 /* Start a compression job */
668 ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue);
669 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
671 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
672 CHECK_EQ(value, ZSTD_HASHLOG_MIN);
674 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
675 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
677 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
678 CHECK_EQ(value, ZSTD_HASHLOG_MIN);
679 /* Reset the parameters */
680 ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);
681 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
683 CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
688 DISPLAYLEVEL(3, "OK \n");
690 /* this test is really too long, and should be made faster */
691 DISPLAYLEVEL(3, "test%3d : overflow protection with large windowLog : ", testNb++);
692 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
693 ZSTD_parameters params = ZSTD_getParams(-999, ZSTD_CONTENTSIZE_UNKNOWN, 0);
694 size_t const nbCompressions = ((1U << 31) / CNBuffSize) + 2; /* ensure U32 overflow protection is triggered */
696 assert(cctx != NULL);
697 params.fParams.contentSizeFlag = 0;
698 params.cParams.windowLog = ZSTD_WINDOWLOG_MAX;
699 for (cnb = 0; cnb < nbCompressions; ++cnb) {
700 DISPLAYLEVEL(6, "run %zu / %zu \n", cnb, nbCompressions);
701 CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN) ); /* re-use same parameters */
702 CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize) );
706 DISPLAYLEVEL(3, "OK \n");
708 DISPLAYLEVEL(3, "test%3d : size down context : ", testNb++);
709 { ZSTD_CCtx* const largeCCtx = ZSTD_createCCtx();
710 assert(largeCCtx != NULL);
711 CHECK_Z( ZSTD_compressBegin(largeCCtx, 19) ); /* streaming implies ZSTD_CONTENTSIZE_UNKNOWN, which maximizes memory usage */
712 CHECK_Z( ZSTD_compressEnd(largeCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1) );
713 { size_t const largeCCtxSize = ZSTD_sizeof_CCtx(largeCCtx); /* size of context must be measured after compression */
714 { ZSTD_CCtx* const smallCCtx = ZSTD_createCCtx();
715 assert(smallCCtx != NULL);
716 CHECK_Z(ZSTD_compressCCtx(smallCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1, 1));
717 { size_t const smallCCtxSize = ZSTD_sizeof_CCtx(smallCCtx);
718 DISPLAYLEVEL(5, "(large) %zuKB > 32*%zuKB (small) : ",
719 largeCCtxSize>>10, smallCCtxSize>>10);
720 assert(largeCCtxSize > 32* smallCCtxSize); /* note : "too large" definition is handled within zstd_compress.c .
721 * make this test case extreme, so that it doesn't depend on a possibly fluctuating definition */
723 ZSTD_freeCCtx(smallCCtx);
725 { U32 const maxNbAttempts = 1100; /* nb of usages before triggering size down is handled within zstd_compress.c.
726 * currently defined as 128x, but could be adjusted in the future.
727 * make this test long enough so that it's not too much tied to the current definition within zstd_compress.c */
729 for (u=0; u<maxNbAttempts; u++) {
730 CHECK_Z(ZSTD_compressCCtx(largeCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1, 1));
731 if (ZSTD_sizeof_CCtx(largeCCtx) < largeCCtxSize) break; /* sized down */
733 DISPLAYLEVEL(5, "size down after %u attempts : ", u);
734 if (u==maxNbAttempts) goto _output_error; /* no sizedown happened */
737 ZSTD_freeCCtx(largeCCtx);
739 DISPLAYLEVEL(3, "OK \n");
741 /* Static CCtx tests */
742 #define STATIC_CCTX_LEVEL 3
743 DISPLAYLEVEL(3, "test%3i : create static CCtx for level %u :", testNb++, STATIC_CCTX_LEVEL);
744 { size_t const staticCCtxSize = ZSTD_estimateCStreamSize(STATIC_CCTX_LEVEL);
745 void* const staticCCtxBuffer = malloc(staticCCtxSize);
746 size_t const staticDCtxSize = ZSTD_estimateDCtxSize();
747 void* const staticDCtxBuffer = malloc(staticDCtxSize);
748 if (staticCCtxBuffer==NULL || staticDCtxBuffer==NULL) {
749 free(staticCCtxBuffer);
750 free(staticDCtxBuffer);
751 DISPLAY("Not enough memory, aborting\n");
755 { ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize);
756 ZSTD_DCtx* staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize);
757 if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error;
758 DISPLAYLEVEL(3, "OK \n");
760 DISPLAYLEVEL(3, "test%3i : init CCtx for level %u : ", testNb++, STATIC_CCTX_LEVEL);
761 { size_t const r = ZSTD_compressBegin(staticCCtx, STATIC_CCTX_LEVEL);
762 if (ZSTD_isError(r)) goto _output_error; }
763 DISPLAYLEVEL(3, "OK \n");
765 DISPLAYLEVEL(3, "test%3i : simple compression test with static CCtx : ", testNb++);
766 CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx,
767 compressedBuffer, compressedBufferSize,
768 CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) );
769 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n",
770 (unsigned)cSize, (double)cSize/CNBuffSize*100);
772 DISPLAYLEVEL(3, "test%3i : simple decompression test with static DCtx : ", testNb++);
773 { size_t const r = ZSTD_decompressDCtx(staticDCtx,
774 decodedBuffer, CNBuffSize,
775 compressedBuffer, cSize);
776 if (r != CNBuffSize) goto _output_error; }
777 DISPLAYLEVEL(3, "OK \n");
779 DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
781 for (u=0; u<CNBuffSize; u++) {
782 if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u])
785 DISPLAYLEVEL(3, "OK \n");
787 DISPLAYLEVEL(3, "test%3i : init CCtx for too large level (must fail) : ", testNb++);
788 { size_t const r = ZSTD_compressBegin(staticCCtx, ZSTD_maxCLevel());
789 if (!ZSTD_isError(r)) goto _output_error; }
790 DISPLAYLEVEL(3, "OK \n");
792 DISPLAYLEVEL(3, "test%3i : init CCtx for small level %u (should work again) : ", testNb++, 1);
793 CHECK( ZSTD_compressBegin(staticCCtx, 1) );
794 DISPLAYLEVEL(3, "OK \n");
796 DISPLAYLEVEL(3, "test%3i : init CStream for small level %u : ", testNb++, 1);
797 CHECK( ZSTD_initCStream(staticCCtx, 1) );
798 DISPLAYLEVEL(3, "OK \n");
800 DISPLAYLEVEL(3, "test%3i : init static CStream with dictionary (should fail) : ", testNb++);
801 { size_t const r = ZSTD_initCStream_usingDict(staticCCtx, CNBuffer, 64 KB, 1);
802 if (!ZSTD_isError(r)) goto _output_error; }
803 DISPLAYLEVEL(3, "OK \n");
805 DISPLAYLEVEL(3, "test%3i : init DStream (should fail) : ", testNb++);
806 { size_t const r = ZSTD_initDStream(staticDCtx);
807 if (ZSTD_isError(r)) goto _output_error; }
808 { ZSTD_outBuffer output = { decodedBuffer, CNBuffSize, 0 };
809 ZSTD_inBuffer input = { compressedBuffer, ZSTD_FRAMEHEADERSIZE_MAX+1, 0 };
810 size_t const r = ZSTD_decompressStream(staticDCtx, &output, &input);
811 if (!ZSTD_isError(r)) goto _output_error;
813 DISPLAYLEVEL(3, "OK \n");
815 free(staticCCtxBuffer);
816 free(staticDCtxBuffer);
819 DISPLAYLEVEL(3, "test%3i : Static negative levels : ", testNb++);
820 { size_t const cctxSizeN1 = ZSTD_estimateCCtxSize(-1);
821 size_t const cctxSizeP1 = ZSTD_estimateCCtxSize(1);
822 size_t const cstreamSizeN1 = ZSTD_estimateCStreamSize(-1);
823 size_t const cstreamSizeP1 = ZSTD_estimateCStreamSize(1);
825 if (!(0 < cctxSizeN1 && cctxSizeN1 <= cctxSizeP1)) goto _output_error;
826 if (!(0 < cstreamSizeN1 && cstreamSizeN1 <= cstreamSizeP1)) goto _output_error;
828 DISPLAYLEVEL(3, "OK \n");
831 /* ZSTDMT simple MT compression test */
832 DISPLAYLEVEL(3, "test%3i : create ZSTDMT CCtx : ", testNb++);
833 { ZSTDMT_CCtx* const mtctx = ZSTDMT_createCCtx(2);
835 DISPLAY("mtctx : not enough memory, aborting \n");
839 DISPLAYLEVEL(3, "OK \n");
841 DISPLAYLEVEL(3, "test%3u : compress %u bytes with 2 threads : ", testNb++, (unsigned)CNBuffSize);
842 CHECK_VAR(cSize, ZSTDMT_compressCCtx(mtctx,
843 compressedBuffer, compressedBufferSize,
844 CNBuffer, CNBuffSize,
846 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
848 DISPLAYLEVEL(3, "test%3i : decompressed size test : ", testNb++);
849 { unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize);
850 if (rSize != CNBuffSize) {
851 DISPLAY("ZSTD_getFrameContentSize incorrect : %u != %u \n", (unsigned)rSize, (unsigned)CNBuffSize);
854 DISPLAYLEVEL(3, "OK \n");
856 DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize);
857 { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);
858 if (r != CNBuffSize) goto _output_error; }
859 DISPLAYLEVEL(3, "OK \n");
861 DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
863 for (u=0; u<CNBuffSize; u++) {
864 if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;
866 DISPLAYLEVEL(3, "OK \n");
868 DISPLAYLEVEL(3, "test%3i : compress -T2 with checksum : ", testNb++);
869 { ZSTD_parameters params = ZSTD_getParams(1, CNBuffSize, 0);
870 params.fParams.checksumFlag = 1;
871 params.fParams.contentSizeFlag = 1;
872 CHECK_VAR(cSize, ZSTDMT_compress_advanced(mtctx,
873 compressedBuffer, compressedBufferSize,
874 CNBuffer, CNBuffSize,
875 NULL, params, 3 /*overlapRLog*/) );
877 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
879 DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize);
880 { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);
881 if (r != CNBuffSize) goto _output_error; }
882 DISPLAYLEVEL(3, "OK \n");
884 ZSTDMT_freeCCtx(mtctx);
887 DISPLAYLEVEL(3, "test%3i : compress -T2 with/without literals compression : ", testNb++)
888 { ZSTD_CCtx* cctx = ZSTD_createCCtx();
889 size_t cSize1, cSize2;
890 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
891 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2) );
892 cSize1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
894 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_literalCompressionMode, ZSTD_lcm_uncompressed) );
895 cSize2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
897 CHECK_LT(cSize1, cSize2);
900 DISPLAYLEVEL(3, "OK \n");
902 DISPLAYLEVEL(3, "test%3i : Multithreaded ZSTD_compress2() with rsyncable : ", testNb++)
903 { ZSTD_CCtx* cctx = ZSTD_createCCtx();
904 /* Set rsyncable and don't give the ZSTD_compressBound(CNBuffSize) so
905 * ZSTDMT is forced to not take the shortcut.
907 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
908 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1) );
909 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_rsyncable, 1) );
910 CHECK( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize - 1, CNBuffer, CNBuffSize) );
913 DISPLAYLEVEL(3, "OK \n");
915 DISPLAYLEVEL(3, "test%3i : setting multithreaded parameters : ", testNb++)
916 { ZSTD_CCtx_params* params = ZSTD_createCCtxParams();
918 /* Check that the overlap log and job size are unset. */
919 CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
921 CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
923 /* Set and check the overlap log and job size. */
924 CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, 5) );
925 CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, 2 MB) );
926 CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
928 CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
929 CHECK_EQ(value, 2 MB);
930 /* Set the number of workers and check the overlap log and job size. */
931 CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, 2) );
932 CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
934 CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
935 CHECK_EQ(value, 2 MB);
936 ZSTD_freeCCtxParams(params);
939 DISPLAYLEVEL(3, "OK \n");
941 /* Simple API multiframe test */
942 DISPLAYLEVEL(3, "test%3i : compress multiple frames : ", testNb++);
946 /* only use the first half so we don't push against size limit of compressedBuffer */
947 size_t const segSize = (CNBuffSize / 2) / segs;
948 for (i = 0; i < segs; i++) {
949 CHECK_NEWV(r, ZSTD_compress(
950 (BYTE*)compressedBuffer + off, CNBuffSize - off,
951 (BYTE*)CNBuffer + segSize * (size_t)i, segSize,
955 /* insert skippable frame */
956 const U32 skipLen = 129 KB;
957 MEM_writeLE32((BYTE*)compressedBuffer + off, ZSTD_MAGIC_SKIPPABLE_START);
958 MEM_writeLE32((BYTE*)compressedBuffer + off + 4, skipLen);
959 off += skipLen + ZSTD_SKIPPABLEHEADERSIZE;
964 DISPLAYLEVEL(3, "OK \n");
966 DISPLAYLEVEL(3, "test%3i : get decompressed size of multiple frames : ", testNb++);
967 { unsigned long long const r = ZSTD_findDecompressedSize(compressedBuffer, cSize);
968 if (r != CNBuffSize / 2) goto _output_error; }
969 DISPLAYLEVEL(3, "OK \n");
971 DISPLAYLEVEL(3, "test%3i : get tight decompressed bound of multiple frames : ", testNb++);
972 { unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, cSize);
973 if (bound != CNBuffSize / 2) goto _output_error; }
974 DISPLAYLEVEL(3, "OK \n");
976 DISPLAYLEVEL(3, "test%3i : decompress multiple frames : ", testNb++);
977 { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize));
978 if (r != CNBuffSize / 2) goto _output_error; }
979 DISPLAYLEVEL(3, "OK \n");
981 DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
982 if (memcmp(decodedBuffer, CNBuffer, CNBuffSize / 2) != 0) goto _output_error;
983 DISPLAYLEVEL(3, "OK \n");
985 /* Dictionary and CCtx Duplication tests */
986 { ZSTD_CCtx* const ctxOrig = ZSTD_createCCtx();
987 ZSTD_CCtx* const ctxDuplicated = ZSTD_createCCtx();
988 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
989 static const size_t dictSize = 551;
990 assert(dctx != NULL); assert(ctxOrig != NULL); assert(ctxDuplicated != NULL);
992 DISPLAYLEVEL(3, "test%3i : copy context too soon : ", testNb++);
993 { size_t const copyResult = ZSTD_copyCCtx(ctxDuplicated, ctxOrig, 0);
994 if (!ZSTD_isError(copyResult)) goto _output_error; } /* error must be detected */
995 DISPLAYLEVEL(3, "OK \n");
997 DISPLAYLEVEL(3, "test%3i : load dictionary into context : ", testNb++);
998 CHECK( ZSTD_compressBegin_usingDict(ctxOrig, CNBuffer, dictSize, 2) );
999 CHECK( ZSTD_copyCCtx(ctxDuplicated, ctxOrig, 0) ); /* Begin_usingDict implies unknown srcSize, so match that */
1000 DISPLAYLEVEL(3, "OK \n");
1002 DISPLAYLEVEL(3, "test%3i : compress with flat dictionary : ", testNb++);
1004 CHECKPLUS(r, ZSTD_compressEnd(ctxOrig,
1005 compressedBuffer, compressedBufferSize,
1006 (const char*)CNBuffer + dictSize, CNBuffSize - dictSize),
1008 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1010 DISPLAYLEVEL(3, "test%3i : frame built with flat dictionary should be decompressible : ", testNb++);
1011 CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,
1012 decodedBuffer, CNBuffSize,
1013 compressedBuffer, cSize,
1014 CNBuffer, dictSize),
1015 if (r != CNBuffSize - dictSize) goto _output_error);
1016 DISPLAYLEVEL(3, "OK \n");
1018 DISPLAYLEVEL(3, "test%3i : compress with duplicated context : ", testNb++);
1019 { size_t const cSizeOrig = cSize;
1021 CHECKPLUS(r, ZSTD_compressEnd(ctxDuplicated,
1022 compressedBuffer, compressedBufferSize,
1023 (const char*)CNBuffer + dictSize, CNBuffSize - dictSize),
1025 if (cSize != cSizeOrig) goto _output_error; /* should be identical ==> same size */
1027 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1029 DISPLAYLEVEL(3, "test%3i : frame built with duplicated context should be decompressible : ", testNb++);
1030 CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,
1031 decodedBuffer, CNBuffSize,
1032 compressedBuffer, cSize,
1033 CNBuffer, dictSize),
1034 if (r != CNBuffSize - dictSize) goto _output_error);
1035 DISPLAYLEVEL(3, "OK \n");
1037 DISPLAYLEVEL(3, "test%3i : decompress with DDict : ", testNb++);
1038 { ZSTD_DDict* const ddict = ZSTD_createDDict(CNBuffer, dictSize);
1039 size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, ddict);
1040 if (r != CNBuffSize - dictSize) goto _output_error;
1041 DISPLAYLEVEL(3, "OK (size of DDict : %u) \n", (unsigned)ZSTD_sizeof_DDict(ddict));
1042 ZSTD_freeDDict(ddict);
1045 DISPLAYLEVEL(3, "test%3i : decompress with static DDict : ", testNb++);
1046 { size_t const ddictBufferSize = ZSTD_estimateDDictSize(dictSize, ZSTD_dlm_byCopy);
1047 void* const ddictBuffer = malloc(ddictBufferSize);
1048 if (ddictBuffer == NULL) goto _output_error;
1049 { const ZSTD_DDict* const ddict = ZSTD_initStaticDDict(ddictBuffer, ddictBufferSize, CNBuffer, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
1050 size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, ddict);
1051 if (r != CNBuffSize - dictSize) goto _output_error;
1054 DISPLAYLEVEL(3, "OK (size of static DDict : %u) \n", (unsigned)ddictBufferSize);
1057 DISPLAYLEVEL(3, "test%3i : check content size on duplicated context : ", testNb++);
1058 { size_t const testSize = CNBuffSize / 3;
1059 { ZSTD_parameters p = ZSTD_getParams(2, testSize, dictSize);
1060 p.fParams.contentSizeFlag = 1;
1061 CHECK( ZSTD_compressBegin_advanced(ctxOrig, CNBuffer, dictSize, p, testSize-1) );
1063 CHECK( ZSTD_copyCCtx(ctxDuplicated, ctxOrig, testSize) );
1065 CHECK_VAR(cSize, ZSTD_compressEnd(ctxDuplicated, compressedBuffer, ZSTD_compressBound(testSize),
1066 (const char*)CNBuffer + dictSize, testSize) );
1067 { ZSTD_frameHeader zfh;
1068 if (ZSTD_getFrameHeader(&zfh, compressedBuffer, cSize)) goto _output_error;
1069 if ((zfh.frameContentSize != testSize) && (zfh.frameContentSize != 0)) goto _output_error;
1071 DISPLAYLEVEL(3, "OK \n");
1073 if ((int)(compressibility * 100 + 0.1) == FUZ_compressibility_default) { /* test only valid with known input */
1074 size_t const flatdictSize = 22 KB;
1075 size_t const contentSize = 9 KB;
1076 const void* const dict = (const char*)CNBuffer;
1077 const void* const contentStart = (const char*)dict + flatdictSize;
1078 size_t const target_nodict_cSize[22+1] = { 3840, 3770, 3870, 3830, 3770,
1079 3770, 3770, 3770, 3750, 3750,
1080 3740, 3670, 3670, 3660, 3660,
1081 3660, 3660, 3660, 3660, 3660,
1083 size_t const target_wdict_cSize[22+1] = { 2830, 2890, 2890, 2820, 2940,
1084 2950, 2950, 2920, 2900, 2890,
1085 2910, 2910, 2910, 2770, 2760,
1086 2750, 2750, 2750, 2750, 2750,
1089 int const maxLevel = ZSTD_maxCLevel();
1091 DISPLAYLEVEL(3, "test%3i : flat-dictionary efficiency test : \n", testNb++);
1092 assert(maxLevel == 22);
1093 RDG_genBuffer(CNBuffer, flatdictSize + contentSize, compressibility, 0., seed);
1094 DISPLAYLEVEL(4, "content hash : %016llx; dict hash : %016llx \n", XXH64(contentStart, contentSize, 0), XXH64(dict, flatdictSize, 0));
1096 for ( ; l <= maxLevel; l++) {
1097 size_t const nodict_cSize = ZSTD_compress(compressedBuffer, compressedBufferSize,
1098 contentStart, contentSize, l);
1099 if (nodict_cSize > target_nodict_cSize[l]) {
1100 DISPLAYLEVEL(1, "error : compression at level %i worse than expected (%u > %u) \n",
1101 l, (unsigned)nodict_cSize, (unsigned)target_nodict_cSize[l]);
1104 DISPLAYLEVEL(4, "level %i : max expected %u >= reached %u \n",
1105 l, (unsigned)target_nodict_cSize[l], (unsigned)nodict_cSize);
1107 for ( l=1 ; l <= maxLevel; l++) {
1108 size_t const wdict_cSize = ZSTD_compress_usingDict(ctxOrig,
1109 compressedBuffer, compressedBufferSize,
1110 contentStart, contentSize,
1113 if (wdict_cSize > target_wdict_cSize[l]) {
1114 DISPLAYLEVEL(1, "error : compression with dictionary at level %i worse than expected (%u > %u) \n",
1115 l, (unsigned)wdict_cSize, (unsigned)target_wdict_cSize[l]);
1118 DISPLAYLEVEL(4, "level %i with dictionary : max expected %u >= reached %u \n",
1119 l, (unsigned)target_wdict_cSize[l], (unsigned)wdict_cSize);
1122 DISPLAYLEVEL(4, "compression efficiency tests OK \n");
1125 ZSTD_freeCCtx(ctxOrig);
1126 ZSTD_freeCCtx(ctxDuplicated);
1127 ZSTD_freeDCtx(dctx);
1130 /* Dictionary and dictBuilder tests */
1131 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
1132 size_t const dictBufferCapacity = 16 KB;
1133 void* const dictBuffer = malloc(dictBufferCapacity);
1134 size_t const totalSampleSize = 1 MB;
1135 size_t const sampleUnitSize = 8 KB;
1136 U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);
1137 size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t));
1141 if (dictBuffer==NULL || samplesSizes==NULL) {
1147 DISPLAYLEVEL(3, "test%3i : dictBuilder on cyclic data : ", testNb++);
1148 assert(compressedBufferSize >= totalSampleSize);
1149 { U32 u; for (u=0; u<totalSampleSize; u++) ((BYTE*)decodedBuffer)[u] = (BYTE)u; }
1150 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1151 { size_t const sDictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity,
1152 decodedBuffer, samplesSizes, nbSamples);
1153 if (ZDICT_isError(sDictSize)) goto _output_error;
1154 DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)sDictSize);
1157 DISPLAYLEVEL(3, "test%3i : dictBuilder : ", testNb++);
1158 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1159 dictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity,
1160 CNBuffer, samplesSizes, nbSamples);
1161 if (ZDICT_isError(dictSize)) goto _output_error;
1162 DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1164 DISPLAYLEVEL(3, "test%3i : Multithreaded COVER dictBuilder : ", testNb++);
1165 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1166 { ZDICT_cover_params_t coverParams;
1167 memset(&coverParams, 0, sizeof(coverParams));
1168 coverParams.steps = 8;
1169 coverParams.nbThreads = 4;
1170 dictSize = ZDICT_optimizeTrainFromBuffer_cover(
1171 dictBuffer, dictBufferCapacity,
1172 CNBuffer, samplesSizes, nbSamples/8, /* less samples for faster tests */
1174 if (ZDICT_isError(dictSize)) goto _output_error;
1176 DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1178 DISPLAYLEVEL(3, "test%3i : COVER dictBuilder with shrinkDict: ", testNb++);
1179 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1180 { ZDICT_cover_params_t coverParams;
1181 memset(&coverParams, 0, sizeof(coverParams));
1182 coverParams.steps = 8;
1183 coverParams.nbThreads = 4;
1184 coverParams.shrinkDict = 1;
1185 coverParams.shrinkDictMaxRegression = 1;
1186 dictSize = ZDICT_optimizeTrainFromBuffer_cover(
1187 dictBuffer, dictBufferCapacity,
1188 CNBuffer, samplesSizes, nbSamples/8, /* less samples for faster tests */
1190 if (ZDICT_isError(dictSize)) goto _output_error;
1192 DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1194 DISPLAYLEVEL(3, "test%3i : Multithreaded FASTCOVER dictBuilder : ", testNb++);
1195 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1196 { ZDICT_fastCover_params_t fastCoverParams;
1197 memset(&fastCoverParams, 0, sizeof(fastCoverParams));
1198 fastCoverParams.steps = 8;
1199 fastCoverParams.nbThreads = 4;
1200 dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(
1201 dictBuffer, dictBufferCapacity,
1202 CNBuffer, samplesSizes, nbSamples,
1204 if (ZDICT_isError(dictSize)) goto _output_error;
1206 DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1208 DISPLAYLEVEL(3, "test%3i : FASTCOVER dictBuilder with shrinkDict: ", testNb++);
1209 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1210 { ZDICT_fastCover_params_t fastCoverParams;
1211 memset(&fastCoverParams, 0, sizeof(fastCoverParams));
1212 fastCoverParams.steps = 8;
1213 fastCoverParams.nbThreads = 4;
1214 fastCoverParams.shrinkDict = 1;
1215 fastCoverParams.shrinkDictMaxRegression = 1;
1216 dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(
1217 dictBuffer, dictBufferCapacity,
1218 CNBuffer, samplesSizes, nbSamples,
1220 if (ZDICT_isError(dictSize)) goto _output_error;
1222 DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1224 DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++);
1225 dictID = ZDICT_getDictID(dictBuffer, dictSize);
1226 if (dictID==0) goto _output_error;
1227 DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID);
1229 DISPLAYLEVEL(3, "test%3i : compress with dictionary : ", testNb++);
1230 cSize = ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize,
1231 CNBuffer, CNBuffSize,
1232 dictBuffer, dictSize, 4);
1233 if (ZSTD_isError(cSize)) goto _output_error;
1234 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1236 DISPLAYLEVEL(3, "test%3i : retrieve dictID from dictionary : ", testNb++);
1237 { U32 const did = ZSTD_getDictID_fromDict(dictBuffer, dictSize);
1238 if (did != dictID) goto _output_error; /* non-conformant (content-only) dictionary */
1240 DISPLAYLEVEL(3, "OK \n");
1242 DISPLAYLEVEL(3, "test%3i : retrieve dictID from frame : ", testNb++);
1243 { U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize);
1244 if (did != dictID) goto _output_error; /* non-conformant (content-only) dictionary */
1246 DISPLAYLEVEL(3, "OK \n");
1248 DISPLAYLEVEL(3, "test%3i : frame built with dictionary should be decompressible : ", testNb++);
1249 { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);
1250 CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,
1251 decodedBuffer, CNBuffSize,
1252 compressedBuffer, cSize,
1253 dictBuffer, dictSize),
1254 if (r != CNBuffSize) goto _output_error);
1255 ZSTD_freeDCtx(dctx);
1257 DISPLAYLEVEL(3, "OK \n");
1259 DISPLAYLEVEL(3, "test%3i : estimate CDict size : ", testNb++);
1260 { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
1261 size_t const estimatedSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byRef);
1262 DISPLAYLEVEL(3, "OK : %u \n", (unsigned)estimatedSize);
1265 DISPLAYLEVEL(3, "test%3i : compress with CDict ", testNb++);
1266 { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
1267 ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize,
1268 ZSTD_dlm_byRef, ZSTD_dct_auto,
1269 cParams, ZSTD_defaultCMem);
1270 assert(cdict != NULL);
1271 DISPLAYLEVEL(3, "(size : %u) : ", (unsigned)ZSTD_sizeof_CDict(cdict));
1272 cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize,
1273 CNBuffer, CNBuffSize, cdict);
1274 ZSTD_freeCDict(cdict);
1275 if (ZSTD_isError(cSize)) goto _output_error;
1277 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1279 DISPLAYLEVEL(3, "test%3i : retrieve dictID from frame : ", testNb++);
1280 { U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize);
1281 if (did != dictID) goto _output_error; /* non-conformant (content-only) dictionary */
1283 DISPLAYLEVEL(3, "OK \n");
1285 DISPLAYLEVEL(3, "test%3i : frame built with dictionary should be decompressible : ", testNb++);
1286 { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);
1287 CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,
1288 decodedBuffer, CNBuffSize,
1289 compressedBuffer, cSize,
1290 dictBuffer, dictSize),
1291 if (r != CNBuffSize) goto _output_error);
1292 ZSTD_freeDCtx(dctx);
1294 DISPLAYLEVEL(3, "OK \n");
1296 DISPLAYLEVEL(3, "test%3i : compress with static CDict : ", testNb++);
1297 { int const maxLevel = ZSTD_maxCLevel();
1299 for (level = 1; level <= maxLevel; ++level) {
1300 ZSTD_compressionParameters const cParams = ZSTD_getCParams(level, CNBuffSize, dictSize);
1301 size_t const cdictSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
1302 void* const cdictBuffer = malloc(cdictSize);
1303 if (cdictBuffer==NULL) goto _output_error;
1304 { const ZSTD_CDict* const cdict = ZSTD_initStaticCDict(
1305 cdictBuffer, cdictSize,
1306 dictBuffer, dictSize,
1307 ZSTD_dlm_byCopy, ZSTD_dct_auto,
1309 if (cdict == NULL) {
1310 DISPLAY("ZSTD_initStaticCDict failed ");
1313 cSize = ZSTD_compress_usingCDict(cctx,
1314 compressedBuffer, compressedBufferSize,
1315 CNBuffer, MIN(10 KB, CNBuffSize), cdict);
1316 if (ZSTD_isError(cSize)) {
1317 DISPLAY("ZSTD_compress_usingCDict failed ");
1322 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1324 DISPLAYLEVEL(3, "test%3i : ZSTD_compress_usingCDict_advanced, no contentSize, no dictID : ", testNb++);
1325 { ZSTD_frameParameters const fParams = { 0 /* frameSize */, 1 /* checksum */, 1 /* noDictID*/ };
1326 ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
1327 ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem);
1328 assert(cdict != NULL);
1329 cSize = ZSTD_compress_usingCDict_advanced(cctx,
1330 compressedBuffer, compressedBufferSize,
1331 CNBuffer, CNBuffSize,
1333 ZSTD_freeCDict(cdict);
1334 if (ZSTD_isError(cSize)) goto _output_error;
1336 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1338 DISPLAYLEVEL(3, "test%3i : try retrieving contentSize from frame : ", testNb++);
1339 { U64 const contentSize = ZSTD_getFrameContentSize(compressedBuffer, cSize);
1340 if (contentSize != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error;
1342 DISPLAYLEVEL(3, "OK (unknown)\n");
1344 DISPLAYLEVEL(3, "test%3i : frame built without dictID should be decompressible : ", testNb++);
1345 { ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1346 assert(dctx != NULL);
1347 CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,
1348 decodedBuffer, CNBuffSize,
1349 compressedBuffer, cSize,
1350 dictBuffer, dictSize),
1351 if (r != CNBuffSize) goto _output_error);
1352 ZSTD_freeDCtx(dctx);
1354 DISPLAYLEVEL(3, "OK \n");
1356 DISPLAYLEVEL(3, "test%3i : ZSTD_compress_advanced, no dictID : ", testNb++);
1357 { ZSTD_parameters p = ZSTD_getParams(3, CNBuffSize, dictSize);
1358 p.fParams.noDictIDFlag = 1;
1359 cSize = ZSTD_compress_advanced(cctx, compressedBuffer, compressedBufferSize,
1360 CNBuffer, CNBuffSize,
1361 dictBuffer, dictSize, p);
1362 if (ZSTD_isError(cSize)) goto _output_error;
1364 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1366 DISPLAYLEVEL(3, "test%3i : frame built without dictID should be decompressible : ", testNb++);
1367 { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);
1368 CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,
1369 decodedBuffer, CNBuffSize,
1370 compressedBuffer, cSize,
1371 dictBuffer, dictSize),
1372 if (r != CNBuffSize) goto _output_error);
1373 ZSTD_freeDCtx(dctx);
1375 DISPLAYLEVEL(3, "OK \n");
1377 DISPLAYLEVEL(3, "test%3i : dictionary containing only header should return error : ", testNb++);
1378 { ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1379 assert(dctx != NULL);
1380 { const size_t ret = ZSTD_decompress_usingDict(
1381 dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize,
1382 "\x37\xa4\x30\xec\x11\x22\x33\x44", 8);
1383 if (ZSTD_getErrorCode(ret) != ZSTD_error_dictionary_corrupted)
1386 ZSTD_freeDCtx(dctx);
1388 DISPLAYLEVEL(3, "OK \n");
1390 DISPLAYLEVEL(3, "test%3i : Building cdict w/ ZSTD_dct_fullDict on a good dictionary : ", testNb++);
1391 { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
1392 ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem);
1393 if (cdict==NULL) goto _output_error;
1394 ZSTD_freeCDict(cdict);
1396 DISPLAYLEVEL(3, "OK \n");
1398 DISPLAYLEVEL(3, "test%3i : Building cdict w/ ZSTD_dct_fullDict on a rawContent (must fail) : ", testNb++);
1399 { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
1400 ZSTD_CDict* const cdict = ZSTD_createCDict_advanced((const char*)dictBuffer+1, dictSize-1, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem);
1401 if (cdict!=NULL) goto _output_error;
1402 ZSTD_freeCDict(cdict);
1404 DISPLAYLEVEL(3, "OK \n");
1406 DISPLAYLEVEL(3, "test%3i : Loading rawContent starting with dict header w/ ZSTD_dct_auto should fail : ", testNb++);
1409 MEM_writeLE32((char*)dictBuffer+2, ZSTD_MAGIC_DICTIONARY);
1410 /* Either operation is allowed to fail, but one must fail. */
1411 ret = ZSTD_CCtx_loadDictionary_advanced(
1412 cctx, (const char*)dictBuffer+2, dictSize-2, ZSTD_dlm_byRef, ZSTD_dct_auto);
1413 if (!ZSTD_isError(ret)) {
1414 ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100));
1415 if (!ZSTD_isError(ret)) goto _output_error;
1418 DISPLAYLEVEL(3, "OK \n");
1420 DISPLAYLEVEL(3, "test%3i : Loading rawContent starting with dict header w/ ZSTD_dct_rawContent should pass : ", testNb++);
1423 MEM_writeLE32((char*)dictBuffer+2, ZSTD_MAGIC_DICTIONARY);
1424 ret = ZSTD_CCtx_loadDictionary_advanced(
1425 cctx, (const char*)dictBuffer+2, dictSize-2, ZSTD_dlm_byRef, ZSTD_dct_rawContent);
1426 if (ZSTD_isError(ret)) goto _output_error;
1427 ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100));
1428 if (ZSTD_isError(ret)) goto _output_error;
1430 DISPLAYLEVEL(3, "OK \n");
1432 DISPLAYLEVEL(3, "test%3i : ZSTD_CCtx_refCDict() then set parameters : ", testNb++);
1433 { ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 1);
1434 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
1435 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 ));
1436 CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
1437 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
1438 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 ));
1439 ZSTD_freeCDict(cdict);
1441 DISPLAYLEVEL(3, "OK \n");
1443 DISPLAYLEVEL(3, "test%3i : Loading dictionary before setting parameters is the same as loading after : ", testNb++);
1445 size_t size1, size2;
1446 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
1447 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) );
1448 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
1449 size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
1450 if (ZSTD_isError(size1)) goto _output_error;
1452 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
1453 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
1454 CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) );
1455 size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
1456 if (ZSTD_isError(size2)) goto _output_error;
1458 if (size1 != size2) goto _output_error;
1460 DISPLAYLEVEL(3, "OK \n");
1462 DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the prefix : ", testNb++);
1464 CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
1465 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
1466 CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
1468 DISPLAYLEVEL(3, "OK \n");
1470 DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the cdict : ", testNb++);
1472 ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
1473 CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
1474 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
1475 CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
1476 ZSTD_freeCDict(cdict);
1478 DISPLAYLEVEL(3, "OK \n");
1480 DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the prefix : ", testNb++);
1482 ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
1483 CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
1484 CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
1485 CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
1486 ZSTD_freeCDict(cdict);
1488 DISPLAYLEVEL(3, "OK \n");
1490 DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the dictionary : ", testNb++);
1492 ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
1493 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
1494 CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
1495 CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
1496 ZSTD_freeCDict(cdict);
1498 DISPLAYLEVEL(3, "OK \n");
1500 DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the dictionary : ", testNb++);
1502 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
1503 CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
1504 CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
1506 DISPLAYLEVEL(3, "OK \n");
1508 DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the cdict : ", testNb++);
1510 ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
1511 CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
1512 CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
1513 CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
1514 ZSTD_freeCDict(cdict);
1516 DISPLAYLEVEL(3, "OK \n");
1518 DISPLAYLEVEL(3, "test%3i : Loaded dictionary persists across reset session : ", testNb++);
1520 size_t size1, size2;
1521 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
1522 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
1523 size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
1524 if (ZSTD_isError(size1)) goto _output_error;
1526 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
1527 size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
1528 if (ZSTD_isError(size2)) goto _output_error;
1530 if (size1 != size2) goto _output_error;
1532 DISPLAYLEVEL(3, "OK \n");
1534 DISPLAYLEVEL(3, "test%3i : Loaded dictionary is cleared after resetting parameters : ", testNb++);
1536 size_t size1, size2;
1537 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
1538 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
1539 size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
1540 if (ZSTD_isError(size1)) goto _output_error;
1542 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
1543 size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
1544 if (ZSTD_isError(size2)) goto _output_error;
1546 if (size1 == size2) goto _output_error;
1548 DISPLAYLEVEL(3, "OK \n");
1550 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
1551 CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, dictBuffer, dictSize) );
1552 cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
1554 DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with dictionary : ", testNb++);
1556 ZSTD_DCtx* dctx = ZSTD_createDCtx();
1558 /* We should fail to decompress without a dictionary. */
1559 ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
1560 ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
1561 if (!ZSTD_isError(ret)) goto _output_error;
1562 /* We should succeed to decompress with the dictionary. */
1563 ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
1564 CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictSize) );
1565 CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
1566 /* The dictionary should presist across calls. */
1567 CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
1568 /* When we reset the context the dictionary is cleared. */
1569 ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
1570 ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
1571 if (!ZSTD_isError(ret)) goto _output_error;
1572 ZSTD_freeDCtx(dctx);
1574 DISPLAYLEVEL(3, "OK \n");
1576 DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with ddict : ", testNb++);
1578 ZSTD_DCtx* dctx = ZSTD_createDCtx();
1579 ZSTD_DDict* ddict = ZSTD_createDDict(dictBuffer, dictSize);
1581 /* We should succeed to decompress with the ddict. */
1582 ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
1583 CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) );
1584 CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
1585 /* The ddict should presist across calls. */
1586 CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
1587 /* When we reset the context the ddict is cleared. */
1588 ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
1589 ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
1590 if (!ZSTD_isError(ret)) goto _output_error;
1591 ZSTD_freeDCtx(dctx);
1592 ZSTD_freeDDict(ddict);
1594 DISPLAYLEVEL(3, "OK \n");
1596 DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with prefix : ", testNb++);
1598 ZSTD_DCtx* dctx = ZSTD_createDCtx();
1600 /* We should succeed to decompress with the prefix. */
1601 ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
1602 CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictBuffer, dictSize, ZSTD_dct_auto) );
1603 CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
1604 /* The prefix should be cleared after the first compression. */
1605 ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
1606 if (!ZSTD_isError(ret)) goto _output_error;
1607 ZSTD_freeDCtx(dctx);
1609 DISPLAYLEVEL(3, "OK \n");
1611 DISPLAYLEVEL(3, "test%3i : Dictionary with non-default repcodes : ", testNb++);
1612 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1613 dictSize = ZDICT_trainFromBuffer(dictBuffer, dictSize,
1614 CNBuffer, samplesSizes, nbSamples);
1615 if (ZDICT_isError(dictSize)) goto _output_error;
1616 /* Set all the repcodes to non-default */
1618 BYTE* dictPtr = (BYTE*)dictBuffer;
1619 BYTE* dictLimit = dictPtr + dictSize - 12;
1620 /* Find the repcodes */
1621 while (dictPtr < dictLimit &&
1622 (MEM_readLE32(dictPtr) != 1 || MEM_readLE32(dictPtr + 4) != 4 ||
1623 MEM_readLE32(dictPtr + 8) != 8)) {
1626 if (dictPtr >= dictLimit) goto _output_error;
1627 MEM_writeLE32(dictPtr + 0, 10);
1628 MEM_writeLE32(dictPtr + 4, 10);
1629 MEM_writeLE32(dictPtr + 8, 10);
1630 /* Set the last 8 bytes to 'x' */
1631 memset((BYTE*)dictBuffer + dictSize - 8, 'x', 8);
1633 /* The optimal parser checks all the repcodes.
1634 * Make sure at least one is a match >= targetLength so that it is
1635 * immediately chosen. This will make sure that the compressor and
1636 * decompressor agree on at least one of the repcodes.
1640 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1641 ZSTD_compressionParameters const cParams = ZSTD_getCParams(19, CNBuffSize, dictSize);
1642 ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize,
1643 ZSTD_dlm_byRef, ZSTD_dct_auto,
1644 cParams, ZSTD_defaultCMem);
1645 assert(dctx != NULL); assert(cdict != NULL);
1646 memset(data, 'x', sizeof(data));
1647 cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize,
1648 data, sizeof(data), cdict);
1649 ZSTD_freeCDict(cdict);
1650 if (ZSTD_isError(cSize)) { DISPLAYLEVEL(5, "Compression error %s : ", ZSTD_getErrorName(cSize)); goto _output_error; }
1651 dSize = ZSTD_decompress_usingDict(dctx, decodedBuffer, sizeof(data), compressedBuffer, cSize, dictBuffer, dictSize);
1652 if (ZSTD_isError(dSize)) { DISPLAYLEVEL(5, "Decompression error %s : ", ZSTD_getErrorName(dSize)); goto _output_error; }
1653 if (memcmp(data, decodedBuffer, sizeof(data))) { DISPLAYLEVEL(5, "Data corruption : "); goto _output_error; }
1654 ZSTD_freeDCtx(dctx);
1656 DISPLAYLEVEL(3, "OK \n");
1658 ZSTD_freeCCtx(cctx);
1663 /* COVER dictionary builder tests */
1664 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
1665 size_t dictSize = 16 KB;
1666 size_t optDictSize = dictSize;
1667 void* dictBuffer = malloc(dictSize);
1668 size_t const totalSampleSize = 1 MB;
1669 size_t const sampleUnitSize = 8 KB;
1670 U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);
1671 size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t));
1673 ZDICT_cover_params_t params;
1676 if (dictBuffer==NULL || samplesSizes==NULL) {
1682 DISPLAYLEVEL(3, "test%3i : ZDICT_trainFromBuffer_cover : ", testNb++);
1683 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1684 memset(¶ms, 0, sizeof(params));
1685 params.d = 1 + (FUZ_rand(&seed32) % 16);
1686 params.k = params.d + (FUZ_rand(&seed32) % 256);
1687 dictSize = ZDICT_trainFromBuffer_cover(dictBuffer, dictSize,
1688 CNBuffer, samplesSizes, nbSamples,
1690 if (ZDICT_isError(dictSize)) goto _output_error;
1691 DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1693 DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++);
1694 dictID = ZDICT_getDictID(dictBuffer, dictSize);
1695 if (dictID==0) goto _output_error;
1696 DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID);
1698 DISPLAYLEVEL(3, "test%3i : ZDICT_optimizeTrainFromBuffer_cover : ", testNb++);
1699 memset(¶ms, 0, sizeof(params));
1701 optDictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, optDictSize,
1702 CNBuffer, samplesSizes,
1703 nbSamples / 4, ¶ms);
1704 if (ZDICT_isError(optDictSize)) goto _output_error;
1705 DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)optDictSize);
1707 DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++);
1708 dictID = ZDICT_getDictID(dictBuffer, optDictSize);
1709 if (dictID==0) goto _output_error;
1710 DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID);
1712 ZSTD_freeCCtx(cctx);
1717 /* Decompression defense tests */
1718 DISPLAYLEVEL(3, "test%3i : Check input length for magic number : ", testNb++);
1719 { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, CNBuffer, 3); /* too small input */
1720 if (!ZSTD_isError(r)) goto _output_error;
1721 if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }
1722 DISPLAYLEVEL(3, "OK \n");
1724 DISPLAYLEVEL(3, "test%3i : Check magic Number : ", testNb++);
1725 ((char*)(CNBuffer))[0] = 1;
1726 { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, CNBuffer, 4);
1727 if (!ZSTD_isError(r)) goto _output_error; }
1728 DISPLAYLEVEL(3, "OK \n");
1730 /* content size verification test */
1731 DISPLAYLEVEL(3, "test%3i : Content size verification : ", testNb++);
1732 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
1733 size_t const srcSize = 5000;
1734 size_t const wrongSrcSize = (srcSize + 1000);
1735 ZSTD_parameters params = ZSTD_getParams(1, wrongSrcSize, 0);
1736 params.fParams.contentSizeFlag = 1;
1737 CHECK( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, wrongSrcSize) );
1738 { size_t const result = ZSTD_compressEnd(cctx, decodedBuffer, CNBuffSize, CNBuffer, srcSize);
1739 if (!ZSTD_isError(result)) goto _output_error;
1740 if (ZSTD_getErrorCode(result) != ZSTD_error_srcSize_wrong) goto _output_error;
1741 DISPLAYLEVEL(3, "OK : %s \n", ZSTD_getErrorName(result));
1743 ZSTD_freeCCtx(cctx);
1746 /* negative compression level test : ensure simple API and advanced API produce same result */
1747 DISPLAYLEVEL(3, "test%3i : negative compression level : ", testNb++);
1748 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
1749 size_t const srcSize = CNBuffSize / 5;
1750 int const compressionLevel = -1;
1752 assert(cctx != NULL);
1753 { ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize, 0);
1754 size_t const cSize_1pass = ZSTD_compress_advanced(cctx,
1755 compressedBuffer, compressedBufferSize,
1759 if (ZSTD_isError(cSize_1pass)) goto _output_error;
1761 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) );
1762 { size_t const compressionResult = ZSTD_compress2(cctx,
1763 compressedBuffer, compressedBufferSize,
1765 DISPLAYLEVEL(5, "simple=%zu vs %zu=advanced : ", cSize_1pass, compressionResult);
1766 if (ZSTD_isError(compressionResult)) goto _output_error;
1767 if (compressionResult != cSize_1pass) goto _output_error;
1769 ZSTD_freeCCtx(cctx);
1771 DISPLAYLEVEL(3, "OK \n");
1773 /* parameters order test */
1774 { size_t const inputSize = CNBuffSize / 2;
1777 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
1778 DISPLAYLEVEL(3, "test%3i : parameters in order : ", testNb++);
1779 assert(cctx != NULL);
1780 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 2) );
1781 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1) );
1782 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18) );
1783 { size_t const compressedSize = ZSTD_compress2(cctx,
1784 compressedBuffer, ZSTD_compressBound(inputSize),
1785 CNBuffer, inputSize);
1786 CHECK(compressedSize);
1787 cSize = compressedSize;
1788 xxh64 = XXH64(compressedBuffer, compressedSize, 0);
1790 DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)cSize);
1791 ZSTD_freeCCtx(cctx);
1794 { ZSTD_CCtx* cctx = ZSTD_createCCtx();
1795 DISPLAYLEVEL(3, "test%3i : parameters disordered : ", testNb++);
1796 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18) );
1797 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1) );
1798 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 2) );
1799 { size_t const result = ZSTD_compress2(cctx,
1800 compressedBuffer, ZSTD_compressBound(inputSize),
1801 CNBuffer, inputSize);
1803 if (result != cSize) goto _output_error; /* must result in same compressed result, hence same size */
1804 if (XXH64(compressedBuffer, result, 0) != xxh64) goto _output_error; /* must result in exactly same content, hence same hash */
1805 DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)result);
1807 ZSTD_freeCCtx(cctx);
1811 /* advanced parameters for decompression */
1812 { ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1813 assert(dctx != NULL);
1815 DISPLAYLEVEL(3, "test%3i : get dParameter bounds ", testNb++);
1816 { ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1817 CHECK(bounds.error);
1819 DISPLAYLEVEL(3, "OK \n");
1821 DISPLAYLEVEL(3, "test%3i : wrong dParameter : ", testNb++);
1822 { size_t const sr = ZSTD_DCtx_setParameter(dctx, (ZSTD_dParameter)999999, 0);
1823 if (!ZSTD_isError(sr)) goto _output_error;
1825 { ZSTD_bounds const bounds = ZSTD_dParam_getBounds((ZSTD_dParameter)999998);
1826 if (!ZSTD_isError(bounds.error)) goto _output_error;
1828 DISPLAYLEVEL(3, "OK \n");
1830 DISPLAYLEVEL(3, "test%3i : out of bound dParameter : ", testNb++);
1831 { size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 9999);
1832 if (!ZSTD_isError(sr)) goto _output_error;
1834 { size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (ZSTD_format_e)888);
1835 if (!ZSTD_isError(sr)) goto _output_error;
1837 DISPLAYLEVEL(3, "OK \n");
1839 ZSTD_freeDCtx(dctx);
1843 /* custom formats tests */
1844 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
1845 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1846 size_t const inputSize = CNBuffSize / 2; /* won't cause pb with small dict size */
1847 assert(dctx != NULL); assert(cctx != NULL);
1849 /* basic block compression */
1850 DISPLAYLEVEL(3, "test%3i : magic-less format test : ", testNb++);
1851 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) );
1852 { ZSTD_inBuffer in = { CNBuffer, inputSize, 0 };
1853 ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(inputSize), 0 };
1854 size_t const result = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);
1855 if (result != 0) goto _output_error;
1856 if (in.pos != in.size) goto _output_error;
1859 DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)cSize);
1861 DISPLAYLEVEL(3, "test%3i : decompress normally (should fail) : ", testNb++);
1862 { size_t const decodeResult = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
1863 if (ZSTD_getErrorCode(decodeResult) != ZSTD_error_prefix_unknown) goto _output_error;
1864 DISPLAYLEVEL(3, "OK : %s \n", ZSTD_getErrorName(decodeResult));
1867 DISPLAYLEVEL(3, "test%3i : decompress of magic-less frame : ", testNb++);
1868 ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
1869 CHECK( ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless) );
1870 { ZSTD_frameHeader zfh;
1871 size_t const zfhrt = ZSTD_getFrameHeader_advanced(&zfh, compressedBuffer, cSize, ZSTD_f_zstd1_magicless);
1872 if (zfhrt != 0) goto _output_error;
1875 { size_t const result = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
1876 if (result != inputSize) goto _output_error;
1877 DISPLAYLEVEL(3, "one-shot OK, ");
1880 { ZSTD_inBuffer in = { compressedBuffer, cSize, 0 };
1881 ZSTD_outBuffer out = { decodedBuffer, CNBuffSize, 0 };
1882 size_t const result = ZSTD_decompressStream(dctx, &out, &in);
1883 if (result != 0) goto _output_error;
1884 if (in.pos != in.size) goto _output_error;
1885 if (out.pos != inputSize) goto _output_error;
1886 DISPLAYLEVEL(3, "streaming OK : regenerated %u bytes \n", (unsigned)out.pos);
1889 /* basic block compression */
1890 DISPLAYLEVEL(3, "test%3i : empty magic-less format test : ", testNb++);
1891 CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) );
1892 { ZSTD_inBuffer in = { CNBuffer, 0, 0 };
1893 ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(0), 0 };
1894 size_t const result = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);
1895 if (result != 0) goto _output_error;
1896 if (in.pos != in.size) goto _output_error;
1899 DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)0, (unsigned)cSize);
1901 DISPLAYLEVEL(3, "test%3i : decompress of empty magic-less frame : ", testNb++);
1902 ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
1903 CHECK( ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless) );
1905 { size_t const result = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
1906 if (result != 0) goto _output_error;
1907 DISPLAYLEVEL(3, "one-shot OK, ");
1910 { ZSTD_inBuffer in = { compressedBuffer, cSize, 0 };
1911 ZSTD_outBuffer out = { decodedBuffer, CNBuffSize, 0 };
1912 size_t const result = ZSTD_decompressStream(dctx, &out, &in);
1913 if (result != 0) goto _output_error;
1914 if (in.pos != in.size) goto _output_error;
1915 if (out.pos != 0) goto _output_error;
1916 DISPLAYLEVEL(3, "streaming OK : regenerated %u bytes \n", (unsigned)out.pos);
1919 ZSTD_freeCCtx(cctx);
1920 ZSTD_freeDCtx(dctx);
1923 /* block API tests */
1924 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
1925 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1926 static const size_t dictSize = 65 KB;
1927 static const size_t blockSize = 100 KB; /* won't cause pb with small dict size */
1929 assert(cctx != NULL); assert(dctx != NULL);
1931 /* basic block compression */
1932 DISPLAYLEVEL(3, "test%3i : Block compression test : ", testNb++);
1933 CHECK( ZSTD_compressBegin(cctx, 5) );
1934 CHECK( ZSTD_getBlockSize(cctx) >= blockSize);
1935 CHECK_VAR(cSize, ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize) );
1936 DISPLAYLEVEL(3, "OK \n");
1938 DISPLAYLEVEL(3, "test%3i : Block decompression test : ", testNb++);
1939 CHECK( ZSTD_decompressBegin(dctx) );
1940 { CHECK_NEWV(r, ZSTD_decompressBlock(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
1941 if (r != blockSize) goto _output_error; }
1942 DISPLAYLEVEL(3, "OK \n");
1944 /* very long stream of block compression */
1945 DISPLAYLEVEL(3, "test%3i : Huge block streaming compression test : ", testNb++);
1946 CHECK( ZSTD_compressBegin(cctx, -199) ); /* we just want to quickly overflow internal U32 index */
1947 CHECK( ZSTD_getBlockSize(cctx) >= blockSize);
1948 { U64 const toCompress = 5000000000ULL; /* > 4 GB */
1950 while (compressed < toCompress) {
1951 size_t const blockCSize = ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize);
1952 assert(blockCSize != 0);
1953 if (ZSTD_isError(blockCSize)) goto _output_error;
1954 compressed += blockCSize;
1956 DISPLAYLEVEL(3, "OK \n");
1958 /* dictionary block compression */
1959 DISPLAYLEVEL(3, "test%3i : Dictionary Block compression test : ", testNb++);
1960 CHECK( ZSTD_compressBegin_usingDict(cctx, CNBuffer, dictSize, 5) );
1961 CHECK_VAR(cSize, ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize, blockSize));
1962 RDG_genBuffer((char*)CNBuffer+dictSize+blockSize, blockSize, 0.0, 0.0, seed); /* create a non-compressible second block */
1963 { CHECK_NEWV(r, ZSTD_compressBlock(cctx, (char*)compressedBuffer+cSize, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize+blockSize, blockSize) ); /* for cctx history consistency */
1964 assert(r == 0); /* non-compressible block */ }
1965 memcpy((char*)compressedBuffer+cSize, (char*)CNBuffer+dictSize+blockSize, blockSize); /* send non-compressed block (without header) */
1966 CHECK_VAR(cSize2, ZSTD_compressBlock(cctx, (char*)compressedBuffer+cSize+blockSize, ZSTD_compressBound(blockSize),
1967 (char*)CNBuffer+dictSize+2*blockSize, blockSize));
1968 DISPLAYLEVEL(3, "OK \n");
1970 DISPLAYLEVEL(3, "test%3i : Dictionary Block decompression test : ", testNb++);
1971 CHECK( ZSTD_decompressBegin_usingDict(dctx, CNBuffer, dictSize) );
1972 { CHECK_NEWV( r, ZSTD_decompressBlock(dctx, decodedBuffer, blockSize, compressedBuffer, cSize) );
1973 if (r != blockSize) {
1974 DISPLAYLEVEL(1, "ZSTD_decompressBlock() with _usingDict() fails : %u, instead of %u expected \n", (unsigned)r, (unsigned)blockSize);
1977 memcpy((char*)decodedBuffer+blockSize, (char*)compressedBuffer+cSize, blockSize);
1978 ZSTD_insertBlock(dctx, (char*)decodedBuffer+blockSize, blockSize); /* insert non-compressed block into dctx history */
1979 { CHECK_NEWV( r, ZSTD_decompressBlock(dctx, (char*)decodedBuffer+2*blockSize, blockSize, (char*)compressedBuffer+cSize+blockSize, cSize2) );
1980 if (r != blockSize) {
1981 DISPLAYLEVEL(1, "ZSTD_decompressBlock() with _usingDict() and after insertBlock() fails : %u, instead of %u expected \n", (unsigned)r, (unsigned)blockSize);
1984 assert(memcpy((char*)CNBuffer+dictSize, decodedBuffer, blockSize*3)); /* ensure regenerated content is identical to origin */
1985 DISPLAYLEVEL(3, "OK \n");
1987 DISPLAYLEVEL(3, "test%3i : Block compression with CDict : ", testNb++);
1988 { ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 3);
1989 if (cdict==NULL) goto _output_error;
1990 CHECK( ZSTD_compressBegin_usingCDict(cctx, cdict) );
1991 CHECK( ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize, blockSize) );
1992 ZSTD_freeCDict(cdict);
1994 DISPLAYLEVEL(3, "OK \n");
1996 ZSTD_freeCCtx(cctx);
1997 ZSTD_freeDCtx(dctx);
2001 { size_t sampleSize = 0;
2002 DISPLAYLEVEL(3, "test%3i : Long RLE test : ", testNb++);
2003 RDG_genBuffer(CNBuffer, sampleSize, compressibility, 0., seed+1);
2004 memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1);
2005 sampleSize += 256 KB - 1;
2006 RDG_genBuffer((char*)CNBuffer+sampleSize, 96 KB, compressibility, 0., seed+2);
2007 sampleSize += 96 KB;
2008 cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize, 1);
2009 if (ZSTD_isError(cSize)) goto _output_error;
2010 { CHECK_NEWV(regenSize, ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize));
2011 if (regenSize!=sampleSize) goto _output_error; }
2012 DISPLAYLEVEL(3, "OK \n");
2015 DISPLAYLEVEL(3, "test%3i : ZSTD_getSequences decode from sequences test : ", testNb++);
2017 size_t srcSize = 100 KB;
2018 BYTE* src = (BYTE*)CNBuffer;
2019 BYTE* decoded = (BYTE*)compressedBuffer;
2021 ZSTD_CCtx* cctx = ZSTD_createCCtx();
2022 ZSTD_Sequence* seqs = (ZSTD_Sequence*)malloc(srcSize * sizeof(ZSTD_Sequence));
2025 if (seqs == NULL) goto _output_error;
2026 assert(cctx != NULL);
2028 /* Populate src with random data */
2029 RDG_genBuffer(CNBuffer, srcSize, compressibility, 0., seed);
2031 /* get the sequences */
2032 seqsSize = ZSTD_getSequences(cctx, seqs, srcSize, src, srcSize);
2034 /* "decode" and compare the sequences */
2035 FUZ_decodeSequences(decoded, seqs, seqsSize, src, srcSize);
2036 assert(!memcmp(CNBuffer, compressedBuffer, srcSize));
2038 ZSTD_freeCCtx(cctx);
2042 /* Multiple blocks of zeros test */
2043 #define LONGZEROSLENGTH 1000000 /* 1MB of zeros */
2044 DISPLAYLEVEL(3, "test%3i : compress %u zeroes : ", testNb++, LONGZEROSLENGTH);
2045 memset(CNBuffer, 0, LONGZEROSLENGTH);
2046 CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(LONGZEROSLENGTH), CNBuffer, LONGZEROSLENGTH, 1) );
2047 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/LONGZEROSLENGTH*100);
2049 DISPLAYLEVEL(3, "test%3i : decompress %u zeroes : ", testNb++, LONGZEROSLENGTH);
2050 { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, LONGZEROSLENGTH, compressedBuffer, cSize) );
2051 if (r != LONGZEROSLENGTH) goto _output_error; }
2052 DISPLAYLEVEL(3, "OK \n");
2054 /* All zeroes test (test bug #137) */
2055 #define ZEROESLENGTH 100
2056 DISPLAYLEVEL(3, "test%3i : compress %u zeroes : ", testNb++, ZEROESLENGTH);
2057 memset(CNBuffer, 0, ZEROESLENGTH);
2058 CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(ZEROESLENGTH), CNBuffer, ZEROESLENGTH, 1) );
2059 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/ZEROESLENGTH*100);
2061 DISPLAYLEVEL(3, "test%3i : decompress %u zeroes : ", testNb++, ZEROESLENGTH);
2062 { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, ZEROESLENGTH, compressedBuffer, cSize) );
2063 if (r != ZEROESLENGTH) goto _output_error; }
2064 DISPLAYLEVEL(3, "OK \n");
2066 /* nbSeq limit test */
2067 #define _3BYTESTESTLENGTH 131000
2068 #define NB3BYTESSEQLOG 9
2069 #define NB3BYTESSEQ (1 << NB3BYTESSEQLOG)
2070 #define NB3BYTESSEQMASK (NB3BYTESSEQ-1)
2071 /* creates a buffer full of 3-bytes sequences */
2072 { BYTE _3BytesSeqs[NB3BYTESSEQ][3];
2075 /* create batch of 3-bytes sequences */
2077 for (i=0; i < NB3BYTESSEQ; i++) {
2078 _3BytesSeqs[i][0] = (BYTE)(FUZ_rand(&rSeed) & 255);
2079 _3BytesSeqs[i][1] = (BYTE)(FUZ_rand(&rSeed) & 255);
2080 _3BytesSeqs[i][2] = (BYTE)(FUZ_rand(&rSeed) & 255);
2083 /* randomly fills CNBuffer with prepared 3-bytes sequences */
2085 for (i=0; i < _3BYTESTESTLENGTH; i += 3) { /* note : CNBuffer size > _3BYTESTESTLENGTH+3 */
2086 U32 const id = FUZ_rand(&rSeed) & NB3BYTESSEQMASK;
2087 ((BYTE*)CNBuffer)[i+0] = _3BytesSeqs[id][0];
2088 ((BYTE*)CNBuffer)[i+1] = _3BytesSeqs[id][1];
2089 ((BYTE*)CNBuffer)[i+2] = _3BytesSeqs[id][2];
2091 DISPLAYLEVEL(3, "test%3i : growing nbSeq : ", testNb++);
2092 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
2093 size_t const maxNbSeq = _3BYTESTESTLENGTH / 3;
2094 size_t const bound = ZSTD_compressBound(_3BYTESTESTLENGTH);
2096 while (nbSeq <= maxNbSeq) {
2097 CHECK(ZSTD_compressCCtx(cctx, compressedBuffer, bound, CNBuffer, nbSeq * 3, 19));
2098 /* Check every sequence for the first 100, then skip more rapidly. */
2102 nbSeq += (nbSeq >> 2);
2105 ZSTD_freeCCtx(cctx);
2107 DISPLAYLEVEL(3, "OK \n");
2109 DISPLAYLEVEL(3, "test%3i : compress lots 3-bytes sequences : ", testNb++);
2110 CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(_3BYTESTESTLENGTH),
2111 CNBuffer, _3BYTESTESTLENGTH, 19) );
2112 DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/_3BYTESTESTLENGTH*100);
2114 DISPLAYLEVEL(3, "test%3i : decompress lots 3-bytes sequence : ", testNb++);
2115 { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, _3BYTESTESTLENGTH, compressedBuffer, cSize) );
2116 if (r != _3BYTESTESTLENGTH) goto _output_error; }
2117 DISPLAYLEVEL(3, "OK \n");
2120 DISPLAYLEVEL(3, "test%3i : growing literals buffer : ", testNb++);
2121 RDG_genBuffer(CNBuffer, CNBuffSize, 0.0, 0.1, seed);
2122 { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
2123 size_t const bound = ZSTD_compressBound(CNBuffSize);
2125 while (size <= CNBuffSize) {
2126 CHECK(ZSTD_compressCCtx(cctx, compressedBuffer, bound, CNBuffer, size, 3));
2127 /* Check every size for the first 100, then skip more rapidly. */
2131 size += (size >> 2);
2134 ZSTD_freeCCtx(cctx);
2136 DISPLAYLEVEL(3, "OK \n");
2138 DISPLAYLEVEL(3, "test%3i : incompressible data and ill suited dictionary : ", testNb++);
2139 { /* Train a dictionary on low characters */
2140 size_t dictSize = 16 KB;
2141 void* const dictBuffer = malloc(dictSize);
2142 size_t const totalSampleSize = 1 MB;
2143 size_t const sampleUnitSize = 8 KB;
2144 U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);
2145 size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t));
2146 if (!dictBuffer || !samplesSizes) goto _output_error;
2147 { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
2148 dictSize = ZDICT_trainFromBuffer(dictBuffer, dictSize, CNBuffer, samplesSizes, nbSamples);
2149 if (ZDICT_isError(dictSize)) goto _output_error;
2150 /* Reverse the characters to make the dictionary ill suited */
2152 for (u = 0; u < CNBuffSize; ++u) {
2153 ((BYTE*)CNBuffer)[u] = 255 - ((BYTE*)CNBuffer)[u];
2156 { /* Compress the data */
2157 size_t const inputSize = 500;
2158 size_t const outputSize = ZSTD_compressBound(inputSize);
2159 void* const outputBuffer = malloc(outputSize);
2160 ZSTD_CCtx* const cctx = ZSTD_createCCtx();
2161 if (!outputBuffer || !cctx) goto _output_error;
2162 CHECK(ZSTD_compress_usingDict(cctx, outputBuffer, outputSize, CNBuffer, inputSize, dictBuffer, dictSize, 1));
2164 ZSTD_freeCCtx(cctx);
2170 DISPLAYLEVEL(3, "OK \n");
2173 /* findFrameCompressedSize on skippable frames */
2174 DISPLAYLEVEL(3, "test%3i : frame compressed size of skippable frame : ", testNb++);
2175 { const char* frame = "\x50\x2a\x4d\x18\x05\x0\x0\0abcde";
2176 size_t const frameSrcSize = 13;
2177 if (ZSTD_findFrameCompressedSize(frame, frameSrcSize) != frameSrcSize) goto _output_error; }
2178 DISPLAYLEVEL(3, "OK \n");
2180 /* error string tests */
2181 DISPLAYLEVEL(3, "test%3i : testing ZSTD error code strings : ", testNb++);
2182 if (strcmp("No error detected", ZSTD_getErrorName((ZSTD_ErrorCode)(0-ZSTD_error_no_error))) != 0) goto _output_error;
2183 if (strcmp("No error detected", ZSTD_getErrorString(ZSTD_error_no_error)) != 0) goto _output_error;
2184 if (strcmp("Unspecified error code", ZSTD_getErrorString((ZSTD_ErrorCode)(0-ZSTD_error_GENERIC))) != 0) goto _output_error;
2185 if (strcmp("Error (generic)", ZSTD_getErrorName((size_t)0-ZSTD_error_GENERIC)) != 0) goto _output_error;
2186 if (strcmp("Error (generic)", ZSTD_getErrorString(ZSTD_error_GENERIC)) != 0) goto _output_error;
2187 if (strcmp("No error detected", ZSTD_getErrorName(ZSTD_error_GENERIC)) != 0) goto _output_error;
2188 DISPLAYLEVEL(3, "OK \n");
2190 DISPLAYLEVEL(3, "test%3i : testing ZSTD dictionary sizes : ", testNb++);
2191 RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed);
2193 size_t const size = MIN(128 KB, CNBuffSize);
2194 ZSTD_CCtx* const cctx = ZSTD_createCCtx();
2195 ZSTD_CDict* const lgCDict = ZSTD_createCDict(CNBuffer, size, 1);
2196 ZSTD_CDict* const smCDict = ZSTD_createCDict(CNBuffer, 1 KB, 1);
2197 ZSTD_frameHeader lgHeader;
2198 ZSTD_frameHeader smHeader;
2200 CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, size, lgCDict));
2201 CHECK_Z(ZSTD_getFrameHeader(&lgHeader, compressedBuffer, compressedBufferSize));
2202 CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, size, smCDict));
2203 CHECK_Z(ZSTD_getFrameHeader(&smHeader, compressedBuffer, compressedBufferSize));
2205 if (lgHeader.windowSize != smHeader.windowSize) goto _output_error;
2207 ZSTD_freeCDict(smCDict);
2208 ZSTD_freeCDict(lgCDict);
2209 ZSTD_freeCCtx(cctx);
2211 DISPLAYLEVEL(3, "OK \n");
2213 DISPLAYLEVEL(3, "test%3i : testing FSE_normalizeCount() PR#1255: ", testNb++);
2217 unsigned const tableLog = 5;
2218 size_t const nbSeq = 32;
2219 unsigned const maxSymbolValue = 31;
2222 for (i = 0; i < 32; ++i)
2224 /* Calling FSE_normalizeCount() on a uniform distribution should not
2225 * cause a division by zero.
2227 FSE_normalizeCount(norm, tableLog, count, nbSeq, maxSymbolValue);
2229 DISPLAYLEVEL(3, "OK \n");
2231 DISPLAYLEVEL(3, "test%3i : table cleanliness through index reduction : ", testNb++);
2234 size_t approxIndex = 0;
2235 size_t maxIndex = ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX)); /* ZSTD_CURRENT_MAX from zstd_compress_internal.h */
2237 /* Provision enough space in a static context so that we can do all
2238 * this without ever reallocating, which would reset the indices. */
2239 size_t const staticCCtxSize = ZSTD_estimateCStreamSize(22);
2240 void* const staticCCtxBuffer = malloc(staticCCtxSize);
2241 ZSTD_CCtx* cctx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize);
2243 /* bump the indices so the following compressions happen at high
2246 ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 };
2247 ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };
2248 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
2249 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, -500));
2250 while (approxIndex <= (maxIndex / 4) * 3) {
2251 CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
2252 approxIndex += in.pos;
2253 CHECK(in.pos == in.size);
2257 CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
2260 /* spew a bunch of stuff into the table area */
2261 for (cLevel = 1; cLevel <= 22; cLevel++) {
2262 ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize / cLevel, 0 };
2263 ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };
2264 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
2265 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel));
2266 CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
2267 CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
2268 approxIndex += in.pos;
2271 /* now crank the indices so we overflow */
2273 ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 };
2274 ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };
2275 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
2276 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, -500));
2277 while (approxIndex <= maxIndex) {
2278 CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
2279 approxIndex += in.pos;
2280 CHECK(in.pos == in.size);
2284 CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
2287 /* do a bunch of compressions again in low indices and ensure we don't
2288 * hit untracked invalid indices */
2289 for (cLevel = 1; cLevel <= 22; cLevel++) {
2290 ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize / cLevel, 0 };
2291 ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };
2292 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
2293 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel));
2294 CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
2295 CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
2296 approxIndex += in.pos;
2299 ZSTD_freeCCtx(cctx);
2300 free(staticCCtxBuffer);
2302 DISPLAYLEVEL(3, "OK \n");
2306 free(compressedBuffer);
2307 free(decodedBuffer);
2312 DISPLAY("Error detected in Unit tests ! \n");
2317 static size_t findDiff(const void* buf1, const void* buf2, size_t max)
2319 const BYTE* b1 = (const BYTE*)buf1;
2320 const BYTE* b2 = (const BYTE*)buf2;
2322 for (u=0; u<max; u++) {
2323 if (b1[u] != b2[u]) break;
2329 static ZSTD_parameters FUZ_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams)
2331 ZSTD_parameters params;
2332 params.cParams = cParams;
2333 params.fParams = fParams;
2337 static size_t FUZ_rLogLength(U32* seed, U32 logLength)
2339 size_t const lengthMask = ((size_t)1 << logLength) - 1;
2340 return (lengthMask+1) + (FUZ_rand(seed) & lengthMask);
2343 static size_t FUZ_randomLength(U32* seed, U32 maxLog)
2345 U32 const logLength = FUZ_rand(seed) % maxLog;
2346 return FUZ_rLogLength(seed, logLength);
2350 #define CHECK(cond, ...) { \
2352 DISPLAY("Error => "); \
2353 DISPLAY(__VA_ARGS__); \
2354 DISPLAY(" (seed %u, test nb %u) \n", (unsigned)seed, testNb); \
2355 goto _output_error; \
2359 #define CHECK_Z(f) { \
2360 size_t const err = f; \
2361 if (ZSTD_isError(err)) { \
2362 DISPLAY("Error => %s : %s ", \
2363 #f, ZSTD_getErrorName(err)); \
2364 DISPLAY(" (seed %u, test nb %u) \n", (unsigned)seed, testNb); \
2365 goto _output_error; \
2369 static int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, U32 const maxDurationS, double compressibility, int bigTests)
2371 static const U32 maxSrcLog = 23;
2372 static const U32 maxSampleLog = 22;
2373 size_t const srcBufferSize = (size_t)1<<maxSrcLog;
2374 size_t const dstBufferSize = (size_t)1<<maxSampleLog;
2375 size_t const cBufferSize = ZSTD_compressBound(dstBufferSize);
2376 BYTE* cNoiseBuffer[5];
2377 BYTE* const cBuffer = (BYTE*) malloc (cBufferSize);
2378 BYTE* const dstBuffer = (BYTE*) malloc (dstBufferSize);
2379 BYTE* const mirrorBuffer = (BYTE*) malloc (dstBufferSize);
2380 ZSTD_CCtx* const refCtx = ZSTD_createCCtx();
2381 ZSTD_CCtx* const ctx = ZSTD_createCCtx();
2382 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
2384 unsigned testNb = 0;
2385 U32 coreSeed = seed;
2386 UTIL_time_t const startClock = UTIL_getTime();
2387 U64 const maxClockSpan = maxDurationS * SEC_TO_MICRO;
2388 int const cLevelLimiter = bigTests ? 3 : 2;
2391 cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
2392 cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize);
2393 cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize);
2394 cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize);
2395 cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize);
2396 CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4]
2397 || !dstBuffer || !mirrorBuffer || !cBuffer || !refCtx || !ctx || !dctx,
2398 "Not enough memory, fuzzer tests cancelled");
2400 /* Create initial samples */
2401 RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed); /* pure noise */
2402 RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed); /* barely compressible */
2403 RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);
2404 RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */
2405 RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */
2407 /* catch up testNb */
2408 for (testNb=1; testNb < startTest; testNb++) FUZ_rand(&coreSeed);
2410 /* main test loop */
2411 for ( ; (testNb <= nbTests) || (UTIL_clockSpanMicro(startClock) < maxClockSpan); testNb++ ) {
2412 BYTE* srcBuffer; /* jumping pointer */
2414 size_t sampleSize, maxTestSize, totalTestSize;
2415 size_t cSize, totalCSize, totalGenSize;
2422 if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); }
2423 else { DISPLAYUPDATE(2, "\r%6u ", testNb); }
2425 FUZ_rand(&coreSeed);
2426 { U32 const prime1 = 2654435761U; lseed = coreSeed ^ prime1; }
2428 /* srcBuffer selection [0-4] */
2429 { U32 buffNb = FUZ_rand(&lseed) & 0x7F;
2430 if (buffNb & 7) buffNb=2; /* most common : compressible (P) */
2434 const U32 tnb[2] = { 1, 3 }; /* barely/highly compressible */
2435 buffNb = tnb[buffNb >> 3];
2437 const U32 tnb[2] = { 0, 4 }; /* not compressible / sparse */
2438 buffNb = tnb[buffNb >> 3];
2440 srcBuffer = cNoiseBuffer[buffNb];
2443 /* select src segment */
2444 sampleSize = FUZ_randomLength(&lseed, maxSampleLog);
2446 /* create sample buffer (to catch read error with valgrind & sanitizers) */
2447 sampleBuffer = (BYTE*)malloc(sampleSize);
2448 CHECK(sampleBuffer==NULL, "not enough memory for sample buffer");
2449 { size_t const sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);
2450 memcpy(sampleBuffer, srcBuffer + sampleStart, sampleSize); }
2451 crcOrig = XXH64(sampleBuffer, sampleSize, 0);
2453 /* compression tests */
2454 { int const cLevelPositive =
2455 ( FUZ_rand(&lseed) %
2456 (ZSTD_maxCLevel() - (FUZ_highbit32((U32)sampleSize) / cLevelLimiter)) )
2458 int const cLevel = ((FUZ_rand(&lseed) & 15) == 3) ?
2459 - (int)((FUZ_rand(&lseed) & 7) + 1) : /* test negative cLevel */
2461 DISPLAYLEVEL(5, "fuzzer t%u: Simple compression test (level %i) \n", testNb, cLevel);
2462 cSize = ZSTD_compressCCtx(ctx, cBuffer, cBufferSize, sampleBuffer, sampleSize, cLevel);
2463 CHECK(ZSTD_isError(cSize), "ZSTD_compressCCtx failed : %s", ZSTD_getErrorName(cSize));
2465 /* compression failure test : too small dest buffer */
2467 { const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1;
2468 const size_t tooSmallSize = cSize - missing;
2469 const unsigned endMark = 0x4DC2B1A9;
2470 memcpy(dstBuffer+tooSmallSize, &endMark, sizeof(endMark));
2471 DISPLAYLEVEL(5, "fuzzer t%u: compress into too small buffer of size %u (missing %u bytes) \n",
2472 testNb, (unsigned)tooSmallSize, (unsigned)missing);
2473 { size_t const errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, sampleBuffer, sampleSize, cLevel);
2474 CHECK(!ZSTD_isError(errorCode), "ZSTD_compressCCtx should have failed ! (buffer too small : %u < %u)", (unsigned)tooSmallSize, (unsigned)cSize); }
2475 { unsigned endCheck; memcpy(&endCheck, dstBuffer+tooSmallSize, sizeof(endCheck));
2476 CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow (check.%08X != %08X.mark)", endCheck, endMark); }
2479 /* frame header decompression test */
2480 { ZSTD_frameHeader zfh;
2481 CHECK_Z( ZSTD_getFrameHeader(&zfh, cBuffer, cSize) );
2482 CHECK(zfh.frameContentSize != sampleSize, "Frame content size incorrect");
2485 /* Decompressed size test */
2486 { unsigned long long const rSize = ZSTD_findDecompressedSize(cBuffer, cSize);
2487 CHECK(rSize != sampleSize, "decompressed size incorrect");
2490 /* successful decompression test */
2491 DISPLAYLEVEL(5, "fuzzer t%u: simple decompression test \n", testNb);
2492 { size_t const margin = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1;
2493 size_t const dSize = ZSTD_decompress(dstBuffer, sampleSize + margin, cBuffer, cSize);
2494 CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (unsigned)sampleSize, (unsigned)cSize);
2495 { U64 const crcDest = XXH64(dstBuffer, sampleSize, 0);
2496 CHECK(crcOrig != crcDest, "decompression result corrupted (pos %u / %u)", (unsigned)findDiff(sampleBuffer, dstBuffer, sampleSize), (unsigned)sampleSize);
2499 free(sampleBuffer); /* no longer useful after this point */
2501 /* truncated src decompression test */
2502 DISPLAYLEVEL(5, "fuzzer t%u: decompression of truncated source \n", testNb);
2503 { size_t const missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
2504 size_t const tooSmallSize = cSize - missing;
2505 void* cBufferTooSmall = malloc(tooSmallSize); /* valgrind will catch read overflows */
2506 CHECK(cBufferTooSmall == NULL, "not enough memory !");
2507 memcpy(cBufferTooSmall, cBuffer, tooSmallSize);
2508 { size_t const errorCode = ZSTD_decompress(dstBuffer, dstBufferSize, cBufferTooSmall, tooSmallSize);
2509 CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed ! (truncated src buffer)"); }
2510 free(cBufferTooSmall);
2513 /* too small dst decompression test */
2514 DISPLAYLEVEL(5, "fuzzer t%u: decompress into too small dst buffer \n", testNb);
2515 if (sampleSize > 3) {
2516 size_t const missing = (FUZ_rand(&lseed) % (sampleSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
2517 size_t const tooSmallSize = sampleSize - missing;
2518 static const BYTE token = 0xA9;
2519 dstBuffer[tooSmallSize] = token;
2520 { size_t const errorCode = ZSTD_decompress(dstBuffer, tooSmallSize, cBuffer, cSize);
2521 CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed : %u > %u (dst buffer too small)", (unsigned)errorCode, (unsigned)tooSmallSize); }
2522 CHECK(dstBuffer[tooSmallSize] != token, "ZSTD_decompress : dst buffer overflow");
2525 /* noisy src decompression test */
2527 /* insert noise into src */
2528 { U32 const maxNbBits = FUZ_highbit32((U32)(cSize-4));
2529 size_t pos = 4; /* preserve magic number (too easy to detect) */
2531 /* keep some original src */
2532 { U32 const nbBits = FUZ_rand(&lseed) % maxNbBits;
2533 size_t const mask = (1<<nbBits) - 1;
2534 size_t const skipLength = FUZ_rand(&lseed) & mask;
2537 if (pos >= cSize) break;
2539 { U32 const nbBitsCodes = FUZ_rand(&lseed) % maxNbBits;
2540 U32 const nbBits = nbBitsCodes ? nbBitsCodes-1 : 0;
2541 size_t const mask = (1<<nbBits) - 1;
2542 size_t const rNoiseLength = (FUZ_rand(&lseed) & mask) + 1;
2543 size_t const noiseLength = MIN(rNoiseLength, cSize-pos);
2544 size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseLength);
2545 memcpy(cBuffer + pos, srcBuffer + noiseStart, noiseLength);
2549 /* decompress noisy source */
2550 DISPLAYLEVEL(5, "fuzzer t%u: decompress noisy source \n", testNb);
2551 { U32 const endMark = 0xA9B1C3D6;
2552 memcpy(dstBuffer+sampleSize, &endMark, 4);
2553 { size_t const decompressResult = ZSTD_decompress(dstBuffer, sampleSize, cBuffer, cSize);
2554 /* result *may* be an unlikely success, but even then, it must strictly respect dst buffer boundaries */
2555 CHECK((!ZSTD_isError(decompressResult)) && (decompressResult>sampleSize),
2556 "ZSTD_decompress on noisy src : result is too large : %u > %u (dst buffer)", (unsigned)decompressResult, (unsigned)sampleSize);
2558 { U32 endCheck; memcpy(&endCheck, dstBuffer+sampleSize, 4);
2559 CHECK(endMark!=endCheck, "ZSTD_decompress on noisy src : dst buffer overflow");
2560 } } } /* noisy src decompression test */
2562 /*===== Bufferless streaming compression test, scattered segments and dictionary =====*/
2563 DISPLAYLEVEL(5, "fuzzer t%u: Bufferless streaming compression test \n", testNb);
2564 { U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
2565 U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;
2566 int const cLevel = (FUZ_rand(&lseed) %
2568 (MAX(testLog, dictLog) / cLevelLimiter))) +
2570 maxTestSize = FUZ_rLogLength(&lseed, testLog);
2571 if (maxTestSize >= dstBufferSize) maxTestSize = dstBufferSize-1;
2573 dictSize = FUZ_rLogLength(&lseed, dictLog); /* needed also for decompression */
2574 dict = srcBuffer + (FUZ_rand(&lseed) % (srcBufferSize - dictSize));
2576 DISPLAYLEVEL(6, "fuzzer t%u: Compressing up to <=%u bytes at level %i with dictionary size %u \n",
2577 testNb, (unsigned)maxTestSize, cLevel, (unsigned)dictSize);
2579 if (FUZ_rand(&lseed) & 0xF) {
2580 CHECK_Z ( ZSTD_compressBegin_usingDict(refCtx, dict, dictSize, cLevel) );
2582 ZSTD_compressionParameters const cPar = ZSTD_getCParams(cLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
2583 ZSTD_frameParameters const fPar = { FUZ_rand(&lseed)&1 /* contentSizeFlag */,
2584 !(FUZ_rand(&lseed)&3) /* contentChecksumFlag*/,
2585 0 /*NodictID*/ }; /* note : since dictionary is fake, dictIDflag has no impact */
2586 ZSTD_parameters const p = FUZ_makeParams(cPar, fPar);
2587 CHECK_Z ( ZSTD_compressBegin_advanced(refCtx, dict, dictSize, p, 0) );
2589 CHECK_Z( ZSTD_copyCCtx(ctx, refCtx, 0) );
2592 { U32 const nbChunks = (FUZ_rand(&lseed) & 127) + 2;
2594 XXH64_state_t xxhState;
2595 XXH64_reset(&xxhState, 0);
2596 for (totalTestSize=0, cSize=0, n=0 ; n<nbChunks ; n++) {
2597 size_t const segmentSize = FUZ_randomLength(&lseed, maxSampleLog);
2598 size_t const segmentStart = FUZ_rand(&lseed) % (srcBufferSize - segmentSize);
2600 if (cBufferSize-cSize < ZSTD_compressBound(segmentSize)) break; /* avoid invalid dstBufferTooSmall */
2601 if (totalTestSize+segmentSize > maxTestSize) break;
2603 { size_t const compressResult = ZSTD_compressContinue(ctx, cBuffer+cSize, cBufferSize-cSize, srcBuffer+segmentStart, segmentSize);
2604 CHECK (ZSTD_isError(compressResult), "multi-segments compression error : %s", ZSTD_getErrorName(compressResult));
2605 cSize += compressResult;
2607 XXH64_update(&xxhState, srcBuffer+segmentStart, segmentSize);
2608 memcpy(mirrorBuffer + totalTestSize, srcBuffer+segmentStart, segmentSize);
2609 totalTestSize += segmentSize;
2612 { size_t const flushResult = ZSTD_compressEnd(ctx, cBuffer+cSize, cBufferSize-cSize, NULL, 0);
2613 CHECK (ZSTD_isError(flushResult), "multi-segments epilogue error : %s", ZSTD_getErrorName(flushResult));
2614 cSize += flushResult;
2616 crcOrig = XXH64_digest(&xxhState);
2619 /* streaming decompression test */
2620 DISPLAYLEVEL(5, "fuzzer t%u: Bufferless streaming decompression test \n", testNb);
2621 /* ensure memory requirement is good enough (should always be true) */
2622 { ZSTD_frameHeader zfh;
2623 CHECK( ZSTD_getFrameHeader(&zfh, cBuffer, ZSTD_FRAMEHEADERSIZE_MAX),
2624 "ZSTD_getFrameHeader(): error retrieving frame information");
2625 { size_t const roundBuffSize = ZSTD_decodingBufferSize_min(zfh.windowSize, zfh.frameContentSize);
2626 CHECK_Z(roundBuffSize);
2627 CHECK((roundBuffSize > totalTestSize) && (zfh.frameContentSize!=ZSTD_CONTENTSIZE_UNKNOWN),
2628 "ZSTD_decodingBufferSize_min() requires more memory (%u) than necessary (%u)",
2629 (unsigned)roundBuffSize, (unsigned)totalTestSize );
2631 if (dictSize<8) dictSize=0, dict=NULL; /* disable dictionary */
2632 CHECK_Z( ZSTD_decompressBegin_usingDict(dctx, dict, dictSize) );
2635 while (totalCSize < cSize) {
2636 size_t const inSize = ZSTD_nextSrcSizeToDecompress(dctx);
2637 size_t const genSize = ZSTD_decompressContinue(dctx, dstBuffer+totalGenSize, dstBufferSize-totalGenSize, cBuffer+totalCSize, inSize);
2638 CHECK (ZSTD_isError(genSize), "ZSTD_decompressContinue error : %s", ZSTD_getErrorName(genSize));
2639 totalGenSize += genSize;
2640 totalCSize += inSize;
2642 CHECK (ZSTD_nextSrcSizeToDecompress(dctx) != 0, "frame not fully decoded");
2643 CHECK (totalGenSize != totalTestSize, "streaming decompressed data : wrong size")
2644 CHECK (totalCSize != cSize, "compressed data should be fully read")
2645 { U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0);
2646 CHECK(crcOrig != crcDest, "streaming decompressed data corrupted (pos %u / %u)",
2647 (unsigned)findDiff(mirrorBuffer, dstBuffer, totalTestSize), (unsigned)totalTestSize);
2649 } /* for ( ; (testNb <= nbTests) */
2650 DISPLAY("\r%u fuzzer tests completed \n", testNb-1);
2653 ZSTD_freeCCtx(refCtx);
2655 ZSTD_freeDCtx(dctx);
2656 free(cNoiseBuffer[0]);
2657 free(cNoiseBuffer[1]);
2658 free(cNoiseBuffer[2]);
2659 free(cNoiseBuffer[3]);
2660 free(cNoiseBuffer[4]);
2672 /*_*******************************************************
2674 *********************************************************/
2675 static int FUZ_usage(const char* programName)
2677 DISPLAY( "Usage :\n");
2678 DISPLAY( " %s [args]\n", programName);
2680 DISPLAY( "Arguments :\n");
2681 DISPLAY( " -i# : Nb of tests (default:%i) \n", nbTestsDefault);
2682 DISPLAY( " -s# : Select seed (default:prompt user)\n");
2683 DISPLAY( " -t# : Select starting test number (default:0)\n");
2684 DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_compressibility_default);
2685 DISPLAY( " -v : verbose\n");
2686 DISPLAY( " -p : pause at the end\n");
2687 DISPLAY( " -h : display help and exit\n");
2691 /*! readU32FromChar() :
2692 @return : unsigned integer value read from input in `char` format
2693 allows and interprets K, KB, KiB, M, MB and MiB suffix.
2694 Will also modify `*stringPtr`, advancing it to position where it stopped reading.
2695 Note : function result can overflow if digit string > MAX_UINT */
2696 static unsigned readU32FromChar(const char** stringPtr)
2698 unsigned result = 0;
2699 while ((**stringPtr >='0') && (**stringPtr <='9'))
2700 result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
2701 if ((**stringPtr=='K') || (**stringPtr=='M')) {
2703 if (**stringPtr=='M') result <<= 10;
2705 if (**stringPtr=='i') (*stringPtr)++;
2706 if (**stringPtr=='B') (*stringPtr)++;
2711 /** longCommandWArg() :
2712 * check if *stringPtr is the same as longCommand.
2713 * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
2714 * @return 0 and doesn't modify *stringPtr otherwise.
2716 static int longCommandWArg(const char** stringPtr, const char* longCommand)
2718 size_t const comSize = strlen(longCommand);
2719 int const result = !strncmp(*stringPtr, longCommand, comSize);
2720 if (result) *stringPtr += comSize;
2724 int main(int argc, const char** argv)
2729 int nbTests = nbTestsDefault;
2731 int proba = FUZ_compressibility_default;
2734 U32 maxDuration = 0;
2736 U32 memTestsOnly = 0;
2737 const char* const programName = argv[0];
2739 /* Check command line */
2740 for (argNb=1; argNb<argc; argNb++) {
2741 const char* argument = argv[argNb];
2742 if(!argument) continue; /* Protection if argument empty */
2744 /* Handle commands. Aggregated commands are allowed */
2745 if (argument[0]=='-') {
2747 if (longCommandWArg(&argument, "--memtest=")) { memTestsOnly = readU32FromChar(&argument); continue; }
2749 if (!strcmp(argument, "--memtest")) { memTestsOnly=1; continue; }
2750 if (!strcmp(argument, "--no-big-tests")) { bigTests=0; continue; }
2753 while (*argument!=0) {
2757 return FUZ_usage(programName);
2769 case 'p': /* pause at the end */
2775 argument++; maxDuration = 0;
2776 nbTests = (int)readU32FromChar(&argument);
2782 maxDuration = readU32FromChar(&argument);
2783 if (*argument=='s') argument++; /* seconds */
2784 if (*argument=='m') maxDuration *= 60, argument++; /* minutes */
2785 if (*argument=='n') argument++;
2791 seed = readU32FromChar(&argument);
2796 testNb = (int)readU32FromChar(&argument);
2799 case 'P': /* compressibility % */
2801 proba = (int)readU32FromChar(&argument);
2802 if (proba>100) proba = 100;
2806 return (FUZ_usage(programName), 1);
2807 } } } } /* for (argNb=1; argNb<argc; argNb++) */
2810 DISPLAY("Starting zstd tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION_STRING);
2813 time_t const t = time(NULL);
2814 U32 const h = XXH32(&t, sizeof(t), 1);
2818 DISPLAY("Seed = %u\n", (unsigned)seed);
2819 if (proba!=FUZ_compressibility_default) DISPLAY("Compressibility : %i%%\n", proba);
2822 g_displayLevel = MAX(3, g_displayLevel);
2823 return FUZ_mallocTests(seed, ((double)proba) / 100, memTestsOnly);
2826 if (nbTests < testNb) nbTests = testNb;
2829 result = basicUnitTests(0, ((double)proba) / 100); /* constant seed for predictability */
2831 result = fuzzerTests(seed, nbTests, testNb, maxDuration, ((double)proba) / 100, bigTests);
2834 DISPLAY("Press Enter \n");