30
# pragma warning(disable : 26451)
31
# pragma warning(disable : 4127)
46
#define LZ4F_STATIC_LINKING_ONLY
49
#define LZ4_STATIC_LINKING_ONLY
51
#define XXH_STATIC_LINKING_ONLY
56
static void FUZ_writeLE32 (void* dstVoidPtr, U32 value32)
58
BYTE* const dstPtr = (BYTE*)dstVoidPtr;
59
dstPtr[0] = (BYTE) value32;
60
dstPtr[1] = (BYTE)(value32 >> 8);
61
dstPtr[2] = (BYTE)(value32 >> 16);
62
dstPtr[3] = (BYTE)(value32 >> 24);
73
static const U32 nbTestsDefault = 256 KB;
74
#define FUZ_COMPRESSIBILITY_DEFAULT 50
75
static const U32 prime1 = 2654435761U;
76
static const U32 prime2 = 2246822519U;
82
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
83
#define DISPLAYLEVEL(l, ...) do { if (displayLevel>=(l)) DISPLAY(__VA_ARGS__); } while (0)
84
#define DISPLAYUPDATE(l, ...) do { if (displayLevel>=(l)) { \
85
if ((FUZ_GetClockSpan(g_clockTime) > refreshRate) || (displayLevel>=4)) \
86
{ g_clockTime = clock(); DISPLAY(__VA_ARGS__); \
87
if (displayLevel>=4) fflush(stdout); } } } while (0)
88
static const clock_t refreshRate = CLOCKS_PER_SEC / 6;
89
static clock_t g_clockTime = 0;
95
static U32 no_prompt = 0;
96
static U32 displayLevel = 2;
97
static U32 use_pause = 0;
103
#define MIN(a,b) ( (a) < (b) ? (a) : (b) )
104
#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
109
static Test_alloc_state g_testAllocState = { 0 };
111
static void* dummy_malloc(void* state, size_t s)
113
Test_alloc_state* const t = (Test_alloc_state*)state;
114
void* const p = malloc(s);
115
if (p==NULL) return NULL;
118
DISPLAYLEVEL(6, "Allocating %u bytes at address %p \n", (unsigned)s, p);
119
DISPLAYLEVEL(5, "nb allocated memory segments : %i \n", t->nbAllocs);
123
static void* dummy_calloc(void* state, size_t s)
125
Test_alloc_state* const t = (Test_alloc_state*)state;
126
void* const p = calloc(1, s);
127
if (p==NULL) return NULL;
130
DISPLAYLEVEL(6, "Allocating and zeroing %u bytes at address %p \n", (unsigned)s, p);
131
DISPLAYLEVEL(5, "nb allocated memory segments : %i \n", t->nbAllocs);
135
static void dummy_free(void* state, void* p)
137
Test_alloc_state* const t = (Test_alloc_state*)state;
139
DISPLAYLEVEL(5, "free() on NULL \n");
142
DISPLAYLEVEL(6, "freeing memory at address %p \n", p);
146
DISPLAYLEVEL(5, "nb of allocated memory segments after this free : %i \n", t->nbAllocs);
147
assert(t->nbAllocs >= 0);
150
static const LZ4F_CustomMem lz4f_cmem_test = {
158
static clock_t FUZ_GetClockSpan(clock_t clockStart)
160
return clock() - clockStart;
163
#define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
164
unsigned int FUZ_rand(unsigned int* src)
169
rand32 = FUZ_rotl32(rand32, 13);
174
#define RAND_BITS(N) (FUZ_rand(randState) & ((1 << (N))-1))
175
#define FUZ_LITERAL (RAND_BITS(6) + '0')
176
#define FUZ_ABOUT(_R) ((FUZ_rand(randState) % (_R)) + (FUZ_rand(randState) % (_R)) + 1)
177
static void FUZ_fillCompressibleNoiseBuffer(void* buffer, size_t bufferSize, double proba, U32* randState)
179
BYTE* BBuffer = (BYTE*)buffer;
181
U32 P32 = (U32)(32768 * proba);
184
BBuffer[pos++] = FUZ_LITERAL;
186
while (pos < bufferSize) {
188
if (RAND_BITS(15) < P32) {
190
size_t const lengthRand = FUZ_ABOUT(8) + 4;
191
size_t const length = MIN(lengthRand, bufferSize - pos);
192
size_t const end = pos + length;
193
size_t const offsetRand = RAND_BITS(15) + 1;
194
size_t const offset = MIN(offsetRand, pos);
195
size_t match = pos - offset;
196
while (pos < end) BBuffer[pos++] = BBuffer[match++];
199
size_t const lengthRand = FUZ_ABOUT(4);
200
size_t const length = MIN(lengthRand, bufferSize - pos);
201
size_t const end = pos + length;
202
while (pos < end) BBuffer[pos++] = FUZ_LITERAL;
206
static unsigned FUZ_highbit(U32 v32)
209
if (v32==0) return 0;
210
while (v32) {v32 >>= 1; nbBits ++;}
219
#define CONTROL(c) { \
221
DISPLAY("Error (line %i) => %s not respected \n", __LINE__, #c); \
225
static int bug1227(void)
228
CONTROL(!LZ4F_isError(LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION)));
231
{ const char s9Buffer[9] = { 0 };
232
char d9Buffer[sizeof(s9Buffer)];
233
size_t const c9SizeBound = LZ4F_compressFrameBound(sizeof(s9Buffer), NULL);
234
void* const c9Buffer = malloc(c9SizeBound);
236
LZ4F_preferences_t pref = LZ4F_INIT_PREFERENCES;
237
pref.frameInfo.contentSize = sizeof(s9Buffer);
238
CONTROL(c9Buffer != NULL);
239
{ size_t const c9Size = LZ4F_compressFrame(c9Buffer, c9SizeBound, s9Buffer, sizeof(s9Buffer), &pref);
240
CONTROL(!LZ4F_isError(c9Size));
243
{ size_t dstSize = sizeof(d9Buffer);
245
size_t const d9Size = LZ4F_decompress(dctx, d9Buffer, &dstSize, c9Buffer, &srcSize, NULL);
246
CONTROL(!LZ4F_isError(d9Size));
247
CONTROL(srcSize < c9Size);
252
LZ4F_resetDecompressionContext(dctx);
255
{ size_t const c0SizeBound = LZ4F_compressFrameBound(0, NULL);
256
void* const c0Buffer = malloc(c0SizeBound);
258
CONTROL(c0Buffer != NULL);
259
{ size_t const c0Size = LZ4F_compressFrame(c0Buffer, c0SizeBound, NULL, 0, NULL);
260
CONTROL(!LZ4F_isError(c0Size));
262
{ size_t dstSize = sizeof(d0Buffer);
263
size_t srcSize = c0Size;
264
size_t const d0Size = LZ4F_decompress(dctx, d0Buffer, &dstSize, c0Buffer, &srcSize, NULL);
265
CONTROL(!LZ4F_isError(d0Size));
266
CONTROL(dstSize == 0);
267
CONTROL(srcSize == c0Size);
272
LZ4F_freeDecompressionContext(dctx);
276
#define CHECK_V(v,f) v = f; if (LZ4F_isError(v)) { fprintf(stderr, "%s \n", LZ4F_getErrorName(v)); goto _output_error; }
277
#define CHECK(f) { LZ4F_errorCode_t const CHECK_V(err_ , f); }
279
static int unitTests(U32 seed, double compressibility)
281
#define COMPRESSIBLE_NOISE_LENGTH (2 MB)
282
void* const CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
283
size_t const cBuffSize = LZ4F_compressFrameBound(COMPRESSIBLE_NOISE_LENGTH, NULL);
284
void* const compressedBuffer = malloc(cBuffSize);
285
void* const decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
287
U32* const randState = &randVal;
288
size_t cSize, testSize;
289
LZ4F_decompressionContext_t dCtx = NULL;
290
LZ4F_compressionContext_t cctx = NULL;
292
int basicTests_error = 0;
293
LZ4F_preferences_t prefs;
294
memset(&prefs, 0, sizeof(prefs));
296
if (!CNBuffer || !compressedBuffer || !decodedBuffer) {
297
DISPLAY("allocation error, not enough memory to start fuzzer tests \n");
300
FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, randState);
301
crcOrig = XXH64(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
304
DISPLAYLEVEL(3, "LZ4F_compressBound(0) = ");
305
{ size_t const cBound = LZ4F_compressBound(0, NULL);
306
if (cBound < 64 KB) goto _output_error;
307
DISPLAYLEVEL(3, " %u \n", (U32)cBound);
311
DISPLAYLEVEL(3, "LZ4F_compressBound(1 KB, autoFlush=1) = ");
313
LZ4F_preferences_t autoFlushPrefs;
314
memset(&autoFlushPrefs, 0, sizeof(autoFlushPrefs));
315
autoFlushPrefs.autoFlush = 1;
316
cBound = LZ4F_compressBound(1 KB, &autoFlushPrefs);
317
if (cBound > 64 KB) goto _output_error;
318
DISPLAYLEVEL(3, " %u \n", (U32)cBound);
322
DISPLAYLEVEL(3, "LZ4F_compressBound(1 KB, autoFlush=0) = ");
323
{ size_t const cBound = LZ4F_compressBound(1 KB, &prefs);
324
if (cBound < 64 KB) goto _output_error;
325
DISPLAYLEVEL(3, " %u \n", (U32)cBound);
330
DISPLAYLEVEL(3, "LZ4F_compressFrame, compress null content : ");
331
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL));
332
DISPLAYLEVEL(3, "null content encoded into a %u bytes frame \n", (unsigned)cSize);
334
DISPLAYLEVEL(3, "LZ4F_createDecompressionContext \n");
335
CHECK ( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) );
337
DISPLAYLEVEL(3, "LZ4F_getFrameInfo on null-content frame (#157) \n");
338
assert(cSize >= LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH);
339
{ LZ4F_frameInfo_t frame_info;
340
size_t const fhs = LZ4F_headerSize(compressedBuffer, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH);
341
size_t avail_in = fhs;
343
CHECK( LZ4F_getFrameInfo(dCtx, &frame_info, compressedBuffer, &avail_in) );
344
if (avail_in != fhs) goto _output_error;
347
DISPLAYLEVEL(3, "LZ4F_freeDecompressionContext \n");
348
CHECK( LZ4F_freeDecompressionContext(dCtx) );
352
testSize = COMPRESSIBLE_NOISE_LENGTH;
354
DISPLAYLEVEL(3, "LZ4F_compressFrame, using fast level -3 : ");
355
{ LZ4F_preferences_t fastCompressPrefs;
356
memset(&fastCompressPrefs, 0, sizeof(fastCompressPrefs));
357
fastCompressPrefs.compressionLevel = -3;
358
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, &fastCompressPrefs));
359
DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize);
362
DISPLAYLEVEL(3, "LZ4F_compressFrame, using default preferences : ");
363
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL));
364
DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize);
366
DISPLAYLEVEL(3, "Decompression test : \n");
367
{ size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
368
size_t compressedBufferSize = cSize;
370
CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) );
372
DISPLAYLEVEL(3, "Single Pass decompression : ");
373
CHECK( LZ4F_decompress(dCtx, decodedBuffer, &decodedBufferSize, compressedBuffer, &compressedBufferSize, NULL) );
374
{ U64 const crcDest = XXH64(decodedBuffer, decodedBufferSize, 1);
375
if (crcDest != crcOrig) goto _output_error; }
376
DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedBufferSize);
378
DISPLAYLEVEL(3, "Reusing decompression context \n");
379
{ size_t const missingBytes = 4;
380
size_t iSize = compressedBufferSize - missingBytes;
381
const BYTE* cBuff = (const BYTE*) compressedBuffer;
382
BYTE* const ostart = (BYTE*)decodedBuffer;
384
BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
385
size_t decResult, oSize = COMPRESSIBLE_NOISE_LENGTH;
386
DISPLAYLEVEL(3, "Missing last %u bytes : ", (U32)missingBytes);
387
CHECK_V(decResult, LZ4F_decompress(dCtx, op, &oSize, cBuff, &iSize, NULL));
388
if (decResult != missingBytes) {
389
DISPLAY("%u bytes missing != %u bytes requested \n", (U32)missingBytes, (U32)decResult);
392
DISPLAYLEVEL(3, "indeed, requests %u bytes \n", (unsigned)decResult);
396
oSize = (size_t)(oend-op);
397
decResult = LZ4F_decompress(dCtx, op, &oSize, cBuff, &iSize, NULL);
398
if (decResult != 0) goto _output_error;
400
if (op>oend) { DISPLAY("decompression write overflow \n"); goto _output_error; }
401
{ U64 const crcDest = XXH64(decodedBuffer, (size_t)(op-ostart), 1);
402
if (crcDest != crcOrig) goto _output_error;
408
const BYTE* ip = (BYTE*)compressedBuffer;
410
DISPLAYLEVEL(3, "Start by feeding 0 bytes, to get next input size : ");
411
CHECK( LZ4F_decompress(dCtx, NULL, &oSize, ip, &iSize, NULL) );
413
DISPLAYLEVEL(3, " OK \n");
415
DISPLAYLEVEL(3, "LZ4F_getFrameInfo on zero-size input : ");
416
{ size_t nullSize = 0;
417
size_t const fiError = LZ4F_getFrameInfo(dCtx, &fi, ip, &nullSize);
418
if (LZ4F_getErrorCode(fiError) != LZ4F_ERROR_frameHeader_incomplete) {
419
DISPLAYLEVEL(3, "incorrect error : %s != ERROR_frameHeader_incomplete \n",
420
LZ4F_getErrorName(fiError));
423
DISPLAYLEVEL(3, " correctly failed : %s \n", LZ4F_getErrorName(fiError));
426
DISPLAYLEVEL(3, "LZ4F_getFrameInfo on not enough input : ");
427
{ size_t inputSize = 6;
428
size_t const fiError = LZ4F_getFrameInfo(dCtx, &fi, ip, &inputSize);
429
if (LZ4F_getErrorCode(fiError) != LZ4F_ERROR_frameHeader_incomplete) {
430
DISPLAYLEVEL(3, "incorrect error : %s != ERROR_frameHeader_incomplete \n", LZ4F_getErrorName(fiError));
433
DISPLAYLEVEL(3, " correctly failed : %s \n", LZ4F_getErrorName(fiError));
436
DISPLAYLEVEL(3, "LZ4F_getFrameInfo on enough input : ");
437
iSize = LZ4F_headerSize(ip, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH);
439
CHECK( LZ4F_getFrameInfo(dCtx, &fi, ip, &iSize) );
440
DISPLAYLEVEL(3, " correctly decoded \n");
443
DISPLAYLEVEL(3, "Decode a buggy input : ");
444
assert(COMPRESSIBLE_NOISE_LENGTH > 64);
446
memcpy(decodedBuffer, (char*)compressedBuffer+16, 32);
447
memcpy((char*)compressedBuffer+16, (const char*)decodedBuffer+32, 32);
448
{ size_t dbSize = COMPRESSIBLE_NOISE_LENGTH;
449
size_t cbSize = cSize;
450
size_t const decompressError = LZ4F_decompress(dCtx, decodedBuffer, &dbSize,
451
compressedBuffer, &cbSize,
453
if (!LZ4F_isError(decompressError)) goto _output_error;
454
DISPLAYLEVEL(3, "error detected : %s \n", LZ4F_getErrorName(decompressError));
456
memcpy((char*)compressedBuffer+16, decodedBuffer, 32);
458
DISPLAYLEVEL(3, "Reset decompression context, since it's left in error state \n");
459
LZ4F_resetDecompressionContext(dCtx);
461
DISPLAYLEVEL(3, "Byte after byte : ");
462
{ BYTE* const ostart = (BYTE*)decodedBuffer;
464
BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
465
const BYTE* ip = (const BYTE*) compressedBuffer;
466
const BYTE* const iend = ip + cSize;
468
size_t oSize = (size_t)(oend-op);
470
CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
474
{ U64 const crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
475
if (crcDest != crcOrig) goto _output_error;
477
DISPLAYLEVEL(3, "Regenerated %u/%u bytes \n", (unsigned)(op-ostart), (unsigned)COMPRESSIBLE_NOISE_LENGTH);
481
DISPLAYLEVEL(3, "Using 64 KB block : ");
482
prefs.frameInfo.blockSizeID = LZ4F_max64KB;
483
prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
484
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs));
485
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
487
DISPLAYLEVEL(3, "without checksum : ");
488
prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum;
489
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs));
490
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
492
DISPLAYLEVEL(3, "Using 256 KB block : ");
493
prefs.frameInfo.blockSizeID = LZ4F_max256KB;
494
prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
495
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs));
496
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
498
DISPLAYLEVEL(3, "Decompression test : \n");
499
{ size_t const decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
500
unsigned const maxBits = FUZ_highbit((U32)decodedBufferSize);
501
BYTE* const ostart = (BYTE*)decodedBuffer;
503
BYTE* const oend = ostart + COMPRESSIBLE_NOISE_LENGTH;
504
const BYTE* ip = (const BYTE*)compressedBuffer;
505
const BYTE* const iend = (const BYTE*)compressedBuffer + cSize;
507
DISPLAYLEVEL(3, "random segment sizes : ");
509
unsigned const nbBits = FUZ_rand(randState) % maxBits;
510
size_t iSize = RAND_BITS(nbBits) + 1;
511
size_t oSize = (size_t)(oend-op);
512
if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip);
513
CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
517
{ size_t const decodedSize = (size_t)(op - ostart);
518
U64 const crcDest = XXH64(decodedBuffer, decodedSize, 1);
519
if (crcDest != crcOrig) goto _output_error;
520
DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
523
CHECK( LZ4F_freeDecompressionContext(dCtx) );
527
DISPLAYLEVEL(3, "without checksum : ");
528
prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum;
529
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) );
530
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
532
DISPLAYLEVEL(3, "Using 1 MB block : ");
533
prefs.frameInfo.blockSizeID = LZ4F_max1MB;
534
prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
535
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) );
536
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
538
DISPLAYLEVEL(3, "without frame checksum : ");
539
prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum;
540
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) );
541
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
543
DISPLAYLEVEL(3, "Using 4 MB block : ");
544
prefs.frameInfo.blockSizeID = LZ4F_max4MB;
545
prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
546
{ size_t const dstCapacity = LZ4F_compressFrameBound(testSize, &prefs);
547
DISPLAYLEVEL(4, "dstCapacity = %u ; ", (U32)dstCapacity);
548
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, dstCapacity, CNBuffer, testSize, &prefs) );
549
DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize);
552
DISPLAYLEVEL(3, "without frame checksum : ");
553
prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum;
554
{ size_t const dstCapacity = LZ4F_compressFrameBound(testSize, &prefs);
555
DISPLAYLEVEL(4, "dstCapacity = %u ; ", (U32)dstCapacity);
556
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, dstCapacity, CNBuffer, testSize, &prefs) );
557
DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize);
560
DISPLAYLEVEL(3, "LZ4F_compressFrame with block checksum : ");
561
memset(&prefs, 0, sizeof(prefs));
562
prefs.frameInfo.blockChecksumFlag = LZ4F_blockChecksumEnabled;
563
CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) );
564
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
566
DISPLAYLEVEL(3, "Decompress with block checksum : ");
567
{ size_t iSize = cSize;
568
size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH;
569
LZ4F_decompressionContext_t dctx;
570
CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
571
CHECK( LZ4F_decompress(dctx, decodedBuffer, &decodedSize, compressedBuffer, &iSize, NULL) );
572
if (decodedSize != testSize) goto _output_error;
573
if (iSize != cSize) goto _output_error;
574
{ U64 const crcDest = XXH64(decodedBuffer, decodedSize, 1);
575
U64 const crcSrc = XXH64(CNBuffer, testSize, 1);
576
if (crcDest != crcSrc) goto _output_error;
578
DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
580
CHECK( LZ4F_freeDecompressionContext(dctx) );
585
BYTE* const ostart = (BYTE*)compressedBuffer;
587
CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) );
589
DISPLAYLEVEL(3, "compress without frameSize : ");
590
memset(&(prefs.frameInfo), 0, sizeof(prefs.frameInfo));
591
CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs));
593
CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL));
595
CHECK( LZ4F_compressEnd(cctx, compressedBuffer, testSize, NULL) );
596
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)(op-ostart));
598
DISPLAYLEVEL(3, "compress with frameSize : ");
599
prefs.frameInfo.contentSize = testSize;
601
CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs));
603
CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL));
605
CHECK( LZ4F_compressEnd(cctx, compressedBuffer, testSize, NULL) );
606
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)(op-ostart));
608
DISPLAYLEVEL(3, "compress with wrong frameSize : ");
609
prefs.frameInfo.contentSize = testSize+1;
611
CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs));
613
CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL));
615
cErr = LZ4F_compressEnd(cctx, op, testSize, NULL);
616
if (!LZ4F_isError(cErr)) goto _output_error;
617
DISPLAYLEVEL(3, "Error correctly detected : %s \n", LZ4F_getErrorName(cErr));
619
CHECK( LZ4F_freeCompressionContext(cctx) );
625
U32 const dictID = 0x99;
627
cctx = LZ4F_createCompressionContext_advanced(lz4f_cmem_test, LZ4F_VERSION);
628
if (cctx==NULL) goto _output_error;
630
DISPLAYLEVEL(3, "insert a dictID : ");
631
memset(&prefs.frameInfo, 0, sizeof(prefs.frameInfo));
632
prefs.frameInfo.dictID = dictID;
633
CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs));
634
DISPLAYLEVEL(3, "created frame header of size %i bytes \n", (int)cErr);
636
DISPLAYLEVEL(3, "read a dictID : ");
637
CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) );
638
memset(&prefs.frameInfo, 0, sizeof(prefs.frameInfo));
639
CHECK( LZ4F_getFrameInfo(dCtx, &prefs.frameInfo, compressedBuffer, &cErr) );
640
if (prefs.frameInfo.dictID != dictID) goto _output_error;
641
DISPLAYLEVEL(3, "%u \n", (U32)prefs.frameInfo.dictID);
643
CHECK( LZ4F_freeDecompressionContext(dCtx) ); dCtx = NULL;
644
CHECK( LZ4F_freeCompressionContext(cctx) ); cctx = NULL;
648
{ size_t const dictSize = 7 KB;
649
size_t const srcSize = 66 KB;
650
size_t const dstCapacity = LZ4F_compressFrameBound(srcSize, NULL);
651
size_t cSizeNoDict, cSizeWithDict;
652
const void* dict = CNBuffer;
653
const void* src = (const char*)CNBuffer + dictSize;
654
char* cPtr = (char*)compressedBuffer;
655
CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) );
659
LZ4F_compressFrame(compressedBuffer, dstCapacity,
665
DISPLAYLEVEL(3, "LZ4F_compressBegin_usingDict: ");
667
{ size_t hSize = LZ4F_compressBegin_usingDict(cctx, cPtr, dstCapacity, dict, dictSize, NULL);
670
cSizeWithDict += hSize;
673
{ size_t bSize = LZ4F_compressUpdate(cctx, cPtr, dstCapacity, src, srcSize, NULL);
675
cSizeWithDict += bSize;
678
{ size_t endSize = LZ4F_compressEnd(cctx, cPtr, dstCapacity, NULL);
680
cSizeWithDict += endSize;
682
DISPLAYLEVEL(3, "compress %u bytes into %u bytes with dict (< %u bytes without) \n",
683
(unsigned)srcSize, (unsigned)cSizeWithDict, (unsigned)cSizeNoDict);
684
if (cSizeWithDict >= cSizeNoDict) {
685
DISPLAYLEVEL(3, "cSizeWithDict (%u) should have been more compact than cSizeNoDict(%u) \n", (unsigned)cSizeWithDict, (unsigned)cSizeNoDict);
688
crcOrig = XXH64(src, srcSize, 0);
690
DISPLAYLEVEL(3, "LZ4F_decompress_usingDict: ");
692
size_t decodedSize = srcSize;
693
size_t compressedSize = cSizeWithDict;
694
CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
695
CHECK( LZ4F_decompress_usingDict(dctx,
696
decodedBuffer, &decodedSize,
697
compressedBuffer, &compressedSize,
700
if (compressedSize != cSizeWithDict) goto _output_error;
701
if (decodedSize != srcSize) goto _output_error;
702
{ U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0);
703
if (crcDest != crcOrig) goto _output_error; }
704
DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
705
CHECK( LZ4F_freeDecompressionContext(dctx) );
709
CHECK( LZ4F_freeCompressionContext(cctx) );
713
{ size_t const dictSize = 7 KB;
714
size_t const srcSize = 65 KB;
715
size_t const dstCapacity = LZ4F_compressFrameBound(srcSize, NULL);
716
size_t cSizeNoDict, cSizeWithDict;
717
LZ4F_CDict* const cdict = LZ4F_createCDict(CNBuffer, dictSize);
718
if (cdict == NULL) goto _output_error;
719
CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) );
721
DISPLAYLEVEL(3, "Testing LZ4F_createCDict_advanced : ");
722
{ LZ4F_CDict* const cda = LZ4F_createCDict_advanced(lz4f_cmem_test, CNBuffer, dictSize);
723
if (cda == NULL) goto _output_error;
726
DISPLAYLEVEL(3, "OK \n");
728
DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with NULL dict : ");
730
LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity,
733
DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeNoDict);
735
DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict : ");
736
CHECK( LZ4F_freeCompressionContext(cctx) );
737
CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) );
738
CHECK_V(cSizeWithDict,
739
LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity,
742
DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n",
743
(unsigned)srcSize, (unsigned)cSizeWithDict);
744
if (cSizeWithDict > cSizeNoDict) {
745
DISPLAYLEVEL(3, "cSizeWithDict (%u) should have been more compact than cSizeNoDict(%u) \n", (unsigned)cSizeWithDict, (unsigned)cSizeNoDict);
748
crcOrig = XXH64(CNBuffer, srcSize, 0);
750
DISPLAYLEVEL(3, "LZ4F_decompress_usingDict : ");
752
size_t decodedSize = srcSize;
753
size_t compressedSize = cSizeWithDict;
754
CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
755
CHECK( LZ4F_decompress_usingDict(dctx,
756
decodedBuffer, &decodedSize,
757
compressedBuffer, &compressedSize,
760
if (compressedSize != cSizeWithDict) goto _output_error;
761
if (decodedSize != srcSize) goto _output_error;
762
{ U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0);
763
if (crcDest != crcOrig) goto _output_error; }
764
DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
765
CHECK( LZ4F_freeDecompressionContext(dctx) );
768
DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict, negative level : ");
769
{ size_t cSizeLevelMax;
770
LZ4F_preferences_t cParams;
771
memset(&cParams, 0, sizeof(cParams));
772
cParams.compressionLevel = -3;
773
CHECK_V(cSizeLevelMax,
774
LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity,
777
DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeLevelMax);
780
DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict, level max : ");
781
{ size_t cSizeLevelMax;
782
LZ4F_preferences_t cParams;
783
memset(&cParams, 0, sizeof(cParams));
784
cParams.compressionLevel = LZ4F_compressionLevel_max();
785
CHECK_V(cSizeLevelMax,
786
LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity,
789
DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeLevelMax);
792
DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, multiple linked blocks : ");
793
{ size_t cSizeContiguous;
794
size_t const inSize = dictSize * 3;
795
size_t const outCapacity = LZ4F_compressFrameBound(inSize, NULL);
796
LZ4F_preferences_t cParams;
797
memset(&cParams, 0, sizeof(cParams));
798
cParams.frameInfo.blockMode = LZ4F_blockLinked;
799
cParams.frameInfo.blockSizeID = LZ4F_max64KB;
800
CHECK_V(cSizeContiguous,
801
LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, outCapacity,
804
DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n",
805
(unsigned)inSize, (unsigned)cSizeContiguous);
807
DISPLAYLEVEL(3, "LZ4F_decompress_usingDict on multiple linked blocks : ");
809
size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH;
810
size_t compressedSize = cSizeContiguous;
811
CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
812
CHECK( LZ4F_decompress_usingDict(dctx,
813
decodedBuffer, &decodedSize,
814
compressedBuffer, &compressedSize,
817
if (compressedSize != cSizeContiguous) goto _output_error;
818
if (decodedSize != inSize) goto _output_error;
819
crcOrig = XXH64(CNBuffer, inSize, 0);
820
{ U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0);
821
if (crcDest != crcOrig) goto _output_error; }
822
DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
823
CHECK( LZ4F_freeDecompressionContext(dctx) );
827
DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, multiple independent blocks : ");
829
size_t const inSize = dictSize * 3;
830
size_t const outCapacity = LZ4F_compressFrameBound(inSize, NULL);
831
LZ4F_preferences_t cParams;
832
memset(&cParams, 0, sizeof(cParams));
833
cParams.frameInfo.blockMode = LZ4F_blockIndependent;
834
cParams.frameInfo.blockSizeID = LZ4F_max64KB;
836
LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, outCapacity,
839
DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n",
840
(unsigned)inSize, (unsigned)cSizeIndep);
842
DISPLAYLEVEL(3, "LZ4F_decompress_usingDict on multiple independent blocks : ");
844
size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH;
845
size_t compressedSize = cSizeIndep;
846
CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
847
CHECK( LZ4F_decompress_usingDict(dctx,
848
decodedBuffer, &decodedSize,
849
compressedBuffer, &compressedSize,
852
if (compressedSize != cSizeIndep) goto _output_error;
853
if (decodedSize != inSize) goto _output_error;
854
crcOrig = XXH64(CNBuffer, inSize, 0);
855
{ U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0);
856
if (crcDest != crcOrig) goto _output_error; }
857
DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
858
CHECK( LZ4F_freeDecompressionContext(dctx) );
862
LZ4F_freeCDict(cdict);
863
CHECK( LZ4F_freeCompressionContext(cctx) ); cctx = NULL;
866
DISPLAYLEVEL(3, "getBlockSize test: \n");
868
unsigned blockSizeID;
869
for (blockSizeID = 4; blockSizeID < 8; ++blockSizeID) {
870
result = LZ4F_getBlockSize((LZ4F_blockSizeID_t)blockSizeID);
872
DISPLAYLEVEL(3, "Returned block size of %u bytes for blockID %u \n",
873
(unsigned)result, blockSizeID);
877
result = LZ4F_getBlockSize((LZ4F_blockSizeID_t)8);
878
if(!LZ4F_isError(result) ||
879
LZ4F_getErrorCode(result) != LZ4F_ERROR_maxBlockSize_invalid)
883
result = LZ4F_getBlockSize((LZ4F_blockSizeID_t)3);
884
if(!LZ4F_isError(result) ||
885
LZ4F_getErrorCode(result) != LZ4F_ERROR_maxBlockSize_invalid)
889
DISPLAYLEVEL(3, "check bug1227: reused dctx after error => ");
890
if (bug1227()) goto _output_error;
891
DISPLAYLEVEL(3, "OK \n");
893
DISPLAYLEVEL(3, "Skippable frame test : \n");
894
{ size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
895
unsigned maxBits = FUZ_highbit((U32)decodedBufferSize);
896
BYTE* op = (BYTE*)decodedBuffer;
897
BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
898
BYTE* ip = (BYTE*)compressedBuffer;
899
BYTE* iend = (BYTE*)compressedBuffer + cSize + 8;
901
CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) );
904
FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START);
905
FUZ_writeLE32(ip+4, (U32)cSize);
907
DISPLAYLEVEL(3, "random segment sizes : \n");
909
unsigned nbBits = FUZ_rand(randState) % maxBits;
910
size_t iSize = RAND_BITS(nbBits) + 1;
911
size_t oSize = (size_t)(oend-op);
912
if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip);
913
CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
917
DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)decodedBufferSize);
920
DISPLAYLEVEL(3, "zero-size skippable frame\n");
921
ip = (BYTE*)compressedBuffer;
922
op = (BYTE*)decodedBuffer;
923
FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START+1);
924
FUZ_writeLE32(ip+4, 0);
928
unsigned const nbBits = FUZ_rand(randState) % maxBits;
929
size_t iSize = RAND_BITS(nbBits) + 1;
930
size_t oSize = (size_t)(oend-op);
931
if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip);
932
CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
936
DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)(ip - (BYTE*)compressedBuffer - 8));
938
DISPLAYLEVEL(3, "Skippable frame header complete in first call \n");
939
ip = (BYTE*)compressedBuffer;
940
op = (BYTE*)decodedBuffer;
941
FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START+2);
942
FUZ_writeLE32(ip+4, 10);
947
if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip);
948
CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
952
DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)(ip - (BYTE*)compressedBuffer - 8));
955
DISPLAY("Basic tests completed \n");
958
free(compressedBuffer);
960
LZ4F_freeDecompressionContext(dCtx); dCtx = NULL;
961
LZ4F_freeCompressionContext(cctx); cctx = NULL;
962
return basicTests_error;
965
basicTests_error = 1;
966
DISPLAY("Error detected ! \n");
971
typedef enum { o_contiguous, o_noncontiguous, o_overwrite } o_scenario_e;
973
static void locateBuffDiff(const void* buff1, const void* buff2, size_t size, o_scenario_e o_scenario)
975
if (displayLevel >= 2) {
977
const BYTE* b1=(const BYTE*)buff1;
978
const BYTE* b2=(const BYTE*)buff2;
979
DISPLAY("locateBuffDiff: looking for error position \n");
980
if (o_scenario != o_contiguous) {
981
DISPLAY("mode %i: non-contiguous output (%u bytes), cannot search \n",
982
(int)o_scenario, (unsigned)size);
985
while (p < size && b1[p]==b2[p]) p++;
987
DISPLAY("Error at pos %i/%i : %02X != %02X \n", (int)p, (int)size, b1[p], b2[p]);
992
#define EXIT_MSG(...) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
993
DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); exit(1); }
995
#define CHECK(cond, ...) { if (cond) { EXIT_MSG(__VA_ARGS__); } }
997
size_t test_lz4f_decompression_wBuffers(
998
const void* cSrc, size_t cSize,
999
void* dst, size_t dstCapacity, o_scenario_e o_scenario,
1000
const void* srcRef, size_t decompressedSize,
1002
U32* const randState,
1003
LZ4F_dctx* const dCtx,
1004
U32 seed, U32 testNb,
1007
const BYTE* ip = (const BYTE*)cSrc;
1008
const BYTE* const iend = ip + cSize;
1010
BYTE* op = (BYTE*)dst;
1011
BYTE* const oend = op + dstCapacity;
1013
unsigned const suggestedBits = FUZ_highbit((U32)cSize);
1014
unsigned const maxBits = MAX(3, suggestedBits);
1015
size_t totalOut = 0;
1016
size_t moreToFlush = 0;
1017
XXH64_state_t xxh64;
1018
XXH64_reset(&xxh64, 1);
1021
unsigned const nbBitsI = (FUZ_rand(randState) % (maxBits-1)) + 1;
1022
unsigned const nbBitsO = (FUZ_rand(randState) % (maxBits)) + 1;
1023
size_t const iSizeCand = RAND_BITS(nbBitsI) + 1;
1024
size_t const iSizeMax = MIN(iSizeCand, (size_t)(iend-ip));
1025
size_t iSize = iSizeMax;
1026
size_t const oSizeCand = RAND_BITS(nbBitsO) + 2;
1027
size_t const oSizeMax = MIN(oSizeCand, (size_t)(oend-op));
1028
int const sentinelTest = (op + oSizeMax < oend);
1029
size_t oSize = oSizeMax;
1030
BYTE const mark = (BYTE)(RAND_BITS(8));
1031
LZ4F_decompressOptions_t dOptions;
1032
memset(&dOptions, 0, sizeof(dOptions));
1033
dOptions.stableDst = RAND_BITS(1);
1034
if (o_scenario == o_overwrite) dOptions.stableDst = 0;
1035
dOptions.skipChecksums = RAND_BITS(1);
1036
if (sentinelTest) op[oSizeMax] = mark;
1038
DISPLAYLEVEL(7, "dstCapacity=%u, presentedInput=%u \n", (unsigned)oSize, (unsigned)iSize);
1041
{ void* const iBuffer = malloc(iSizeMax);
1043
void* const tmpop = RAND_BITS(oSize == 0) ? NULL : op;
1044
const void* const tmpip = RAND_BITS(iSize == 0) ? NULL : iBuffer;
1045
assert(iBuffer != NULL);
1046
memcpy(iBuffer, ip, iSizeMax);
1047
moreToFlush = LZ4F_decompress(dCtx, tmpop, &oSize, tmpip, &iSize, &dOptions);
1050
DISPLAYLEVEL(7, "oSize=%u, readSize=%u \n", (unsigned)oSize, (unsigned)iSize);
1053
CHECK(op[oSizeMax] != mark, "op[oSizeMax] = %02X != %02X : "
1054
"Decompression overwrites beyond assigned dst size",
1055
op[oSizeMax], mark);
1057
if (LZ4F_getErrorCode(moreToFlush) == LZ4F_ERROR_contentChecksum_invalid) {
1058
if (findErrorPos) DISPLAYLEVEL(2, "checksum error detected \n");
1059
if (findErrorPos) locateBuffDiff(srcRef, dst, decompressedSize, o_scenario);
1061
if (LZ4F_isError(moreToFlush)) return moreToFlush;
1063
XXH64_update(&xxh64, op, oSize);
1067
if (o_scenario == o_noncontiguous) {
1068
if (op == oend) return LZ4F_ERROR_GENERIC;
1071
if (o_scenario==o_overwrite) op = (BYTE*)dst;
1076
if (moreToFlush != 0) return LZ4F_ERROR_decompressionFailed;
1078
U64 const crcDecoded = XXH64_digest(&xxh64);
1079
if (crcDecoded != crcOrig) {
1080
if (findErrorPos) locateBuffDiff(srcRef, dst, decompressedSize, o_scenario);
1081
return LZ4F_ERROR_contentChecksum_invalid;
1087
size_t test_lz4f_decompression(const void* cSrc, size_t cSize,
1088
const void* srcRef, size_t decompressedSize,
1090
U32* const randState,
1091
LZ4F_dctx* const dCtx,
1092
U32 seed, U32 testNb,
1095
o_scenario_e const o_scenario = (o_scenario_e)(FUZ_rand(randState) % 3);
1097
size_t const dstCapacity = (o_scenario == o_noncontiguous) ?
1098
(decompressedSize * 2) + 128 :
1101
void* const dstBuffer = malloc(dstCapacity);
1102
assert(dstBuffer != NULL);
1104
result = test_lz4f_decompression_wBuffers(cSrc, cSize,
1105
dstBuffer, dstCapacity, o_scenario,
1106
srcRef, decompressedSize,
1110
seed, testNb, findErrorPos);
1117
int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressibility, U32 duration_s)
1119
unsigned testNb = 0;
1120
size_t const CNBufferLength = 9 MB;
1121
void* CNBuffer = NULL;
1122
size_t const compressedBufferSize = LZ4F_compressFrameBound(CNBufferLength, NULL) + 4 MB;
1123
void* compressedBuffer = NULL;
1124
void* decodedBuffer = NULL;
1125
U32 coreRand = seed;
1126
LZ4F_decompressionContext_t dCtx = NULL;
1127
LZ4F_compressionContext_t cCtx = NULL;
1128
clock_t const startClock = clock();
1129
clock_t const clockDuration = duration_s * CLOCKS_PER_SEC;
1132
{ size_t const creationStatus = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
1133
CHECK(LZ4F_isError(creationStatus), "Allocation failed (error %i)", (int)creationStatus); }
1134
{ size_t const creationStatus = LZ4F_createCompressionContext(&cCtx, LZ4F_VERSION);
1135
CHECK(LZ4F_isError(creationStatus), "Allocation failed (error %i)", (int)creationStatus); }
1136
CNBuffer = malloc(CNBufferLength);
1137
CHECK(CNBuffer==NULL, "CNBuffer Allocation failed");
1138
compressedBuffer = malloc(compressedBufferSize);
1139
CHECK(compressedBuffer==NULL, "compressedBuffer Allocation failed");
1140
decodedBuffer = calloc(1, CNBufferLength);
1141
CHECK(decodedBuffer==NULL, "decodedBuffer Allocation failed");
1142
FUZ_fillCompressibleNoiseBuffer(CNBuffer, CNBufferLength, compressibility, &coreRand);
1145
for (testNb =0; (testNb < startTest); testNb++) (void)FUZ_rand(&coreRand);
1148
for ( ; (testNb < nbTests) || (clockDuration > FUZ_GetClockSpan(startClock)) ; testNb++) {
1149
U32 randState = coreRand ^ prime1;
1150
unsigned const srcBits = (FUZ_rand(&randState) % (FUZ_highbit((U32)(CNBufferLength-1)) - 1)) + 1;
1151
size_t const srcSize = (FUZ_rand(&randState) & ((1<<srcBits)-1));
1152
size_t const srcStartId = FUZ_rand(&randState) % (CNBufferLength - srcSize);
1153
const BYTE* const srcStart = (const BYTE*)CNBuffer + srcStartId;
1154
unsigned const neverFlush = (FUZ_rand(&randState) & 15) == 1;
1155
U64 const crcOrig = XXH64(srcStart, srcSize, 1);
1156
LZ4F_preferences_t prefs;
1157
const LZ4F_preferences_t* prefsPtr = &prefs;
1160
(void)FUZ_rand(&coreRand);
1161
memset(&prefs, 0, sizeof(prefs));
1162
prefs.frameInfo.blockMode = (LZ4F_blockMode_t)(FUZ_rand(&randState) & 1);
1163
prefs.frameInfo.blockSizeID = (LZ4F_blockSizeID_t)(4 + (FUZ_rand(&randState) & 3));
1164
prefs.frameInfo.blockChecksumFlag = (LZ4F_blockChecksum_t)(FUZ_rand(&randState) & 1);
1165
prefs.frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)(FUZ_rand(&randState) & 1);
1166
prefs.frameInfo.contentSize = ((FUZ_rand(&randState) & 0xF) == 1) ? srcSize : 0;
1167
prefs.autoFlush = neverFlush ? 0 : (FUZ_rand(&randState) & 7) == 2;
1168
prefs.compressionLevel = -5 + (int)(FUZ_rand(&randState) % 11);
1169
if ((FUZ_rand(&randState) & 0xF) == 1) prefsPtr = NULL;
1171
DISPLAYUPDATE(2, "\r%5u ", testNb);
1173
if ((FUZ_rand(&randState) & 0xFFF) == 0) {
1175
BYTE* op = (BYTE*)compressedBuffer;
1176
FUZ_writeLE32(op, LZ4F_MAGIC_SKIPPABLE_START + (FUZ_rand(&randState) & 15));
1177
FUZ_writeLE32(op+4, (U32)srcSize);
1180
} else if ((FUZ_rand(&randState) & 0xF) == 2) {
1181
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(srcSize, prefsPtr), srcStart, srcSize, prefsPtr);
1182
CHECK(LZ4F_isError(cSize), "LZ4F_compressFrame failed : error %i (%s)", (int)cSize, LZ4F_getErrorName(cSize));
1185
const BYTE* ip = srcStart;
1186
const BYTE* const iend = srcStart + srcSize;
1187
BYTE* op = (BYTE*)compressedBuffer;
1188
BYTE* const oend = op + (neverFlush ? LZ4F_compressFrameBound(srcSize, prefsPtr) : compressedBufferSize);
1189
unsigned const maxBits = FUZ_highbit((U32)srcSize);
1190
LZ4F_compressOptions_t cOptions;
1191
memset(&cOptions, 0, sizeof(cOptions));
1192
{ size_t const fhSize = LZ4F_compressBegin(cCtx, op, (size_t)(oend-op), prefsPtr);
1193
CHECK(LZ4F_isError(fhSize), "Compression header failed (error %i)",
1198
unsigned const nbBitsSeg = FUZ_rand(&randState) % maxBits;
1199
size_t const sampleMax = (FUZ_rand(&randState) & ((1<<nbBitsSeg)-1)) + 1;
1200
size_t iSize = MIN(sampleMax, (size_t)(iend-ip));
1201
size_t const oSize = LZ4F_compressBound(iSize, prefsPtr);
1202
cOptions.stableSrc = ((FUZ_rand(&randState) & 3) == 1);
1203
DISPLAYLEVEL(6, "Sending %u bytes to compress (stableSrc:%u) \n",
1204
(unsigned)iSize, cOptions.stableSrc);
1211
&& prefs.frameInfo.blockMode == LZ4F_blockIndependent
1212
&& (FUZ_rand(&randState) & 15) == 1 ) {
1213
size_t const uSize = FUZ_rand(&randState) % iSize;
1214
size_t const flushedSize = LZ4F_uncompressedUpdate(cCtx, op, (size_t)(oend-op), ip, uSize, &cOptions);
1215
CHECK(LZ4F_isError(flushedSize), "Insert uncompressed data failed (error %i : %s)",
1216
(int)flushedSize, LZ4F_getErrorName(flushedSize));
1223
{ size_t const flushedSize = LZ4F_compressUpdate(cCtx, op, oSize, ip, iSize, &cOptions);
1224
CHECK(LZ4F_isError(flushedSize), "Compression failed (error %i : %s)",
1225
(int)flushedSize, LZ4F_getErrorName(flushedSize));
1230
{ unsigned const forceFlush = neverFlush ? 0 : ((FUZ_rand(&randState) & 3) == 1);
1232
size_t const flushSize = LZ4F_flush(cCtx, op, (size_t)(oend-op), &cOptions);
1233
DISPLAYLEVEL(6,"flushing %u bytes \n", (unsigned)flushSize);
1234
CHECK(LZ4F_isError(flushSize), "Compression failed (error %i)", (int)flushSize);
1236
if ((FUZ_rand(&randState) % 1024) == 3) {
1238
op[0] = op[1] = op[2] = 0;
1241
if ((prefsPtr!= NULL) && prefsPtr->frameInfo.blockChecksumFlag) {
1243
FUZ_writeLE32(op, XXH32(op, 0, 0));
1247
CHECK(op>=oend, "LZ4F_compressFrameBound overflow");
1248
{ size_t const dstEndSafeSize = LZ4F_compressBound(0, prefsPtr);
1249
int const tooSmallDstEnd = ((FUZ_rand(&randState) & 31) == 3);
1250
size_t const dstEndTooSmallSize = (FUZ_rand(&randState) % dstEndSafeSize) + 1;
1251
size_t const dstEndSize = tooSmallDstEnd ? dstEndTooSmallSize : dstEndSafeSize;
1252
BYTE const canaryByte = (BYTE)(FUZ_rand(&randState) & 255);
1254
DISPLAYLEVEL(7,"canaryByte at pos %u / %u \n",
1255
(unsigned)((size_t)(op - (BYTE*)compressedBuffer) + dstEndSize),
1256
(unsigned)compressedBufferSize);
1257
assert(op + dstEndSize < (BYTE*)compressedBuffer + compressedBufferSize);
1258
op[dstEndSize] = canaryByte;
1259
flushedSize = LZ4F_compressEnd(cCtx, op, dstEndSize, &cOptions);
1260
CHECK(op[dstEndSize] != canaryByte, "LZ4F_compressEnd writes beyond dstCapacity !");
1261
if (LZ4F_isError(flushedSize)) {
1262
if (tooSmallDstEnd) continue;
1263
CHECK(!tooSmallDstEnd, "Compression completion failed (error %i : %s)",
1264
(int)flushedSize, LZ4F_getErrorName(flushedSize));
1268
cSize = (size_t)(op - (BYTE*)compressedBuffer);
1269
DISPLAYLEVEL(5, "\nCompressed %u bytes into %u \n", (U32)srcSize, (U32)cSize);
1274
DISPLAYLEVEL(6, "normal decompression \n");
1275
{ size_t result = test_lz4f_decompression(compressedBuffer, cSize, srcStart, srcSize, crcOrig, &randState, dCtx, seed, testNb, 1 );
1276
CHECK (LZ4F_isError(result), "multi-segment decompression failed (error %i => %s)",
1277
(int)result, LZ4F_getErrorName(result));
1281
{ U32 const maxNbBits = FUZ_highbit((U32)cSize);
1285
{ U32 const nbBits = FUZ_rand(&randState) % maxNbBits;
1286
size_t const mask = (1<<nbBits) - 1;
1287
size_t const skipLength = FUZ_rand(&randState) & mask;
1290
if (pos >= cSize) break;
1292
{ U32 const nbBitsCodes = FUZ_rand(&randState) % maxNbBits;
1293
U32 const nbBits = nbBitsCodes ? nbBitsCodes-1 : 0;
1294
size_t const mask = (1<<nbBits) - 1;
1295
size_t const rNoiseLength = (FUZ_rand(&randState) & mask) + 1;
1296
size_t const noiseLength = MIN(rNoiseLength, cSize-pos);
1297
size_t const noiseStart = FUZ_rand(&randState) % (CNBufferLength - noiseLength);
1298
memcpy((BYTE*)compressedBuffer + pos, (const char*)CNBuffer + noiseStart, noiseLength);
1303
DISPLAYLEVEL(6, "noisy decompression \n");
1304
test_lz4f_decompression(compressedBuffer, cSize, srcStart, srcSize, crcOrig, &randState, dCtx, seed, testNb, 0 );
1307
LZ4F_resetDecompressionContext(dCtx);
1311
DISPLAYLEVEL(2, "\rAll tests completed \n");
1313
LZ4F_freeDecompressionContext(dCtx);
1314
LZ4F_freeCompressionContext(cCtx);
1316
free(compressedBuffer);
1317
free(decodedBuffer);
1320
DISPLAY("press enter to finish \n");
1327
int FUZ_usage(const char* programName)
1329
DISPLAY( "Usage :\n");
1330
DISPLAY( " %s [args]\n", programName);
1332
DISPLAY( "Arguments :\n");
1333
DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault);
1334
DISPLAY( " -T# : Duration of tests, in seconds (default: use Nb of tests) \n");
1335
DISPLAY( " -s# : Select seed (default:prompt user)\n");
1336
DISPLAY( " -t# : Select starting test number (default:0)\n");
1337
DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
1338
DISPLAY( " -v : verbose\n");
1339
DISPLAY( " -h : display help and exit\n");
1344
int main(int argc, const char** argv)
1349
unsigned nbTests = nbTestsDefault;
1350
unsigned testNb = 0;
1351
int proba = FUZ_COMPRESSIBILITY_DEFAULT;
1353
const char* const programName = argv[0];
1356
for (argNb=1; argNb<argc; argNb++) {
1357
const char* argument = argv[argNb];
1359
if(!argument) continue;
1362
if (argument[0]=='-') {
1363
if (!strcmp(argument, "--no-prompt")) {
1371
while (*argument!=0) {
1375
return FUZ_usage(programName);
1391
nbTests=0; duration=0;
1392
while ((*argument>='0') && (*argument<='9')) {
1394
nbTests += (unsigned)(*argument - '0');
1401
nbTests = 0; duration = 0;
1405
case 'm': duration *= 60; argument++; continue;
1407
case 'n': argument++; continue;
1417
case '9': duration *= 10; duration += (U32)(*argument++ - '0'); continue;
1427
while ((*argument>='0') && (*argument<='9')) {
1429
seed += (U32)(*argument - '0');
1436
while ((*argument>='0') && (*argument<='9')) {
1438
testNb += (unsigned)(*argument - '0');
1445
while ((*argument>='0') && (*argument<='9')) {
1447
proba += *argument - '0';
1450
if (proba<0) proba=0;
1451
if (proba>100) proba=100;
1455
return FUZ_usage(programName);
1461
DISPLAY("Starting lz4frame tester (%i-bits, %s) \n", (int)(sizeof(size_t)*8), LZ4_VERSION_STRING);
1465
time_t const t = time(NULL);
1466
U32 const h = XXH32(&t, sizeof(t), 1);
1469
DISPLAY("Seed = %u \n", seed);
1470
if (proba != FUZ_COMPRESSIBILITY_DEFAULT)
1471
DISPLAY("Compressibility : %i%% \n", proba);
1473
{ double const compressibility = (double)proba / 100;
1476
if (unitTests(seed, compressibility))
1480
nbTests += (nbTests==0);
1481
return fuzzerTests(seed, nbTests, testNb, compressibility, duration);