2 * Copyright (c) 2015-present, Yann Collet, Facebook, Inc.
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
12 /*-************************************
14 **************************************/
15 #ifdef _MSC_VER /* Visual Studio */
16 # define _CRT_SECURE_NO_WARNINGS /* fgets */
17 # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
18 # pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
22 /*-************************************
24 **************************************/
25 #include <stdlib.h> /* free */
26 #include <stdio.h> /* fgets, sscanf */
27 #include <string.h> /* strcmp */
28 #include "timefn.h" /* UTIL_time_t */
30 #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */
31 #include "zstd.h" /* ZSTD_compressBound */
32 #define ZBUFF_STATIC_LINKING_ONLY /* ZBUFF_createCCtx_advanced */
33 #include "zbuff.h" /* ZBUFF_isError */
34 #include "datagen.h" /* RDG_genBuffer */
35 #define XXH_STATIC_LINKING_ONLY
36 #include "xxhash.h" /* XXH64_* */
40 /*-************************************
42 **************************************/
47 static const U32 nbTestsDefault
= 10000;
48 #define COMPRESSIBLE_NOISE_LENGTH (10 MB)
49 #define FUZ_COMPRESSIBILITY_DEFAULT 50
50 static const U32 prime1
= 2654435761U;
51 static const U32 prime2
= 2246822519U;
55 /*-************************************
57 **************************************/
58 #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
59 #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
60 static U32 g_displayLevel
= 2;
62 static const U64 g_refreshRate
= SEC_TO_MICRO
/ 6;
63 static UTIL_time_t g_displayClock
= UTIL_TIME_INITIALIZER
;
65 #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
66 if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \
67 { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \
68 if (g_displayLevel>=4) fflush(stderr); } }
70 static U64 g_clockTime
= 0;
73 /*-*******************************************************
75 *********************************************************/
78 #define MIN(a,b) ((a)<(b)?(a):(b))
79 #define MAX(a,b) ((a)>(b)?(a):(b))
81 @return : a 27 bits random value, from a 32-bits `seed`.
82 `seed` is also modified */
83 # define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
84 unsigned int FUZ_rand(unsigned int* seedPtr
)
86 U32 rand32
= *seedPtr
;
89 rand32
= FUZ_rotl32(rand32
, 13);
96 static unsigned FUZ_highbit32(U32 v32)
100 for ( ; v32 ; v32>>=1) nbBits++;
105 static void* ZBUFF_allocFunction(void* opaque
, size_t size
)
107 void* address
= malloc(size
);
109 /* DISPLAYLEVEL(4, "alloc %p, %d opaque=%p \n", address, (int)size, opaque); */
113 static void ZBUFF_freeFunction(void* opaque
, void* address
)
116 /* if (address) DISPLAYLEVEL(4, "free %p opaque=%p \n", address, opaque); */
120 static int basicUnitTests(U32 seed
, double compressibility
, ZSTD_customMem customMem
)
123 size_t CNBufferSize
= COMPRESSIBLE_NOISE_LENGTH
;
124 void* CNBuffer
= malloc(CNBufferSize
);
125 size_t const skippableFrameSize
= 11;
126 size_t const compressedBufferSize
= (8 + skippableFrameSize
) + ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH
);
127 void* compressedBuffer
= malloc(compressedBufferSize
);
128 size_t const decodedBufferSize
= CNBufferSize
;
129 void* decodedBuffer
= malloc(decodedBufferSize
);
130 size_t cSize
, readSize
, readSkipSize
, genSize
;
132 ZBUFF_CCtx
* zc
= ZBUFF_createCCtx_advanced(customMem
);
133 ZBUFF_DCtx
* zd
= ZBUFF_createDCtx_advanced(customMem
);
135 /* Create compressible test buffer */
136 if (!CNBuffer
|| !compressedBuffer
|| !decodedBuffer
|| !zc
|| !zd
) {
137 DISPLAY("Not enough memory, aborting\n");
140 RDG_genBuffer(CNBuffer
, CNBufferSize
, compressibility
, 0., seed
);
142 /* generate skippable frame */
143 MEM_writeLE32(compressedBuffer
, ZSTD_MAGIC_SKIPPABLE_START
);
144 MEM_writeLE32(((char*)compressedBuffer
)+4, (U32
)skippableFrameSize
);
145 cSize
= skippableFrameSize
+ 8;
147 /* Basic compression test */
148 DISPLAYLEVEL(4, "test%3i : compress %u bytes : ", testNb
++, COMPRESSIBLE_NOISE_LENGTH
);
149 ZBUFF_compressInitDictionary(zc
, CNBuffer
, 128 KB
, 1);
150 readSize
= CNBufferSize
;
151 genSize
= compressedBufferSize
;
152 { size_t const r
= ZBUFF_compressContinue(zc
, ((char*)compressedBuffer
)+cSize
, &genSize
, CNBuffer
, &readSize
);
153 if (ZBUFF_isError(r
)) goto _output_error
; }
154 if (readSize
!= CNBufferSize
) goto _output_error
; /* entire input should be consumed */
156 genSize
= compressedBufferSize
- cSize
;
157 { size_t const r
= ZBUFF_compressEnd(zc
, ((char*)compressedBuffer
)+cSize
, &genSize
);
158 if (r
!= 0) goto _output_error
; } /* error, or some data not flushed */
160 DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32
)cSize
, (double)cSize
/COMPRESSIBLE_NOISE_LENGTH
*100);
162 /* skippable frame test */
163 DISPLAYLEVEL(4, "test%3i : decompress skippable frame : ", testNb
++);
164 ZBUFF_decompressInitDictionary(zd
, CNBuffer
, 128 KB
);
165 readSkipSize
= cSize
;
166 genSize
= CNBufferSize
;
167 { size_t const r
= ZBUFF_decompressContinue(zd
, decodedBuffer
, &genSize
, compressedBuffer
, &readSkipSize
);
168 if (r
!= 0) goto _output_error
; }
169 if (genSize
!= 0) goto _output_error
; /* skippable frame len is 0 */
170 DISPLAYLEVEL(4, "OK \n");
172 /* Basic decompression test */
173 DISPLAYLEVEL(4, "test%3i : decompress %u bytes : ", testNb
++, COMPRESSIBLE_NOISE_LENGTH
);
174 ZBUFF_decompressInitDictionary(zd
, CNBuffer
, 128 KB
);
175 readSize
= cSize
- readSkipSize
;
176 genSize
= CNBufferSize
;
177 { size_t const r
= ZBUFF_decompressContinue(zd
, decodedBuffer
, &genSize
, ((char*)compressedBuffer
)+readSkipSize
, &readSize
);
178 if (r
!= 0) goto _output_error
; } /* should reach end of frame == 0; otherwise, some data left, or an error */
179 if (genSize
!= CNBufferSize
) goto _output_error
; /* should regenerate the same amount */
180 if (readSize
+readSkipSize
!= cSize
) goto _output_error
; /* should have read the entire frame */
181 DISPLAYLEVEL(4, "OK \n");
183 /* check regenerated data is byte exact */
184 DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb
++);
186 for (i
=0; i
<CNBufferSize
; i
++) {
187 if (((BYTE
*)decodedBuffer
)[i
] != ((BYTE
*)CNBuffer
)[i
]) goto _output_error
;;
189 DISPLAYLEVEL(4, "OK \n");
191 /* Byte-by-byte decompression test */
192 DISPLAYLEVEL(4, "test%3i : decompress byte-by-byte : ", testNb
++);
193 { size_t r
, pIn
=0, pOut
=0;
195 { ZBUFF_decompressInitDictionary(zd
, CNBuffer
, 128 KB
);
200 r
= ZBUFF_decompressContinue(zd
, ((BYTE
*)decodedBuffer
)+pOut
, &outS
, ((BYTE
*)compressedBuffer
)+pIn
, &inS
);
206 } while (genSize
==0);
208 if (genSize
!= CNBufferSize
) goto _output_error
; /* should regenerate the same amount */
209 if (readSize
!= cSize
) goto _output_error
; /* should have read the entire frame */
210 DISPLAYLEVEL(4, "OK \n");
212 /* check regenerated data is byte exact */
213 DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb
++);
215 for (i
=0; i
<CNBufferSize
; i
++) {
216 if (((BYTE
*)decodedBuffer
)[i
] != ((BYTE
*)CNBuffer
)[i
]) goto _output_error
;;
218 DISPLAYLEVEL(4, "OK \n");
224 free(compressedBuffer
);
230 DISPLAY("Error detected in Unit tests ! \n");
235 static size_t findDiff(const void* buf1
, const void* buf2
, size_t max
)
237 const BYTE
* b1
= (const BYTE
*)buf1
;
238 const BYTE
* b2
= (const BYTE
*)buf2
;
240 for (u
=0; u
<max
; u
++) {
241 if (b1
[u
] != b2
[u
]) break;
246 static size_t FUZ_rLogLength(U32
* seed
, U32 logLength
)
248 size_t const lengthMask
= ((size_t)1 << logLength
) - 1;
249 return (lengthMask
+1) + (FUZ_rand(seed
) & lengthMask
);
252 static size_t FUZ_randomLength(U32
* seed
, U32 maxLog
)
254 U32
const logLength
= FUZ_rand(seed
) % maxLog
;
255 return FUZ_rLogLength(seed
, logLength
);
258 #define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
259 DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
261 static int fuzzerTests(U32 seed
, U32 nbTests
, unsigned startTest
, double compressibility
)
263 static const U32 maxSrcLog
= 24;
264 static const U32 maxSampleLog
= 19;
265 BYTE
* cNoiseBuffer
[5];
266 size_t const srcBufferSize
= (size_t)1<<maxSrcLog
;
268 size_t const copyBufferSize
= srcBufferSize
+ (1<<maxSampleLog
);
270 size_t const cBufferSize
= ZSTD_compressBound(srcBufferSize
);
272 size_t dstBufferSize
= srcBufferSize
;
278 UTIL_time_t startClock
= UTIL_getTime();
281 zc
= ZBUFF_createCCtx();
282 zd
= ZBUFF_createDCtx();
283 cNoiseBuffer
[0] = (BYTE
*)malloc (srcBufferSize
);
284 cNoiseBuffer
[1] = (BYTE
*)malloc (srcBufferSize
);
285 cNoiseBuffer
[2] = (BYTE
*)malloc (srcBufferSize
);
286 cNoiseBuffer
[3] = (BYTE
*)malloc (srcBufferSize
);
287 cNoiseBuffer
[4] = (BYTE
*)malloc (srcBufferSize
);
288 copyBuffer
= (BYTE
*)malloc (copyBufferSize
);
289 dstBuffer
= (BYTE
*)malloc (dstBufferSize
);
290 cBuffer
= (BYTE
*)malloc (cBufferSize
);
291 CHECK (!cNoiseBuffer
[0] || !cNoiseBuffer
[1] || !cNoiseBuffer
[2] || !cNoiseBuffer
[3] || !cNoiseBuffer
[4] ||
292 !copyBuffer
|| !dstBuffer
|| !cBuffer
|| !zc
|| !zd
,
293 "Not enough memory, fuzzer tests cancelled");
295 /* Create initial samples */
296 RDG_genBuffer(cNoiseBuffer
[0], srcBufferSize
, 0.00, 0., coreSeed
); /* pure noise */
297 RDG_genBuffer(cNoiseBuffer
[1], srcBufferSize
, 0.05, 0., coreSeed
); /* barely compressible */
298 RDG_genBuffer(cNoiseBuffer
[2], srcBufferSize
, compressibility
, 0., coreSeed
);
299 RDG_genBuffer(cNoiseBuffer
[3], srcBufferSize
, 0.95, 0., coreSeed
); /* highly compressible */
300 RDG_genBuffer(cNoiseBuffer
[4], srcBufferSize
, 1.00, 0., coreSeed
); /* sparse content */
301 memset(copyBuffer
, 0x65, copyBufferSize
); /* make copyBuffer considered initialized */
303 /* catch up testNb */
304 for (testNb
=1; testNb
< startTest
; testNb
++)
308 for ( ; (testNb
<= nbTests
) || (UTIL_clockSpanMicro(startClock
) < g_clockTime
) ; testNb
++ ) {
310 const BYTE
* srcBuffer
;
312 size_t maxTestSize
, dictSize
;
313 size_t cSize
, totalTestSize
, totalCSize
, totalGenSize
;
316 XXH64_state_t xxhState
;
320 DISPLAYUPDATE(2, "\r%6u", testNb
);
321 if (nbTests
>= testNb
) DISPLAYUPDATE(2, "/%6u ", nbTests
);
323 lseed
= coreSeed
^ prime1
;
325 /* states full reset (unsynchronized) */
326 /* some issues only happen when reusing states in a specific sequence of parameters */
327 if ((FUZ_rand(&lseed
) & 0xFF) == 131) { ZBUFF_freeCCtx(zc
); zc
= ZBUFF_createCCtx(); }
328 if ((FUZ_rand(&lseed
) & 0xFF) == 132) { ZBUFF_freeDCtx(zd
); zd
= ZBUFF_createDCtx(); }
330 /* srcBuffer selection [0-4] */
331 { U32 buffNb
= FUZ_rand(&lseed
) & 0x7F;
332 if (buffNb
& 7) buffNb
=2; /* most common : compressible (P) */
336 const U32 tnb
[2] = { 1, 3 }; /* barely/highly compressible */
337 buffNb
= tnb
[buffNb
>> 3];
339 const U32 tnb
[2] = { 0, 4 }; /* not compressible / sparse */
340 buffNb
= tnb
[buffNb
>> 3];
342 srcBuffer
= cNoiseBuffer
[buffNb
];
345 /* compression init */
346 { U32
const testLog
= FUZ_rand(&lseed
) % maxSrcLog
;
347 U32
const cLevel
= (FUZ_rand(&lseed
) % (ZSTD_maxCLevel() - (testLog
/3))) + 1;
348 maxTestSize
= FUZ_rLogLength(&lseed
, testLog
);
349 dictSize
= (FUZ_rand(&lseed
)==1) ? FUZ_randomLength(&lseed
, maxSampleLog
) : 0;
350 /* random dictionary selection */
351 { size_t const dictStart
= FUZ_rand(&lseed
) % (srcBufferSize
- dictSize
);
352 dict
= srcBuffer
+ dictStart
;
354 { ZSTD_parameters params
= ZSTD_getParams(cLevel
, 0, dictSize
);
355 params
.fParams
.checksumFlag
= FUZ_rand(&lseed
) & 1;
356 params
.fParams
.noDictIDFlag
= FUZ_rand(&lseed
) & 1;
357 { size_t const initError
= ZBUFF_compressInit_advanced(zc
, dict
, dictSize
, params
, ZSTD_CONTENTSIZE_UNKNOWN
);
358 CHECK (ZBUFF_isError(initError
),"init error : %s", ZBUFF_getErrorName(initError
));
361 /* multi-segments compression test */
362 XXH64_reset(&xxhState
, 0);
363 nbChunks
= (FUZ_rand(&lseed
) & 127) + 2;
364 for (n
=0, cSize
=0, totalTestSize
=0 ; (n
<nbChunks
) && (totalTestSize
< maxTestSize
) ; n
++) {
365 /* compress random chunk into random size dst buffer */
366 { size_t readChunkSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
367 size_t const randomDstSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
368 size_t dstBuffSize
= MIN(cBufferSize
- cSize
, randomDstSize
);
369 size_t const srcStart
= FUZ_rand(&lseed
) % (srcBufferSize
- readChunkSize
);
371 size_t const compressionError
= ZBUFF_compressContinue(zc
, cBuffer
+cSize
, &dstBuffSize
, srcBuffer
+srcStart
, &readChunkSize
);
372 CHECK (ZBUFF_isError(compressionError
), "compression error : %s", ZBUFF_getErrorName(compressionError
));
374 XXH64_update(&xxhState
, srcBuffer
+srcStart
, readChunkSize
);
375 memcpy(copyBuffer
+totalTestSize
, srcBuffer
+srcStart
, readChunkSize
);
376 cSize
+= dstBuffSize
;
377 totalTestSize
+= readChunkSize
;
380 /* random flush operation, to mess around */
381 if ((FUZ_rand(&lseed
) & 15) == 0) {
382 size_t const randomDstSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
383 size_t dstBuffSize
= MIN(cBufferSize
- cSize
, randomDstSize
);
384 size_t const flushError
= ZBUFF_compressFlush(zc
, cBuffer
+cSize
, &dstBuffSize
);
385 CHECK (ZBUFF_isError(flushError
), "flush error : %s", ZBUFF_getErrorName(flushError
));
386 cSize
+= dstBuffSize
;
389 /* final frame epilogue */
390 { size_t remainingToFlush
= (size_t)(-1);
391 while (remainingToFlush
) {
392 size_t const randomDstSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
393 size_t dstBuffSize
= MIN(cBufferSize
- cSize
, randomDstSize
);
394 U32
const enoughDstSize
= dstBuffSize
>= remainingToFlush
;
395 remainingToFlush
= ZBUFF_compressEnd(zc
, cBuffer
+cSize
, &dstBuffSize
);
396 CHECK (ZBUFF_isError(remainingToFlush
), "flush error : %s", ZBUFF_getErrorName(remainingToFlush
));
397 CHECK (enoughDstSize
&& remainingToFlush
, "ZBUFF_compressEnd() not fully flushed (%u remaining), but enough space available", (U32
)remainingToFlush
);
398 cSize
+= dstBuffSize
;
400 crcOrig
= XXH64_digest(&xxhState
);
402 /* multi - fragments decompression test */
403 ZBUFF_decompressInitDictionary(zd
, dict
, dictSize
);
405 for (totalCSize
= 0, totalGenSize
= 0 ; errorCode
; ) {
406 size_t readCSrcSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
407 size_t const randomDstSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
408 size_t dstBuffSize
= MIN(dstBufferSize
- totalGenSize
, randomDstSize
);
409 errorCode
= ZBUFF_decompressContinue(zd
, dstBuffer
+totalGenSize
, &dstBuffSize
, cBuffer
+totalCSize
, &readCSrcSize
);
410 CHECK (ZBUFF_isError(errorCode
), "decompression error : %s", ZBUFF_getErrorName(errorCode
));
411 totalGenSize
+= dstBuffSize
;
412 totalCSize
+= readCSrcSize
;
414 CHECK (errorCode
!= 0, "frame not fully decoded");
415 CHECK (totalGenSize
!= totalTestSize
, "decompressed data : wrong size")
416 CHECK (totalCSize
!= cSize
, "compressed data should be fully read")
417 { U64
const crcDest
= XXH64(dstBuffer
, totalTestSize
, 0);
418 if (crcDest
!=crcOrig
) findDiff(copyBuffer
, dstBuffer
, totalTestSize
);
419 CHECK (crcDest
!=crcOrig
, "decompressed data corrupted"); }
421 /*===== noisy/erroneous src decompression test =====*/
424 { U32
const nbNoiseChunks
= (FUZ_rand(&lseed
) & 7) + 2;
425 U32 nn
; for (nn
=0; nn
<nbNoiseChunks
; nn
++) {
426 size_t const randomNoiseSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
427 size_t const noiseSize
= MIN((cSize
/3) , randomNoiseSize
);
428 size_t const noiseStart
= FUZ_rand(&lseed
) % (srcBufferSize
- noiseSize
);
429 size_t const cStart
= FUZ_rand(&lseed
) % (cSize
- noiseSize
);
430 memcpy(cBuffer
+cStart
, srcBuffer
+noiseStart
, noiseSize
);
433 /* try decompression on noisy data */
434 ZBUFF_decompressInit(zd
);
437 while ( (totalCSize
< cSize
) && (totalGenSize
< dstBufferSize
) ) {
438 size_t readCSrcSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
439 size_t const randomDstSize
= FUZ_randomLength(&lseed
, maxSampleLog
);
440 size_t dstBuffSize
= MIN(dstBufferSize
- totalGenSize
, randomDstSize
);
441 size_t const decompressError
= ZBUFF_decompressContinue(zd
, dstBuffer
+totalGenSize
, &dstBuffSize
, cBuffer
+totalCSize
, &readCSrcSize
);
442 if (ZBUFF_isError(decompressError
)) break; /* error correctly detected */
443 totalGenSize
+= dstBuffSize
;
444 totalCSize
+= readCSrcSize
;
446 DISPLAY("\r%u fuzzer tests completed \n", testNb
);
451 free(cNoiseBuffer
[0]);
452 free(cNoiseBuffer
[1]);
453 free(cNoiseBuffer
[2]);
454 free(cNoiseBuffer
[3]);
455 free(cNoiseBuffer
[4]);
467 /*-*******************************************************
469 *********************************************************/
470 int FUZ_usage(const char* programName
)
472 DISPLAY( "Usage :\n");
473 DISPLAY( " %s [args]\n", programName
);
475 DISPLAY( "Arguments :\n");
476 DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault
);
477 DISPLAY( " -s# : Select seed (default:prompt user)\n");
478 DISPLAY( " -t# : Select starting test number (default:0)\n");
479 DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT
);
480 DISPLAY( " -v : verbose\n");
481 DISPLAY( " -p : pause at the end\n");
482 DISPLAY( " -h : display help and exit\n");
487 int main(int argc
, const char** argv
)
492 int nbTests
= nbTestsDefault
;
494 int proba
= FUZ_COMPRESSIBILITY_DEFAULT
;
497 const char* programName
= argv
[0];
498 ZSTD_customMem customMem
= { ZBUFF_allocFunction
, ZBUFF_freeFunction
, NULL
};
499 ZSTD_customMem customNULL
= { NULL
, NULL
, NULL
};
501 /* Check command line */
502 for(argNb
=1; argNb
<argc
; argNb
++) {
503 const char* argument
= argv
[argNb
];
504 if(!argument
) continue; /* Protection if argument empty */
506 /* Parsing commands. Aggregated commands are allowed */
507 if (argument
[0]=='-') {
510 while (*argument
!=0) {
514 return FUZ_usage(programName
);
523 case 'p': /* pause at the end */
530 nbTests
=0; g_clockTime
=0;
531 while ((*argument
>='0') && (*argument
<='9')) {
533 nbTests
+= *argument
- '0';
540 nbTests
=0; g_clockTime
=0;
541 while ((*argument
>='0') && (*argument
<='9')) {
543 g_clockTime
+= *argument
- '0';
546 if (*argument
=='m') g_clockTime
*=60, argument
++;
547 if (*argument
=='n') argument
++;
548 g_clockTime
*= SEC_TO_MICRO
;
555 while ((*argument
>='0') && (*argument
<='9')) {
557 seed
+= *argument
- '0';
565 while ((*argument
>='0') && (*argument
<='9')) {
567 testNb
+= *argument
- '0';
572 case 'P': /* compressibility % */
575 while ((*argument
>='0') && (*argument
<='9')) {
577 proba
+= *argument
- '0';
580 if (proba
<0) proba
=0;
581 if (proba
>100) proba
=100;
585 return FUZ_usage(programName
);
587 } } } /* for(argNb=1; argNb<argc; argNb++) */
590 DISPLAY("Starting zstd_buffered tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION_STRING
);
593 time_t const t
= time(NULL
);
594 U32
const h
= XXH32(&t
, sizeof(t
), 1);
597 DISPLAY("Seed = %u\n", seed
);
598 if (proba
!=FUZ_COMPRESSIBILITY_DEFAULT
) DISPLAY("Compressibility : %i%%\n", proba
);
600 if (nbTests
<=0) nbTests
=1;
603 result
= basicUnitTests(0, ((double)proba
) / 100, customNULL
); /* constant seed for predictability */
605 DISPLAYLEVEL(4, "Unit tests using customMem :\n")
606 result
= basicUnitTests(0, ((double)proba
) / 100, customMem
); /* use custom memory allocation functions */
610 result
= fuzzerTests(seed
, nbTests
, testNb
, ((double)proba
) / 100);
614 DISPLAY("Press Enter \n");