blob: b72f7e57429f2a5b64bc3f522424c78e8d6758e4 [file] [log] [blame]
Yann Collet4856a002015-01-24 01:58:16 +01001/*
2 Fuzzer test tool for zstd
3 Copyright (C) Yann Collet 2014-2105
4
5 GPL v2 License
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 You can contact the author at :
22 - ZSTD source repository : https://github.com/Cyan4973/zstd
23 - ZSTD public forum : https://groups.google.com/forum/#!forum/lz4c
24*/
25
26/**************************************
27* Compiler specific
28**************************************/
29#ifdef _MSC_VER /* Visual Studio */
30# define _CRT_SECURE_NO_WARNINGS /* fgets */
31# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
32# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
33#endif
34
35#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
36#ifdef __GNUC__
37# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
38# pragma GCC diagnostic ignored "-Wmissing-field-initializers" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
39#endif
40
41
42/**************************************
43* Includes
44**************************************/
45#include <stdlib.h> /* free */
46#include <stdio.h> /* fgets, sscanf */
47#include <sys/timeb.h> /* timeb */
48#include <string.h> /* strcmp */
49#include "zstd_static.h"
Yann Colletd5d9bc32015-08-23 23:13:49 +010050#include "datagen.h" /* RDG_genBuffer */
Yann Collet4856a002015-01-24 01:58:16 +010051#include "xxhash.h" /* XXH64 */
Yann Collet353c5d22015-10-21 14:39:26 +010052#include "mem.h"
Yann Collet4856a002015-01-24 01:58:16 +010053
54
55/**************************************
56 Constants
57**************************************/
58#ifndef ZSTD_VERSION
59# define ZSTD_VERSION ""
60#endif
61
62#define KB *(1U<<10)
63#define MB *(1U<<20)
64#define GB *(1U<<30)
65
Yann Collet110cc142015-11-19 12:02:28 +010066static const U32 nbTestsDefault = 30000;
Yann Collet4856a002015-01-24 01:58:16 +010067#define COMPRESSIBLE_NOISE_LENGTH (10 MB)
68#define FUZ_COMPRESSIBILITY_DEFAULT 50
69static const U32 prime1 = 2654435761U;
70static const U32 prime2 = 2246822519U;
71
72
73
74/**************************************
75* Display Macros
76**************************************/
77#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
78#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
79static U32 g_displayLevel = 2;
80
81#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
Yann Collet553cf6a2015-12-04 17:25:26 +010082 if ((FUZ_GetMilliSpan(g_displayTime) > g_refreshRate) || (g_displayLevel>=4)) \
83 { g_displayTime = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); \
Yann Collet4856a002015-01-24 01:58:16 +010084 if (g_displayLevel>=4) fflush(stdout); } }
85static const U32 g_refreshRate = 150;
Yann Collet553cf6a2015-12-04 17:25:26 +010086static U32 g_displayTime = 0;
87
88static U32 g_testTime = 0;
Yann Collet4856a002015-01-24 01:58:16 +010089
90
91/*********************************************************
92* Fuzzer functions
93*********************************************************/
Yann Collet110cc142015-11-19 12:02:28 +010094#define MAX(a,b) ((a)>(b)?(a):(b))
95
Yann Collet4856a002015-01-24 01:58:16 +010096static U32 FUZ_GetMilliStart(void)
97{
98 struct timeb tb;
99 U32 nCount;
100 ftime( &tb );
101 nCount = (U32) (((tb.time & 0xFFFFF) * 1000) + tb.millitm);
102 return nCount;
103}
104
105
106static U32 FUZ_GetMilliSpan(U32 nTimeStart)
107{
108 U32 nCurrent = FUZ_GetMilliStart();
109 U32 nSpan = nCurrent - nTimeStart;
110 if (nTimeStart > nCurrent)
111 nSpan += 0x100000 * 1000;
112 return nSpan;
113}
114
115
116# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
117unsigned int FUZ_rand(unsigned int* src)
118{
119 U32 rand32 = *src;
120 rand32 *= prime1;
121 rand32 += prime2;
122 rand32 = FUZ_rotl32(rand32, 13);
123 *src = rand32;
124 return rand32 >> 5;
125}
126
127
Yann Collet997f9ee2015-08-21 02:44:20 +0100128static unsigned FUZ_highbit32(U32 v32)
Yann Collet4856a002015-01-24 01:58:16 +0100129{
130 unsigned nbBits = 0;
131 if (v32==0) return 0;
132 while (v32)
133 {
134 v32 >>= 1;
135 nbBits ++;
136 }
137 return nbBits;
138}
Yann Collet4856a002015-01-24 01:58:16 +0100139
140
141static int basicUnitTests(U32 seed, double compressibility)
142{
143 int testResult = 0;
144 void* CNBuffer;
145 void* compressedBuffer;
146 void* decodedBuffer;
147 U32 randState = seed;
148 size_t result, cSize;
149 U32 testNb=0;
150
Yann Colletd5d9bc32015-08-23 23:13:49 +0100151 /* Create compressible test buffer */
Yann Collet4856a002015-01-24 01:58:16 +0100152 CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
153 compressedBuffer = malloc(ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH));
154 decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
Yann Collet94f998b2015-07-04 23:10:40 -0800155 if (!CNBuffer || !compressedBuffer || !decodedBuffer)
156 {
157 DISPLAY("Not enough memory, aborting\n");
158 testResult = 1;
159 goto _end;
160 }
Yann Colletd5d9bc32015-08-23 23:13:49 +0100161 RDG_genBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, 0., randState);
Yann Collet4856a002015-01-24 01:58:16 +0100162
Yann Colletd5d9bc32015-08-23 23:13:49 +0100163 /* Basic tests */
Yann Collet4856a002015-01-24 01:58:16 +0100164 DISPLAYLEVEL(4, "test%3i : compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
Yann Collet5be2dd22015-11-11 13:43:58 +0100165 result = ZSTD_compress(compressedBuffer, ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH), CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
Yann Collet4856a002015-01-24 01:58:16 +0100166 if (ZSTD_isError(result)) goto _output_error;
167 cSize = result;
168 DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
169
170 DISPLAYLEVEL(4, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
171 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize);
172 if (ZSTD_isError(result)) goto _output_error;
173 DISPLAYLEVEL(4, "OK \n");
174
175 {
176 size_t i;
177 DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
178 for (i=0; i<COMPRESSIBLE_NOISE_LENGTH; i++)
179 {
180 if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
181 }
182 DISPLAYLEVEL(4, "OK \n");
183 }
184
185 DISPLAYLEVEL(4, "test%3i : decompress with 1 missing byte : ", testNb++);
186 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize-1);
187 if (!ZSTD_isError(result)) goto _output_error;
Yann Collet977f1f32016-01-21 15:38:47 +0100188 if (result != (size_t)-ZSTD_error_srcSize_wrong) goto _output_error;
Yann Collet4856a002015-01-24 01:58:16 +0100189 DISPLAYLEVEL(4, "OK \n");
190
191 DISPLAYLEVEL(4, "test%3i : decompress with 1 too much byte : ", testNb++);
192 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize+1);
193 if (!ZSTD_isError(result)) goto _output_error;
Yann Collet977f1f32016-01-21 15:38:47 +0100194 if (result != (size_t)-ZSTD_error_srcSize_wrong) goto _output_error;
Yann Collet4856a002015-01-24 01:58:16 +0100195 DISPLAYLEVEL(4, "OK \n");
196
Yann Collet60096272016-01-08 17:27:50 +0100197 /* Dictionary and Duplication tests */
198 {
199 ZSTD_CCtx* ctxOrig = ZSTD_createCCtx();
200 ZSTD_CCtx* ctxDuplicated = ZSTD_createCCtx();
201 ZSTD_DCtx* dctx = ZSTD_createDCtx();
202 const size_t dictSize = 500;
203 size_t cSizeOrig;
204
205 DISPLAYLEVEL(4, "test%3i : load dictionary into context : ", testNb++);
206 result = ZSTD_compressBegin(ctxOrig, 2);
207 if (ZSTD_isError(result)) goto _output_error;
208 result = ZSTD_compress_insertDictionary(ctxOrig, CNBuffer, dictSize);
209 if (ZSTD_isError(result)) goto _output_error;
Yann Collet7b51a292016-01-26 15:58:49 +0100210 result = ZSTD_copyCCtx(ctxDuplicated, ctxOrig);
Yann Collet60096272016-01-08 17:27:50 +0100211 if (ZSTD_isError(result)) goto _output_error;
212 DISPLAYLEVEL(4, "OK \n");
213
214 DISPLAYLEVEL(4, "test%3i : compress with dictionary : ", testNb++);
215 cSize = 0;
216 result = ZSTD_compressContinue(ctxOrig, compressedBuffer, ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH), (const char*)CNBuffer + dictSize, COMPRESSIBLE_NOISE_LENGTH - dictSize);
217 if (ZSTD_isError(result)) goto _output_error;
218 cSize += result;
219 result = ZSTD_compressEnd(ctxOrig, (char*)compressedBuffer+cSize, ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH)-cSize);
220 if (ZSTD_isError(result)) goto _output_error;
221 cSize += result;
222 DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
223
224 DISPLAYLEVEL(4, "test%3i : frame built with dictionary should be decompressible : ", testNb++);
225 result = ZSTD_decompress_usingDict(dctx,
226 decodedBuffer, COMPRESSIBLE_NOISE_LENGTH,
227 compressedBuffer, cSize,
228 CNBuffer, dictSize);
229 if (ZSTD_isError(result)) goto _output_error;
Yann Colletbf42c8e2016-01-09 01:08:23 +0100230 if (result != COMPRESSIBLE_NOISE_LENGTH - dictSize) goto _output_error;
Yann Collet60096272016-01-08 17:27:50 +0100231 ZSTD_freeCCtx(ctxOrig); /* if ctxOrig is read, will produce segfault */
232 DISPLAYLEVEL(4, "OK \n");
233
234 DISPLAYLEVEL(4, "test%3i : compress with duplicated context : ", testNb++);
235 cSizeOrig = cSize;
236 cSize = 0;
237 result = ZSTD_compressContinue(ctxDuplicated, compressedBuffer, ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH), (const char*)CNBuffer + dictSize, COMPRESSIBLE_NOISE_LENGTH - dictSize);
238 if (ZSTD_isError(result)) goto _output_error;
239 cSize += result;
240 result = ZSTD_compressEnd(ctxDuplicated, (char*)compressedBuffer+cSize, ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH)-cSize);
241 if (ZSTD_isError(result)) goto _output_error;
242 cSize += result;
243 if (cSize != cSizeOrig) goto _output_error; /* should be identical == have same size */
244 ZSTD_freeCCtx(ctxDuplicated);
245 DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
246
247 DISPLAYLEVEL(4, "test%3i : frame built with duplicated context should be decompressible : ", testNb++);
248 result = ZSTD_decompress_usingDict(dctx,
249 decodedBuffer, COMPRESSIBLE_NOISE_LENGTH,
250 compressedBuffer, cSize,
251 CNBuffer, dictSize);
252 if (ZSTD_isError(result)) goto _output_error;
Yann Colletbf42c8e2016-01-09 01:08:23 +0100253 if (result != COMPRESSIBLE_NOISE_LENGTH - dictSize) goto _output_error;
Yann Collet60096272016-01-08 17:27:50 +0100254 ZSTD_freeDCtx(dctx);
255 DISPLAYLEVEL(4, "OK \n");
256 }
257
Yann Collet4856a002015-01-24 01:58:16 +0100258 /* Decompression defense tests */
259 DISPLAYLEVEL(4, "test%3i : Check input length for magic number : ", testNb++);
260 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, CNBuffer, 3);
261 if (!ZSTD_isError(result)) goto _output_error;
Yann Collet977f1f32016-01-21 15:38:47 +0100262 if (result != (size_t)-ZSTD_error_srcSize_wrong) goto _output_error;
Yann Collet4856a002015-01-24 01:58:16 +0100263 DISPLAYLEVEL(4, "OK \n");
264
265 DISPLAYLEVEL(4, "test%3i : Check magic Number : ", testNb++);
266 ((char*)(CNBuffer))[0] = 1;
267 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, CNBuffer, 4);
268 if (!ZSTD_isError(result)) goto _output_error;
Yann Collet4856a002015-01-24 01:58:16 +0100269 DISPLAYLEVEL(4, "OK \n");
270
Yann Colletbf42c8e2016-01-09 01:08:23 +0100271 /* block API tests */
272 {
273 ZSTD_CCtx* const cctx = ZSTD_createCCtx();
274 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
275 const size_t blockSize = 100 KB;
Yann Colletb0125102016-01-09 02:00:10 +0100276 const size_t dictSize = 16 KB;
Yann Colletbf42c8e2016-01-09 01:08:23 +0100277
278 /* basic block compression */
279 DISPLAYLEVEL(4, "test%3i : Block compression test : ", testNb++);
280 result = ZSTD_compressBegin(cctx, 5);
281 if (ZSTD_isError(result)) goto _output_error;
282 cSize = ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize);
283 if (ZSTD_isError(cSize)) goto _output_error;
284 DISPLAYLEVEL(4, "OK \n");
285
286 DISPLAYLEVEL(4, "test%3i : Block decompression test : ", testNb++);
Yann Collet7b51a292016-01-26 15:58:49 +0100287 result = ZSTD_decompressBegin(dctx);
Yann Colletbf42c8e2016-01-09 01:08:23 +0100288 if (ZSTD_isError(result)) goto _output_error;
289 result = ZSTD_decompressBlock(dctx, decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize);
290 if (ZSTD_isError(result)) goto _output_error;
291 if (result != blockSize) goto _output_error;
292 DISPLAYLEVEL(4, "OK \n");
293
Yann Colletb0125102016-01-09 02:00:10 +0100294 /* dictionary block compression */
295 DISPLAYLEVEL(4, "test%3i : Dictionary Block compression test : ", testNb++);
296 result = ZSTD_compressBegin(cctx, 5);
297 if (ZSTD_isError(result)) goto _output_error;
298 result = ZSTD_compress_insertDictionary(cctx, CNBuffer, dictSize);
299 if (ZSTD_isError(result)) goto _output_error;
300 cSize = ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize, blockSize);
301 if (ZSTD_isError(cSize)) goto _output_error;
302 DISPLAYLEVEL(4, "OK \n");
303
304 DISPLAYLEVEL(4, "test%3i : Dictionary Block decompression test : ", testNb++);
Yann Collet7b51a292016-01-26 15:58:49 +0100305 result = ZSTD_decompressBegin_usingDict(dctx, CNBuffer, dictSize);
Yann Colletb0125102016-01-09 02:00:10 +0100306 if (ZSTD_isError(result)) goto _output_error;
Yann Colletb0125102016-01-09 02:00:10 +0100307 result = ZSTD_decompressBlock(dctx, decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize);
308 if (ZSTD_isError(result)) goto _output_error;
309 if (result != blockSize) goto _output_error;
310 DISPLAYLEVEL(4, "OK \n");
311
Yann Colletbf42c8e2016-01-09 01:08:23 +0100312 ZSTD_freeCCtx(cctx);
313 ZSTD_freeDCtx(dctx);
314 }
315
Yann Collet213089c2015-06-18 07:43:16 -0800316 /* long rle test */
317 {
318 size_t sampleSize = 0;
319 DISPLAYLEVEL(4, "test%3i : Long RLE test : ", testNb++);
Yann Colletd5d9bc32015-08-23 23:13:49 +0100320 RDG_genBuffer(CNBuffer, sampleSize, compressibility, 0., randState);
Yann Collet213089c2015-06-18 07:43:16 -0800321 memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1);
322 sampleSize += 256 KB - 1;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100323 RDG_genBuffer((char*)CNBuffer+sampleSize, 96 KB, compressibility, 0., randState);
Yann Collet213089c2015-06-18 07:43:16 -0800324 sampleSize += 96 KB;
Yann Collet5be2dd22015-11-11 13:43:58 +0100325 cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize, 1);
Yann Collet213089c2015-06-18 07:43:16 -0800326 if (ZSTD_isError(cSize)) goto _output_error;
327 result = ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize);
328 if (ZSTD_isError(result)) goto _output_error;
329 if (result!=sampleSize) goto _output_error;
330 DISPLAYLEVEL(4, "OK \n");
331 }
332
Yann Collet4856a002015-01-24 01:58:16 +0100333_end:
334 free(CNBuffer);
335 free(compressedBuffer);
336 free(decodedBuffer);
337 return testResult;
338
339_output_error:
340 testResult = 1;
341 DISPLAY("Error detected in Unit tests ! \n");
342 goto _end;
343}
344
345
346static size_t findDiff(const void* buf1, const void* buf2, size_t max)
347{
Yann Collet213089c2015-06-18 07:43:16 -0800348 const BYTE* b1 = (const BYTE*)buf1;
349 const BYTE* b2 = (const BYTE*)buf2;
Yann Collet4856a002015-01-24 01:58:16 +0100350 size_t i;
351 for (i=0; i<max; i++)
352 {
353 if (b1[i] != b2[i]) break;
354 }
355 return i;
356}
357
358# define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
359 DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
360
361static const U32 maxSrcLog = 23;
362static const U32 maxSampleLog = 22;
363
364int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibility)
365{
Yann Colletd5d9bc32015-08-23 23:13:49 +0100366 BYTE* cNoiseBuffer[5];
Yann Collet4856a002015-01-24 01:58:16 +0100367 BYTE* srcBuffer;
368 BYTE* cBuffer;
369 BYTE* dstBuffer;
Yann Collete47c4e52015-12-05 09:23:53 +0100370 BYTE* mirrorBuffer;
Yann Collet4856a002015-01-24 01:58:16 +0100371 size_t srcBufferSize = (size_t)1<<maxSrcLog;
372 size_t dstBufferSize = (size_t)1<<maxSampleLog;
373 size_t cBufferSize = ZSTD_compressBound(dstBufferSize);
374 U32 result = 0;
375 U32 testNb = 0;
376 U32 coreSeed = seed, lseed = 0;
Yann Colletecd651b2016-01-07 15:35:18 +0100377 ZSTD_CCtx* refCtx;
Yann Collet2f648e52015-10-29 18:23:38 +0100378 ZSTD_CCtx* ctx;
Yann Collete47c4e52015-12-05 09:23:53 +0100379 ZSTD_DCtx* dctx;
Yann Collet553cf6a2015-12-04 17:25:26 +0100380 U32 startTime = FUZ_GetMilliStart();
Yann Collet4856a002015-01-24 01:58:16 +0100381
382 /* allocation */
Yann Colletecd651b2016-01-07 15:35:18 +0100383 refCtx = ZSTD_createCCtx();
Yann Collet2f648e52015-10-29 18:23:38 +0100384 ctx = ZSTD_createCCtx();
Yann Collete47c4e52015-12-05 09:23:53 +0100385 dctx= ZSTD_createDCtx();
Yann Colletd5d9bc32015-08-23 23:13:49 +0100386 cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
387 cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize);
388 cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize);
389 cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize);
390 cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize);
Yann Collet213089c2015-06-18 07:43:16 -0800391 dstBuffer = (BYTE*)malloc (dstBufferSize);
Yann Collete47c4e52015-12-05 09:23:53 +0100392 mirrorBuffer = (BYTE*)malloc (dstBufferSize);
Yann Collet213089c2015-06-18 07:43:16 -0800393 cBuffer = (BYTE*)malloc (cBufferSize);
Yann Collete47c4e52015-12-05 09:23:53 +0100394 CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4]
Yann Colletecd651b2016-01-07 15:35:18 +0100395 || !dstBuffer || !mirrorBuffer || !cBuffer || !refCtx || !ctx || !dctx,
Yann Colletd5d9bc32015-08-23 23:13:49 +0100396 "Not enough memory, fuzzer tests cancelled");
Yann Collet4856a002015-01-24 01:58:16 +0100397
Yann Colletd5d9bc32015-08-23 23:13:49 +0100398 /* Create initial samples */
399 RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed); /* pure noise */
400 RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed); /* barely compressible */
401 RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);
402 RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */
403 RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */
404 srcBuffer = cNoiseBuffer[2];
Yann Collet4856a002015-01-24 01:58:16 +0100405
406 /* catch up testNb */
Yann Colletf3cb79b2015-08-20 00:02:43 +0100407 for (testNb=1; testNb < startTest; testNb++)
Yann Collet4856a002015-01-24 01:58:16 +0100408 FUZ_rand(&coreSeed);
409
410 /* test loop */
Yann Collet553cf6a2015-12-04 17:25:26 +0100411 for ( ; (testNb <= nbTests) || (FUZ_GetMilliSpan(startTime) < g_testTime); testNb++ )
Yann Collet4856a002015-01-24 01:58:16 +0100412 {
Yann Collet417890c2015-12-04 17:16:37 +0100413 size_t sampleSize, sampleStart, maxTestSize, totalTestSize;
Yann Collete47c4e52015-12-05 09:23:53 +0100414 size_t cSize, dSize, dSupSize, errorCode, totalCSize, totalGenSize;
Yann Collet417890c2015-12-04 17:16:37 +0100415 U32 sampleSizeLog, buffNb, cLevelMod, nbChunks, n;
Yann Collet5835e1b2016-01-05 01:44:36 +0100416 XXH64_CREATESTATE_STATIC(xxh64);
Yann Collet4856a002015-01-24 01:58:16 +0100417 U64 crcOrig, crcDest;
Yann Collet2f648e52015-10-29 18:23:38 +0100418 int cLevel;
Yann Collet110cc142015-11-19 12:02:28 +0100419 BYTE* sampleBuffer;
Yann Collet4bfe4152015-12-06 13:18:37 +0100420 const BYTE* dict;
421 size_t dictSize;
Yann Collet4856a002015-01-24 01:58:16 +0100422
423 /* init */
Yann Collet1c2ddba2015-12-04 17:45:35 +0100424 if (nbTests >= testNb)
425 { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); }
426 else { DISPLAYUPDATE(2, "\r%6u ", testNb); }
427
Yann Collet4856a002015-01-24 01:58:16 +0100428 FUZ_rand(&coreSeed);
429 lseed = coreSeed ^ prime1;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100430 buffNb = FUZ_rand(&lseed) & 127;
431 if (buffNb & 7) buffNb=2;
432 else
433 {
434 buffNb >>= 3;
435 if (buffNb & 7)
436 {
437 const U32 tnb[2] = { 1, 3 };
438 buffNb = tnb[buffNb >> 3];
439 }
440 else
441 {
442 const U32 tnb[2] = { 0, 4 };
443 buffNb = tnb[buffNb >> 3];
444 }
445 }
446 srcBuffer = cNoiseBuffer[buffNb];
Yann Collet4856a002015-01-24 01:58:16 +0100447 sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
Yann Colletf4ce8912015-08-11 14:18:45 +0100448 sampleSize = (size_t)1 << sampleSizeLog;
Yann Collet4856a002015-01-24 01:58:16 +0100449 sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
450 sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);
Yann Collet4856a002015-01-24 01:58:16 +0100451
Yann Collet110cc142015-11-19 12:02:28 +0100452 /* create sample buffer (to catch read error with valgrind & sanitizers) */
453 sampleBuffer = (BYTE*)malloc(sampleSize);
454 CHECK (sampleBuffer==NULL, "not enough memory for sample buffer");
455 memcpy(sampleBuffer, srcBuffer + sampleStart, sampleSize);
456 crcOrig = XXH64(sampleBuffer, sampleSize, 0);
457
458 /* compression test */
Yann Collet4c7aae32015-11-08 14:24:59 +0100459 cLevelMod = MAX(1, 38 - (int)(MAX(9, sampleSizeLog) * 2)); /* use high compression levels with small samples, for speed */
460 cLevel = (FUZ_rand(&lseed) % cLevelMod) +1;
Yann Colletdc5e3e92015-11-20 09:23:56 +0100461 cSize = ZSTD_compressCCtx(ctx, cBuffer, cBufferSize, sampleBuffer, sampleSize, cLevel);
Yann Collet5be2dd22015-11-11 13:43:58 +0100462 CHECK(ZSTD_isError(cSize), "ZSTD_compressCCtx failed");
Yann Collet4856a002015-01-24 01:58:16 +0100463
Yann Colletf3cb79b2015-08-20 00:02:43 +0100464 /* compression failure test : too small dest buffer */
Yann Colletd5d9bc32015-08-23 23:13:49 +0100465 if (cSize > 3)
Yann Collete9853b22015-08-07 19:07:32 +0100466 {
Yann Colletf4ce8912015-08-11 14:18:45 +0100467 const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
468 const size_t tooSmallSize = cSize - missing;
Yann Collet602834f2015-08-20 07:46:10 +0100469 static const U32 endMark = 0x4DC2B1A9;
470 U32 endCheck;
471 memcpy(dstBuffer+tooSmallSize, &endMark, 4);
Yann Colletdc5e3e92015-11-20 09:23:56 +0100472 errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, sampleBuffer, sampleSize, cLevel);
Yann Collet5be2dd22015-11-11 13:43:58 +0100473 CHECK(!ZSTD_isError(errorCode), "ZSTD_compressCCtx should have failed ! (buffer too small : %u < %u)", (U32)tooSmallSize, (U32)cSize);
Yann Collet602834f2015-08-20 07:46:10 +0100474 memcpy(&endCheck, dstBuffer+tooSmallSize, 4);
Yann Collet5be2dd22015-11-11 13:43:58 +0100475 CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow");
Yann Collete9853b22015-08-07 19:07:32 +0100476 }
477
Yann Colletf3cb79b2015-08-20 00:02:43 +0100478 /* successfull decompression tests*/
Yann Collet4856a002015-01-24 01:58:16 +0100479 dSupSize = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1;
480 dSize = ZSTD_decompress(dstBuffer, sampleSize + dSupSize, cBuffer, cSize);
Yann Collet3e358272015-11-04 18:19:39 +0100481 CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (U32)sampleSize, (U32)cSize);
Yann Collet4856a002015-01-24 01:58:16 +0100482 crcDest = XXH64(dstBuffer, sampleSize, 0);
Yann Collet110cc142015-11-19 12:02:28 +0100483 CHECK(crcOrig != crcDest, "decompression result corrupted (pos %u / %u)", (U32)findDiff(sampleBuffer, dstBuffer, sampleSize), (U32)sampleSize);
484
485 free(sampleBuffer); /* no longer useful after this point */
Yann Colletf3cb79b2015-08-20 00:02:43 +0100486
487 /* truncated src decompression test */
488 {
Yann Colletf3cb79b2015-08-20 00:02:43 +0100489 const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
490 const size_t tooSmallSize = cSize - missing;
491 void* cBufferTooSmall = malloc(tooSmallSize); /* valgrind will catch overflows */
Yann Colletf3cb79b2015-08-20 00:02:43 +0100492 CHECK(cBufferTooSmall == NULL, "not enough memory !");
Yann Colletd5d9bc32015-08-23 23:13:49 +0100493 memcpy(cBufferTooSmall, cBuffer, tooSmallSize);
Yann Colletf3cb79b2015-08-20 00:02:43 +0100494 errorCode = ZSTD_decompress(dstBuffer, dstBufferSize, cBufferTooSmall, tooSmallSize);
495 CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed ! (truncated src buffer)");
496 free(cBufferTooSmall);
497 }
498
499 /* too small dst decompression test */
500 if (sampleSize > 3)
501 {
Yann Colletf3cb79b2015-08-20 00:02:43 +0100502 const size_t missing = (FUZ_rand(&lseed) % (sampleSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
503 const size_t tooSmallSize = sampleSize - missing;
504 static const BYTE token = 0xA9;
505 dstBuffer[tooSmallSize] = token;
506 errorCode = ZSTD_decompress(dstBuffer, tooSmallSize, cBuffer, cSize);
507 CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed : %u > %u (dst buffer too small)", (U32)errorCode, (U32)tooSmallSize);
508 CHECK(dstBuffer[tooSmallSize] != token, "ZSTD_decompress : dst buffer overflow");
509 }
Yann Collet997f9ee2015-08-21 02:44:20 +0100510
511 /* noisy src decompression test */
512 if (cSize > 6)
513 {
514 const U32 maxNbBits = FUZ_highbit32((U32)(cSize-4));
515 size_t pos = 4; /* preserve magic number (too easy to detect) */
516 U32 nbBits = FUZ_rand(&lseed) % maxNbBits;
517 size_t mask = (1<<nbBits) - 1;
518 size_t skipLength = FUZ_rand(&lseed) & mask;
519 pos += skipLength;
520
521 while (pos < cSize)
522 {
523 /* add noise */
524 size_t noiseStart, noiseLength;
525 nbBits = FUZ_rand(&lseed) % maxNbBits;
526 if (nbBits>0) nbBits--;
527 mask = (1<<nbBits) - 1;
528 noiseLength = (FUZ_rand(&lseed) & mask) + 1;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100529 if ( pos+noiseLength > cSize ) noiseLength = cSize-pos;
Yann Collet997f9ee2015-08-21 02:44:20 +0100530 noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseLength);
531 memcpy(cBuffer + pos, srcBuffer + noiseStart, noiseLength);
532 pos += noiseLength;
533
534 /* keep some original src */
535 nbBits = FUZ_rand(&lseed) % maxNbBits;
536 mask = (1<<nbBits) - 1;
537 skipLength = FUZ_rand(&lseed) & mask;
538 pos += skipLength;
539 }
540
541 /* decompress noisy source */
542 {
Yann Colletd5d9bc32015-08-23 23:13:49 +0100543 U32 noiseSrc = FUZ_rand(&lseed) % 5;
Yann Collet997f9ee2015-08-21 02:44:20 +0100544 const U32 endMark = 0xA9B1C3D6;
545 U32 endCheck;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100546 srcBuffer = cNoiseBuffer[noiseSrc];
Yann Collet997f9ee2015-08-21 02:44:20 +0100547 memcpy(dstBuffer+sampleSize, &endMark, 4);
548 errorCode = ZSTD_decompress(dstBuffer, sampleSize, cBuffer, cSize);
549 /* result *may* be an unlikely success, but even then, it must strictly respect dest buffer boundaries */
550 CHECK((!ZSTD_isError(errorCode)) && (errorCode>sampleSize),
551 "ZSTD_decompress on noisy src : result is too large : %u > %u (dst buffer)", (U32)errorCode, (U32)sampleSize);
552 memcpy(&endCheck, dstBuffer+sampleSize, 4);
553 CHECK(endMark!=endCheck, "ZSTD_decompress on noisy src : dst buffer overflow");
554 }
555 }
Yann Collet417890c2015-12-04 17:16:37 +0100556
Yann Collete47c4e52015-12-05 09:23:53 +0100557 /* Streaming compression of scattered segments test */
Yann Collet5835e1b2016-01-05 01:44:36 +0100558 XXH64_reset(xxh64, 0);
Yann Collet417890c2015-12-04 17:16:37 +0100559 nbChunks = (FUZ_rand(&lseed) & 127) + 2;
560 sampleSizeLog = FUZ_rand(&lseed) % maxSrcLog;
561 maxTestSize = (size_t)1 << sampleSizeLog;
562 maxTestSize += FUZ_rand(&lseed) & (maxTestSize-1);
Yann Collete47c4e52015-12-05 09:23:53 +0100563 if (maxTestSize >= dstBufferSize) maxTestSize = dstBufferSize-1;
Yann Collet4bfe4152015-12-06 13:18:37 +0100564
565 sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
566 sampleSize = (size_t)1 << sampleSizeLog;
567 sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
568 sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);
569 dict = srcBuffer + sampleStart;
570 dictSize = sampleSize;
571
Yann Colletecd651b2016-01-07 15:35:18 +0100572 errorCode = ZSTD_compressBegin(refCtx, (FUZ_rand(&lseed) % (20 - (sampleSizeLog/3))) + 1);
573 CHECK (ZSTD_isError(errorCode), "start streaming error : %s", ZSTD_getErrorName(errorCode));
574 errorCode = ZSTD_compress_insertDictionary(refCtx, dict, dictSize);
Yann Collet4bfe4152015-12-06 13:18:37 +0100575 CHECK (ZSTD_isError(errorCode), "dictionary insertion error : %s", ZSTD_getErrorName(errorCode));
Yann Collet7b51a292016-01-26 15:58:49 +0100576 errorCode = ZSTD_copyCCtx(ctx, refCtx);
Yann Colletecd651b2016-01-07 15:35:18 +0100577 CHECK (ZSTD_isError(errorCode), "context duplication error : %s", ZSTD_getErrorName(errorCode));
578 totalTestSize = 0; cSize = 0;
Yann Collet417890c2015-12-04 17:16:37 +0100579 for (n=0; n<nbChunks; n++)
580 {
581 sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
582 sampleSize = (size_t)1 << sampleSizeLog;
583 sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
584 sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);
585
586 if (cBufferSize-cSize < ZSTD_compressBound(sampleSize))
587 /* avoid invalid dstBufferTooSmall */
588 break;
Yann Collete47c4e52015-12-05 09:23:53 +0100589 if (totalTestSize+sampleSize > maxTestSize) break;
Yann Collet417890c2015-12-04 17:16:37 +0100590
591 errorCode = ZSTD_compressContinue(ctx, cBuffer+cSize, cBufferSize-cSize, srcBuffer+sampleStart, sampleSize);
592 CHECK (ZSTD_isError(errorCode), "multi-segments compression error : %s", ZSTD_getErrorName(errorCode));
593 cSize += errorCode;
594
Yann Collet5835e1b2016-01-05 01:44:36 +0100595 XXH64_update(xxh64, srcBuffer+sampleStart, sampleSize);
Yann Collete47c4e52015-12-05 09:23:53 +0100596 memcpy(mirrorBuffer + totalTestSize, srcBuffer+sampleStart, sampleSize);
Yann Collet417890c2015-12-04 17:16:37 +0100597 totalTestSize += sampleSize;
Yann Collet417890c2015-12-04 17:16:37 +0100598 }
599 errorCode = ZSTD_compressEnd(ctx, cBuffer+cSize, cBufferSize-cSize);
600 CHECK (ZSTD_isError(errorCode), "multi-segments epilogue error : %s", ZSTD_getErrorName(errorCode));
601 cSize += errorCode;
Yann Collet5835e1b2016-01-05 01:44:36 +0100602 crcOrig = XXH64_digest(xxh64);
Yann Collete47c4e52015-12-05 09:23:53 +0100603
604 /* streaming decompression test */
Yann Collet7b51a292016-01-26 15:58:49 +0100605 errorCode = ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
Yann Collete47c4e52015-12-05 09:23:53 +0100606 CHECK (ZSTD_isError(errorCode), "cannot init DCtx : %s", ZSTD_getErrorName(errorCode));
607 totalCSize = 0;
608 totalGenSize = 0;
609 while (totalCSize < cSize)
610 {
611 size_t inSize = ZSTD_nextSrcSizeToDecompress(dctx);
612 size_t genSize = ZSTD_decompressContinue(dctx, dstBuffer+totalGenSize, dstBufferSize-totalGenSize, cBuffer+totalCSize, inSize);
613 CHECK (ZSTD_isError(genSize), "streaming decompression error : %s", ZSTD_getErrorName(genSize));
614 totalGenSize += genSize;
615 totalCSize += inSize;
616 }
617 CHECK (ZSTD_nextSrcSizeToDecompress(dctx) != 0, "frame not fully decoded");
618 CHECK (totalGenSize != totalTestSize, "decompressed data : wrong size")
619 CHECK (totalCSize != cSize, "compressed data should be fully read")
620 crcDest = XXH64(dstBuffer, totalTestSize, 0);
621 if (crcDest!=crcOrig)
622 errorCode = findDiff(mirrorBuffer, dstBuffer, totalTestSize);
623 CHECK (crcDest!=crcOrig, "streaming decompressed data corrupted : byte %u / %u (%02X!=%02X)",
624 (U32)errorCode, (U32)totalTestSize, dstBuffer[errorCode], mirrorBuffer[errorCode]);
625
Yann Collet4856a002015-01-24 01:58:16 +0100626 }
Yann Collet1c2ddba2015-12-04 17:45:35 +0100627 DISPLAY("\r%u fuzzer tests completed \n", testNb-1);
Yann Collet4856a002015-01-24 01:58:16 +0100628
629_cleanup:
Yann Colletecd651b2016-01-07 15:35:18 +0100630 ZSTD_freeCCtx(refCtx);
Yann Collet2f648e52015-10-29 18:23:38 +0100631 ZSTD_freeCCtx(ctx);
Yann Collete47c4e52015-12-05 09:23:53 +0100632 ZSTD_freeDCtx(dctx);
Yann Colletd5d9bc32015-08-23 23:13:49 +0100633 free(cNoiseBuffer[0]);
634 free(cNoiseBuffer[1]);
635 free(cNoiseBuffer[2]);
636 free(cNoiseBuffer[3]);
637 free(cNoiseBuffer[4]);
Yann Collet4856a002015-01-24 01:58:16 +0100638 free(cBuffer);
639 free(dstBuffer);
Yann Collete47c4e52015-12-05 09:23:53 +0100640 free(mirrorBuffer);
Yann Collet4856a002015-01-24 01:58:16 +0100641 return result;
642
643_output_error:
644 result = 1;
645 goto _cleanup;
646}
647
648
649/*********************************************************
650* Command line
651*********************************************************/
652int FUZ_usage(char* programName)
653{
654 DISPLAY( "Usage :\n");
655 DISPLAY( " %s [args]\n", programName);
656 DISPLAY( "\n");
657 DISPLAY( "Arguments :\n");
658 DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault);
659 DISPLAY( " -s# : Select seed (default:prompt user)\n");
660 DISPLAY( " -t# : Select starting test number (default:0)\n");
Yann Collete9853b22015-08-07 19:07:32 +0100661 DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
Yann Collet4856a002015-01-24 01:58:16 +0100662 DISPLAY( " -v : verbose\n");
Yann Collete9853b22015-08-07 19:07:32 +0100663 DISPLAY( " -p : pause at the end\n");
Yann Collet4856a002015-01-24 01:58:16 +0100664 DISPLAY( " -h : display help and exit\n");
665 return 0;
666}
667
668
669int main(int argc, char** argv)
670{
671 U32 seed=0;
672 int seedset=0;
673 int argNb;
674 int nbTests = nbTestsDefault;
675 int testNb = 0;
676 int proba = FUZ_COMPRESSIBILITY_DEFAULT;
677 int result=0;
678 U32 mainPause = 0;
679 char* programName;
680
681 /* Check command line */
682 programName = argv[0];
683 for(argNb=1; argNb<argc; argNb++)
684 {
685 char* argument = argv[argNb];
686
687 if(!argument) continue; /* Protection if argument empty */
688
689 /* Handle commands. Aggregated commands are allowed */
690 if (argument[0]=='-')
691 {
692 argument++;
693
694 while (*argument!=0)
695 {
696 switch(*argument)
697 {
698 case 'h':
699 return FUZ_usage(programName);
700 case 'v':
701 argument++;
702 g_displayLevel=4;
703 break;
704 case 'q':
705 argument++;
706 g_displayLevel--;
707 break;
708 case 'p': /* pause at the end */
709 argument++;
710 mainPause = 1;
711 break;
712
713 case 'i':
Yann Collet553cf6a2015-12-04 17:25:26 +0100714 argument++; g_testTime=0;
Yann Collet4856a002015-01-24 01:58:16 +0100715 nbTests=0;
716 while ((*argument>='0') && (*argument<='9'))
717 {
718 nbTests *= 10;
719 nbTests += *argument - '0';
720 argument++;
721 }
722 break;
723
Yann Collet553cf6a2015-12-04 17:25:26 +0100724 case 'T':
725 argument++;
726 nbTests=0; g_testTime=0;
727 while ((*argument>='0') && (*argument<='9'))
728 {
729 g_testTime *= 10;
730 g_testTime += *argument - '0';
731 argument++;
732 }
733 if (*argument=='m') g_testTime *=60, argument++;
734 if (*argument=='n') argument++;
735 g_testTime *= 1000;
736 break;
737
Yann Collet4856a002015-01-24 01:58:16 +0100738 case 's':
739 argument++;
740 seed=0;
741 seedset=1;
742 while ((*argument>='0') && (*argument<='9'))
743 {
744 seed *= 10;
745 seed += *argument - '0';
746 argument++;
747 }
748 break;
749
750 case 't':
751 argument++;
752 testNb=0;
753 while ((*argument>='0') && (*argument<='9'))
754 {
755 testNb *= 10;
756 testNb += *argument - '0';
757 argument++;
758 }
759 break;
760
761 case 'P': /* compressibility % */
762 argument++;
763 proba=0;
764 while ((*argument>='0') && (*argument<='9'))
765 {
766 proba *= 10;
767 proba += *argument - '0';
768 argument++;
769 }
770 if (proba<0) proba=0;
771 if (proba>100) proba=100;
772 break;
773
774 default:
775 return FUZ_usage(programName);
776 }
777 }
778 }
779 }
780
781 /* Get Seed */
782 DISPLAY("Starting zstd tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION);
783
784 if (!seedset) seed = FUZ_GetMilliStart() % 10000;
785 DISPLAY("Seed = %u\n", seed);
786 if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) DISPLAY("Compressibility : %i%%\n", proba);
787
Yann Collet4856a002015-01-24 01:58:16 +0100788 if (testNb==0) result = basicUnitTests(0, ((double)proba) / 100); /* constant seed for predictability */
789 if (!result)
790 result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
791 if (mainPause)
792 {
Yann Colletb5e06dc2015-07-04 23:20:56 -0800793 int unused;
Yann Collet4856a002015-01-24 01:58:16 +0100794 DISPLAY("Press Enter \n");
Yann Colletb5e06dc2015-07-04 23:20:56 -0800795 unused = getchar();
796 (void)unused;
Yann Collet4856a002015-01-24 01:58:16 +0100797 }
798 return result;
799}