1 /*
2 frameTest - test tool for lz4frame
3 Copyright (C) Yann Collet 2014
4 GPL v2 License
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 You can contact the author at :
21 - LZ4 source repository : http://code.google.com/p/lz4/
22 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
23 */
24
25 /**************************************
26 Compiler specific
27 **************************************/
28 #define _CRT_SECURE_NO_WARNINGS // fgets
29 #ifdef _MSC_VER /* Visual Studio */
30 # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
31 # pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
32 #endif
33 #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
34 #ifdef __GNUC__
35 # 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) */
36 # 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) */
37 #endif
38
39
40 /**************************************
41 Includes
42 **************************************/
43 #include <stdlib.h> // free
44 #include <stdio.h> // fgets, sscanf
45 #include <sys/timeb.h> // timeb
46 #include <string.h> // strcmp
47 #include "lz4frame_static.h"
48 #include "xxhash.h" // XXH64
49
50
51 /**************************************
52 Basic Types
53 **************************************/
54 #if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
55 # include <stdint.h>
56 typedef uint8_t BYTE;
57 typedef uint16_t U16;
58 typedef uint32_t U32;
59 typedef int32_t S32;
60 typedef uint64_t U64;
61 #else
62 typedef unsigned char BYTE;
63 typedef unsigned short U16;
64 typedef unsigned int U32;
65 typedef signed int S32;
66 typedef unsigned long long U64;
67 #endif
68
69
70 /**************************************
71 Constants
72 **************************************/
73 #ifndef LZ4_VERSION
74 # define LZ4_VERSION ""
75 #endif
76
77 #define KB *(1U<<10)
78 #define MB *(1U<<20)
79 #define GB *(1U<<30)
80
81 static const U32 nbTestsDefault = 256 KB;
82 #define COMPRESSIBLE_NOISE_LENGTH (2 MB)
83 #define FUZ_COMPRESSIBILITY_DEFAULT 50
84 static const U32 prime1 = 2654435761U;
85 static const U32 prime2 = 2246822519U;
86
87
88
89 /**************************************
90 Macros
91 **************************************/
92 #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
93 #define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
94 #define DISPLAYUPDATE(l, ...) if (displayLevel>=l) { \
95 if ((FUZ_GetMilliSpan(g_time) > refreshRate) || (displayLevel>=4)) \
96 { g_time = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); \
97 if (displayLevel>=4) fflush(stdout); } }
98 static const U32 refreshRate = 150;
99 static U32 g_time = 0;
100
101
102 /*****************************************
103 Local Parameters
104 *****************************************/
105 static U32 no_prompt = 0;
106 static char* programName;
107 static U32 displayLevel = 2;
108 static U32 pause = 0;
109
110
111 /*********************************************************
112 Fuzzer functions
113 *********************************************************/
FUZ_GetMilliStart(void)114 static U32 FUZ_GetMilliStart(void)
115 {
116 struct timeb tb;
117 U32 nCount;
118 ftime( &tb );
119 nCount = (U32) (((tb.time & 0xFFFFF) * 1000) + tb.millitm);
120 return nCount;
121 }
122
123
FUZ_GetMilliSpan(U32 nTimeStart)124 static U32 FUZ_GetMilliSpan(U32 nTimeStart)
125 {
126 U32 nCurrent = FUZ_GetMilliStart();
127 U32 nSpan = nCurrent - nTimeStart;
128 if (nTimeStart > nCurrent)
129 nSpan += 0x100000 * 1000;
130 return nSpan;
131 }
132
133
134 # define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
FUZ_rand(unsigned int * src)135 unsigned int FUZ_rand(unsigned int* src)
136 {
137 U32 rand32 = *src;
138 rand32 *= prime1;
139 rand32 += prime2;
140 rand32 = FUZ_rotl32(rand32, 13);
141 *src = rand32;
142 return rand32 >> 5;
143 }
144
145
146 #define FUZ_RAND15BITS (FUZ_rand(seed) & 0x7FFF)
147 #define FUZ_RANDLENGTH ( (FUZ_rand(seed) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
FUZ_fillCompressibleNoiseBuffer(void * buffer,unsigned bufferSize,double proba,U32 * seed)148 static void FUZ_fillCompressibleNoiseBuffer(void* buffer, unsigned bufferSize, double proba, U32* seed)
149 {
150 BYTE* BBuffer = (BYTE*)buffer;
151 unsigned pos = 0;
152 U32 P32 = (U32)(32768 * proba);
153
154 // First Byte
155 BBuffer[pos++] = (BYTE)(FUZ_rand(seed));
156
157 while (pos < bufferSize)
158 {
159 // Select : Literal (noise) or copy (within 64K)
160 if (FUZ_RAND15BITS < P32)
161 {
162 // Copy (within 64K)
163 unsigned match, end;
164 unsigned length = FUZ_RANDLENGTH + 4;
165 unsigned offset = FUZ_RAND15BITS + 1;
166 if (offset > pos) offset = pos;
167 if (pos + length > bufferSize) length = bufferSize - pos;
168 match = pos - offset;
169 end = pos + length;
170 while (pos < end) BBuffer[pos++] = BBuffer[match++];
171 }
172 else
173 {
174 // Literal (noise)
175 unsigned end;
176 unsigned length = FUZ_RANDLENGTH;
177 if (pos + length > bufferSize) length = bufferSize - pos;
178 end = pos + length;
179 while (pos < end) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5);
180 }
181 }
182 }
183
184
FUZ_highbit(U32 v32)185 static unsigned FUZ_highbit(U32 v32)
186 {
187 unsigned nbBits = 0;
188 if (v32==0) return 0;
189 while (v32)
190 {
191 v32 >>= 1;
192 nbBits ++;
193 }
194 return nbBits;
195 }
196
197
basicTests(U32 seed,double compressibility)198 int basicTests(U32 seed, double compressibility)
199 {
200 int testResult = 0;
201 void* CNBuffer;
202 void* compressedBuffer;
203 void* decodedBuffer;
204 U32 randState = seed;
205 size_t cSize, testSize;
206 LZ4F_preferences_t prefs = { 0 };
207 LZ4F_decompressionContext_t dCtx;
208 U64 crcOrig;
209
210 // Create compressible test buffer
211 CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
212 compressedBuffer = malloc(LZ4F_compressFrameBound(COMPRESSIBLE_NOISE_LENGTH, NULL));
213 decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
214 FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState);
215 crcOrig = XXH64(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
216
217 // Trivial tests : one-step frame
218 testSize = COMPRESSIBLE_NOISE_LENGTH;
219 DISPLAYLEVEL(3, "Using NULL preferences : \n");
220 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL);
221 if (LZ4F_isError(cSize)) goto _output_error;
222 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
223
224 DISPLAYLEVEL(3, "Decompression test : \n");
225 {
226 size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
227 size_t compressedBufferSize = cSize;
228 BYTE* op = (BYTE*)decodedBuffer;
229 BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
230 BYTE* ip = (BYTE*)compressedBuffer;
231 BYTE* const iend = (BYTE*)compressedBuffer + cSize;
232 U64 crcDest;
233
234 LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
235 if (LZ4F_isError(errorCode)) goto _output_error;
236
237 DISPLAYLEVEL(3, "Single Block : \n");
238 errorCode = LZ4F_decompress(dCtx, decodedBuffer, &decodedBufferSize, compressedBuffer, &compressedBufferSize, NULL);
239 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
240 if (crcDest != crcOrig) goto _output_error;
241 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
242
243 DISPLAYLEVEL(3, "Byte after byte : \n");
244 while (ip < iend)
245 {
246 size_t oSize = oend-op;
247 size_t iSize = 1;
248 //DISPLAY("%7i \n", (int)(ip-(BYTE*)compressedBuffer));
249 errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
250 if (LZ4F_isError(errorCode)) goto _output_error;
251 op += oSize;
252 ip += iSize;
253 }
254 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
255 if (crcDest != crcOrig) goto _output_error;
256 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
257
258 errorCode = LZ4F_freeDecompressionContext(dCtx);
259 if (LZ4F_isError(errorCode)) goto _output_error;
260 }
261
262 DISPLAYLEVEL(3, "Using 64 KB block : \n");
263 prefs.frameInfo.blockSizeID = max64KB;
264 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
265 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
266 if (LZ4F_isError(cSize)) goto _output_error;
267 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
268
269 DISPLAYLEVEL(3, "without checksum : \n");
270 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
271 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
272 if (LZ4F_isError(cSize)) goto _output_error;
273 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
274
275 DISPLAYLEVEL(3, "Using 256 KB block : \n");
276 prefs.frameInfo.blockSizeID = max256KB;
277 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
278 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
279 if (LZ4F_isError(cSize)) goto _output_error;
280 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
281
282 DISPLAYLEVEL(3, "Decompression test : \n");
283 {
284 size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
285 unsigned maxBits = FUZ_highbit((U32)decodedBufferSize);
286 BYTE* op = (BYTE*)decodedBuffer;
287 BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
288 BYTE* ip = (BYTE*)compressedBuffer;
289 BYTE* const iend = (BYTE*)compressedBuffer + cSize;
290 U64 crcDest;
291
292 LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
293 if (LZ4F_isError(errorCode)) goto _output_error;
294
295 DISPLAYLEVEL(3, "random segment sizes : \n");
296 while (ip < iend)
297 {
298 unsigned nbBits = FUZ_rand(&randState) % maxBits;
299 size_t iSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
300 size_t oSize = oend-op;
301 if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
302 //DISPLAY("%7i : + %6i\n", (int)(ip-(BYTE*)compressedBuffer), (int)iSize);
303 errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
304 if (LZ4F_isError(errorCode)) goto _output_error;
305 op += oSize;
306 ip += iSize;
307 }
308 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
309 if (crcDest != crcOrig) goto _output_error;
310 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
311
312 errorCode = LZ4F_freeDecompressionContext(dCtx);
313 if (LZ4F_isError(errorCode)) goto _output_error;
314 }
315
316 DISPLAYLEVEL(3, "without checksum : \n");
317 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
318 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
319 if (LZ4F_isError(cSize)) goto _output_error;
320 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
321
322 DISPLAYLEVEL(3, "Using 1 MB block : \n");
323 prefs.frameInfo.blockSizeID = max1MB;
324 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
325 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
326 if (LZ4F_isError(cSize)) goto _output_error;
327 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
328
329 DISPLAYLEVEL(3, "without checksum : \n");
330 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
331 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
332 if (LZ4F_isError(cSize)) goto _output_error;
333 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
334
335 DISPLAYLEVEL(3, "Using 4 MB block : \n");
336 prefs.frameInfo.blockSizeID = max4MB;
337 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
338 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
339 if (LZ4F_isError(cSize)) goto _output_error;
340 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
341
342 DISPLAYLEVEL(3, "without checksum : \n");
343 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
344 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
345 if (LZ4F_isError(cSize)) goto _output_error;
346 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
347
348 DISPLAY("Basic tests completed \n");
349 _end:
350 free(CNBuffer);
351 free(compressedBuffer);
352 free(decodedBuffer);
353 return testResult;
354
355 _output_error:
356 testResult = 1;
357 DISPLAY("Error detected ! \n");
358 goto _end;
359 }
360
361
locateBuffDiff(const void * buff1,const void * buff2,size_t size,unsigned nonContiguous)362 static void locateBuffDiff(const void* buff1, const void* buff2, size_t size, unsigned nonContiguous)
363 {
364 int p=0;
365 BYTE* b1=(BYTE*)buff1;
366 BYTE* b2=(BYTE*)buff2;
367 if (nonContiguous)
368 {
369 DISPLAY("Non-contiguous output test (%i bytes)\n", (int)size);
370 return;
371 }
372 while (b1[p]==b2[p]) p++;
373 DISPLAY("Error at pos %i/%i : %02X != %02X \n", p, (int)size, b1[p], b2[p]);
374 }
375
376
377 static const U32 srcDataLength = 9 MB; /* needs to be > 2x4MB to test large blocks */
378
fuzzerTests(U32 seed,unsigned nbTests,unsigned startTest,double compressibility)379 int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressibility)
380 {
381 unsigned testResult = 0;
382 unsigned testNb = 0;
383 void* srcBuffer = NULL;
384 void* compressedBuffer = NULL;
385 void* decodedBuffer = NULL;
386 U32 coreRand = seed;
387 LZ4F_decompressionContext_t dCtx = NULL;
388 LZ4F_compressionContext_t cCtx = NULL;
389 size_t result;
390 XXH64_state_t xxh64;
391 # define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
392 DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
393
394 // Create buffers
395 result = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
396 CHECK(LZ4F_isError(result), "Allocation failed (error %i)", (int)result);
397 result = LZ4F_createCompressionContext(&cCtx, LZ4F_VERSION);
398 CHECK(LZ4F_isError(result), "Allocation failed (error %i)", (int)result);
399 srcBuffer = malloc(srcDataLength);
400 CHECK(srcBuffer==NULL, "srcBuffer Allocation failed");
401 compressedBuffer = malloc(LZ4F_compressFrameBound(srcDataLength, NULL));
402 CHECK(compressedBuffer==NULL, "compressedBuffer Allocation failed");
403 decodedBuffer = malloc(srcDataLength);
404 CHECK(decodedBuffer==NULL, "decodedBuffer Allocation failed");
405 FUZ_fillCompressibleNoiseBuffer(srcBuffer, srcDataLength, compressibility, &coreRand);
406
407 // jump to requested testNb
408 for (testNb =0; testNb < startTest; testNb++) (void)FUZ_rand(&coreRand); // sync randomizer
409
410 // main fuzzer loop
411 for ( ; testNb < nbTests; testNb++)
412 {
413 U32 randState = coreRand ^ prime1;
414 unsigned BSId = 4 + (FUZ_rand(&randState) & 3);
415 unsigned BMId = FUZ_rand(&randState) & 1;
416 unsigned CCflag = FUZ_rand(&randState) & 1;
417 unsigned autoflush = (FUZ_rand(&randState) & 7) == 2;
418 LZ4F_preferences_t prefs = { 0 };
419 LZ4F_compressOptions_t cOptions = { 0 };
420 LZ4F_decompressOptions_t dOptions = { 0 };
421 unsigned nbBits = (FUZ_rand(&randState) % (FUZ_highbit(srcDataLength-1) - 1)) + 1;
422 size_t srcSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
423 size_t srcStart = FUZ_rand(&randState) % (srcDataLength - srcSize);
424 size_t cSize;
425 U64 crcOrig, crcDecoded;
426 LZ4F_preferences_t* prefsPtr = &prefs;
427
428 (void)FUZ_rand(&coreRand); // update rand seed
429 prefs.frameInfo.blockMode = (blockMode_t)BMId;
430 prefs.frameInfo.blockSizeID = (blockSizeID_t)BSId;
431 prefs.frameInfo.contentChecksumFlag = (contentChecksum_t)CCflag;
432 prefs.autoFlush = autoflush;
433 prefs.compressionLevel = FUZ_rand(&randState) % 5;
434 if ((FUZ_rand(&randState)&0xF) == 1) prefsPtr = NULL;
435
436 DISPLAYUPDATE(2, "\r%5u ", testNb);
437 crcOrig = XXH64((BYTE*)srcBuffer+srcStart, (U32)srcSize, 1);
438
439 if ((FUZ_rand(&randState)&0xF) == 2)
440 {
441 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(srcSize, prefsPtr), (char*)srcBuffer + srcStart, srcSize, prefsPtr);
442 CHECK(LZ4F_isError(cSize), "LZ4F_compressFrame failed : error %i (%s)", (int)cSize, LZ4F_getErrorName(cSize));
443 }
444 else
445 {
446 const BYTE* ip = (const BYTE*)srcBuffer + srcStart;
447 const BYTE* const iend = ip + srcSize;
448 BYTE* op = (BYTE*)compressedBuffer;
449 BYTE* const oend = op + LZ4F_compressFrameBound(srcDataLength, NULL);
450 unsigned maxBits = FUZ_highbit((U32)srcSize);
451 result = LZ4F_compressBegin(cCtx, op, oend-op, prefsPtr);
452 CHECK(LZ4F_isError(result), "Compression header failed (error %i)", (int)result);
453 op += result;
454 while (ip < iend)
455 {
456 unsigned nbBitsSeg = FUZ_rand(&randState) % maxBits;
457 size_t iSize = (FUZ_rand(&randState) & ((1<<nbBitsSeg)-1)) + 1;
458 size_t oSize = LZ4F_compressBound(iSize, prefsPtr);
459 unsigned forceFlush = ((FUZ_rand(&randState) & 3) == 1);
460 if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
461 cOptions.stableSrc = ((FUZ_rand(&randState) & 3) == 1);
462
463 result = LZ4F_compressUpdate(cCtx, op, oSize, ip, iSize, &cOptions);
464 CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result);
465 op += result;
466 ip += iSize;
467
468 if (forceFlush)
469 {
470 result = LZ4F_flush(cCtx, op, oend-op, &cOptions);
471 CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result);
472 op += result;
473 }
474 }
475 result = LZ4F_compressEnd(cCtx, op, oend-op, &cOptions);
476 CHECK(LZ4F_isError(result), "Compression completion failed (error %i)", (int)result);
477 op += result;
478 cSize = op-(BYTE*)compressedBuffer;
479 }
480
481 {
482 const BYTE* ip = (const BYTE*)compressedBuffer;
483 const BYTE* const iend = ip + cSize;
484 BYTE* op = (BYTE*)decodedBuffer;
485 BYTE* const oend = op + srcDataLength;
486 unsigned maxBits = FUZ_highbit((U32)cSize);
487 unsigned nonContiguousDst = (FUZ_rand(&randState) & 3) == 1;
488 nonContiguousDst += FUZ_rand(&randState) & nonContiguousDst; /* 0=>0; 1=>1,2 */
489 XXH64_reset(&xxh64, 1);
490 while (ip < iend)
491 {
492 unsigned nbBitsI = (FUZ_rand(&randState) % (maxBits-1)) + 1;
493 unsigned nbBitsO = (FUZ_rand(&randState) % (maxBits)) + 1;
494 size_t iSize = (FUZ_rand(&randState) & ((1<<nbBitsI)-1)) + 1;
495 size_t oSize = (FUZ_rand(&randState) & ((1<<nbBitsO)-1)) + 2;
496 if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
497 if (oSize > (size_t)(oend-op)) oSize = oend-op;
498 dOptions.stableDst = FUZ_rand(&randState) & 1;
499 if (nonContiguousDst==2) dOptions.stableDst = 0;
500 //if (ip == compressedBuffer+62073) DISPLAY("oSize : %i : pos %i \n", (int)oSize, (int)(op-(BYTE*)decodedBuffer));
501 result = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, &dOptions);
502 //if (op+oSize >= (BYTE*)decodedBuffer+94727) DISPLAY("iSize : %i : pos %i \n", (int)iSize, (int)(ip-(BYTE*)compressedBuffer));
503 //if ((int)result<0) DISPLAY("iSize : %i : pos %i \n", (int)iSize, (int)(ip-(BYTE*)compressedBuffer));
504 if (result == (size_t)-ERROR_checksum_invalid) locateBuffDiff((BYTE*)srcBuffer+srcStart, decodedBuffer, srcSize, nonContiguousDst);
505 CHECK(LZ4F_isError(result), "Decompression failed (error %i:%s)", (int)result, LZ4F_getErrorName((LZ4F_errorCode_t)result));
506 XXH64_update(&xxh64, op, (U32)oSize);
507 op += oSize;
508 ip += iSize;
509 op += nonContiguousDst;
510 if (nonContiguousDst==2) op = decodedBuffer; // overwritten destination
511 }
512 CHECK(result != 0, "Frame decompression failed (error %i)", (int)result);
513 crcDecoded = XXH64_digest(&xxh64);
514 if (crcDecoded != crcOrig) locateBuffDiff((BYTE*)srcBuffer+srcStart, decodedBuffer, srcSize, nonContiguousDst);
515 CHECK(crcDecoded != crcOrig, "Decompression corruption");
516 }
517 }
518
519 DISPLAYLEVEL(2, "\rAll tests completed \n");
520
521 _end:
522 LZ4F_freeDecompressionContext(dCtx);
523 LZ4F_freeCompressionContext(cCtx);
524 free(srcBuffer);
525 free(compressedBuffer);
526 free(decodedBuffer);
527
528 if (pause)
529 {
530 DISPLAY("press enter to finish \n");
531 getchar();
532 }
533 return testResult;
534
535 _output_error:
536 testResult = 1;
537 goto _end;
538 }
539
540
FUZ_usage(void)541 int FUZ_usage(void)
542 {
543 DISPLAY( "Usage :\n");
544 DISPLAY( " %s [args]\n", programName);
545 DISPLAY( "\n");
546 DISPLAY( "Arguments :\n");
547 DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault);
548 DISPLAY( " -s# : Select seed (default:prompt user)\n");
549 DISPLAY( " -t# : Select starting test number (default:0)\n");
550 DISPLAY( " -p# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
551 DISPLAY( " -v : verbose\n");
552 DISPLAY( " -h : display help and exit\n");
553 return 0;
554 }
555
556
main(int argc,char ** argv)557 int main(int argc, char** argv)
558 {
559 U32 seed=0;
560 int seedset=0;
561 int argNb;
562 int nbTests = nbTestsDefault;
563 int testNb = 0;
564 int proba = FUZ_COMPRESSIBILITY_DEFAULT;
565 int result=0;
566
567 // Check command line
568 programName = argv[0];
569 for(argNb=1; argNb<argc; argNb++)
570 {
571 char* argument = argv[argNb];
572
573 if(!argument) continue; // Protection if argument empty
574
575 // Decode command (note : aggregated commands are allowed)
576 if (argument[0]=='-')
577 {
578 if (!strcmp(argument, "--no-prompt"))
579 {
580 no_prompt=1;
581 seedset=1;
582 displayLevel=1;
583 continue;
584 }
585 argument++;
586
587 while (*argument!=0)
588 {
589 switch(*argument)
590 {
591 case 'h':
592 return FUZ_usage();
593 case 'v':
594 argument++;
595 displayLevel=4;
596 break;
597 case 'q':
598 argument++;
599 displayLevel--;
600 break;
601 case 'p': /* pause at the end */
602 argument++;
603 pause = 1;
604 break;
605
606 case 'i':
607 argument++;
608 nbTests=0;
609 while ((*argument>='0') && (*argument<='9'))
610 {
611 nbTests *= 10;
612 nbTests += *argument - '0';
613 argument++;
614 }
615 break;
616 case 's':
617 argument++;
618 seed=0;
619 seedset=1;
620 while ((*argument>='0') && (*argument<='9'))
621 {
622 seed *= 10;
623 seed += *argument - '0';
624 argument++;
625 }
626 break;
627 case 't':
628 argument++;
629 testNb=0;
630 while ((*argument>='0') && (*argument<='9'))
631 {
632 testNb *= 10;
633 testNb += *argument - '0';
634 argument++;
635 }
636 break;
637 case 'P': /* compressibility % */
638 argument++;
639 proba=0;
640 while ((*argument>='0') && (*argument<='9'))
641 {
642 proba *= 10;
643 proba += *argument - '0';
644 argument++;
645 }
646 if (proba<0) proba=0;
647 if (proba>100) proba=100;
648 break;
649 default:
650 ;
651 return FUZ_usage();
652 }
653 }
654 }
655 }
656
657 // Get Seed
658 printf("Starting lz4frame tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION);
659
660 if (!seedset) seed = FUZ_GetMilliStart() % 10000;
661 printf("Seed = %u\n", seed);
662 if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) printf("Compressibility : %i%%\n", proba);
663
664 if (nbTests<=0) nbTests=1;
665
666 if (testNb==0) result = basicTests(seed, ((double)proba) / 100);
667 if (result) return 1;
668 return fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
669 }
670