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 *********************************************************/ 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 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))) 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) 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 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 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 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 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 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 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