diff options
Diffstat (limited to 'tests/fuzzer.c')
-rw-r--r-- | tests/fuzzer.c | 576 |
1 files changed, 404 insertions, 172 deletions
diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 5616285b9ed70..946844e1614ae 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -47,8 +47,8 @@ #define MB *(1U<<20) #define GB *(1U<<30) -static const U32 FUZ_compressibility_default = 50; -static const U32 nbTestsDefault = 30000; +static const int FUZ_compressibility_default = 50; +static const int nbTestsDefault = 30000; /*-************************************ @@ -88,7 +88,7 @@ void FUZ_bug976(void) #define MAX(a,b) ((a)>(b)?(a):(b)) #define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r))) -static unsigned FUZ_rand(unsigned* src) +static U32 FUZ_rand(U32* src) { static const U32 prime1 = 2654435761U; static const U32 prime2 = 2246822519U; @@ -100,7 +100,7 @@ static unsigned FUZ_rand(unsigned* src) return rand32 >> 5; } -static unsigned FUZ_highbit32(U32 v32) +static U32 FUZ_highbit32(U32 v32) { unsigned nbBits = 0; if (v32==0) return 0; @@ -155,7 +155,7 @@ static void* FUZ_mallocDebug(void* counter, size_t size) void* const ptr = malloc(size); if (ptr==NULL) return NULL; DISPLAYLEVEL(4, "allocating %u KB => effectively %u KB \n", - (U32)(size >> 10), (U32)(malloc_size(ptr) >> 10)); /* OS-X specific */ + (unsigned)(size >> 10), (unsigned)(malloc_size(ptr) >> 10)); /* OS-X specific */ mcPtr->totalMalloc += size; mcPtr->currentMalloc += size; if (mcPtr->currentMalloc > mcPtr->peakMalloc) @@ -167,7 +167,7 @@ static void* FUZ_mallocDebug(void* counter, size_t size) static void FUZ_freeDebug(void* counter, void* address) { mallocCounter_t* const mcPtr = (mallocCounter_t*)counter; - DISPLAYLEVEL(4, "freeing %u KB \n", (U32)(malloc_size(address) >> 10)); + DISPLAYLEVEL(4, "freeing %u KB \n", (unsigned)(malloc_size(address) >> 10)); mcPtr->nbFree += 1; mcPtr->currentMalloc -= malloc_size(address); /* OS-X specific */ free(address); @@ -176,9 +176,9 @@ static void FUZ_freeDebug(void* counter, void* address) static void FUZ_displayMallocStats(mallocCounter_t count) { DISPLAYLEVEL(3, "peak:%6u KB, nbMallocs:%2u, total:%6u KB \n", - (U32)(count.peakMalloc >> 10), + (unsigned)(count.peakMalloc >> 10), count.nbMalloc, - (U32)(count.totalMalloc >> 10)); + (unsigned)(count.totalMalloc >> 10)); } static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsigned part, @@ -226,18 +226,16 @@ static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsig /* advanced MT API test */ if (part <= 3) - { U32 nbThreads; + { unsigned nbThreads; for (nbThreads=1; nbThreads<=4; nbThreads++) { int compressionLevel; for (compressionLevel=1; compressionLevel<=6; compressionLevel++) { mallocCounter_t malcount = INIT_MALLOC_COUNTER; ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount }; ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem); - ZSTD_outBuffer out = { outBuffer, outSize, 0 }; - ZSTD_inBuffer in = { inBuffer, inSize, 0 }; - CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, (U32)compressionLevel) ); - CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_p_nbWorkers, nbThreads) ); - while ( ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_end) ) {} + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) ); + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads) ); + CHECK_Z( ZSTD_compress2(cctx, outBuffer, outSize, inBuffer, inSize) ); ZSTD_freeCCtx(cctx); DISPLAYLEVEL(3, "compress_generic,-T%u,end level %i : ", nbThreads, compressionLevel); @@ -246,7 +244,7 @@ static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsig /* advanced MT streaming API test */ if (part <= 4) - { U32 nbThreads; + { unsigned nbThreads; for (nbThreads=1; nbThreads<=4; nbThreads++) { int compressionLevel; for (compressionLevel=1; compressionLevel<=6; compressionLevel++) { @@ -255,10 +253,10 @@ static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsig ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem); ZSTD_outBuffer out = { outBuffer, outSize, 0 }; ZSTD_inBuffer in = { inBuffer, inSize, 0 }; - CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, (U32)compressionLevel) ); - CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_p_nbWorkers, nbThreads) ); - CHECK_Z( ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_continue) ); - while ( ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_end) ) {} + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) ); + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads) ); + CHECK_Z( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue) ); + while ( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) ) {} ZSTD_freeCCtx(cctx); DISPLAYLEVEL(3, "compress_generic,-T%u,continue level %i : ", nbThreads, compressionLevel); @@ -311,9 +309,8 @@ static int basicUnitTests(U32 seed, double compressibility) size_t const compressedBufferSize = ZSTD_compressBound(CNBuffSize); void* const compressedBuffer = malloc(compressedBufferSize); void* const decodedBuffer = malloc(CNBuffSize); - ZSTD_DCtx* dctx = ZSTD_createDCtx(); int testResult = 0; - U32 testNb=0; + unsigned testNb=0; size_t cSize; /* Create compressible noise */ @@ -325,37 +322,45 @@ static int basicUnitTests(U32 seed, double compressibility) RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed); /* Basic tests */ - DISPLAYLEVEL(3, "test%3i : ZSTD_getErrorName : ", testNb++); + DISPLAYLEVEL(3, "test%3u : ZSTD_getErrorName : ", testNb++); { const char* errorString = ZSTD_getErrorName(0); DISPLAYLEVEL(3, "OK : %s \n", errorString); } - DISPLAYLEVEL(3, "test%3i : ZSTD_getErrorName with wrong value : ", testNb++); + DISPLAYLEVEL(3, "test%3u : ZSTD_getErrorName with wrong value : ", testNb++); { const char* errorString = ZSTD_getErrorName(499); DISPLAYLEVEL(3, "OK : %s \n", errorString); } - DISPLAYLEVEL(3, "test%3i : min compression level : ", testNb++); + DISPLAYLEVEL(3, "test%3u : min compression level : ", testNb++); { int const mcl = ZSTD_minCLevel(); DISPLAYLEVEL(3, "%i (OK) \n", mcl); } - DISPLAYLEVEL(3, "test%3i : compress %u bytes : ", testNb++, (U32)CNBuffSize); + DISPLAYLEVEL(3, "test%3u : compress %u bytes : ", testNb++, (unsigned)CNBuffSize); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); if (cctx==NULL) goto _output_error; CHECKPLUS(r, ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, 1), cSize=r ); - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : size of cctx for level 1 : ", testNb++); { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx); - DISPLAYLEVEL(3, "%u bytes \n", (U32)cctxSize); + DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cctxSize); } ZSTD_freeCCtx(cctx); } + DISPLAYLEVEL(3, "test%3i : decompress skippable frame -8 size : ", testNb++); + { + char const skippable8[] = "\x50\x2a\x4d\x18\xf8\xff\xff\xff"; + size_t const size = ZSTD_decompress(NULL, 0, skippable8, 8); + if (!ZSTD_isError(size)) goto _output_error; + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameContentSize test : ", testNb++); { unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize); @@ -369,7 +374,7 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (U32)CNBuffSize); + DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize); { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); if (r != CNBuffSize) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); @@ -383,13 +388,27 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "test%3i : decompress with null dict : ", testNb++); - { size_t const r = ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, NULL, 0); - if (r != CNBuffSize) goto _output_error; } + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); + { size_t const r = ZSTD_decompress_usingDict(dctx, + decodedBuffer, CNBuffSize, + compressedBuffer, cSize, + NULL, 0); + if (r != CNBuffSize) goto _output_error; + } + ZSTD_freeDCtx(dctx); + } DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : decompress with null DDict : ", testNb++); - { size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, NULL); - if (r != CNBuffSize) goto _output_error; } + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); + { size_t const r = ZSTD_decompress_usingDDict(dctx, + decodedBuffer, CNBuffSize, + compressedBuffer, cSize, + NULL); + if (r != CNBuffSize) goto _output_error; + } + ZSTD_freeDCtx(dctx); + } DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : decompress with 1 missing byte : ", testNb++); @@ -411,11 +430,55 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3d : check CCtx size after compressing empty input : ", testNb++); - { ZSTD_CCtx* cctx = ZSTD_createCCtx(); + { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19); if (ZSTD_isError(r)) goto _output_error; if (ZSTD_sizeof_CCtx(cctx) > (1U << 20)) goto _output_error; ZSTD_freeCCtx(cctx); + cSize = r; + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3d : decompress empty frame into NULL : ", testNb++); + { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, cSize); + if (ZSTD_isError(r)) goto _output_error; + if (r != 0) goto _output_error; + } + { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + ZSTD_outBuffer output; + if (cctx==NULL) goto _output_error; + output.dst = compressedBuffer; + output.size = compressedBufferSize; + output.pos = 0; + CHECK_Z( ZSTD_initCStream(cctx, 1) ); /* content size unknown */ + CHECK_Z( ZSTD_flushStream(cctx, &output) ); /* ensure no possibility to "concatenate" and determine the content size */ + CHECK_Z( ZSTD_endStream(cctx, &output) ); + ZSTD_freeCCtx(cctx); + /* single scan decompression */ + { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, output.pos); + if (ZSTD_isError(r)) goto _output_error; + if (r != 0) goto _output_error; + } + /* streaming decompression */ + { ZSTD_DCtx* const dstream = ZSTD_createDStream(); + ZSTD_inBuffer dinput; + ZSTD_outBuffer doutput; + size_t ipos; + if (dstream==NULL) goto _output_error; + dinput.src = compressedBuffer; + dinput.size = 0; + dinput.pos = 0; + doutput.dst = NULL; + doutput.size = 0; + doutput.pos = 0; + CHECK_Z ( ZSTD_initDStream(dstream) ); + for (ipos=1; ipos<=output.pos; ipos++) { + dinput.size = ipos; + CHECK_Z ( ZSTD_decompressStream(dstream, &doutput, &dinput) ); + } + if (doutput.pos != 0) goto _output_error; + ZSTD_freeDStream(dstream); + } } DISPLAYLEVEL(3, "OK \n"); @@ -437,7 +500,8 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3d : re-using a CCtx should compress the same : ", testNb++); - { int i; + { size_t const sampleSize = 30; + int i; for (i=0; i<20; i++) ((char*)CNBuffer)[i] = (char)i; /* ensure no match during initial section */ memcpy((char*)CNBuffer + 20, CNBuffer, 10); /* create one match, starting from beginning of sample, which is the difficult case (see #1241) */ @@ -445,54 +509,117 @@ static int basicUnitTests(U32 seed, double compressibility) ZSTD_CCtx* const cctx = ZSTD_createCCtx(); size_t size1, size2; DISPLAYLEVEL(5, "l%i ", i); - size1 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, 30, i); + size1 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i); CHECK_Z(size1); - size2 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, 30, i); + + size2 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i); + CHECK_Z(size2); + CHECK_EQ(size1, size2); + + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, i) ); + size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize); + CHECK_Z(size2); + CHECK_EQ(size1, size2); + + size2 = ZSTD_compress2(cctx, compressedBuffer, ZSTD_compressBound(sampleSize) - 1, CNBuffer, sampleSize); /* force streaming, as output buffer is not large enough to guarantee success */ CHECK_Z(size2); CHECK_EQ(size1, size2); + { ZSTD_inBuffer inb; + ZSTD_outBuffer outb; + inb.src = CNBuffer; + inb.pos = 0; + inb.size = sampleSize; + outb.dst = compressedBuffer; + outb.pos = 0; + outb.size = ZSTD_compressBound(sampleSize) - 1; /* force streaming, as output buffer is not large enough to guarantee success */ + CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) ); + assert(inb.pos == inb.size); + CHECK_EQ(size1, outb.pos); + } + ZSTD_freeCCtx(cctx); } } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3d : btultra2 & 1st block : ", testNb++); + { size_t const sampleSize = 1024; + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + ZSTD_inBuffer inb; + ZSTD_outBuffer outb; + inb.src = CNBuffer; + inb.pos = 0; + inb.size = 0; + outb.dst = compressedBuffer; + outb.pos = 0; + outb.size = compressedBufferSize; + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, ZSTD_maxCLevel()) ); + + inb.size = sampleSize; /* start with something, so that context is already used */ + CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) ); /* will break internal assert if stats_init is not disabled */ + assert(inb.pos == inb.size); + outb.pos = 0; /* cancel output */ + + CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(cctx, sampleSize) ); + inb.size = 4; /* too small size : compression will be skipped */ + inb.pos = 0; + CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) ); + assert(inb.pos == inb.size); + + inb.size += 5; /* too small size : compression will be skipped */ + CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) ); + assert(inb.pos == inb.size); + + inb.size += 11; /* small enough to attempt compression */ + CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) ); + assert(inb.pos == inb.size); + + assert(inb.pos < sampleSize); + inb.size = sampleSize; /* large enough to trigger stats_init, but no longer at beginning */ + CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) ); /* will break internal assert if stats_init is not disabled */ + assert(inb.pos == inb.size); + ZSTD_freeCCtx(cctx); + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3d : ZSTD_CCtx_getParameter() : ", testNb++); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); ZSTD_outBuffer out = {NULL, 0, 0}; ZSTD_inBuffer in = {NULL, 0, 0}; - unsigned value; + int value; - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_compressionLevel, &value)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); CHECK_EQ(value, 3); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_hashLog, &value)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); CHECK_EQ(value, 0); - CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_p_hashLog, ZSTD_HASHLOG_MIN)); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_compressionLevel, &value)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, ZSTD_HASHLOG_MIN)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); CHECK_EQ(value, 3); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_hashLog, &value)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); CHECK_EQ(value, ZSTD_HASHLOG_MIN); - CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, 7)); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_compressionLevel, &value)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); CHECK_EQ(value, 7); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_hashLog, &value)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); CHECK_EQ(value, ZSTD_HASHLOG_MIN); /* Start a compression job */ - ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_continue); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_compressionLevel, &value)); + ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); CHECK_EQ(value, 7); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_hashLog, &value)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); CHECK_EQ(value, ZSTD_HASHLOG_MIN); /* Reset the CCtx */ - ZSTD_CCtx_reset(cctx); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_compressionLevel, &value)); + ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); CHECK_EQ(value, 7); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_hashLog, &value)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); CHECK_EQ(value, ZSTD_HASHLOG_MIN); /* Reset the parameters */ - ZSTD_CCtx_resetParameters(cctx); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_compressionLevel, &value)); + ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value)); CHECK_EQ(value, 3); - CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_hashLog, &value)); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); CHECK_EQ(value, 0); ZSTD_freeCCtx(cctx); @@ -502,8 +629,8 @@ static int basicUnitTests(U32 seed, double compressibility) /* this test is really too long, and should be made faster */ DISPLAYLEVEL(3, "test%3d : overflow protection with large windowLog : ", testNb++); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); - ZSTD_parameters params = ZSTD_getParams(-9, ZSTD_CONTENTSIZE_UNKNOWN, 0); - size_t const nbCompressions = ((1U << 31) / CNBuffSize) + 1; /* ensure U32 overflow protection is triggered */ + ZSTD_parameters params = ZSTD_getParams(-999, ZSTD_CONTENTSIZE_UNKNOWN, 0); + size_t const nbCompressions = ((1U << 31) / CNBuffSize) + 2; /* ensure U32 overflow protection is triggered */ size_t cnb; assert(cctx != NULL); params.fParams.contentSizeFlag = 0; @@ -537,7 +664,7 @@ static int basicUnitTests(U32 seed, double compressibility) { U32 const maxNbAttempts = 1100; /* nb of usages before triggering size down is handled within zstd_compress.c. * currently defined as 128x, but could be adjusted in the future. * make this test long enough so that it's not too much tied to the current definition within zstd_compress.c */ - U32 u; + unsigned u; for (u=0; u<maxNbAttempts; u++) { CHECK_Z(ZSTD_compressCCtx(largeCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1, 1)); if (ZSTD_sizeof_CCtx(largeCCtx) < largeCCtxSize) break; /* sized down */ @@ -580,7 +707,7 @@ static int basicUnitTests(U32 seed, double compressibility) CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL), cSize=r ); DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", - (U32)cSize, (double)cSize/CNBuffSize*100); + (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : simple decompression test with static DCtx : ", testNb++); { size_t const r = ZSTD_decompressDCtx(staticDCtx, @@ -631,6 +758,17 @@ static int basicUnitTests(U32 seed, double compressibility) free(staticDCtxBuffer); } + DISPLAYLEVEL(3, "test%3i : Static negative levels : ", testNb++); + { size_t const cctxSizeN1 = ZSTD_estimateCCtxSize(-1); + size_t const cctxSizeP1 = ZSTD_estimateCCtxSize(1); + size_t const cstreamSizeN1 = ZSTD_estimateCStreamSize(-1); + size_t const cstreamSizeP1 = ZSTD_estimateCStreamSize(1); + + if (!(0 < cctxSizeN1 && cctxSizeN1 <= cctxSizeP1)) goto _output_error; + if (!(0 < cstreamSizeN1 && cstreamSizeN1 <= cstreamSizeP1)) goto _output_error; + } + DISPLAYLEVEL(3, "OK \n"); + /* ZSTDMT simple MT compression test */ DISPLAYLEVEL(3, "test%3i : create ZSTDMT CCtx : ", testNb++); @@ -642,23 +780,23 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3i : compress %u bytes with 2 threads : ", testNb++, (U32)CNBuffSize); + DISPLAYLEVEL(3, "test%3u : compress %u bytes with 2 threads : ", testNb++, (unsigned)CNBuffSize); CHECKPLUS(r, ZSTDMT_compressCCtx(mtctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, 1), cSize=r ); - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : decompressed size test : ", testNb++); { unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize); if (rSize != CNBuffSize) { - DISPLAY("ZSTD_getFrameContentSize incorrect : %u != %u \n", (U32)rSize, (U32)CNBuffSize); + DISPLAY("ZSTD_getFrameContentSize incorrect : %u != %u \n", (unsigned)rSize, (unsigned)CNBuffSize); goto _output_error; } } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (U32)CNBuffSize); + DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize); { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); if (r != CNBuffSize) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); @@ -680,9 +818,9 @@ static int basicUnitTests(U32 seed, double compressibility) NULL, params, 3 /*overlapRLog*/), cSize=r ); } - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); - DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (U32)CNBuffSize); + DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize); { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); if (r != CNBuffSize) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); @@ -709,7 +847,7 @@ static int basicUnitTests(U32 seed, double compressibility) const U32 skipLen = 129 KB; MEM_writeLE32((BYTE*)compressedBuffer + off, ZSTD_MAGIC_SKIPPABLE_START); MEM_writeLE32((BYTE*)compressedBuffer + off + 4, skipLen); - off += skipLen + ZSTD_skippableHeaderSize; + off += skipLen + ZSTD_SKIPPABLEHEADERSIZE; } } cSize = off; @@ -733,7 +871,9 @@ static int basicUnitTests(U32 seed, double compressibility) /* Dictionary and CCtx Duplication tests */ { ZSTD_CCtx* const ctxOrig = ZSTD_createCCtx(); ZSTD_CCtx* const ctxDuplicated = ZSTD_createCCtx(); + ZSTD_DCtx* const dctx = ZSTD_createDCtx(); static const size_t dictSize = 551; + assert(dctx != NULL); assert(ctxOrig != NULL); assert(ctxDuplicated != NULL); DISPLAYLEVEL(3, "test%3i : copy context too soon : ", testNb++); { size_t const copyResult = ZSTD_copyCCtx(ctxDuplicated, ctxOrig, 0); @@ -750,7 +890,7 @@ static int basicUnitTests(U32 seed, double compressibility) CHECKPLUS(r, ZSTD_compressEnd(ctxOrig, compressedBuffer, compressedBufferSize, (const char*)CNBuffer + dictSize, CNBuffSize - dictSize), cSize += r); - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : frame built with flat dictionary should be decompressible : ", testNb++); CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, @@ -768,7 +908,7 @@ static int basicUnitTests(U32 seed, double compressibility) cSize += r); if (cSize != cSizeOrig) goto _output_error; /* should be identical ==> same size */ } - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : frame built with duplicated context should be decompressible : ", testNb++); CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, @@ -782,7 +922,7 @@ static int basicUnitTests(U32 seed, double compressibility) { ZSTD_DDict* const ddict = ZSTD_createDDict(CNBuffer, dictSize); size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, ddict); if (r != CNBuffSize - dictSize) goto _output_error; - DISPLAYLEVEL(3, "OK (size of DDict : %u) \n", (U32)ZSTD_sizeof_DDict(ddict)); + DISPLAYLEVEL(3, "OK (size of DDict : %u) \n", (unsigned)ZSTD_sizeof_DDict(ddict)); ZSTD_freeDDict(ddict); } @@ -795,7 +935,7 @@ static int basicUnitTests(U32 seed, double compressibility) if (r != CNBuffSize - dictSize) goto _output_error; } free(ddictBuffer); - DISPLAYLEVEL(3, "OK (size of static DDict : %u) \n", (U32)ddictBufferSize); + DISPLAYLEVEL(3, "OK (size of static DDict : %u) \n", (unsigned)ddictBufferSize); } DISPLAYLEVEL(3, "test%3i : check content size on duplicated context : ", testNb++); @@ -817,6 +957,7 @@ static int basicUnitTests(U32 seed, double compressibility) ZSTD_freeCCtx(ctxOrig); ZSTD_freeCCtx(ctxDuplicated); + ZSTD_freeDCtx(dctx); } /* Dictionary and dictBuilder tests */ @@ -843,7 +984,7 @@ static int basicUnitTests(U32 seed, double compressibility) { size_t const sDictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity, decodedBuffer, samplesSizes, nbSamples); if (ZDICT_isError(sDictSize)) goto _output_error; - DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (U32)sDictSize); + DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)sDictSize); } DISPLAYLEVEL(3, "test%3i : dictBuilder : ", testNb++); @@ -851,19 +992,47 @@ static int basicUnitTests(U32 seed, double compressibility) dictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity, CNBuffer, samplesSizes, nbSamples); if (ZDICT_isError(dictSize)) goto _output_error; - DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (U32)dictSize); + DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); + + DISPLAYLEVEL(3, "test%3i : Multithreaded COVER dictBuilder : ", testNb++); + { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } + { ZDICT_cover_params_t coverParams; + memset(&coverParams, 0, sizeof(coverParams)); + coverParams.steps = 8; + coverParams.nbThreads = 4; + dictSize = ZDICT_optimizeTrainFromBuffer_cover( + dictBuffer, dictBufferCapacity, + CNBuffer, samplesSizes, nbSamples/8, /* less samples for faster tests */ + &coverParams); + if (ZDICT_isError(dictSize)) goto _output_error; + } + DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); + + DISPLAYLEVEL(3, "test%3i : Multithreaded FASTCOVER dictBuilder : ", testNb++); + { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; } + { ZDICT_fastCover_params_t fastCoverParams; + memset(&fastCoverParams, 0, sizeof(fastCoverParams)); + fastCoverParams.steps = 8; + fastCoverParams.nbThreads = 4; + dictSize = ZDICT_optimizeTrainFromBuffer_fastCover( + dictBuffer, dictBufferCapacity, + CNBuffer, samplesSizes, nbSamples, + &fastCoverParams); + if (ZDICT_isError(dictSize)) goto _output_error; + } + DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++); dictID = ZDICT_getDictID(dictBuffer, dictSize); if (dictID==0) goto _output_error; - DISPLAYLEVEL(3, "OK : %u \n", dictID); + DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID); DISPLAYLEVEL(3, "test%3i : compress with dictionary : ", testNb++); cSize = ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, dictBuffer, dictSize, 4); if (ZSTD_isError(cSize)) goto _output_error; - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : retrieve dictID from dictionary : ", testNb++); { U32 const did = ZSTD_getDictID_fromDict(dictBuffer, dictSize); @@ -878,17 +1047,20 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : frame built with dictionary should be decompressible : ", testNb++); - CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, - decodedBuffer, CNBuffSize, - compressedBuffer, cSize, - dictBuffer, dictSize), - if (r != CNBuffSize) goto _output_error); + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); + CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, + decodedBuffer, CNBuffSize, + compressedBuffer, cSize, + dictBuffer, dictSize), + if (r != CNBuffSize) goto _output_error); + ZSTD_freeDCtx(dctx); + } DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : estimate CDict size : ", testNb++); { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); size_t const estimatedSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byRef); - DISPLAYLEVEL(3, "OK : %u \n", (U32)estimatedSize); + DISPLAYLEVEL(3, "OK : %u \n", (unsigned)estimatedSize); } DISPLAYLEVEL(3, "test%3i : compress with CDict ", testNb++); @@ -896,13 +1068,13 @@ static int basicUnitTests(U32 seed, double compressibility) ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); - DISPLAYLEVEL(3, "(size : %u) : ", (U32)ZSTD_sizeof_CDict(cdict)); + DISPLAYLEVEL(3, "(size : %u) : ", (unsigned)ZSTD_sizeof_CDict(cdict)); cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, cdict); ZSTD_freeCDict(cdict); if (ZSTD_isError(cSize)) goto _output_error; } - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : retrieve dictID from frame : ", testNb++); { U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize); @@ -911,11 +1083,14 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : frame built with dictionary should be decompressible : ", testNb++); - CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, - decodedBuffer, CNBuffSize, - compressedBuffer, cSize, - dictBuffer, dictSize), - if (r != CNBuffSize) goto _output_error); + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); + CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, + decodedBuffer, CNBuffSize, + compressedBuffer, cSize, + dictBuffer, dictSize), + if (r != CNBuffSize) goto _output_error); + ZSTD_freeDCtx(dctx); + } DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : compress with static CDict : ", testNb++); @@ -944,7 +1119,7 @@ static int basicUnitTests(U32 seed, double compressibility) } } free(cdictBuffer); } } - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : ZSTD_compress_usingCDict_advanced, no contentSize, no dictID : ", testNb++); { ZSTD_frameParameters const fParams = { 0 /* frameSize */, 1 /* checksum */, 1 /* noDictID*/ }; @@ -955,7 +1130,7 @@ static int basicUnitTests(U32 seed, double compressibility) ZSTD_freeCDict(cdict); if (ZSTD_isError(cSize)) goto _output_error; } - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : try retrieving contentSize from frame : ", testNb++); { U64 const contentSize = ZSTD_getFrameContentSize(compressedBuffer, cSize); @@ -964,11 +1139,14 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "OK (unknown)\n"); DISPLAYLEVEL(3, "test%3i : frame built without dictID should be decompressible : ", testNb++); - CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, - decodedBuffer, CNBuffSize, - compressedBuffer, cSize, - dictBuffer, dictSize), - if (r != CNBuffSize) goto _output_error); + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); + CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, + decodedBuffer, CNBuffSize, + compressedBuffer, cSize, + dictBuffer, dictSize), + if (r != CNBuffSize) goto _output_error); + ZSTD_freeDCtx(dctx); + } DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : ZSTD_compress_advanced, no dictID : ", testNb++); @@ -979,22 +1157,29 @@ static int basicUnitTests(U32 seed, double compressibility) dictBuffer, dictSize, p); if (ZSTD_isError(cSize)) goto _output_error; } - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); DISPLAYLEVEL(3, "test%3i : frame built without dictID should be decompressible : ", testNb++); - CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, - decodedBuffer, CNBuffSize, - compressedBuffer, cSize, - dictBuffer, dictSize), - if (r != CNBuffSize) goto _output_error); + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); + CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, + decodedBuffer, CNBuffSize, + compressedBuffer, cSize, + dictBuffer, dictSize), + if (r != CNBuffSize) goto _output_error); + ZSTD_freeDCtx(dctx); + } DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : dictionary containing only header should return error : ", testNb++); - { - const size_t ret = ZSTD_decompress_usingDict( - dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, - "\x37\xa4\x30\xec\x11\x22\x33\x44", 8); - if (ZSTD_getErrorCode(ret) != ZSTD_error_dictionary_corrupted) goto _output_error; + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); + assert(dctx != NULL); + { const size_t ret = ZSTD_decompress_usingDict( + dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, + "\x37\xa4\x30\xec\x11\x22\x33\x44", 8); + if (ZSTD_getErrorCode(ret) != ZSTD_error_dictionary_corrupted) + goto _output_error; + } + ZSTD_freeDCtx(dctx); } DISPLAYLEVEL(3, "OK \n"); @@ -1063,10 +1248,12 @@ static int basicUnitTests(U32 seed, double compressibility) */ { size_t dSize; BYTE data[1024]; + ZSTD_DCtx* const dctx = ZSTD_createDCtx(); ZSTD_compressionParameters const cParams = ZSTD_getCParams(19, CNBuffSize, dictSize); ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); + assert(dctx != NULL); assert(cdict != NULL); memset(data, 'x', sizeof(data)); cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, data, sizeof(data), cdict); @@ -1075,6 +1262,7 @@ static int basicUnitTests(U32 seed, double compressibility) dSize = ZSTD_decompress_usingDict(dctx, decodedBuffer, sizeof(data), compressedBuffer, cSize, dictBuffer, dictSize); if (ZSTD_isError(dSize)) { DISPLAYLEVEL(5, "Decompression error %s : ", ZSTD_getErrorName(dSize)); goto _output_error; } if (memcmp(data, decodedBuffer, sizeof(data))) { DISPLAYLEVEL(5, "Data corruption : "); goto _output_error; } + ZSTD_freeDCtx(dctx); } DISPLAYLEVEL(3, "OK \n"); @@ -1110,12 +1298,12 @@ static int basicUnitTests(U32 seed, double compressibility) CNBuffer, samplesSizes, nbSamples, params); if (ZDICT_isError(dictSize)) goto _output_error; - DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (U32)dictSize); + DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++); dictID = ZDICT_getDictID(dictBuffer, dictSize); if (dictID==0) goto _output_error; - DISPLAYLEVEL(3, "OK : %u \n", dictID); + DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID); DISPLAYLEVEL(3, "test%3i : ZDICT_optimizeTrainFromBuffer_cover : ", testNb++); memset(¶ms, 0, sizeof(params)); @@ -1124,12 +1312,12 @@ static int basicUnitTests(U32 seed, double compressibility) CNBuffer, samplesSizes, nbSamples / 4, ¶ms); if (ZDICT_isError(optDictSize)) goto _output_error; - DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (U32)optDictSize); + DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)optDictSize); DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++); dictID = ZDICT_getDictID(dictBuffer, optDictSize); if (dictID==0) goto _output_error; - DISPLAYLEVEL(3, "OK : %u \n", dictID); + DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID); ZSTD_freeCCtx(cctx); free(dictBuffer); @@ -1180,13 +1368,13 @@ static int basicUnitTests(U32 seed, double compressibility) params); if (ZSTD_isError(cSize_1pass)) goto _output_error; - CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, (unsigned)compressionLevel) ); - { ZSTD_inBuffer in = { CNBuffer, srcSize, 0 }; - ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 }; - size_t const compressionResult = ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_end); - DISPLAYLEVEL(5, "simple=%zu vs %zu=advanced : ", cSize_1pass, out.pos); + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) ); + { size_t const compressionResult = ZSTD_compress2(cctx, + compressedBuffer, compressedBufferSize, + CNBuffer, srcSize); + DISPLAYLEVEL(5, "simple=%zu vs %zu=advanced : ", cSize_1pass, compressionResult); if (ZSTD_isError(compressionResult)) goto _output_error; - if (out.pos != cSize_1pass) goto _output_error; + if (compressionResult != cSize_1pass) goto _output_error; } } ZSTD_freeCCtx(cctx); } @@ -1199,54 +1387,86 @@ static int basicUnitTests(U32 seed, double compressibility) { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); DISPLAYLEVEL(3, "test%3i : parameters in order : ", testNb++); assert(cctx != NULL); - CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, 2) ); - CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_enableLongDistanceMatching, 1) ); - CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_windowLog, 18) ); - { ZSTD_inBuffer in = { CNBuffer, inputSize, 0 }; - ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(inputSize), 0 }; - size_t const result = ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_end); - if (result != 0) goto _output_error; - if (in.pos != in.size) goto _output_error; - cSize = out.pos; - xxh64 = XXH64(out.dst, out.pos, 0); + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 2) ); + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1) ); + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18) ); + { size_t const compressedSize = ZSTD_compress2(cctx, + compressedBuffer, ZSTD_compressBound(inputSize), + CNBuffer, inputSize); + CHECK(compressedSize); + cSize = compressedSize; + xxh64 = XXH64(compressedBuffer, compressedSize, 0); } - DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (U32)inputSize, (U32)cSize); + DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)cSize); ZSTD_freeCCtx(cctx); } { ZSTD_CCtx* cctx = ZSTD_createCCtx(); DISPLAYLEVEL(3, "test%3i : parameters disordered : ", testNb++); - CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_windowLog, 18) ); - CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_enableLongDistanceMatching, 1) ); - CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, 2) ); - { ZSTD_inBuffer in = { CNBuffer, inputSize, 0 }; - ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(inputSize), 0 }; - size_t const result = ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_end); - if (result != 0) goto _output_error; - if (in.pos != in.size) goto _output_error; - if (out.pos != cSize) goto _output_error; /* must result in same compressed result, hence same size */ - if (XXH64(out.dst, out.pos, 0) != xxh64) goto _output_error; /* must result in exactly same content, hence same hash */ - DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (U32)inputSize, (U32)out.pos); + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18) ); + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1) ); + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 2) ); + { size_t const result = ZSTD_compress2(cctx, + compressedBuffer, ZSTD_compressBound(inputSize), + CNBuffer, inputSize); + CHECK(result); + if (result != cSize) goto _output_error; /* must result in same compressed result, hence same size */ + if (XXH64(compressedBuffer, result, 0) != xxh64) goto _output_error; /* must result in exactly same content, hence same hash */ + DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)result); } ZSTD_freeCCtx(cctx); } } + /* advanced parameters for decompression */ + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); + assert(dctx != NULL); + + DISPLAYLEVEL(3, "test%3i : get dParameter bounds ", testNb++); + { ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax); + CHECK(bounds.error); + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : wrong dParameter : ", testNb++); + { size_t const sr = ZSTD_DCtx_setParameter(dctx, (ZSTD_dParameter)999999, 0); + if (!ZSTD_isError(sr)) goto _output_error; + } + { ZSTD_bounds const bounds = ZSTD_dParam_getBounds((ZSTD_dParameter)999998); + if (!ZSTD_isError(bounds.error)) goto _output_error; + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : out of bound dParameter : ", testNb++); + { size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 9999); + if (!ZSTD_isError(sr)) goto _output_error; + } + { size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (ZSTD_format_e)888); + if (!ZSTD_isError(sr)) goto _output_error; + } + DISPLAYLEVEL(3, "OK \n"); + + ZSTD_freeDCtx(dctx); + } + + /* custom formats tests */ { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + ZSTD_DCtx* const dctx = ZSTD_createDCtx(); size_t const inputSize = CNBuffSize / 2; /* won't cause pb with small dict size */ + assert(dctx != NULL); assert(cctx != NULL); /* basic block compression */ DISPLAYLEVEL(3, "test%3i : magic-less format test : ", testNb++); - CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_format, ZSTD_f_zstd1_magicless) ); + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) ); { ZSTD_inBuffer in = { CNBuffer, inputSize, 0 }; ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(inputSize), 0 }; - size_t const result = ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_end); + size_t const result = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end); if (result != 0) goto _output_error; if (in.pos != in.size) goto _output_error; cSize = out.pos; } - DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (U32)inputSize, (U32)cSize); + DISPLAYLEVEL(3, "OK (compress : %u -> %u bytes)\n", (unsigned)inputSize, (unsigned)cSize); DISPLAYLEVEL(3, "test%3i : decompress normally (should fail) : ", testNb++); { size_t const decodeResult = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); @@ -1255,29 +1475,38 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "test%3i : decompress of magic-less frame : ", testNb++); - ZSTD_DCtx_reset(dctx); - CHECK( ZSTD_DCtx_setFormat(dctx, ZSTD_f_zstd1_magicless) ); + ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); + CHECK( ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless) ); { ZSTD_frameHeader zfh; size_t const zfhrt = ZSTD_getFrameHeader_advanced(&zfh, compressedBuffer, cSize, ZSTD_f_zstd1_magicless); if (zfhrt != 0) goto _output_error; } + /* one shot */ + { size_t const result = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize); + if (result != inputSize) goto _output_error; + DISPLAYLEVEL(3, "one-shot OK, "); + } + /* streaming */ { ZSTD_inBuffer in = { compressedBuffer, cSize, 0 }; ZSTD_outBuffer out = { decodedBuffer, CNBuffSize, 0 }; - size_t const result = ZSTD_decompress_generic(dctx, &out, &in); + size_t const result = ZSTD_decompressStream(dctx, &out, &in); if (result != 0) goto _output_error; if (in.pos != in.size) goto _output_error; if (out.pos != inputSize) goto _output_error; - DISPLAYLEVEL(3, "OK : regenerated %u bytes \n", (U32)out.pos); + DISPLAYLEVEL(3, "streaming OK : regenerated %u bytes \n", (unsigned)out.pos); } ZSTD_freeCCtx(cctx); + ZSTD_freeDCtx(dctx); } /* block API tests */ { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + ZSTD_DCtx* const dctx = ZSTD_createDCtx(); static const size_t dictSize = 65 KB; static const size_t blockSize = 100 KB; /* won't cause pb with small dict size */ size_t cSize2; + assert(cctx != NULL); assert(dctx != NULL); /* basic block compression */ DISPLAYLEVEL(3, "test%3i : Block compression test : ", testNb++); @@ -1295,13 +1524,14 @@ static int basicUnitTests(U32 seed, double compressibility) /* very long stream of block compression */ DISPLAYLEVEL(3, "test%3i : Huge block streaming compression test : ", testNb++); - CHECK( ZSTD_compressBegin(cctx, -99) ); /* we just want to quickly overflow internal U32 index */ + CHECK( ZSTD_compressBegin(cctx, -199) ); /* we just want to quickly overflow internal U32 index */ CHECK( ZSTD_getBlockSize(cctx) >= blockSize); { U64 const toCompress = 5000000000ULL; /* > 4 GB */ U64 compressed = 0; while (compressed < toCompress) { size_t const blockCSize = ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize); - if (ZSTD_isError(cSize)) goto _output_error; + assert(blockCSize != 0); + if (ZSTD_isError(blockCSize)) goto _output_error; compressed += blockCSize; } } @@ -1339,8 +1569,8 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); ZSTD_freeCCtx(cctx); + ZSTD_freeDCtx(dctx); } - ZSTD_freeDCtx(dctx); /* long rle test */ { size_t sampleSize = 0; @@ -1363,7 +1593,7 @@ static int basicUnitTests(U32 seed, double compressibility) memset(CNBuffer, 0, ZEROESLENGTH); { CHECK_V(r, ZSTD_compress(compressedBuffer, ZSTD_compressBound(ZEROESLENGTH), CNBuffer, ZEROESLENGTH, 1) ); cSize = r; } - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/ZEROESLENGTH*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/ZEROESLENGTH*100); DISPLAYLEVEL(3, "test%3i : decompress %u zeroes : ", testNb++, ZEROESLENGTH); { CHECK_V(r, ZSTD_decompress(decodedBuffer, ZEROESLENGTH, compressedBuffer, cSize) ); @@ -1417,7 +1647,7 @@ static int basicUnitTests(U32 seed, double compressibility) { CHECK_V(r, ZSTD_compress(compressedBuffer, ZSTD_compressBound(_3BYTESTESTLENGTH), CNBuffer, _3BYTESTESTLENGTH, 19) ); cSize = r; } - DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/_3BYTESTESTLENGTH*100); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/_3BYTESTESTLENGTH*100); DISPLAYLEVEL(3, "test%3i : decompress lots 3-bytes sequence : ", testNb++); { CHECK_V(r, ZSTD_decompress(decodedBuffer, _3BYTESTESTLENGTH, compressedBuffer, cSize) ); @@ -1586,7 +1816,7 @@ static size_t FUZ_randomLength(U32* seed, U32 maxLog) if (cond) { \ DISPLAY("Error => "); \ DISPLAY(__VA_ARGS__); \ - DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); \ + DISPLAY(" (seed %u, test nb %u) \n", (unsigned)seed, testNb); \ goto _output_error; \ } } @@ -1596,12 +1826,12 @@ static size_t FUZ_randomLength(U32* seed, U32 maxLog) if (ZSTD_isError(err)) { \ DISPLAY("Error => %s : %s ", \ #f, ZSTD_getErrorName(err)); \ - DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); \ + DISPLAY(" (seed %u, test nb %u) \n", (unsigned)seed, testNb); \ goto _output_error; \ } } -static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxDurationS, double compressibility, int bigTests) +static int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, U32 const maxDurationS, double compressibility, int bigTests) { static const U32 maxSrcLog = 23; static const U32 maxSampleLog = 22; @@ -1616,7 +1846,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD ZSTD_CCtx* const ctx = ZSTD_createCCtx(); ZSTD_DCtx* const dctx = ZSTD_createDCtx(); U32 result = 0; - U32 testNb = 0; + unsigned testNb = 0; U32 coreSeed = seed; UTIL_time_t const startClock = UTIL_getTime(); U64 const maxClockSpan = maxDurationS * SEC_TO_MICRO; @@ -1698,15 +1928,17 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD CHECK(ZSTD_isError(cSize), "ZSTD_compressCCtx failed : %s", ZSTD_getErrorName(cSize)); /* compression failure test : too small dest buffer */ - if (cSize > 3) { - const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */ + assert(cSize > 3); + { const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; const size_t tooSmallSize = cSize - missing; - const U32 endMark = 0x4DC2B1A9; - memcpy(dstBuffer+tooSmallSize, &endMark, 4); + const unsigned endMark = 0x4DC2B1A9; + memcpy(dstBuffer+tooSmallSize, &endMark, sizeof(endMark)); + DISPLAYLEVEL(5, "fuzzer t%u: compress into too small buffer of size %u (missing %u bytes) \n", + testNb, (unsigned)tooSmallSize, (unsigned)missing); { size_t const errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, sampleBuffer, sampleSize, cLevel); - CHECK(!ZSTD_isError(errorCode), "ZSTD_compressCCtx should have failed ! (buffer too small : %u < %u)", (U32)tooSmallSize, (U32)cSize); } - { U32 endCheck; memcpy(&endCheck, dstBuffer+tooSmallSize, 4); - CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow"); } + CHECK(!ZSTD_isError(errorCode), "ZSTD_compressCCtx should have failed ! (buffer too small : %u < %u)", (unsigned)tooSmallSize, (unsigned)cSize); } + { unsigned endCheck; memcpy(&endCheck, dstBuffer+tooSmallSize, sizeof(endCheck)); + CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow (check.%08X != %08X.mark)", endCheck, endMark); } } } /* frame header decompression test */ @@ -1724,9 +1956,9 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD DISPLAYLEVEL(5, "fuzzer t%u: simple decompression test \n", testNb); { size_t const margin = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1; size_t const dSize = ZSTD_decompress(dstBuffer, sampleSize + margin, cBuffer, cSize); - CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (U32)sampleSize, (U32)cSize); + CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (unsigned)sampleSize, (unsigned)cSize); { U64 const crcDest = XXH64(dstBuffer, sampleSize, 0); - CHECK(crcOrig != crcDest, "decompression result corrupted (pos %u / %u)", (U32)findDiff(sampleBuffer, dstBuffer, sampleSize), (U32)sampleSize); + CHECK(crcOrig != crcDest, "decompression result corrupted (pos %u / %u)", (unsigned)findDiff(sampleBuffer, dstBuffer, sampleSize), (unsigned)sampleSize); } } free(sampleBuffer); /* no longer useful after this point */ @@ -1751,7 +1983,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD static const BYTE token = 0xA9; dstBuffer[tooSmallSize] = token; { size_t const errorCode = ZSTD_decompress(dstBuffer, tooSmallSize, cBuffer, cSize); - CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed : %u > %u (dst buffer too small)", (U32)errorCode, (U32)tooSmallSize); } + CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed : %u > %u (dst buffer too small)", (unsigned)errorCode, (unsigned)tooSmallSize); } CHECK(dstBuffer[tooSmallSize] != token, "ZSTD_decompress : dst buffer overflow"); } @@ -1786,7 +2018,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD { size_t const decompressResult = ZSTD_decompress(dstBuffer, sampleSize, cBuffer, cSize); /* result *may* be an unlikely success, but even then, it must strictly respect dst buffer boundaries */ CHECK((!ZSTD_isError(decompressResult)) && (decompressResult>sampleSize), - "ZSTD_decompress on noisy src : result is too large : %u > %u (dst buffer)", (U32)decompressResult, (U32)sampleSize); + "ZSTD_decompress on noisy src : result is too large : %u > %u (dst buffer)", (unsigned)decompressResult, (unsigned)sampleSize); } { U32 endCheck; memcpy(&endCheck, dstBuffer+sampleSize, 4); CHECK(endMark!=endCheck, "ZSTD_decompress on noisy src : dst buffer overflow"); @@ -1807,7 +2039,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD dict = srcBuffer + (FUZ_rand(&lseed) % (srcBufferSize - dictSize)); DISPLAYLEVEL(6, "fuzzer t%u: Compressing up to <=%u bytes at level %i with dictionary size %u \n", - testNb, (U32)maxTestSize, cLevel, (U32)dictSize); + testNb, (unsigned)maxTestSize, cLevel, (unsigned)dictSize); if (FUZ_rand(&lseed) & 0xF) { CHECK_Z ( ZSTD_compressBegin_usingDict(refCtx, dict, dictSize, cLevel) ); @@ -1853,13 +2085,13 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD DISPLAYLEVEL(5, "fuzzer t%u: Bufferless streaming decompression test \n", testNb); /* ensure memory requirement is good enough (should always be true) */ { ZSTD_frameHeader zfh; - CHECK( ZSTD_getFrameHeader(&zfh, cBuffer, ZSTD_frameHeaderSize_max), + CHECK( ZSTD_getFrameHeader(&zfh, cBuffer, ZSTD_FRAMEHEADERSIZE_MAX), "ZSTD_getFrameHeader(): error retrieving frame information"); { size_t const roundBuffSize = ZSTD_decodingBufferSize_min(zfh.windowSize, zfh.frameContentSize); CHECK_Z(roundBuffSize); CHECK((roundBuffSize > totalTestSize) && (zfh.frameContentSize!=ZSTD_CONTENTSIZE_UNKNOWN), "ZSTD_decodingBufferSize_min() requires more memory (%u) than necessary (%u)", - (U32)roundBuffSize, (U32)totalTestSize ); + (unsigned)roundBuffSize, (unsigned)totalTestSize ); } } if (dictSize<8) dictSize=0, dict=NULL; /* disable dictionary */ CHECK_Z( ZSTD_decompressBegin_usingDict(dctx, dict, dictSize) ); @@ -1877,7 +2109,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD CHECK (totalCSize != cSize, "compressed data should be fully read") { U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0); CHECK(crcOrig != crcDest, "streaming decompressed data corrupted (pos %u / %u)", - (U32)findDiff(mirrorBuffer, dstBuffer, totalTestSize), (U32)totalTestSize); + (unsigned)findDiff(mirrorBuffer, dstBuffer, totalTestSize), (unsigned)totalTestSize); } } /* for ( ; (testNb <= nbTests) */ DISPLAY("\r%u fuzzer tests completed \n", testNb-1); @@ -1911,10 +2143,10 @@ static int FUZ_usage(const char* programName) DISPLAY( " %s [args]\n", programName); DISPLAY( "\n"); DISPLAY( "Arguments :\n"); - DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault); + DISPLAY( " -i# : Nb of tests (default:%i) \n", nbTestsDefault); DISPLAY( " -s# : Select seed (default:prompt user)\n"); DISPLAY( " -t# : Select starting test number (default:0)\n"); - DISPLAY( " -P# : Select compressibility in %% (default:%u%%)\n", FUZ_compressibility_default); + DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_compressibility_default); DISPLAY( " -v : verbose\n"); DISPLAY( " -p : pause at the end\n"); DISPLAY( " -h : display help and exit\n"); @@ -1961,7 +2193,7 @@ int main(int argc, const char** argv) int argNb; int nbTests = nbTestsDefault; int testNb = 0; - U32 proba = FUZ_compressibility_default; + int proba = FUZ_compressibility_default; int result = 0; U32 mainPause = 0; U32 maxDuration = 0; @@ -2048,8 +2280,8 @@ int main(int argc, const char** argv) seed = h % 10000; } - DISPLAY("Seed = %u\n", seed); - if (proba!=FUZ_compressibility_default) DISPLAY("Compressibility : %u%%\n", proba); + DISPLAY("Seed = %u\n", (unsigned)seed); + if (proba!=FUZ_compressibility_default) DISPLAY("Compressibility : %i%%\n", proba); if (memTestsOnly) { g_displayLevel = MAX(3, g_displayLevel); |