]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/fuzzer.c
Import Zstd 1.4.4
[FreeBSD/FreeBSD.git] / tests / fuzzer.c
1 /*
2  * Copyright (c) 2015-present, Yann Collet, Facebook, Inc.
3  * All rights reserved.
4  *
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.
9  */
10
11
12 /*-************************************
13 *  Compiler specific
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 */
19 #endif
20
21
22 /*-************************************
23 *  Includes
24 **************************************/
25 #include <stdlib.h>       /* free */
26 #include <stdio.h>        /* fgets, sscanf */
27 #include <string.h>       /* strcmp */
28 #include <assert.h>
29 #define ZSTD_STATIC_LINKING_ONLY  /* ZSTD_compressContinue, ZSTD_compressBlock */
30 #include "fse.h"
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 */
37 #include "mem.h"
38 #define XXH_STATIC_LINKING_ONLY   /* XXH64_state_t */
39 #include "xxhash.h"       /* XXH64 */
40 #include "util.h"
41 #include "timefn.h"       /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */
42
43
44 /*-************************************
45 *  Constants
46 **************************************/
47 #define KB *(1U<<10)
48 #define MB *(1U<<20)
49 #define GB *(1U<<30)
50
51 static const int FUZ_compressibility_default = 50;
52 static const int nbTestsDefault = 30000;
53
54
55 /*-************************************
56 *  Display Macros
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;
61
62 static const U64 g_refreshRate = SEC_TO_MICRO / 6;
63 static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
64
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); } \
70     }
71
72
73 /*-*******************************************************
74 *  Compile time test
75 *********************************************************/
76 #undef MIN
77 #undef MAX
78 /* Declaring the function, to avoid -Wmissing-prototype */
79 void FUZ_bug976(void);
80 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);
84 }
85
86
87 /*-*******************************************************
88 *  Internal functions
89 *********************************************************/
90 #define MIN(a,b) ((a)<(b)?(a):(b))
91 #define MAX(a,b) ((a)>(b)?(a):(b))
92
93 #define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
94 static U32 FUZ_rand(U32* src)
95 {
96     static const U32 prime1 = 2654435761U;
97     static const U32 prime2 = 2246822519U;
98     U32 rand32 = *src;
99     rand32 *= prime1;
100     rand32 += prime2;
101     rand32  = FUZ_rotl32(rand32, 13);
102     *src = rand32;
103     return rand32 >> 5;
104 }
105
106 static U32 FUZ_highbit32(U32 v32)
107 {
108     unsigned nbBits = 0;
109     if (v32==0) return 0;
110     while (v32) v32 >>= 1, nbBits++;
111     return nbBits;
112 }
113
114
115 /*=============================================
116 *   Test macros
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));       \
123         exit(1);                                   \
124 }   }
125
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; }
130
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;                                       \
135     }                                                             \
136 }
137 #define CHECK_EQ(lhs, rhs) CHECK_OP(==, lhs, rhs)
138 #define CHECK_LT(lhs, rhs) CHECK_OP(<, lhs, rhs)
139
140
141 /*=============================================
142 *   Memory Tests
143 =============================================*/
144 #if defined(__APPLE__) && defined(__MACH__)
145
146 #include <malloc/malloc.h>    /* malloc_size */
147
148 typedef struct {
149     unsigned long long totalMalloc;
150     size_t currentMalloc;
151     size_t peakMalloc;
152     unsigned nbMalloc;
153     unsigned nbFree;
154 } mallocCounter_t;
155
156 static const mallocCounter_t INIT_MALLOC_COUNTER = { 0, 0, 0, 0, 0 };
157
158 static void* FUZ_mallocDebug(void* counter, size_t size)
159 {
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;
170     return ptr;
171 }
172
173 static void FUZ_freeDebug(void* counter, void* address)
174 {
175     mallocCounter_t* const mcPtr = (mallocCounter_t*)counter;
176     DISPLAYLEVEL(4, "freeing %u KB \n", (unsigned)(malloc_size(address) >> 10));
177     mcPtr->nbFree += 1;
178     mcPtr->currentMalloc -= malloc_size(address);  /* OS-X specific */
179     free(address);
180 }
181
182 static void FUZ_displayMallocStats(mallocCounter_t count)
183 {
184     DISPLAYLEVEL(3, "peak:%6u KB,  nbMallocs:%2u, total:%6u KB \n",
185         (unsigned)(count.peakMalloc >> 10),
186         count.nbMalloc,
187         (unsigned)(count.totalMalloc >> 10));
188 }
189
190 static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsigned part,
191                 void* inBuffer, size_t inSize, void* outBuffer, size_t outSize)
192 {
193     /* test only played in verbose mode, as they are long */
194     if (g_displayLevel<3) return 0;
195
196     /* Create compressible noise */
197     if (!inBuffer || !outBuffer) {
198         DISPLAY("Not enough memory, aborting\n");
199         exit(1);
200     }
201     RDG_genBuffer(inBuffer, inSize, compressibility, 0. /*auto*/, seed);
202
203     /* simple compression tests */
204     if (part <= 1)
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) );
211             ZSTD_freeCCtx(cctx);
212             DISPLAYLEVEL(3, "compressCCtx level %i : ", compressionLevel);
213             FUZ_displayMallocStats(malcount);
214     }   }
215
216     /* streaming compression tests */
217     if (part <= 2)
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);
231     }   }
232
233     /* advanced MT API test */
234     if (part <= 3)
235     {   int nbThreads;
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) );
245                 ZSTD_freeCCtx(cctx);
246                 DISPLAYLEVEL(3, "compress_generic,-T%i,end level %i : ",
247                                 nbThreads, compressionLevel);
248                 FUZ_displayMallocStats(malcount);
249     }   }   }
250
251     /* advanced MT streaming API test */
252     if (part <= 4)
253     {   int nbThreads;
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) ) {}
266                 ZSTD_freeCCtx(cctx);
267                 DISPLAYLEVEL(3, "compress_generic,-T%i,continue level %i : ",
268                                 nbThreads, compressionLevel);
269                 FUZ_displayMallocStats(malcount);
270     }   }   }
271
272     return 0;
273 }
274
275 static int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part)
276 {
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);
281     int result;
282
283     /* Create compressible noise */
284     if (!inBuffer || !outBuffer) {
285         DISPLAY("Not enough memory, aborting \n");
286         exit(1);
287     }
288
289     result = FUZ_mallocTests_internal(seed, compressibility, part,
290                     inBuffer, inSize, outBuffer, outSize);
291
292     free(inBuffer);
293     free(outBuffer);
294     return result;
295 }
296
297 #else
298
299 static int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part)
300 {
301     (void)seed; (void)compressibility; (void)part;
302     return 0;
303 }
304
305 #endif
306
307 static void FUZ_decodeSequences(BYTE* dst, ZSTD_Sequence* seqs, size_t seqsSize, BYTE* src, size_t size)
308 {
309     size_t i;
310     size_t j;
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);
314
315         memcpy(dst, src, seqs[i].litLength);
316         dst += seqs[i].litLength;
317         src += seqs[i].litLength;
318         size -= seqs[i].litLength;
319
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;
325     }
326     memcpy(dst, src, size);
327 }
328
329 /*=============================================
330 *   Unit tests
331 =============================================*/
332
333 static int basicUnitTests(U32 const seed, double compressibility)
334 {
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);
340     int testResult = 0;
341     unsigned testNb=0;
342     size_t cSize;
343
344     /* Create compressible noise */
345     if (!CNBuffer || !compressedBuffer || !decodedBuffer) {
346         DISPLAY("Not enough memory, aborting\n");
347         testResult = 1;
348         goto _end;
349     }
350     RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed);
351
352     /* Basic tests */
353     DISPLAYLEVEL(3, "test%3u : ZSTD_getErrorName : ", testNb++);
354     {   const char* errorString = ZSTD_getErrorName(0);
355         DISPLAYLEVEL(3, "OK : %s \n", errorString);
356     }
357
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);
361     }
362
363     DISPLAYLEVEL(3, "test%3u : min compression level : ", testNb++);
364     {   int const mcl = ZSTD_minCLevel();
365         DISPLAYLEVEL(3, "%i (OK) \n", mcl);
366     }
367
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);
375
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);
379         }
380         ZSTD_freeCCtx(cctx);
381     }
382
383     DISPLAYLEVEL(3, "test%3i : decompress skippable frame -8 size : ", testNb++);
384     {
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;
388     }
389     DISPLAYLEVEL(3, "OK \n");
390
391
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;
395     }
396     DISPLAYLEVEL(3, "OK \n");
397
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;
401     }
402     DISPLAYLEVEL(3, "OK \n");
403
404     DISPLAYLEVEL(3, "test%3i : tight ZSTD_decompressBound test : ", testNb++);
405     {
406         unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize);
407         if (bound != CNBuffSize) goto _output_error;
408     }
409     DISPLAYLEVEL(3, "OK \n");
410
411     DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with invalid srcSize : ", testNb++);
412     {
413         unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize - 1);
414         if (bound != ZSTD_CONTENTSIZE_ERROR) goto _output_error;
415     }
416     DISPLAYLEVEL(3, "OK \n");
417
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");
422
423     DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
424     {   size_t u;
425         for (u=0; u<CNBuffSize; u++) {
426             if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;
427     }   }
428     DISPLAYLEVEL(3, "OK \n");
429
430
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,
436                                                     NULL, 0);
437             if (r != CNBuffSize) goto _output_error;
438         }
439         ZSTD_freeDCtx(dctx);
440     }
441     DISPLAYLEVEL(3, "OK \n");
442
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,
448                                                     NULL);
449             if (r != CNBuffSize) goto _output_error;
450         }
451         ZSTD_freeDCtx(dctx);
452     }
453     DISPLAYLEVEL(3, "OK \n");
454
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");
460
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");
466
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");
472
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) );
480         ZSTD_freeCCtx(cctx);
481     }
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;
486     }
487     {   /* ensure CNBuffSize <= decompressBound */
488         unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, compressedBufferSize);
489         if (CNBuffSize > bound) goto _output_error;
490     }
491     DISPLAYLEVEL(3, "OK \n");
492
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;
498         ZSTD_freeCCtx(cctx);
499         cSize = r;
500     }
501     DISPLAYLEVEL(3, "OK \n");
502
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;
507     }
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;
513         output.pos = 0;
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) );
517         ZSTD_freeCCtx(cctx);
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;
522         }
523         /* streaming decompression */
524         {   ZSTD_DCtx* const dstream = ZSTD_createDStream();
525             ZSTD_inBuffer dinput;
526             ZSTD_outBuffer doutput;
527             size_t ipos;
528             if (dstream==NULL) goto _output_error;
529             dinput.src = compressedBuffer;
530             dinput.size = 0;
531             dinput.pos = 0;
532             doutput.dst = NULL;
533             doutput.size = 0;
534             doutput.pos = 0;
535             CHECK_Z ( ZSTD_initDStream(dstream) );
536             for (ipos=1; ipos<=output.pos; ipos++) {
537                 dinput.size = ipos;
538                 CHECK_Z ( ZSTD_decompressStream(dstream, &doutput, &dinput) );
539             }
540             if (doutput.pos != 0) goto _output_error;
541             ZSTD_freeDStream(dstream);
542         }
543     }
544     DISPLAYLEVEL(3, "OK \n");
545
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 */
552
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 */
558         }
559         ZSTD_freeCCtx(cctx);
560     }
561     DISPLAYLEVEL(3, "OK \n");
562
563     DISPLAYLEVEL(3, "test%3d : re-using a CCtx should compress the same : ", testNb++);
564     {   size_t const sampleSize = 30;
565         int i;
566         for (i=0; i<20; i++)
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();
571             size_t size1, size2;
572             DISPLAYLEVEL(5, "l%i ", i);
573             size1 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i);
574             CHECK_Z(size1);
575
576             size2 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i);
577             CHECK_Z(size2);
578             CHECK_EQ(size1, size2);
579
580             CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, i) );
581             size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize);
582             CHECK_Z(size2);
583             CHECK_EQ(size1, size2);
584
585             size2 = ZSTD_compress2(cctx, compressedBuffer, ZSTD_compressBound(sampleSize) - 1, CNBuffer, sampleSize);  /* force streaming, as output buffer is not large enough to guarantee success */
586             CHECK_Z(size2);
587             CHECK_EQ(size1, size2);
588
589             {   ZSTD_inBuffer inb;
590                 ZSTD_outBuffer outb;
591                 inb.src = CNBuffer;
592                 inb.pos = 0;
593                 inb.size = sampleSize;
594                 outb.dst = compressedBuffer;
595                 outb.pos = 0;
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);
600             }
601
602             ZSTD_freeCCtx(cctx);
603         }
604     }
605     DISPLAYLEVEL(3, "OK \n");
606
607     DISPLAYLEVEL(3, "test%3d : btultra2 & 1st block : ", testNb++);
608     {   size_t const sampleSize = 1024;
609         ZSTD_CCtx* const cctx = ZSTD_createCCtx();
610         ZSTD_inBuffer inb;
611         ZSTD_outBuffer outb;
612         inb.src = CNBuffer;
613         inb.pos = 0;
614         inb.size = 0;
615         outb.dst = compressedBuffer;
616         outb.pos = 0;
617         outb.size = compressedBufferSize;
618         CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, ZSTD_maxCLevel()) );
619
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 */
624
625         CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(cctx, sampleSize) );
626         inb.size = 4;   /* too small size : compression will be skipped */
627         inb.pos = 0;
628         CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) );
629         assert(inb.pos == inb.size);
630
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);
634
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);
638
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);
643         ZSTD_freeCCtx(cctx);
644     }
645     DISPLAYLEVEL(3, "OK \n");
646
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};
651         int value;
652
653         CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
654         CHECK_EQ(value, 3);
655         CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
656         CHECK_EQ(value, 0);
657         CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, ZSTD_HASHLOG_MIN));
658         CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
659         CHECK_EQ(value, 3);
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));
664         CHECK_EQ(value, 7);
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));
670         CHECK_EQ(value, 7);
671         CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
672         CHECK_EQ(value, ZSTD_HASHLOG_MIN);
673         /* Reset the CCtx */
674         ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
675         CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));
676         CHECK_EQ(value, 7);
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));
682         CHECK_EQ(value, 3);
683         CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));
684         CHECK_EQ(value, 0);
685
686         ZSTD_freeCCtx(cctx);
687     }
688     DISPLAYLEVEL(3, "OK \n");
689
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 */
695         size_t cnb;
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) );
703         }
704         ZSTD_freeCCtx(cctx);
705     }
706     DISPLAYLEVEL(3, "OK \n");
707
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 */
722                 }
723                 ZSTD_freeCCtx(smallCCtx);
724             }
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 */
728                 unsigned u;
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 */
732                 }
733                 DISPLAYLEVEL(5, "size down after %u attempts : ", u);
734                 if (u==maxNbAttempts) goto _output_error;   /* no sizedown happened */
735             }
736         }
737         ZSTD_freeCCtx(largeCCtx);
738     }
739     DISPLAYLEVEL(3, "OK \n");
740
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");
752             testResult = 1;
753             goto _end;
754         }
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");
759
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");
764
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);
771
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");
778
779             DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
780             {   size_t u;
781                 for (u=0; u<CNBuffSize; u++) {
782                     if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u])
783                         goto _output_error;
784             }   }
785             DISPLAYLEVEL(3, "OK \n");
786
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");
791
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");
795
796             DISPLAYLEVEL(3, "test%3i : init CStream for small level %u : ", testNb++, 1);
797             CHECK( ZSTD_initCStream(staticCCtx, 1) );
798             DISPLAYLEVEL(3, "OK \n");
799
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");
804
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;
812             }
813             DISPLAYLEVEL(3, "OK \n");
814         }
815         free(staticCCtxBuffer);
816         free(staticDCtxBuffer);
817     }
818
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);
824
825         if (!(0 < cctxSizeN1 && cctxSizeN1 <= cctxSizeP1)) goto _output_error;
826         if (!(0 < cstreamSizeN1 && cstreamSizeN1 <= cstreamSizeP1)) goto _output_error;
827     }
828     DISPLAYLEVEL(3, "OK \n");
829
830
831     /* ZSTDMT simple MT compression test */
832     DISPLAYLEVEL(3, "test%3i : create ZSTDMT CCtx : ", testNb++);
833     {   ZSTDMT_CCtx* const mtctx = ZSTDMT_createCCtx(2);
834         if (mtctx==NULL) {
835             DISPLAY("mtctx : not enough memory, aborting \n");
836             testResult = 1;
837             goto _end;
838         }
839         DISPLAYLEVEL(3, "OK \n");
840
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,
845                                 1) );
846         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
847
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);
852                 goto _output_error;
853         }   }
854         DISPLAYLEVEL(3, "OK \n");
855
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");
860
861         DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
862         {   size_t u;
863             for (u=0; u<CNBuffSize; u++) {
864                 if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;
865         }   }
866         DISPLAYLEVEL(3, "OK \n");
867
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*/) );
876         }
877         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
878
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");
883
884         ZSTDMT_freeCCtx(mtctx);
885     }
886
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);
893         CHECK(cSize1);
894         CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_literalCompressionMode, ZSTD_lcm_uncompressed) );
895         cSize2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
896         CHECK(cSize2);
897         CHECK_LT(cSize1, cSize2);
898         ZSTD_freeCCtx(cctx);
899     }
900     DISPLAYLEVEL(3, "OK \n");
901
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.
906          */
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) );
911         ZSTD_freeCCtx(cctx);
912     }
913     DISPLAYLEVEL(3, "OK \n");
914
915     DISPLAYLEVEL(3, "test%3i : setting multithreaded parameters : ", testNb++)
916     {   ZSTD_CCtx_params* params = ZSTD_createCCtxParams();
917         int value;
918         /* Check that the overlap log and job size are unset. */
919         CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
920         CHECK_EQ(value, 0);
921         CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
922         CHECK_EQ(value, 0);
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) );
927         CHECK_EQ(value, 5);
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) );
933         CHECK_EQ(value, 5);
934         CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
935         CHECK_EQ(value, 2 MB);
936         ZSTD_freeCCtxParams(params);
937
938     }
939     DISPLAYLEVEL(3, "OK \n");
940
941     /* Simple API multiframe test */
942     DISPLAYLEVEL(3, "test%3i : compress multiple frames : ", testNb++);
943     {   size_t off = 0;
944         int i;
945         int const segs = 4;
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,
952                             5) );
953             off += r;
954             if (i == segs/2) {
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;
960             }
961         }
962         cSize = off;
963     }
964     DISPLAYLEVEL(3, "OK \n");
965
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");
970
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");
975
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");
980
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");
984
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);
991
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");
996
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");
1001
1002         DISPLAYLEVEL(3, "test%3i : compress with flat dictionary : ", testNb++);
1003         cSize = 0;
1004         CHECKPLUS(r, ZSTD_compressEnd(ctxOrig,
1005                                       compressedBuffer, compressedBufferSize,
1006                          (const char*)CNBuffer + dictSize, CNBuffSize - dictSize),
1007                   cSize += r);
1008         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1009
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");
1017
1018         DISPLAYLEVEL(3, "test%3i : compress with duplicated context : ", testNb++);
1019         {   size_t const cSizeOrig = cSize;
1020             cSize = 0;
1021             CHECKPLUS(r, ZSTD_compressEnd(ctxDuplicated,
1022                                     compressedBuffer, compressedBufferSize,
1023                        (const char*)CNBuffer + dictSize, CNBuffSize - dictSize),
1024                       cSize += r);
1025             if (cSize != cSizeOrig) goto _output_error;   /* should be identical ==> same size */
1026         }
1027         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1028
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");
1036
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);
1043         }
1044
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;
1052             }
1053             free(ddictBuffer);
1054             DISPLAYLEVEL(3, "OK (size of static DDict : %u) \n", (unsigned)ddictBufferSize);
1055         }
1056
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) );
1062             }
1063             CHECK( ZSTD_copyCCtx(ctxDuplicated, ctxOrig, testSize) );
1064
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;
1070         }   }
1071         DISPLAYLEVEL(3, "OK \n");
1072
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,
1082                                                        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,
1087                                                        2750, 2750, 2750 };
1088             int l = 1;
1089             int const maxLevel = ZSTD_maxCLevel();
1090
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));
1095
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]);
1102                     goto _output_error;
1103                 }
1104                 DISPLAYLEVEL(4, "level %i : max expected %u >= reached %u \n",
1105                                 l, (unsigned)target_nodict_cSize[l], (unsigned)nodict_cSize);
1106             }
1107             for ( l=1 ; l <= maxLevel; l++) {
1108                 size_t const wdict_cSize = ZSTD_compress_usingDict(ctxOrig,
1109                                                           compressedBuffer, compressedBufferSize,
1110                                                           contentStart, contentSize,
1111                                                           dict, flatdictSize,
1112                                                           l);
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]);
1116                     goto _output_error;
1117                 }
1118                 DISPLAYLEVEL(4, "level %i with dictionary : max expected %u >= reached %u \n",
1119                                 l, (unsigned)target_wdict_cSize[l], (unsigned)wdict_cSize);
1120             }
1121
1122             DISPLAYLEVEL(4, "compression efficiency tests OK \n");
1123         }
1124
1125         ZSTD_freeCCtx(ctxOrig);
1126         ZSTD_freeCCtx(ctxDuplicated);
1127         ZSTD_freeDCtx(dctx);
1128     }
1129
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));
1138         size_t dictSize;
1139         U32 dictID;
1140
1141         if (dictBuffer==NULL || samplesSizes==NULL) {
1142             free(dictBuffer);
1143             free(samplesSizes);
1144             goto _output_error;
1145         }
1146
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);
1155         }
1156
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);
1163
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 */
1173                 &coverParams);
1174             if (ZDICT_isError(dictSize)) goto _output_error;
1175         }
1176         DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1177
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 */
1189                 &coverParams);
1190             if (ZDICT_isError(dictSize)) goto _output_error;
1191         }
1192         DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1193
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,
1203                 &fastCoverParams);
1204             if (ZDICT_isError(dictSize)) goto _output_error;
1205         }
1206         DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1207
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,
1219                 &fastCoverParams);
1220             if (ZDICT_isError(dictSize)) goto _output_error;
1221         }
1222         DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1223
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);
1228
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);
1235
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 */
1239         }
1240         DISPLAYLEVEL(3, "OK \n");
1241
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 */
1245         }
1246         DISPLAYLEVEL(3, "OK \n");
1247
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);
1256         }
1257         DISPLAYLEVEL(3, "OK \n");
1258
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);
1263         }
1264
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;
1276         }
1277         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1278
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 */
1282         }
1283         DISPLAYLEVEL(3, "OK \n");
1284
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);
1293         }
1294         DISPLAYLEVEL(3, "OK \n");
1295
1296         DISPLAYLEVEL(3, "test%3i : compress with static CDict : ", testNb++);
1297         {   int const maxLevel = ZSTD_maxCLevel();
1298             int level;
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,
1308                                                 cParams);
1309                     if (cdict == NULL) {
1310                         DISPLAY("ZSTD_initStaticCDict failed ");
1311                         goto _output_error;
1312                     }
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 ");
1318                         goto _output_error;
1319                 }   }
1320                 free(cdictBuffer);
1321         }   }
1322         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1323
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,
1332                                                       cdict, fParams);
1333             ZSTD_freeCDict(cdict);
1334             if (ZSTD_isError(cSize)) goto _output_error;
1335         }
1336         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1337
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;
1341         }
1342         DISPLAYLEVEL(3, "OK (unknown)\n");
1343
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);
1353         }
1354         DISPLAYLEVEL(3, "OK \n");
1355
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;
1363         }
1364         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100);
1365
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);
1374         }
1375         DISPLAYLEVEL(3, "OK \n");
1376
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)
1384                     goto _output_error;
1385             }
1386             ZSTD_freeDCtx(dctx);
1387         }
1388         DISPLAYLEVEL(3, "OK \n");
1389
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);
1395         }
1396         DISPLAYLEVEL(3, "OK \n");
1397
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);
1403         }
1404         DISPLAYLEVEL(3, "OK \n");
1405
1406         DISPLAYLEVEL(3, "test%3i : Loading rawContent starting with dict header w/ ZSTD_dct_auto should fail : ", testNb++);
1407         {
1408             size_t ret;
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;
1416             }
1417         }
1418         DISPLAYLEVEL(3, "OK \n");
1419
1420         DISPLAYLEVEL(3, "test%3i : Loading rawContent starting with dict header w/ ZSTD_dct_rawContent should pass : ", testNb++);
1421         {
1422             size_t ret;
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;
1429         }
1430         DISPLAYLEVEL(3, "OK \n");
1431
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);
1440         }
1441         DISPLAYLEVEL(3, "OK \n");
1442
1443         DISPLAYLEVEL(3, "test%3i : Loading dictionary before setting parameters is the same as loading after : ", testNb++);
1444         {
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;
1451
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;
1457
1458             if (size1 != size2) goto _output_error;
1459         }
1460         DISPLAYLEVEL(3, "OK \n");
1461
1462         DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the prefix : ", testNb++);
1463         {
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)) );
1467         }
1468         DISPLAYLEVEL(3, "OK \n");
1469
1470         DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the cdict : ", testNb++);
1471         {
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);
1477         }
1478         DISPLAYLEVEL(3, "OK \n");
1479
1480         DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the prefix : ", testNb++);
1481         {
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);
1487         }
1488         DISPLAYLEVEL(3, "OK \n");
1489
1490         DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the dictionary : ", testNb++);
1491         {
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);
1497         }
1498         DISPLAYLEVEL(3, "OK \n");
1499
1500         DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the dictionary : ", testNb++);
1501         {
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)) );
1505         }
1506         DISPLAYLEVEL(3, "OK \n");
1507
1508         DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the cdict : ", testNb++);
1509         {
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);
1515         }
1516         DISPLAYLEVEL(3, "OK \n");
1517
1518         DISPLAYLEVEL(3, "test%3i : Loaded dictionary persists across reset session : ", testNb++);
1519         {
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;
1525
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;
1529
1530             if (size1 != size2) goto _output_error;
1531         }
1532         DISPLAYLEVEL(3, "OK \n");
1533
1534         DISPLAYLEVEL(3, "test%3i : Loaded dictionary is cleared after resetting parameters : ", testNb++);
1535         {
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;
1541
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;
1545
1546             if (size1 == size2) goto _output_error;
1547         }
1548         DISPLAYLEVEL(3, "OK \n");
1549
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));
1553         CHECK_Z(cSize);
1554         DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with dictionary : ", testNb++);
1555         {
1556             ZSTD_DCtx* dctx = ZSTD_createDCtx();
1557             size_t ret;
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);
1573         }
1574         DISPLAYLEVEL(3, "OK \n");
1575
1576         DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with ddict : ", testNb++);
1577         {
1578             ZSTD_DCtx* dctx = ZSTD_createDCtx();
1579             ZSTD_DDict* ddict = ZSTD_createDDict(dictBuffer, dictSize);
1580             size_t ret;
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);
1593         }
1594         DISPLAYLEVEL(3, "OK \n");
1595
1596         DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with prefix : ", testNb++);
1597         {
1598             ZSTD_DCtx* dctx = ZSTD_createDCtx();
1599             size_t ret;
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);
1608         }
1609         DISPLAYLEVEL(3, "OK \n");
1610
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 */
1617         {
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)) {
1624                 ++dictPtr;
1625             }
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);
1632         }
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.
1637          */
1638         {   size_t dSize;
1639             BYTE data[1024];
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);
1655         }
1656         DISPLAYLEVEL(3, "OK \n");
1657
1658         ZSTD_freeCCtx(cctx);
1659         free(dictBuffer);
1660         free(samplesSizes);
1661     }
1662
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));
1672         U32 seed32 = seed;
1673         ZDICT_cover_params_t params;
1674         U32 dictID;
1675
1676         if (dictBuffer==NULL || samplesSizes==NULL) {
1677             free(dictBuffer);
1678             free(samplesSizes);
1679             goto _output_error;
1680         }
1681
1682         DISPLAYLEVEL(3, "test%3i : ZDICT_trainFromBuffer_cover : ", testNb++);
1683         { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
1684         memset(&params, 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,
1689                                                params);
1690         if (ZDICT_isError(dictSize)) goto _output_error;
1691         DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
1692
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);
1697
1698         DISPLAYLEVEL(3, "test%3i : ZDICT_optimizeTrainFromBuffer_cover : ", testNb++);
1699         memset(&params, 0, sizeof(params));
1700         params.steps = 4;
1701         optDictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, optDictSize,
1702                                                           CNBuffer, samplesSizes,
1703                                                           nbSamples / 4, &params);
1704         if (ZDICT_isError(optDictSize)) goto _output_error;
1705         DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)optDictSize);
1706
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);
1711
1712         ZSTD_freeCCtx(cctx);
1713         free(dictBuffer);
1714         free(samplesSizes);
1715     }
1716
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");
1723
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");
1729
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));
1742         }
1743         ZSTD_freeCCtx(cctx);
1744     }
1745
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;
1751
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,
1756                                         CNBuffer, srcSize,
1757                                         NULL, 0,
1758                                         params);
1759             if (ZSTD_isError(cSize_1pass)) goto _output_error;
1760
1761             CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) );
1762             {   size_t const compressionResult = ZSTD_compress2(cctx,
1763                                     compressedBuffer, compressedBufferSize,
1764                                     CNBuffer, srcSize);
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;
1768         }   }
1769         ZSTD_freeCCtx(cctx);
1770     }
1771     DISPLAYLEVEL(3, "OK \n");
1772
1773     /* parameters order test */
1774     {   size_t const inputSize = CNBuffSize / 2;
1775         U64 xxh64;
1776
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);
1789             }
1790             DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)cSize);
1791             ZSTD_freeCCtx(cctx);
1792         }
1793
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);
1802                 CHECK(result);
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);
1806             }
1807             ZSTD_freeCCtx(cctx);
1808         }
1809     }
1810
1811     /* advanced parameters for decompression */
1812     {   ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1813         assert(dctx != NULL);
1814
1815         DISPLAYLEVEL(3, "test%3i : get dParameter bounds ", testNb++);
1816         {   ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1817             CHECK(bounds.error);
1818         }
1819         DISPLAYLEVEL(3, "OK \n");
1820
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;
1824         }
1825         {   ZSTD_bounds const bounds = ZSTD_dParam_getBounds((ZSTD_dParameter)999998);
1826             if (!ZSTD_isError(bounds.error)) goto _output_error;
1827         }
1828         DISPLAYLEVEL(3, "OK \n");
1829
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;
1833         }
1834         {   size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (ZSTD_format_e)888);
1835             if (!ZSTD_isError(sr)) goto _output_error;
1836         }
1837         DISPLAYLEVEL(3, "OK \n");
1838
1839         ZSTD_freeDCtx(dctx);
1840     }
1841
1842
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);
1848
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;
1857             cSize = out.pos;
1858         }
1859         DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)cSize);
1860
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));
1865         }
1866
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;
1873         }
1874         /* one shot */
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, ");
1878         }
1879         /* streaming */
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);
1887         }
1888
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;
1897             cSize = out.pos;
1898         }
1899         DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)0, (unsigned)cSize);
1900
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) );
1904         /* one shot */
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, ");
1908         }
1909         /* streaming */
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);
1917         }
1918
1919         ZSTD_freeCCtx(cctx);
1920         ZSTD_freeDCtx(dctx);
1921     }
1922
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 */
1928         size_t cSize2;
1929         assert(cctx != NULL); assert(dctx != NULL);
1930
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");
1937
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");
1943
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 */
1949             U64 compressed = 0;
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;
1955         }   }
1956         DISPLAYLEVEL(3, "OK \n");
1957
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");
1969
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);
1975                 goto _output_error;
1976         }   }
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);
1982                 goto _output_error;
1983         }   }
1984         assert(memcpy((char*)CNBuffer+dictSize, decodedBuffer, blockSize*3));  /* ensure regenerated content is identical to origin */
1985         DISPLAYLEVEL(3, "OK \n");
1986
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);
1993         }
1994         DISPLAYLEVEL(3, "OK \n");
1995
1996         ZSTD_freeCCtx(cctx);
1997         ZSTD_freeDCtx(dctx);
1998     }
1999
2000     /* long rle test */
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");
2013     }
2014
2015     DISPLAYLEVEL(3, "test%3i : ZSTD_getSequences decode from sequences test : ", testNb++);
2016     {
2017         size_t srcSize = 100 KB;
2018         BYTE* src = (BYTE*)CNBuffer;
2019         BYTE* decoded = (BYTE*)compressedBuffer;
2020
2021         ZSTD_CCtx* cctx = ZSTD_createCCtx();
2022         ZSTD_Sequence* seqs = (ZSTD_Sequence*)malloc(srcSize * sizeof(ZSTD_Sequence));
2023         size_t seqsSize;
2024
2025         if (seqs == NULL) goto _output_error;
2026         assert(cctx != NULL);
2027
2028         /* Populate src with random data */
2029         RDG_genBuffer(CNBuffer, srcSize, compressibility, 0., seed);
2030
2031         /* get the sequences */
2032         seqsSize = ZSTD_getSequences(cctx, seqs, srcSize, src, srcSize);
2033
2034         /* "decode" and compare the sequences */
2035         FUZ_decodeSequences(decoded, seqs, seqsSize, src, srcSize);
2036         assert(!memcmp(CNBuffer, compressedBuffer, srcSize));
2037
2038         ZSTD_freeCCtx(cctx);
2039         free(seqs);
2040     }
2041
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);
2048
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");
2053
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);
2060
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");
2065
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];
2073         U32 rSeed = 1;
2074
2075         /* create batch of 3-bytes sequences */
2076         {   int i;
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);
2081         }   }
2082
2083         /* randomly fills CNBuffer with prepared 3-bytes sequences */
2084         {   int i;
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];
2090     }   }   }
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);
2095         size_t nbSeq = 1;
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. */
2099           if (nbSeq < 100) {
2100             ++nbSeq;
2101           } else {
2102             nbSeq += (nbSeq >> 2);
2103           }
2104         }
2105         ZSTD_freeCCtx(cctx);
2106     }
2107     DISPLAYLEVEL(3, "OK \n");
2108
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);
2113
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");
2118
2119
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);
2124         size_t size = 1;
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. */
2128           if (size < 100) {
2129             ++size;
2130           } else {
2131             size += (size >> 2);
2132           }
2133         }
2134         ZSTD_freeCCtx(cctx);
2135     }
2136     DISPLAYLEVEL(3, "OK \n");
2137
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 */
2151         {   U32 u;
2152             for (u = 0; u < CNBuffSize; ++u) {
2153               ((BYTE*)CNBuffer)[u] = 255 - ((BYTE*)CNBuffer)[u];
2154             }
2155         }
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));
2163             free(outputBuffer);
2164             ZSTD_freeCCtx(cctx);
2165         }
2166
2167         free(dictBuffer);
2168         free(samplesSizes);
2169     }
2170     DISPLAYLEVEL(3, "OK \n");
2171
2172
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");
2179
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");
2189
2190     DISPLAYLEVEL(3, "test%3i : testing ZSTD dictionary sizes : ", testNb++);
2191     RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed);
2192     {
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;
2199
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));
2204
2205         if (lgHeader.windowSize != smHeader.windowSize) goto _output_error;
2206
2207         ZSTD_freeCDict(smCDict);
2208         ZSTD_freeCDict(lgCDict);
2209         ZSTD_freeCCtx(cctx);
2210     }
2211     DISPLAYLEVEL(3, "OK \n");
2212
2213     DISPLAYLEVEL(3, "test%3i : testing FSE_normalizeCount() PR#1255: ", testNb++);
2214     {
2215         short norm[32];
2216         unsigned count[32];
2217         unsigned const tableLog = 5;
2218         size_t const nbSeq = 32;
2219         unsigned const maxSymbolValue = 31;
2220         size_t i;
2221
2222         for (i = 0; i < 32; ++i)
2223             count[i] = 1;
2224         /* Calling FSE_normalizeCount() on a uniform distribution should not
2225          * cause a division by zero.
2226          */
2227         FSE_normalizeCount(norm, tableLog, count, nbSeq, maxSymbolValue);
2228     }
2229     DISPLAYLEVEL(3, "OK \n");
2230
2231     DISPLAYLEVEL(3, "test%3i : table cleanliness through index reduction : ", testNb++);
2232     {
2233         int cLevel;
2234         size_t approxIndex = 0;
2235         size_t maxIndex = ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX)); /* ZSTD_CURRENT_MAX from zstd_compress_internal.h */
2236
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);
2242
2243         /* bump the indices so the following compressions happen at high
2244          * indices. */
2245         {
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);
2254                 in.pos = 0;
2255                 out.pos = 0;
2256             }
2257             CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
2258         }
2259
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;
2269         }
2270
2271         /* now crank the indices so we overflow */
2272         {
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);
2281                 in.pos = 0;
2282                 out.pos = 0;
2283             }
2284             CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
2285         }
2286
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;
2297         }
2298
2299         ZSTD_freeCCtx(cctx);
2300         free(staticCCtxBuffer);
2301     }
2302     DISPLAYLEVEL(3, "OK \n");
2303
2304 _end:
2305     free(CNBuffer);
2306     free(compressedBuffer);
2307     free(decodedBuffer);
2308     return testResult;
2309
2310 _output_error:
2311     testResult = 1;
2312     DISPLAY("Error detected in Unit tests ! \n");
2313     goto _end;
2314 }
2315
2316
2317 static size_t findDiff(const void* buf1, const void* buf2, size_t max)
2318 {
2319     const BYTE* b1 = (const BYTE*)buf1;
2320     const BYTE* b2 = (const BYTE*)buf2;
2321     size_t u;
2322     for (u=0; u<max; u++) {
2323         if (b1[u] != b2[u]) break;
2324     }
2325     return u;
2326 }
2327
2328
2329 static ZSTD_parameters FUZ_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams)
2330 {
2331     ZSTD_parameters params;
2332     params.cParams = cParams;
2333     params.fParams = fParams;
2334     return params;
2335 }
2336
2337 static size_t FUZ_rLogLength(U32* seed, U32 logLength)
2338 {
2339     size_t const lengthMask = ((size_t)1 << logLength) - 1;
2340     return (lengthMask+1) + (FUZ_rand(seed) & lengthMask);
2341 }
2342
2343 static size_t FUZ_randomLength(U32* seed, U32 maxLog)
2344 {
2345     U32 const logLength = FUZ_rand(seed) % maxLog;
2346     return FUZ_rLogLength(seed, logLength);
2347 }
2348
2349 #undef CHECK
2350 #define CHECK(cond, ...) {                                    \
2351     if (cond) {                                               \
2352         DISPLAY("Error => ");                                 \
2353         DISPLAY(__VA_ARGS__);                                 \
2354         DISPLAY(" (seed %u, test nb %u)  \n", (unsigned)seed, testNb);  \
2355         goto _output_error;                                   \
2356 }   }
2357
2358 #undef CHECK_Z
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;                                   \
2366 }   }
2367
2368
2369 static int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, U32 const maxDurationS, double compressibility, int bigTests)
2370 {
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();
2383     U32 result = 0;
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;
2389
2390     /* allocation */
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");
2399
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 */
2406
2407     /* catch up testNb */
2408     for (testNb=1; testNb < startTest; testNb++) FUZ_rand(&coreSeed);
2409
2410     /* main test loop */
2411     for ( ; (testNb <= nbTests) || (UTIL_clockSpanMicro(startClock) < maxClockSpan); testNb++ ) {
2412         BYTE* srcBuffer;   /* jumping pointer */
2413         U32 lseed;
2414         size_t sampleSize, maxTestSize, totalTestSize;
2415         size_t cSize, totalCSize, totalGenSize;
2416         U64 crcOrig;
2417         BYTE* sampleBuffer;
2418         const BYTE* dict;
2419         size_t dictSize;
2420
2421         /* notification */
2422         if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u    ", testNb, nbTests); }
2423         else { DISPLAYUPDATE(2, "\r%6u          ", testNb); }
2424
2425         FUZ_rand(&coreSeed);
2426         { U32 const prime1 = 2654435761U; lseed = coreSeed ^ prime1; }
2427
2428         /* srcBuffer selection [0-4] */
2429         {   U32 buffNb = FUZ_rand(&lseed) & 0x7F;
2430             if (buffNb & 7) buffNb=2;   /* most common : compressible (P) */
2431             else {
2432                 buffNb >>= 3;
2433                 if (buffNb & 7) {
2434                     const U32 tnb[2] = { 1, 3 };   /* barely/highly compressible */
2435                     buffNb = tnb[buffNb >> 3];
2436                 } else {
2437                     const U32 tnb[2] = { 0, 4 };   /* not compressible / sparse */
2438                     buffNb = tnb[buffNb >> 3];
2439             }   }
2440             srcBuffer = cNoiseBuffer[buffNb];
2441         }
2442
2443         /* select src segment */
2444         sampleSize = FUZ_randomLength(&lseed, maxSampleLog);
2445
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);
2452
2453         /* compression tests */
2454         {   int const cLevelPositive =
2455                     ( FUZ_rand(&lseed) %
2456                      (ZSTD_maxCLevel() - (FUZ_highbit32((U32)sampleSize) / cLevelLimiter)) )
2457                     + 1;
2458             int const cLevel = ((FUZ_rand(&lseed) & 15) == 3) ?
2459                              - (int)((FUZ_rand(&lseed) & 7) + 1) :   /* test negative cLevel */
2460                              cLevelPositive;
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));
2464
2465             /* compression failure test : too small dest buffer */
2466             assert(cSize > 3);
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); }
2477         }   }
2478
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");
2483         }
2484
2485         /* Decompressed size test */
2486         {   unsigned long long const rSize = ZSTD_findDecompressedSize(cBuffer, cSize);
2487             CHECK(rSize != sampleSize, "decompressed size incorrect");
2488         }
2489
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);
2497         }   }
2498
2499         free(sampleBuffer);   /* no longer useful after this point */
2500
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);
2511         }
2512
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");
2523         }
2524
2525         /* noisy src decompression test */
2526         if (cSize > 6) {
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) */
2530                 for (;;) {
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;
2535                         pos += skipLength;
2536                     }
2537                     if (pos >= cSize) break;
2538                     /* add noise */
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);
2546                         pos += noiseLength;
2547             }   }   }
2548
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);
2557                 }
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 */
2561
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) %
2567                                 (ZSTD_maxCLevel() -
2568                                  (MAX(testLog, dictLog) / cLevelLimiter))) +
2569                                1;
2570             maxTestSize = FUZ_rLogLength(&lseed, testLog);
2571             if (maxTestSize >= dstBufferSize) maxTestSize = dstBufferSize-1;
2572
2573             dictSize = FUZ_rLogLength(&lseed, dictLog);   /* needed also for decompression */
2574             dict = srcBuffer + (FUZ_rand(&lseed) % (srcBufferSize - dictSize));
2575
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);
2578
2579             if (FUZ_rand(&lseed) & 0xF) {
2580                 CHECK_Z ( ZSTD_compressBegin_usingDict(refCtx, dict, dictSize, cLevel) );
2581             } else {
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) );
2588             }
2589             CHECK_Z( ZSTD_copyCCtx(ctx, refCtx, 0) );
2590         }
2591
2592         {   U32 const nbChunks = (FUZ_rand(&lseed) & 127) + 2;
2593             U32 n;
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);
2599
2600                 if (cBufferSize-cSize < ZSTD_compressBound(segmentSize)) break;   /* avoid invalid dstBufferTooSmall */
2601                 if (totalTestSize+segmentSize > maxTestSize) break;
2602
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;
2606                 }
2607                 XXH64_update(&xxhState, srcBuffer+segmentStart, segmentSize);
2608                 memcpy(mirrorBuffer + totalTestSize, srcBuffer+segmentStart, segmentSize);
2609                 totalTestSize += segmentSize;
2610             }
2611
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;
2615             }
2616             crcOrig = XXH64_digest(&xxhState);
2617         }
2618
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 );
2630         }   }
2631         if (dictSize<8) dictSize=0, dict=NULL;   /* disable dictionary */
2632         CHECK_Z( ZSTD_decompressBegin_usingDict(dctx, dict, dictSize) );
2633         totalCSize = 0;
2634         totalGenSize = 0;
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;
2641         }
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);
2648         }
2649     }   /* for ( ; (testNb <= nbTests) */
2650     DISPLAY("\r%u fuzzer tests completed   \n", testNb-1);
2651
2652 _cleanup:
2653     ZSTD_freeCCtx(refCtx);
2654     ZSTD_freeCCtx(ctx);
2655     ZSTD_freeDCtx(dctx);
2656     free(cNoiseBuffer[0]);
2657     free(cNoiseBuffer[1]);
2658     free(cNoiseBuffer[2]);
2659     free(cNoiseBuffer[3]);
2660     free(cNoiseBuffer[4]);
2661     free(cBuffer);
2662     free(dstBuffer);
2663     free(mirrorBuffer);
2664     return result;
2665
2666 _output_error:
2667     result = 1;
2668     goto _cleanup;
2669 }
2670
2671
2672 /*_*******************************************************
2673 *  Command line
2674 *********************************************************/
2675 static int FUZ_usage(const char* programName)
2676 {
2677     DISPLAY( "Usage :\n");
2678     DISPLAY( "      %s [args]\n", programName);
2679     DISPLAY( "\n");
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");
2688     return 0;
2689 }
2690
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)
2697 {
2698     unsigned result = 0;
2699     while ((**stringPtr >='0') && (**stringPtr <='9'))
2700         result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
2701     if ((**stringPtr=='K') || (**stringPtr=='M')) {
2702         result <<= 10;
2703         if (**stringPtr=='M') result <<= 10;
2704         (*stringPtr)++ ;
2705         if (**stringPtr=='i') (*stringPtr)++;
2706         if (**stringPtr=='B') (*stringPtr)++;
2707     }
2708     return result;
2709 }
2710
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.
2715  */
2716 static int longCommandWArg(const char** stringPtr, const char* longCommand)
2717 {
2718     size_t const comSize = strlen(longCommand);
2719     int const result = !strncmp(*stringPtr, longCommand, comSize);
2720     if (result) *stringPtr += comSize;
2721     return result;
2722 }
2723
2724 int main(int argc, const char** argv)
2725 {
2726     U32 seed = 0;
2727     int seedset = 0;
2728     int argNb;
2729     int nbTests = nbTestsDefault;
2730     int testNb = 0;
2731     int proba = FUZ_compressibility_default;
2732     int result = 0;
2733     U32 mainPause = 0;
2734     U32 maxDuration = 0;
2735     int bigTests = 1;
2736     U32 memTestsOnly = 0;
2737     const char* const programName = argv[0];
2738
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 */
2743
2744         /* Handle commands. Aggregated commands are allowed */
2745         if (argument[0]=='-') {
2746
2747             if (longCommandWArg(&argument, "--memtest=")) { memTestsOnly = readU32FromChar(&argument); continue; }
2748
2749             if (!strcmp(argument, "--memtest")) { memTestsOnly=1; continue; }
2750             if (!strcmp(argument, "--no-big-tests")) { bigTests=0; continue; }
2751
2752             argument++;
2753             while (*argument!=0) {
2754                 switch(*argument)
2755                 {
2756                 case 'h':
2757                     return FUZ_usage(programName);
2758
2759                 case 'v':
2760                     argument++;
2761                     g_displayLevel++;
2762                     break;
2763
2764                 case 'q':
2765                     argument++;
2766                     g_displayLevel--;
2767                     break;
2768
2769                 case 'p': /* pause at the end */
2770                     argument++;
2771                     mainPause = 1;
2772                     break;
2773
2774                 case 'i':
2775                     argument++; maxDuration = 0;
2776                     nbTests = (int)readU32FromChar(&argument);
2777                     break;
2778
2779                 case 'T':
2780                     argument++;
2781                     nbTests = 0;
2782                     maxDuration = readU32FromChar(&argument);
2783                     if (*argument=='s') argument++;   /* seconds */
2784                     if (*argument=='m') maxDuration *= 60, argument++;   /* minutes */
2785                     if (*argument=='n') argument++;
2786                     break;
2787
2788                 case 's':
2789                     argument++;
2790                     seedset = 1;
2791                     seed = readU32FromChar(&argument);
2792                     break;
2793
2794                 case 't':
2795                     argument++;
2796                     testNb = (int)readU32FromChar(&argument);
2797                     break;
2798
2799                 case 'P':   /* compressibility % */
2800                     argument++;
2801                     proba = (int)readU32FromChar(&argument);
2802                     if (proba>100) proba = 100;
2803                     break;
2804
2805                 default:
2806                     return (FUZ_usage(programName), 1);
2807     }   }   }   }   /* for (argNb=1; argNb<argc; argNb++) */
2808
2809     /* Get Seed */
2810     DISPLAY("Starting zstd tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION_STRING);
2811
2812     if (!seedset) {
2813         time_t const t = time(NULL);
2814         U32 const h = XXH32(&t, sizeof(t), 1);
2815         seed = h % 10000;
2816     }
2817
2818     DISPLAY("Seed = %u\n", (unsigned)seed);
2819     if (proba!=FUZ_compressibility_default) DISPLAY("Compressibility : %i%%\n", proba);
2820
2821     if (memTestsOnly) {
2822         g_displayLevel = MAX(3, g_displayLevel);
2823         return FUZ_mallocTests(seed, ((double)proba) / 100, memTestsOnly);
2824     }
2825
2826     if (nbTests < testNb) nbTests = testNb;
2827
2828     if (testNb==0)
2829         result = basicUnitTests(0, ((double)proba) / 100);  /* constant seed for predictability */
2830     if (!result)
2831         result = fuzzerTests(seed, nbTests, testNb, maxDuration, ((double)proba) / 100, bigTests);
2832     if (mainPause) {
2833         int unused;
2834         DISPLAY("Press Enter \n");
2835         unused = getchar();
2836         (void)unused;
2837     }
2838     return result;
2839 }