summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2017-07-14 14:51:28 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2017-07-14 14:51:28 +0000
commitaffe9eaf7807e0a5c3aa99d79dece91c3bbc3854 (patch)
tree86f382469abb446221bb5f590e38193c99fc4214 /tests
parentffcbc2d7ba03067492045e4cbead519a3b3c27ef (diff)
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile77
-rw-r--r--tests/datagencli.c19
-rw-r--r--tests/decodecorpus.c394
-rw-r--r--tests/fullbench.c176
-rw-r--r--tests/fuzzer.c229
-rw-r--r--tests/paramgrill.c34
-rwxr-xr-xtests/playTests.sh98
-rw-r--r--tests/roundTripCrash.c15
-rw-r--r--tests/symbols.c9
-rw-r--r--tests/zstreamtest.c565
10 files changed, 1354 insertions, 262 deletions
diff --git a/tests/Makefile b/tests/Makefile
index ea58c0fe5119e..82f12887bf9b4 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -25,17 +25,18 @@ PRGDIR = ../programs
PYTHON ?= python3
TESTARTEFACT := versionsTest namespaceTest
-
-DEBUGFLAGS=-g -DZSTD_DEBUG=1
-CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
- -I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR) \
- $(DEBUGFLAG)
-CFLAGS ?= -O3
-CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
- -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
- -Wstrict-prototypes -Wundef -Wformat-security
-CFLAGS += $(MOREFLAGS)
-FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
+DEBUGLEVEL= 1
+DEBUGFLAGS= -g -DZSTD_DEBUG=$(DEBUGLEVEL)
+CPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
+ -I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR)
+CFLAGS ?= -O3
+CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
+ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
+ -Wstrict-prototypes -Wundef -Wformat-security \
+ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
+ -Wredundant-decls
+CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
+FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
ZSTDCOMMON_FILES := $(ZSTDDIR)/common/*.c
@@ -92,11 +93,12 @@ zstd-nolegacy:
gzstd:
$(MAKE) -C $(PRGDIR) $@
-fullbench : $(ZSTD_FILES) $(PRGDIR)/datagen.c fullbench.c
- $(CC) $(FLAGS) $^ -o $@$(EXT)
-
-fullbench32 : $(ZSTD_FILES) $(PRGDIR)/datagen.c fullbench.c
- $(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
+fullbench32: CPPFLAGS += -m32
+fullbench fullbench32 : CPPFLAGS += $(MULTITHREAD_CPP)
+fullbench fullbench32 : LDFLAGS += $(MULTITHREAD_LD)
+fullbench fullbench32 : DEBUGFLAGS = # turn off assert() for speed measurements
+fullbench fullbench32 : $(ZSTD_FILES) $(PRGDIR)/datagen.c fullbench.c
+ $(CC) $(FLAGS) $^ -o $@$(EXT)
fullbench-lib: $(PRGDIR)/datagen.c fullbench.c
$(MAKE) -C $(ZSTDDIR) libzstd.a
@@ -157,7 +159,7 @@ zstreamtest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/datagen.c zstreamtest.c
$(MAKE) -C $(ZSTDDIR) libzstd
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@$(EXT)
-paramgrill : DEBUGFLAG =
+paramgrill : DEBUGFLAGS =
paramgrill : $(ZSTD_FILES) $(PRGDIR)/datagen.c paramgrill.c
$(CC) $(FLAGS) $^ -lm -o $@$(EXT)
@@ -178,7 +180,7 @@ legacy : CPPFLAGS+= -I$(ZSTDDIR)/legacy
legacy : $(ZSTD_FILES) $(wildcard $(ZSTDDIR)/legacy/*.c) legacy.c
$(CC) $(FLAGS) $^ -o $@$(EXT)
-decodecorpus : $(filter-out $(ZSTDDIR)/compress/zstd_compress.c, $(wildcard $(ZSTD_FILES))) decodecorpus.c
+decodecorpus : $(filter-out $(ZSTDDIR)/compress/zstd_compress.c, $(wildcard $(ZSTD_FILES))) $(ZDICT_FILES) decodecorpus.c
$(CC) $(FLAGS) $^ -o $@$(EXT) -lm
symbols : symbols.c
@@ -222,7 +224,7 @@ clean:
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS))
HOST_OS = POSIX
-valgrindTest: VALGRIND = valgrind --leak-check=full --error-exitcode=1
+valgrindTest: VALGRIND = valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1
valgrindTest: zstd datagen fuzzer fullbench
@echo "\n ---- valgrind tests : memory analyzer ----"
$(VALGRIND) ./datagen -g50M > $(VOID)
@@ -270,7 +272,7 @@ endif
test32: test-zstd32 test-fullbench32 test-fuzzer32 test-zstream32
-test-all: test test32 valgrindTest
+test-all: test test32 valgrindTest test-decodecorpus-cli
test-zstd: ZSTD = $(PRGDIR)/zstd
test-zstd: zstd zstd-playTests
@@ -319,6 +321,8 @@ test-zbuff32: zbufftest32
test-zstream: zstreamtest
$(QEMU_SYS) ./zstreamtest $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)
+ $(QEMU_SYS) ./zstreamtest --mt $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)
+ $(QEMU_SYS) ./zstreamtest --newapi $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)
test-zstream32: zstreamtest32
$(QEMU_SYS) ./zstreamtest32 $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)
@@ -338,6 +342,39 @@ test-legacy: legacy
test-decodecorpus: decodecorpus
$(QEMU_SYS) ./decodecorpus -t $(DECODECORPUS_TESTTIME)
+test-decodecorpus-cli: decodecorpus
+ @echo "\n ---- decodecorpus basic cli tests ----"
+ @mkdir testdir
+ ./decodecorpus -n5 -otestdir -ptestdir
+ @cd testdir && \
+ $(ZSTD) -d z000000.zst -o tmp0 && \
+ $(ZSTD) -d z000001.zst -o tmp1 && \
+ $(ZSTD) -d z000002.zst -o tmp2 && \
+ $(ZSTD) -d z000003.zst -o tmp3 && \
+ $(ZSTD) -d z000004.zst -o tmp4 && \
+ diff z000000 tmp0 && \
+ diff z000001 tmp1 && \
+ diff z000002 tmp2 && \
+ diff z000003 tmp3 && \
+ diff z000004 tmp4 && \
+ rm ./* && \
+ cd ..
+ @echo "\n ---- decodecorpus dictionary cli tests ----"
+ ./decodecorpus -n5 -otestdir -ptestdir --use-dict=1MB
+ @cd testdir && \
+ $(ZSTD) -d z000000.zst -D dictionary -o tmp0 && \
+ $(ZSTD) -d z000001.zst -D dictionary -o tmp1 && \
+ $(ZSTD) -d z000002.zst -D dictionary -o tmp2 && \
+ $(ZSTD) -d z000003.zst -D dictionary -o tmp3 && \
+ $(ZSTD) -d z000004.zst -D dictionary -o tmp4 && \
+ diff z000000 tmp0 && \
+ diff z000001 tmp1 && \
+ diff z000002 tmp2 && \
+ diff z000003 tmp3 && \
+ diff z000004 tmp4 && \
+ cd ..
+ @rm -rf testdir
+
test-pool: pool
$(QEMU_SYS) ./pool
diff --git a/tests/datagencli.c b/tests/datagencli.c
index 2f3ebc4d6863f..8a81939d16de1 100644
--- a/tests/datagencli.c
+++ b/tests/datagencli.c
@@ -48,7 +48,8 @@ static int usage(const char* programName)
DISPLAY( "Arguments :\n");
DISPLAY( " -g# : generate # data (default:%i)\n", SIZE_DEFAULT);
DISPLAY( " -s# : Select seed (default:%i)\n", SEED_DEFAULT);
- DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", COMPRESSIBILITY_DEFAULT);
+ DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n",
+ COMPRESSIBILITY_DEFAULT);
DISPLAY( " -h : display help and exit\n");
return 0;
}
@@ -56,7 +57,7 @@ static int usage(const char* programName)
int main(int argc, const char** argv)
{
- double proba = (double)COMPRESSIBILITY_DEFAULT / 100;
+ unsigned probaU32 = COMPRESSIBILITY_DEFAULT;
double litProba = 0.0;
U64 size = SIZE_DEFAULT;
U32 seed = SEED_DEFAULT;
@@ -94,11 +95,10 @@ int main(int argc, const char** argv)
break;
case 'P':
argument++;
- proba=0.0;
+ probaU32 = 0;
while ((*argument>='0') && (*argument<='9'))
- proba *= 10, proba += *argument++ - '0';
- if (proba>100.) proba=100.;
- proba /= 100.;
+ probaU32 *= 10, probaU32 += *argument++ - '0';
+ if (probaU32>100) probaU32 = 100;
break;
case 'L': /* hidden argument : Literal distribution probability */
argument++;
@@ -117,11 +117,12 @@ int main(int argc, const char** argv)
}
} } } /* for(argNb=1; argNb<argc; argNb++) */
- DISPLAYLEVEL(4, "Data Generator \n");
+ DISPLAYLEVEL(4, "Compressible data Generator \n");
+ if (probaU32!=COMPRESSIBILITY_DEFAULT)
+ DISPLAYLEVEL(3, "Compressibility : %i%%\n", probaU32);
DISPLAYLEVEL(3, "Seed = %u \n", seed);
- if (proba!=COMPRESSIBILITY_DEFAULT) DISPLAYLEVEL(3, "Compressibility : %i%%\n", (U32)(proba*100));
- RDG_genStdout(size, proba, litProba, seed);
+ RDG_genStdout(size, (double)probaU32/100, litProba, seed);
DISPLAYLEVEL(1, "\n");
return 0;
diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c
index f7b3c854fdb25..eaf07457894f1 100644
--- a/tests/decodecorpus.c
+++ b/tests/decodecorpus.c
@@ -18,6 +18,8 @@
#include "zstd.h"
#include "zstd_internal.h"
#include "mem.h"
+#define ZDICT_STATIC_LINKING_ONLY
+#include "zdict.h"
// Direct access to internal compression functions is required
#include "zstd_compress.c"
@@ -73,8 +75,6 @@ static clock_t clockSpan(clock_t cStart)
/*-*******************************************************
* Random function
*********************************************************/
-#define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
-
static unsigned RAND(unsigned* src)
{
#define RAND_rotl32(x,r) ((x << r) | (x >> (32 - r)))
@@ -231,6 +231,12 @@ typedef struct {
cblockStats_t oldStats; /* so they can be rolled back if uncompressible */
} frame_t;
+typedef struct {
+ int useDict;
+ U32 dictID;
+ size_t dictContentSize;
+ BYTE* dictContent;
+} dictInfo;
/*-*******************************************************
* Generator Functions
*********************************************************/
@@ -240,7 +246,7 @@ struct {
} opts; /* advanced options on generation */
/* Generate and write a random frame header */
-static void writeFrameHeader(U32* seed, frame_t* frame)
+static void writeFrameHeader(U32* seed, frame_t* frame, dictInfo info)
{
BYTE* const op = frame->data;
size_t pos = 0;
@@ -306,15 +312,26 @@ static void writeFrameHeader(U32* seed, frame_t* frame)
pos += 4;
{
+ /*
+ * fcsCode: 2-bit flag specifying how many bytes used to represent Frame_Content_Size (bits 7-6)
+ * singleSegment: 1-bit flag describing if data must be regenerated within a single continuous memory segment. (bit 5)
+ * contentChecksumFlag: 1-bit flag that is set if frame includes checksum at the end -- set to 1 below (bit 2)
+ * dictBits: 2-bit flag describing how many bytes Dictionary_ID uses -- set to 3 (bits 1-0)
+ * For more information: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#frame_header
+ */
+ int const dictBits = info.useDict ? 3 : 0;
BYTE const frameHeaderDescriptor =
- (BYTE) ((fcsCode << 6) | (singleSegment << 5) | (1 << 2));
+ (BYTE) ((fcsCode << 6) | (singleSegment << 5) | (1 << 2) | dictBits);
op[pos++] = frameHeaderDescriptor;
}
if (!singleSegment) {
op[pos++] = windowByte;
}
-
+ if (info.useDict) {
+ MEM_writeLE32(op + pos, (U32) info.dictID);
+ pos += 4;
+ }
if (contentSizeFlag) {
switch (fcsCode) {
default: /* Impossible */
@@ -605,7 +622,7 @@ static inline void initSeqStore(seqStore_t *seqStore) {
/* Randomly generate sequence commands */
static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
- size_t contentSize, size_t literalsSize)
+ size_t contentSize, size_t literalsSize, dictInfo info)
{
/* The total length of all the matches */
size_t const remainingMatch = contentSize - literalsSize;
@@ -629,7 +646,6 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
}
DISPLAYLEVEL(5, " total match lengths: %u\n", (U32)remainingMatch);
-
for (i = 0; i < numSequences; i++) {
/* Generate match and literal lengths by exponential distribution to
* ensure nice numbers */
@@ -654,14 +670,33 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
memcpy(srcPtr, literals, literalLen);
srcPtr += literalLen;
-
do {
if (RAND(seed) & 7) {
/* do a normal offset */
+ U32 const dataDecompressed = (U32)((BYTE*)srcPtr-(BYTE*)frame->srcStart);
offset = (RAND(seed) %
MIN(frame->header.windowSize,
(size_t)((BYTE*)srcPtr - (BYTE*)frame->srcStart))) +
1;
+ if (info.useDict && (RAND(seed) & 1) && i + 1 != numSequences && dataDecompressed < frame->header.windowSize) {
+ /* need to occasionally generate offsets that go past the start */
+ /* including i+1 != numSequences because the last sequences has to adhere to predetermined contentSize */
+ U32 lenPastStart = (RAND(seed) % info.dictContentSize) + 1;
+ offset = (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart)+lenPastStart;
+ if (offset > frame->header.windowSize) {
+ if (lenPastStart < MIN_SEQ_LEN) {
+ /* when offset > windowSize, matchLen bound by end of dictionary (lenPastStart) */
+ /* this also means that lenPastStart must be greater than MIN_SEQ_LEN */
+ /* make sure lenPastStart does not go past dictionary start though */
+ lenPastStart = MIN(lenPastStart+MIN_SEQ_LEN, (U32)info.dictContentSize);
+ offset = (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart) + lenPastStart;
+ }
+ {
+ U32 const matchLenBound = MIN(frame->header.windowSize, lenPastStart);
+ matchLen = MIN(matchLen, matchLenBound);
+ }
+ }
+ }
offsetCode = offset + ZSTD_REP_MOVE;
repIndex = 2;
} else {
@@ -677,11 +712,20 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
repIndex = MIN(2, offsetCode + 1);
}
}
- } while (offset > (size_t)((BYTE*)srcPtr - (BYTE*)frame->srcStart) || offset == 0);
+ } while (((!info.useDict) && (offset > (size_t)((BYTE*)srcPtr - (BYTE*)frame->srcStart))) || offset == 0);
- { size_t j;
+ {
+ size_t j;
+ BYTE* const dictEnd = info.dictContent + info.dictContentSize;
for (j = 0; j < matchLen; j++) {
- *srcPtr = *(srcPtr-offset);
+ if ((U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart) < offset) {
+ /* copy from dictionary instead of literals */
+ size_t const dictOffset = offset - (srcPtr - (BYTE*)frame->srcStart);
+ *srcPtr = *(dictEnd - dictOffset);
+ }
+ else {
+ *srcPtr = *(srcPtr-offset);
+ }
srcPtr++;
}
}
@@ -931,7 +975,7 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
}
static size_t writeSequencesBlock(U32* seed, frame_t* frame, size_t contentSize,
- size_t literalsSize)
+ size_t literalsSize, dictInfo info)
{
seqStore_t seqStore;
size_t numSequences;
@@ -940,14 +984,14 @@ static size_t writeSequencesBlock(U32* seed, frame_t* frame, size_t contentSize,
initSeqStore(&seqStore);
/* randomly generate sequences */
- numSequences = generateSequences(seed, frame, &seqStore, contentSize, literalsSize);
+ numSequences = generateSequences(seed, frame, &seqStore, contentSize, literalsSize, info);
/* write them out to the frame data */
CHECKERR(writeSequences(seed, frame, &seqStore, numSequences));
return numSequences;
}
-static size_t writeCompressedBlock(U32* seed, frame_t* frame, size_t contentSize)
+static size_t writeCompressedBlock(U32* seed, frame_t* frame, size_t contentSize, dictInfo info)
{
BYTE* const blockStart = (BYTE*)frame->data;
size_t literalsSize;
@@ -959,7 +1003,7 @@ static size_t writeCompressedBlock(U32* seed, frame_t* frame, size_t contentSize
DISPLAYLEVEL(4, " literals size: %u\n", (U32)literalsSize);
- nbSeq = writeSequencesBlock(seed, frame, contentSize, literalsSize);
+ nbSeq = writeSequencesBlock(seed, frame, contentSize, literalsSize, info);
DISPLAYLEVEL(4, " number of sequences: %u\n", (U32)nbSeq);
@@ -967,7 +1011,7 @@ static size_t writeCompressedBlock(U32* seed, frame_t* frame, size_t contentSize
}
static void writeBlock(U32* seed, frame_t* frame, size_t contentSize,
- int lastBlock)
+ int lastBlock, dictInfo info)
{
int const blockTypeDesc = RAND(seed) % 8;
size_t blockSize;
@@ -1007,7 +1051,7 @@ static void writeBlock(U32* seed, frame_t* frame, size_t contentSize,
frame->oldStats = frame->stats;
frame->data = op;
- compressedSize = writeCompressedBlock(seed, frame, contentSize);
+ compressedSize = writeCompressedBlock(seed, frame, contentSize, info);
if (compressedSize > contentSize) {
blockType = 0;
memcpy(op, frame->src, contentSize);
@@ -1033,7 +1077,7 @@ static void writeBlock(U32* seed, frame_t* frame, size_t contentSize,
frame->data = op;
}
-static void writeBlocks(U32* seed, frame_t* frame)
+static void writeBlocks(U32* seed, frame_t* frame, dictInfo info)
{
size_t contentLeft = frame->header.contentSize;
size_t const maxBlockSize = MIN(MAX_BLOCK_SIZE, frame->header.windowSize);
@@ -1056,7 +1100,7 @@ static void writeBlocks(U32* seed, frame_t* frame)
}
}
- writeBlock(seed, frame, blockContentSize, lastBlock);
+ writeBlock(seed, frame, blockContentSize, lastBlock, info);
contentLeft -= blockContentSize;
if (lastBlock) break;
@@ -1121,20 +1165,102 @@ static void initFrame(frame_t* fr)
}
/* Return the final seed */
-static U32 generateFrame(U32 seed, frame_t* fr)
+static U32 generateFrame(U32 seed, frame_t* fr, dictInfo info)
{
/* generate a complete frame */
DISPLAYLEVEL(1, "frame seed: %u\n", seed);
-
initFrame(fr);
- writeFrameHeader(&seed, fr);
- writeBlocks(&seed, fr);
+ writeFrameHeader(&seed, fr, info);
+ writeBlocks(&seed, fr, info);
writeChecksum(fr);
return seed;
}
+/*_*******************************************************
+* Dictionary Helper Functions
+*********************************************************/
+/* returns 0 if successful, otherwise returns 1 upon error */
+static int genRandomDict(U32 dictID, U32 seed, size_t dictSize, BYTE* fullDict){
+ /* allocate space for samples */
+ int ret = 0;
+ unsigned const numSamples = 4;
+ size_t sampleSizes[4];
+ BYTE* const samples = malloc(5000*sizeof(BYTE));
+ if (samples == NULL) {
+ DISPLAY("Error: could not allocate space for samples\n");
+ return 1;
+ }
+
+ /* generate samples */
+ {
+ unsigned literalValue = 1;
+ unsigned samplesPos = 0;
+ size_t currSize = 1;
+ while (literalValue <= 4) {
+ sampleSizes[literalValue - 1] = currSize;
+ {
+ size_t k;
+ for (k = 0; k < currSize; k++) {
+ *(samples + (samplesPos++)) = (BYTE)literalValue;
+ }
+ }
+ literalValue++;
+ currSize *= 16;
+ }
+ }
+
+
+ {
+ /* create variables */
+ size_t dictWriteSize = 0;
+ ZDICT_params_t zdictParams;
+ size_t const headerSize = MAX(dictSize/4, 256);
+ size_t const dictContentSize = dictSize - headerSize;
+ BYTE* const dictContent = fullDict + headerSize;
+ if (dictContentSize < ZDICT_CONTENTSIZE_MIN || dictSize < ZDICT_DICTSIZE_MIN) {
+ DISPLAY("Error: dictionary size is too small\n");
+ ret = 1;
+ goto exitGenRandomDict;
+ }
+
+ /* init dictionary params */
+ memset(&zdictParams, 0, sizeof(zdictParams));
+ zdictParams.dictID = dictID;
+ zdictParams.notificationLevel = 1;
+
+ /* fill in dictionary content */
+ RAND_buffer(&seed, (void*)dictContent, dictContentSize);
+
+ /* finalize dictionary with random samples */
+ dictWriteSize = ZDICT_finalizeDictionary(fullDict, dictSize,
+ dictContent, dictContentSize,
+ samples, sampleSizes, numSamples,
+ zdictParams);
+
+ if (ZDICT_isError(dictWriteSize)) {
+ DISPLAY("Could not finalize dictionary: %s\n", ZDICT_getErrorName(dictWriteSize));
+ ret = 1;
+ }
+ }
+
+exitGenRandomDict:
+ free(samples);
+ return ret;
+}
+
+static dictInfo initDictInfo(int useDict, size_t dictContentSize, BYTE* dictContent, U32 dictID){
+ /* allocate space statically */
+ dictInfo dictOp;
+ memset(&dictOp, 0, sizeof(dictOp));
+ dictOp.useDict = useDict;
+ dictOp.dictContentSize = dictContentSize;
+ dictOp.dictContent = dictContent;
+ dictOp.dictID = dictID;
+ return dictOp;
+}
+
/*-*******************************************************
* Test Mode
*********************************************************/
@@ -1196,6 +1322,65 @@ cleanup:
return ret;
}
+static size_t testDecodeWithDict(U32 seed)
+{
+ /* create variables */
+ size_t const dictSize = RAND(&seed) % (10 << 20) + ZDICT_DICTSIZE_MIN + ZDICT_CONTENTSIZE_MIN;
+ U32 const dictID = RAND(&seed);
+ size_t errorDetected = 0;
+ BYTE* const fullDict = malloc(dictSize);
+ if (fullDict == NULL) {
+ return ERROR(GENERIC);
+ }
+
+ /* generate random dictionary */
+ {
+ int const ret = genRandomDict(dictID, seed, dictSize, fullDict);
+ if (ret != 0) {
+ errorDetected = ERROR(GENERIC);
+ goto dictTestCleanup;
+ }
+ }
+
+
+ {
+ frame_t fr;
+
+ /* generate frame */
+ {
+ size_t const headerSize = MAX(dictSize/4, 256);
+ size_t const dictContentSize = dictSize-headerSize;
+ BYTE* const dictContent = fullDict+headerSize;
+ dictInfo const info = initDictInfo(1, dictContentSize, dictContent, dictID);
+ seed = generateFrame(seed, &fr, info);
+ }
+
+ /* manually decompress and check difference */
+ {
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx();
+ {
+ size_t const returnValue = ZSTD_decompress_usingDict(dctx, DECOMPRESSED_BUFFER, MAX_DECOMPRESSED_SIZE,
+ fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart,
+ fullDict, dictSize);
+ if (ZSTD_isError(returnValue)) {
+ errorDetected = returnValue;
+ goto dictTestCleanup;
+ }
+ }
+
+ if (memcmp(DECOMPRESSED_BUFFER, fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart) != 0) {
+ errorDetected = ERROR(corruption_detected);
+ goto dictTestCleanup;
+ }
+ ZSTD_freeDCtx(dctx);
+ }
+ }
+
+dictTestCleanup:
+ free(fullDict);
+ return errorDetected;
+}
+
static int runTestMode(U32 seed, unsigned numFiles, unsigned const testDurationS)
{
unsigned fnum;
@@ -1209,28 +1394,39 @@ static int runTestMode(U32 seed, unsigned numFiles, unsigned const testDurationS
for (fnum = 0; fnum < numFiles || clockSpan(startClock) < maxClockSpan; fnum++) {
frame_t fr;
-
+ U32 const seedCopy = seed;
if (fnum < numFiles)
DISPLAYUPDATE("\r%u/%u ", fnum, numFiles);
else
DISPLAYUPDATE("\r%u ", fnum);
- seed = generateFrame(seed, &fr);
+ {
+ dictInfo const info = initDictInfo(0, 0, NULL, 0);
+ seed = generateFrame(seed, &fr, info);
+ }
{ size_t const r = testDecodeSimple(&fr);
if (ZSTD_isError(r)) {
- DISPLAY("Error in simple mode on test seed %u: %s\n", seed + fnum,
+ DISPLAY("Error in simple mode on test seed %u: %s\n", seedCopy,
ZSTD_getErrorName(r));
return 1;
}
}
{ size_t const r = testDecodeStreaming(&fr);
if (ZSTD_isError(r)) {
- DISPLAY("Error in streaming mode on test seed %u: %s\n", seed + fnum,
+ DISPLAY("Error in streaming mode on test seed %u: %s\n", seedCopy,
ZSTD_getErrorName(r));
return 1;
}
}
+ {
+ /* don't create a dictionary that is too big */
+ size_t const r = testDecodeWithDict(seed);
+ if (ZSTD_isError(r)) {
+ DISPLAY("Error in dictionary mode on test seed %u: %s\n", seedCopy, ZSTD_getErrorName(r));
+ return 1;
+ }
+ }
}
DISPLAY("\r%u tests completed: ", fnum);
@@ -1250,7 +1446,10 @@ static int generateFile(U32 seed, const char* const path,
DISPLAY("seed: %u\n", seed);
- generateFrame(seed, &fr);
+ {
+ dictInfo const info = initDictInfo(0, 0, NULL, 0);
+ generateFrame(seed, &fr, info);
+ }
outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, path);
if (origPath) {
@@ -1272,7 +1471,10 @@ static int generateCorpus(U32 seed, unsigned numFiles, const char* const path,
DISPLAYUPDATE("\r%u/%u ", fnum, numFiles);
- seed = generateFrame(seed, &fr);
+ {
+ dictInfo const info = initDictInfo(0, 0, NULL, 0);
+ seed = generateFrame(seed, &fr, info);
+ }
if (snprintf(outPath, MAX_PATH, "%s/z%06u.zst", path, fnum) + 1 > MAX_PATH) {
DISPLAY("Error: path too long\n");
@@ -1294,6 +1496,93 @@ static int generateCorpus(U32 seed, unsigned numFiles, const char* const path,
return 0;
}
+static int generateCorpusWithDict(U32 seed, unsigned numFiles, const char* const path,
+ const char* const origPath, const size_t dictSize)
+{
+ char outPath[MAX_PATH];
+ BYTE* fullDict;
+ U32 const dictID = RAND(&seed);
+ int errorDetected = 0;
+
+ if (snprintf(outPath, MAX_PATH, "%s/dictionary", path) + 1 > MAX_PATH) {
+ DISPLAY("Error: path too long\n");
+ return 1;
+ }
+
+ /* allocate space for the dictionary */
+ fullDict = malloc(dictSize);
+ if (fullDict == NULL) {
+ DISPLAY("Error: could not allocate space for full dictionary.\n");
+ return 1;
+ }
+
+ /* randomly generate the dictionary */
+ {
+ int const ret = genRandomDict(dictID, seed, dictSize, fullDict);
+ if (ret != 0) {
+ errorDetected = ret;
+ goto dictCleanup;
+ }
+ }
+
+ /* write out dictionary */
+ if (numFiles != 0) {
+ if (snprintf(outPath, MAX_PATH, "%s/dictionary", path) + 1 > MAX_PATH) {
+ DISPLAY("Error: dictionary path too long\n");
+ errorDetected = 1;
+ goto dictCleanup;
+ }
+ outputBuffer(fullDict, dictSize, outPath);
+ }
+ else {
+ outputBuffer(fullDict, dictSize, "dictionary");
+ }
+
+ /* generate random compressed/decompressed files */
+ {
+ unsigned fnum;
+ for (fnum = 0; fnum < MAX(numFiles, 1); fnum++) {
+ frame_t fr;
+ DISPLAYUPDATE("\r%u/%u ", fnum, numFiles);
+ {
+ size_t const headerSize = MAX(dictSize/4, 256);
+ size_t const dictContentSize = dictSize-headerSize;
+ BYTE* const dictContent = fullDict+headerSize;
+ dictInfo const info = initDictInfo(1, dictContentSize, dictContent, dictID);
+ seed = generateFrame(seed, &fr, info);
+ }
+
+ if (numFiles != 0) {
+ if (snprintf(outPath, MAX_PATH, "%s/z%06u.zst", path, fnum) + 1 > MAX_PATH) {
+ DISPLAY("Error: path too long\n");
+ errorDetected = 1;
+ goto dictCleanup;
+ }
+ outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, outPath);
+
+ if (origPath) {
+ if (snprintf(outPath, MAX_PATH, "%s/z%06u", origPath, fnum) + 1 > MAX_PATH) {
+ DISPLAY("Error: path too long\n");
+ errorDetected = 1;
+ goto dictCleanup;
+ }
+ outputBuffer(fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart, outPath);
+ }
+ }
+ else {
+ outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, path);
+ if (origPath) {
+ outputBuffer(fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart, origPath);
+ }
+ }
+ }
+ }
+
+dictCleanup:
+ free(fullDict);
+ return errorDetected;
+}
+
/*_*******************************************************
* Command line
@@ -1339,6 +1628,40 @@ static void advancedUsage(const char* programName)
DISPLAY( "\n");
DISPLAY( "Advanced arguments :\n");
DISPLAY( " --content-size : always include the content size in the frame header\n");
+ DISPLAY( " --use-dict=# : include a dictionary used to decompress the corpus\n");
+}
+
+/*! readU32FromChar() :
+ @return : unsigned integer value read from input in `char` format
+ allows and interprets K, KB, KiB, M, MB and MiB suffix.
+ Will also modify `*stringPtr`, advancing it to position where it stopped reading.
+ Note : function result can overflow if digit string > MAX_UINT */
+static unsigned readU32FromChar(const char** stringPtr)
+{
+ unsigned result = 0;
+ while ((**stringPtr >='0') && (**stringPtr <='9'))
+ result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
+ if ((**stringPtr=='K') || (**stringPtr=='M')) {
+ result <<= 10;
+ if (**stringPtr=='M') result <<= 10;
+ (*stringPtr)++ ;
+ if (**stringPtr=='i') (*stringPtr)++;
+ if (**stringPtr=='B') (*stringPtr)++;
+ }
+ return result;
+}
+
+/** longCommandWArg() :
+ * check if *stringPtr is the same as longCommand.
+ * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
+ * @return 0 and doesn't modify *stringPtr otherwise.
+ */
+static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
+{
+ size_t const comSize = strlen(longCommand);
+ int const result = !strncmp(*stringPtr, longCommand, comSize);
+ if (result) *stringPtr += comSize;
+ return result;
}
int main(int argc, char** argv)
@@ -1350,6 +1673,8 @@ int main(int argc, char** argv)
int testMode = 0;
const char* path = NULL;
const char* origPath = NULL;
+ int useDict = 0;
+ unsigned dictSize = (10 << 10); /* 10 kB default */
int argNb;
@@ -1410,6 +1735,9 @@ int main(int argc, char** argv)
argument++;
if (strcmp(argument, "content-size") == 0) {
opts.contentSize = 1;
+ } else if (longCommandWArg(&argument, "use-dict=")) {
+ dictSize = readU32FromChar(&argument);
+ useDict = 1;
} else {
advancedUsage(argv[0]);
return 1;
@@ -1441,9 +1769,13 @@ int main(int argc, char** argv)
return 1;
}
- if (numFiles == 0) {
+ if (numFiles == 0 && useDict == 0) {
return generateFile(seed, path, origPath);
- } else {
+ } else if (useDict == 0){
return generateCorpus(seed, numFiles, path, origPath);
+ } else {
+ /* should generate files with a dictionary */
+ return generateCorpusWithDict(seed, numFiles, path, origPath, dictSize);
}
+
}
diff --git a/tests/fullbench.c b/tests/fullbench.c
index 38cf22fa7ebce..81de5157b8e16 100644
--- a/tests/fullbench.c
+++ b/tests/fullbench.c
@@ -14,19 +14,19 @@
#include "util.h" /* Compiler options, UTIL_GetFileSize */
#include <stdlib.h> /* malloc */
#include <stdio.h> /* fprintf, fopen, ftello64 */
-#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
-#include "mem.h"
+#include "mem.h" /* U32 */
#ifndef ZSTD_DLL_IMPORT
#include "zstd_internal.h" /* ZSTD_blockHeaderSize, blockType_e, KB, MB */
- #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressBegin, ZSTD_compressContinue, etc. */
#else
#define KB *(1 <<10)
#define MB *(1 <<20)
#define GB *(1U<<30)
typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
#endif
-#include "zstd.h" /* ZSTD_VERSION_STRING */
+#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressBegin, ZSTD_compressContinue, etc. */
+#include "zstd.h" /* ZSTD_versionString */
+#include "util.h" /* time functions */
#include "datagen.h"
@@ -35,7 +35,7 @@
**************************************/
#define PROGRAM_DESCRIPTION "Zstandard speed analyzer"
#define AUTHOR "Yann Collet"
-#define WELCOME_MESSAGE "*** %s %s %i-bits, by %s (%s) ***\n", PROGRAM_DESCRIPTION, ZSTD_VERSION_STRING, (int)(sizeof(void*)*8), AUTHOR, __DATE__
+#define WELCOME_MESSAGE "*** %s %s %i-bits, by %s (%s) ***\n", PROGRAM_DESCRIPTION, ZSTD_versionString(), (int)(sizeof(void*)*8), AUTHOR, __DATE__
#define NBLOOPS 6
#define TIMELOOP_S 2
@@ -69,12 +69,6 @@ static void BMK_SetNbIterations(U32 nbLoops)
/*_*******************************************************
* Private functions
*********************************************************/
-static clock_t BMK_clockSpan( clock_t clockStart )
-{
- return clock() - clockStart; /* works even if overflow, span limited to <= ~30mn */
-}
-
-
static size_t BMK_findMaxMem(U64 requiredMem)
{
size_t const step = 64 MB;
@@ -116,8 +110,9 @@ size_t local_ZSTD_decompress(void* dst, size_t dstSize, void* buff2, const void*
return ZSTD_decompress(dst, dstSize, buff2, g_cSize);
}
-#ifndef ZSTD_DLL_IMPORT
static ZSTD_DCtx* g_zdc = NULL;
+
+#ifndef ZSTD_DLL_IMPORT
extern size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* ctx, const void* src, size_t srcSize);
size_t local_ZSTD_decodeLiteralsBlock(void* dst, size_t dstSize, void* buff2, const void* src, size_t srcSize)
{
@@ -153,6 +148,74 @@ size_t local_ZSTD_compressStream(void* dst, size_t dstCapacity, void* buff2, con
return buffOut.pos;
}
+static size_t local_ZSTD_compress_generic_end(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
+{
+ ZSTD_outBuffer buffOut;
+ ZSTD_inBuffer buffIn;
+ (void)buff2;
+ ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_compressionLevel, 1);
+ buffOut.dst = dst;
+ buffOut.size = dstCapacity;
+ buffOut.pos = 0;
+ buffIn.src = src;
+ buffIn.size = srcSize;
+ buffIn.pos = 0;
+ ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_end);
+ return buffOut.pos;
+}
+
+static size_t local_ZSTD_compress_generic_continue(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
+{
+ ZSTD_outBuffer buffOut;
+ ZSTD_inBuffer buffIn;
+ (void)buff2;
+ ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_compressionLevel, 1);
+ buffOut.dst = dst;
+ buffOut.size = dstCapacity;
+ buffOut.pos = 0;
+ buffIn.src = src;
+ buffIn.size = srcSize;
+ buffIn.pos = 0;
+ ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_continue);
+ ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_end);
+ return buffOut.pos;
+}
+
+static size_t local_ZSTD_compress_generic_T2_end(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
+{
+ ZSTD_outBuffer buffOut;
+ ZSTD_inBuffer buffIn;
+ (void)buff2;
+ ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_compressionLevel, 1);
+ ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_nbThreads, 2);
+ buffOut.dst = dst;
+ buffOut.size = dstCapacity;
+ buffOut.pos = 0;
+ buffIn.src = src;
+ buffIn.size = srcSize;
+ buffIn.pos = 0;
+ while (ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_end)) {}
+ return buffOut.pos;
+}
+
+static size_t local_ZSTD_compress_generic_T2_continue(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
+{
+ ZSTD_outBuffer buffOut;
+ ZSTD_inBuffer buffIn;
+ (void)buff2;
+ ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_compressionLevel, 1);
+ ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_nbThreads, 2);
+ buffOut.dst = dst;
+ buffOut.size = dstCapacity;
+ buffOut.pos = 0;
+ buffIn.src = src;
+ buffIn.size = srcSize;
+ buffIn.pos = 0;
+ ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_continue);
+ while(ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_end)) {}
+ return buffOut.pos;
+}
+
static ZSTD_DStream* g_dstream= NULL;
static size_t local_ZSTD_decompressStream(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
{
@@ -170,8 +233,9 @@ static size_t local_ZSTD_decompressStream(void* dst, size_t dstCapacity, void* b
return buffOut.pos;
}
-#ifndef ZSTD_DLL_IMPORT
static ZSTD_CCtx* g_zcc = NULL;
+
+#ifndef ZSTD_DLL_IMPORT
size_t local_ZSTD_compressContinue(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
{
(void)buff2;
@@ -236,33 +300,45 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
switch(benchNb)
{
case 1:
- benchFunction = local_ZSTD_compress; benchName = "ZSTD_compress";
+ benchFunction = local_ZSTD_compress; benchName = "compress(1)";
break;
case 2:
- benchFunction = local_ZSTD_decompress; benchName = "ZSTD_decompress";
+ benchFunction = local_ZSTD_decompress; benchName = "decompress";
break;
#ifndef ZSTD_DLL_IMPORT
case 11:
- benchFunction = local_ZSTD_compressContinue; benchName = "ZSTD_compressContinue";
+ benchFunction = local_ZSTD_compressContinue; benchName = "compressContinue(1)";
break;
case 12:
- benchFunction = local_ZSTD_compressContinue_extDict; benchName = "ZSTD_compressContinue_extDict";
+ benchFunction = local_ZSTD_compressContinue_extDict; benchName = "compressContinue_extDict";
break;
case 13:
- benchFunction = local_ZSTD_decompressContinue; benchName = "ZSTD_decompressContinue";
+ benchFunction = local_ZSTD_decompressContinue; benchName = "decompressContinue";
break;
case 31:
- benchFunction = local_ZSTD_decodeLiteralsBlock; benchName = "ZSTD_decodeLiteralsBlock";
+ benchFunction = local_ZSTD_decodeLiteralsBlock; benchName = "decodeLiteralsBlock";
break;
case 32:
- benchFunction = local_ZSTD_decodeSeqHeaders; benchName = "ZSTD_decodeSeqHeaders";
+ benchFunction = local_ZSTD_decodeSeqHeaders; benchName = "decodeSeqHeaders";
break;
#endif
case 41:
- benchFunction = local_ZSTD_compressStream; benchName = "ZSTD_compressStream";
+ benchFunction = local_ZSTD_compressStream; benchName = "compressStream(1)";
break;
case 42:
- benchFunction = local_ZSTD_decompressStream; benchName = "ZSTD_decompressStream";
+ benchFunction = local_ZSTD_decompressStream; benchName = "decompressStream";
+ break;
+ case 51:
+ benchFunction = local_ZSTD_compress_generic_continue; benchName = "compress_generic, continue";
+ break;
+ case 52:
+ benchFunction = local_ZSTD_compress_generic_end; benchName = "compress_generic, end";
+ break;
+ case 61:
+ benchFunction = local_ZSTD_compress_generic_T2_continue; benchName = "compress_generic, -T2, continue";
+ break;
+ case 62:
+ benchFunction = local_ZSTD_compress_generic_T2_end; benchName = "compress_generic, -T2, end";
break;
default :
return 0;
@@ -276,6 +352,10 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
free(dstBuff); free(buff2);
return 12;
}
+ if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();
+ if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();
+ if (g_cstream==NULL) g_cstream = ZSTD_createCStream();
+ if (g_dstream==NULL) g_dstream = ZSTD_createDStream();
/* Preparation */
switch(benchNb)
@@ -284,23 +364,15 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, 1);
break;
#ifndef ZSTD_DLL_IMPORT
- case 11 :
- if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();
- break;
- case 12 :
- if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();
- break;
case 13 :
- if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();
g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, 1);
break;
case 31: /* ZSTD_decodeLiteralsBlock */
- if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();
{ blockProperties_t bp;
- ZSTD_frameParams zfp;
+ ZSTD_frameHeader zfp;
size_t frameHeaderSize, skippedSize;
g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, 1);
- frameHeaderSize = ZSTD_getFrameParams(&zfp, dstBuff, ZSTD_frameHeaderSize_min);
+ frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_frameHeaderSize_min);
if (frameHeaderSize==0) frameHeaderSize = ZSTD_frameHeaderSize_min;
ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */
if (bp.blockType != bt_compressed) {
@@ -313,15 +385,14 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
break;
}
case 32: /* ZSTD_decodeSeqHeaders */
- if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();
{ blockProperties_t bp;
- ZSTD_frameParams zfp;
+ ZSTD_frameHeader zfp;
const BYTE* ip = dstBuff;
const BYTE* iend;
size_t frameHeaderSize, cBlockSize;
ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, 1); /* it would be better to use direct block compression here */
g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, 1);
- frameHeaderSize = ZSTD_getFrameParams(&zfp, dstBuff, ZSTD_frameHeaderSize_min);
+ frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_frameHeaderSize_min);
if (frameHeaderSize==0) frameHeaderSize = ZSTD_frameHeaderSize_min;
ip += frameHeaderSize; /* Skip frame Header */
cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */
@@ -342,11 +413,7 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
case 31:
goto _cleanOut;
#endif
- case 41 :
- if (g_cstream==NULL) g_cstream = ZSTD_createCStream();
- break;
case 42 :
- if (g_dstream==NULL) g_dstream = ZSTD_createDStream();
g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, 1);
break;
@@ -359,30 +426,37 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
{ size_t i; for (i=0; i<dstBuffSize; i++) dstBuff[i]=(BYTE)i; } /* warming up memory */
{ U32 loopNb;
+# define TIME_SEC_MICROSEC (1*1000000ULL) /* 1 second */
+ U64 const clockLoop = TIMELOOP_S * TIME_SEC_MICROSEC;
+ UTIL_freq_t ticksPerSecond;
+ UTIL_initTimer(&ticksPerSecond);
DISPLAY("%2i- %-30.30s : \r", benchNb, benchName);
for (loopNb = 1; loopNb <= g_nbIterations; loopNb++) {
- clock_t const timeLoop = TIMELOOP_S * CLOCKS_PER_SEC;
- clock_t clockStart;
- U32 nbRounds;
+ UTIL_time_t clockStart;
size_t benchResult=0;
- double averageTime;
+ U32 nbRounds;
- clockStart = clock();
- while (clock() == clockStart);
- clockStart = clock();
- for (nbRounds=0; BMK_clockSpan(clockStart) < timeLoop; nbRounds++) {
+ UTIL_sleepMilli(1); /* give processor time to other processes */
+ UTIL_waitForNextTick(ticksPerSecond);
+ UTIL_getTime(&clockStart);
+ for (nbRounds=0; UTIL_clockSpanMicro(clockStart, ticksPerSecond) < clockLoop; nbRounds++) {
benchResult = benchFunction(dstBuff, dstBuffSize, buff2, src, srcSize);
if (ZSTD_isError(benchResult)) { DISPLAY("ERROR ! %s() => %s !! \n", benchName, ZSTD_getErrorName(benchResult)); exit(1); }
}
- averageTime = (((double)BMK_clockSpan(clockStart)) / CLOCKS_PER_SEC) / nbRounds;
- if (averageTime < bestTime) bestTime = averageTime;
- DISPLAY("%2i- %-30.30s : %7.1f MB/s (%9u)\r", loopNb, benchName, (double)srcSize / (1 MB) / bestTime, (U32)benchResult);
- } }
+ { U64 const clockSpanMicro = UTIL_clockSpanMicro(clockStart, ticksPerSecond);
+ double const averageTime = (double)clockSpanMicro / TIME_SEC_MICROSEC / nbRounds;
+ if (averageTime < bestTime) bestTime = averageTime;
+ DISPLAY("%2i- %-30.30s : %7.1f MB/s (%9u)\r", loopNb, benchName, (double)srcSize / (1 MB) / bestTime, (U32)benchResult);
+ } } }
DISPLAY("%2u\n", benchNb);
_cleanOut:
free(dstBuff);
free(buff2);
+ ZSTD_freeCCtx(g_zcc); g_zcc=NULL;
+ ZSTD_freeDCtx(g_zdc); g_zdc=NULL;
+ ZSTD_freeCStream(g_cstream); g_cstream=NULL;
+ ZSTD_freeDStream(g_dstream); g_dstream=NULL;
return 0;
}
diff --git a/tests/fuzzer.c b/tests/fuzzer.c
index a9dcf12e07026..b8f5147855428 100644
--- a/tests/fuzzer.c
+++ b/tests/fuzzer.c
@@ -12,9 +12,9 @@
* Compiler specific
**************************************/
#ifdef _MSC_VER /* Visual Studio */
-# define _CRT_SECURE_NO_WARNINGS /* fgets */
-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
+# define _CRT_SECURE_NO_WARNINGS /* fgets */
+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
+# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
#endif
@@ -25,7 +25,7 @@
#include <stdio.h> /* fgets, sscanf */
#include <string.h> /* strcmp */
#include <time.h> /* clock_t */
-#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressContinue, ZSTD_compressBlock */
+#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressContinue, ZSTD_compressBlock */
#include "zstd.h" /* ZSTD_VERSION_STRING */
#include "zstd_errors.h" /* ZSTD_getErrorCode */
#include "zstdmt_compress.h"
@@ -74,7 +74,6 @@ static clock_t FUZ_clockSpan(clock_t cStart)
return clock() - cStart; /* works even when overflow; max span ~ 30mn */
}
-
#define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
static unsigned FUZ_rand(unsigned* src)
{
@@ -104,6 +103,7 @@ static unsigned FUZ_highbit32(U32 v32)
#define CHECK_V(var, fn) size_t const var = fn; if (ZSTD_isError(var)) goto _output_error
#define CHECK(fn) { CHECK_V(err, fn); }
#define CHECKPLUS(var, fn, more) { CHECK_V(var, fn); more; }
+
static int basicUnitTests(U32 seed, double compressibility)
{
size_t const CNBuffSize = 5 MB;
@@ -190,6 +190,89 @@ static int basicUnitTests(U32 seed, double compressibility)
DISPLAYLEVEL(4, "OK \n");
+ /* Static CCtx tests */
+#define STATIC_CCTX_LEVEL 3
+ DISPLAYLEVEL(4, "test%3i : create static CCtx for level %u :", testNb++, STATIC_CCTX_LEVEL);
+ { size_t const staticCCtxSize = ZSTD_estimateCStreamSize(STATIC_CCTX_LEVEL);
+ void* const staticCCtxBuffer = malloc(staticCCtxSize);
+ size_t const staticDCtxSize = ZSTD_estimateDCtxSize();
+ void* const staticDCtxBuffer = malloc(staticDCtxSize);
+ if (staticCCtxBuffer==NULL || staticDCtxBuffer==NULL) {
+ free(staticCCtxBuffer);
+ free(staticDCtxBuffer);
+ DISPLAY("Not enough memory, aborting\n");
+ testResult = 1;
+ goto _end;
+ }
+ { ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize);
+ ZSTD_DCtx* staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize);
+ if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error;
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : init CCtx for level %u : ", testNb++, STATIC_CCTX_LEVEL);
+ { size_t const r = ZSTD_compressBegin(staticCCtx, STATIC_CCTX_LEVEL);
+ if (ZSTD_isError(r)) goto _output_error; }
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : simple compression test with static CCtx : ", testNb++);
+ CHECKPLUS(r, ZSTD_compressCCtx(staticCCtx,
+ compressedBuffer, ZSTD_compressBound(CNBuffSize),
+ CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL),
+ cSize=r );
+ DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n",
+ (U32)cSize, (double)cSize/CNBuffSize*100);
+
+ DISPLAYLEVEL(4, "test%3i : simple decompression test with static DCtx : ", testNb++);
+ { size_t const r = ZSTD_decompressDCtx(staticDCtx,
+ decodedBuffer, CNBuffSize,
+ compressedBuffer, cSize);
+ if (r != CNBuffSize) goto _output_error; }
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
+ { size_t u;
+ for (u=0; u<CNBuffSize; u++) {
+ if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u])
+ goto _output_error;;
+ } }
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : init CCtx for too large level (must fail) : ", testNb++);
+ { size_t const r = ZSTD_compressBegin(staticCCtx, ZSTD_maxCLevel());
+ if (!ZSTD_isError(r)) goto _output_error; }
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : init CCtx for small level %u (should work again) : ", testNb++, 1);
+ { size_t const r = ZSTD_compressBegin(staticCCtx, 1);
+ if (ZSTD_isError(r)) goto _output_error; }
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : init CStream for small level %u : ", testNb++, 1);
+ { size_t const r = ZSTD_initCStream(staticCCtx, 1);
+ if (ZSTD_isError(r)) goto _output_error; }
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : init CStream with dictionary (should fail) : ", testNb++);
+ { size_t const r = ZSTD_initCStream_usingDict(staticCCtx, CNBuffer, 64 KB, 1);
+ if (!ZSTD_isError(r)) goto _output_error; }
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : init DStream (should fail) : ", testNb++);
+ { size_t const r = ZSTD_initDStream(staticDCtx);
+ if (ZSTD_isError(r)) goto _output_error; }
+ { ZSTD_outBuffer output = { decodedBuffer, CNBuffSize, 0 };
+ ZSTD_inBuffer input = { compressedBuffer, ZSTD_FRAMEHEADERSIZE_MAX+1, 0 };
+ size_t const r = ZSTD_decompressStream(staticDCtx, &output, &input);
+ if (!ZSTD_isError(r)) goto _output_error;
+ }
+ DISPLAYLEVEL(4, "OK \n");
+ }
+ free(staticCCtxBuffer);
+ free(staticDCtxBuffer);
+ }
+
+
+
/* ZSTDMT simple MT compression test */
DISPLAYLEVEL(4, "test%3i : create ZSTDMT CCtx : ", testNb++);
{ ZSTDMT_CCtx* mtctx = ZSTDMT_createCCtx(2);
@@ -321,13 +404,25 @@ static int basicUnitTests(U32 seed, double compressibility)
DISPLAYLEVEL(4, "OK \n");
DISPLAYLEVEL(4, "test%3i : decompress with DDict : ", testNb++);
- { ZSTD_DDict* const ddict = ZSTD_createDDict_byReference(CNBuffer, dictSize);
+ { 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(4, "OK (size of DDict : %u) \n", (U32)ZSTD_sizeof_DDict(ddict));
ZSTD_freeDDict(ddict);
}
+ DISPLAYLEVEL(4, "test%3i : decompress with static DDict : ", testNb++);
+ { size_t const ddictBufferSize = ZSTD_estimateDDictSize(dictSize, 0);
+ void* ddictBuffer = malloc(ddictBufferSize);
+ if (ddictBuffer == NULL) goto _output_error;
+ { ZSTD_DDict* const ddict = ZSTD_initStaticDDict(ddictBuffer, ddictBufferSize, CNBuffer, dictSize, 0);
+ size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, ddict);
+ if (r != CNBuffSize - dictSize) goto _output_error;
+ }
+ free(ddictBuffer);
+ DISPLAYLEVEL(4, "OK (size of static DDict : %u) \n", (U32)ddictBufferSize);
+ }
+
DISPLAYLEVEL(4, "test%3i : check content size on duplicated context : ", testNb++);
{ size_t const testSize = CNBuffSize / 3;
{ ZSTD_parameters p = ZSTD_getParams(2, testSize, dictSize);
@@ -339,8 +434,8 @@ static int basicUnitTests(U32 seed, double compressibility)
CHECKPLUS(r, ZSTD_compressEnd(ctxDuplicated, compressedBuffer, ZSTD_compressBound(testSize),
(const char*)CNBuffer + dictSize, testSize),
cSize = r);
- { ZSTD_frameParams fp;
- if (ZSTD_getFrameParams(&fp, compressedBuffer, cSize)) goto _output_error;
+ { ZSTD_frameHeader fp;
+ if (ZSTD_getFrameHeader(&fp, compressedBuffer, cSize)) goto _output_error;
if ((fp.frameContentSize != testSize) && (fp.frameContentSize != 0)) goto _output_error;
} }
DISPLAYLEVEL(4, "OK \n");
@@ -404,10 +499,18 @@ static int basicUnitTests(U32 seed, double compressibility)
if (r != CNBuffSize) goto _output_error);
DISPLAYLEVEL(4, "OK \n");
- DISPLAYLEVEL(4, "test%3i : compress with preprocessed dictionary : ", testNb++);
+ DISPLAYLEVEL(4, "test%3i : estimate CDict size : ", testNb++);
{ ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
- ZSTD_customMem customMem = { NULL, NULL, NULL };
- ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, 1, cParams, customMem);
+ size_t const estimatedSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, 1 /*byReference*/);
+ DISPLAYLEVEL(4, "OK : %u \n", (U32)estimatedSize);
+ }
+
+ DISPLAYLEVEL(4, "test%3i : compress with CDict ", testNb++);
+ { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
+ ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize,
+ 1 /* byReference */, ZSTD_dm_auto,
+ cParams, ZSTD_defaultCMem);
+ DISPLAYLEVEL(4, "(size : %u) : ", (U32)ZSTD_sizeof_CDict(cdict));
cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, ZSTD_compressBound(CNBuffSize),
CNBuffer, CNBuffSize, cdict);
ZSTD_freeCDict(cdict);
@@ -429,11 +532,34 @@ static int basicUnitTests(U32 seed, double compressibility)
if (r != CNBuffSize) goto _output_error);
DISPLAYLEVEL(4, "OK \n");
+ DISPLAYLEVEL(4, "test%3i : compress with static CDict : ", testNb++);
+ { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
+ size_t const cdictSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, 0);
+ void* const cdictBuffer = malloc(cdictSize);
+ if (cdictBuffer==NULL) goto _output_error;
+ { ZSTD_CDict* const cdict = ZSTD_initStaticCDict(cdictBuffer, cdictSize,
+ dictBuffer, dictSize,
+ 0 /* by Reference */, ZSTD_dm_auto,
+ cParams);
+ if (cdict == NULL) {
+ DISPLAY("ZSTD_initStaticCDict failed ");
+ goto _output_error;
+ }
+ cSize = ZSTD_compress_usingCDict(cctx,
+ compressedBuffer, ZSTD_compressBound(CNBuffSize),
+ CNBuffer, CNBuffSize, cdict);
+ if (ZSTD_isError(cSize)) {
+ DISPLAY("ZSTD_compress_usingCDict failed ");
+ goto _output_error;
+ } }
+ free(cdictBuffer);
+ }
+ DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100);
+
DISPLAYLEVEL(4, "test%3i : ZSTD_compress_usingCDict_advanced, no contentSize, no dictID : ", testNb++);
{ ZSTD_frameParameters const fParams = { 0 /* frameSize */, 1 /* checksum */, 1 /* noDictID*/ };
ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
- ZSTD_customMem const customMem = { NULL, NULL, NULL };
- ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, 1, cParams, customMem);
+ ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, 1 /*byRef*/, ZSTD_dm_auto, cParams, ZSTD_defaultCMem);
cSize = ZSTD_compress_usingCDict_advanced(cctx, compressedBuffer, ZSTD_compressBound(CNBuffSize),
CNBuffer, CNBuffSize, cdict, fParams);
ZSTD_freeCDict(cdict);
@@ -482,6 +608,22 @@ static int basicUnitTests(U32 seed, double compressibility)
}
DISPLAYLEVEL(4, "OK \n");
+ DISPLAYLEVEL(4, "test%3i : Building cdict w/ ZSTD_dm_fullDict on a good dictionary : ", testNb++);
+ { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
+ ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, 1 /*byRef*/, ZSTD_dm_fullDict, cParams, ZSTD_defaultCMem);
+ if (cdict==NULL) goto _output_error;
+ ZSTD_freeCDict(cdict);
+ }
+ DISPLAYLEVEL(4, "OK \n");
+
+ DISPLAYLEVEL(4, "test%3i : Building cdict w/ ZSTD_dm_fullDict on a rawContent (must fail) : ", testNb++);
+ { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
+ ZSTD_CDict* const cdict = ZSTD_createCDict_advanced((const char*)dictBuffer+1, dictSize-1, 1 /*byRef*/, ZSTD_dm_fullDict, cParams, ZSTD_defaultCMem);
+ if (cdict!=NULL) goto _output_error;
+ ZSTD_freeCDict(cdict);
+ }
+ DISPLAYLEVEL(4, "OK \n");
+
ZSTD_freeCCtx(cctx);
free(dictBuffer);
free(samplesSizes);
@@ -496,7 +638,7 @@ static int basicUnitTests(U32 seed, double compressibility)
size_t const sampleUnitSize = 8 KB;
U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);
size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t));
- COVER_params_t params;
+ ZDICT_cover_params_t params;
U32 dictID;
if (dictBuffer==NULL || samplesSizes==NULL) {
@@ -505,14 +647,14 @@ static int basicUnitTests(U32 seed, double compressibility)
goto _output_error;
}
- DISPLAYLEVEL(4, "test%3i : COVER_trainFromBuffer : ", testNb++);
+ DISPLAYLEVEL(4, "test%3i : ZDICT_trainFromBuffer_cover : ", testNb++);
{ U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
memset(&params, 0, sizeof(params));
params.d = 1 + (FUZ_rand(&seed) % 16);
params.k = params.d + (FUZ_rand(&seed) % 256);
- dictSize = COVER_trainFromBuffer(dictBuffer, dictSize,
- CNBuffer, samplesSizes, nbSamples,
- params);
+ dictSize = ZDICT_trainFromBuffer_cover(dictBuffer, dictSize,
+ CNBuffer, samplesSizes, nbSamples,
+ params);
if (ZDICT_isError(dictSize)) goto _output_error;
DISPLAYLEVEL(4, "OK, created dictionary of size %u \n", (U32)dictSize);
@@ -521,12 +663,12 @@ static int basicUnitTests(U32 seed, double compressibility)
if (dictID==0) goto _output_error;
DISPLAYLEVEL(4, "OK : %u \n", dictID);
- DISPLAYLEVEL(4, "test%3i : COVER_optimizeTrainFromBuffer : ", testNb++);
+ DISPLAYLEVEL(4, "test%3i : ZDICT_optimizeTrainFromBuffer_cover : ", testNb++);
memset(&params, 0, sizeof(params));
params.steps = 4;
- optDictSize = COVER_optimizeTrainFromBuffer(dictBuffer, optDictSize,
- CNBuffer, samplesSizes, nbSamples / 4,
- &params);
+ optDictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, optDictSize,
+ CNBuffer, samplesSizes,
+ nbSamples / 4, &params);
if (ZDICT_isError(optDictSize)) goto _output_error;
DISPLAYLEVEL(4, "OK, created dictionary of size %u \n", (U32)optDictSize);
@@ -560,9 +702,7 @@ static int basicUnitTests(U32 seed, double compressibility)
size_t const wrongSrcSize = (srcSize + 1000);
ZSTD_parameters params = ZSTD_getParams(1, wrongSrcSize, 0);
params.fParams.contentSizeFlag = 1;
- { size_t const result = ZSTD_compressBegin_advanced(cctx, NULL, 0, params, wrongSrcSize);
- if (ZSTD_isError(result)) goto _output_error;
- }
+ CHECK( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, wrongSrcSize) );
{ size_t const result = ZSTD_compressEnd(cctx, decodedBuffer, CNBuffSize, CNBuffer, srcSize);
if (!ZSTD_isError(result)) goto _output_error;
if (ZSTD_getErrorCode(result) != ZSTD_error_srcSize_wrong) goto _output_error;
@@ -580,6 +720,7 @@ static int basicUnitTests(U32 seed, double compressibility)
/* basic block compression */
DISPLAYLEVEL(4, "test%3i : Block compression test : ", testNb++);
CHECK( ZSTD_compressBegin(cctx, 5) );
+ CHECK( ZSTD_getBlockSize(cctx) >= blockSize);
cSize = ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize);
if (ZSTD_isError(cSize)) goto _output_error;
DISPLAYLEVEL(4, "OK \n");
@@ -743,8 +884,23 @@ static size_t FUZ_randomLength(U32* seed, U32 maxLog)
}
#undef CHECK
-#define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
- DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
+#define CHECK(cond, ...) { \
+ if (cond) { \
+ DISPLAY("Error => "); \
+ DISPLAY(__VA_ARGS__); \
+ DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); \
+ goto _output_error; \
+} }
+
+#define CHECK_Z(f) { \
+ size_t const err = f; \
+ if (ZSTD_isError(err)) { \
+ DISPLAY("Error => %s : %s ", \
+ #f, ZSTD_getErrorName(err)); \
+ DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); \
+ goto _output_error; \
+} }
+
static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxDurationS, double compressibility, int bigTests)
{
@@ -856,9 +1012,8 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
}
/* frame header decompression test */
- { ZSTD_frameParams dParams;
- size_t const check = ZSTD_getFrameParams(&dParams, cBuffer, cSize);
- CHECK(ZSTD_isError(check), "Frame Parameters extraction failed");
+ { ZSTD_frameHeader dParams;
+ CHECK_Z( ZSTD_getFrameHeader(&dParams, cBuffer, cSize) );
CHECK(dParams.frameContentSize != sampleSize, "Frame content size incorrect");
}
@@ -945,20 +1100,17 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
dict = srcBuffer + (FUZ_rand(&lseed) % (srcBufferSize - dictSize));
if (FUZ_rand(&lseed) & 0xF) {
- size_t const errorCode = ZSTD_compressBegin_usingDict(refCtx, dict, dictSize, cLevel);
- CHECK (ZSTD_isError(errorCode), "ZSTD_compressBegin_usingDict error : %s", ZSTD_getErrorName(errorCode));
+ CHECK_Z ( ZSTD_compressBegin_usingDict(refCtx, dict, dictSize, cLevel) );
} else {
ZSTD_compressionParameters const cPar = ZSTD_getCParams(cLevel, 0, dictSize);
ZSTD_frameParameters const fPar = { FUZ_rand(&lseed)&1 /* contentSizeFlag */,
!(FUZ_rand(&lseed)&3) /* contentChecksumFlag*/,
0 /*NodictID*/ }; /* note : since dictionary is fake, dictIDflag has no impact */
ZSTD_parameters const p = FUZ_makeParams(cPar, fPar);
- size_t const errorCode = ZSTD_compressBegin_advanced(refCtx, dict, dictSize, p, 0);
- CHECK (ZSTD_isError(errorCode), "ZSTD_compressBegin_advanced error : %s", ZSTD_getErrorName(errorCode));
+ CHECK_Z ( ZSTD_compressBegin_advanced(refCtx, dict, dictSize, p, 0) );
}
- { size_t const errorCode = ZSTD_copyCCtx(ctx, refCtx, 0);
- CHECK (ZSTD_isError(errorCode), "ZSTD_copyCCtx error : %s", ZSTD_getErrorName(errorCode));
- } }
+ CHECK_Z( ZSTD_copyCCtx(ctx, refCtx, 0) );
+ }
ZSTD_setCCtxParameter(ctx, ZSTD_p_forceWindow, FUZ_rand(&lseed) & 1);
{ U32 const nbChunks = (FUZ_rand(&lseed) & 127) + 2;
@@ -990,8 +1142,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
/* streaming decompression test */
if (dictSize<8) dictSize=0, dict=NULL; /* disable dictionary */
- { size_t const errorCode = ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
- CHECK (ZSTD_isError(errorCode), "ZSTD_decompressBegin_usingDict error : %s", ZSTD_getErrorName(errorCode)); }
+ CHECK_Z( ZSTD_decompressBegin_usingDict(dctx, dict, dictSize) );
totalCSize = 0;
totalGenSize = 0;
while (totalCSize < cSize) {
diff --git a/tests/paramgrill.c b/tests/paramgrill.c
index 1913b54d0a54a..da06ccb52aabb 100644
--- a/tests/paramgrill.c
+++ b/tests/paramgrill.c
@@ -38,7 +38,7 @@
#define GB *(1ULL<<30)
#define NBLOOPS 2
-#define TIMELOOP (2 * CLOCKS_PER_SEC)
+#define TIMELOOP (2 * CLOCKS_PER_SEC)
#define NB_LEVELS_TRACKED 30
@@ -47,7 +47,7 @@ static const size_t maxMemory = (sizeof(size_t)==4) ? (2 GB - 64 MB) : (size_t
#define COMPRESSIBILITY_DEFAULT 0.50
static const size_t sampleSize = 10000000;
-static const U32 g_grillDuration_s = 60000; /* about 16 hours */
+static const double g_grillDuration_s = 90000; /* about 24 hours */
static const clock_t g_maxParamTime = 15 * CLOCKS_PER_SEC;
static const clock_t g_maxVariationTime = 60 * CLOCKS_PER_SEC;
static const int g_maxNbVariations = 64;
@@ -87,9 +87,11 @@ void BMK_SetNbIterations(int nbLoops)
* Private functions
*********************************************************/
-static clock_t BMK_clockSpan(clock_t cStart) { return clock() - cStart; } /* works even if overflow ; max span ~ 30 mn */
+/* works even if overflow ; max span ~ 30 mn */
+static clock_t BMK_clockSpan(clock_t cStart) { return clock() - cStart; }
-static U32 BMK_timeSpan(time_t tStart) { return (U32)difftime(time(NULL), tStart); } /* accuracy in seconds only, span can be multiple years */
+/* accuracy in seconds only, span can be multiple years */
+static double BMK_timeSpan(time_t tStart) { return difftime(time(NULL), tStart); }
static size_t BMK_findMaxMem(U64 requiredMem)
@@ -307,14 +309,14 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
}
-const char* g_stratName[] = { "ZSTD_fast ",
- "ZSTD_dfast ",
- "ZSTD_greedy ",
- "ZSTD_lazy ",
- "ZSTD_lazy2 ",
- "ZSTD_btlazy2",
- "ZSTD_btopt ",
- "ZSTD_btopt2 "};
+const char* g_stratName[] = { "ZSTD_fast ",
+ "ZSTD_dfast ",
+ "ZSTD_greedy ",
+ "ZSTD_lazy ",
+ "ZSTD_lazy2 ",
+ "ZSTD_btlazy2 ",
+ "ZSTD_btopt ",
+ "ZSTD_btultra "};
static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_compressionParameters params, size_t srcSize)
{
@@ -388,8 +390,8 @@ static int BMK_seed(winnerInfo_t* winners, const ZSTD_compressionParameters para
double W_DMemUsed_note = W_ratioNote * ( 40 + 9*cLevel) - log((double)W_DMemUsed);
double O_DMemUsed_note = O_ratioNote * ( 40 + 9*cLevel) - log((double)O_DMemUsed);
- size_t W_CMemUsed = (1 << params.windowLog) + ZSTD_estimateCCtxSize(params);
- size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + ZSTD_estimateCCtxSize(winners[cLevel].params);
+ size_t W_CMemUsed = (1 << params.windowLog) + ZSTD_estimateCCtxSize_advanced(params);
+ size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + ZSTD_estimateCCtxSize_advanced(winners[cLevel].params);
double W_CMemUsed_note = W_ratioNote * ( 50 + 13*cLevel) - log((double)W_CMemUsed);
double O_CMemUsed_note = O_ratioNote * ( 50 + 13*cLevel) - log((double)O_CMemUsed);
@@ -454,7 +456,7 @@ static ZSTD_compressionParameters* sanitizeParams(ZSTD_compressionParameters par
g_params.chainLog = 0, g_params.searchLog = 0;
if (params.strategy == ZSTD_dfast)
g_params.searchLog = 0;
- if (params.strategy != ZSTD_btopt && params.strategy != ZSTD_btopt2)
+ if (params.strategy != ZSTD_btopt && params.strategy != ZSTD_btultra)
g_params.targetLength = 0;
return &g_params;
}
@@ -558,7 +560,7 @@ static ZSTD_compressionParameters randomParams(void)
p.windowLog = FUZ_rand(&g_rand) % (ZSTD_WINDOWLOG_MAX+1 - ZSTD_WINDOWLOG_MIN) + ZSTD_WINDOWLOG_MIN;
p.searchLength=FUZ_rand(&g_rand) % (ZSTD_SEARCHLENGTH_MAX+1 - ZSTD_SEARCHLENGTH_MIN) + ZSTD_SEARCHLENGTH_MIN;
p.targetLength=FUZ_rand(&g_rand) % (ZSTD_TARGETLENGTH_MAX+1 - ZSTD_TARGETLENGTH_MIN) + ZSTD_TARGETLENGTH_MIN;
- p.strategy = (ZSTD_strategy) (FUZ_rand(&g_rand) % (ZSTD_btopt2 +1));
+ p.strategy = (ZSTD_strategy) (FUZ_rand(&g_rand) % (ZSTD_btultra +1));
validated = !ZSTD_isError(ZSTD_checkCParams(p));
}
return p;
diff --git a/tests/playTests.sh b/tests/playTests.sh
index 021fd59fe2afe..2e1cc6826f11e 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -92,7 +92,7 @@ $ZSTD tmp --stdout > tmpCompressed # long command format
$ECHO "test : compress to named file"
rm tmpCompressed
$ZSTD tmp -o tmpCompressed
-ls tmpCompressed # must work
+test -f tmpCompressed # file must be created
$ECHO "test : -o must be followed by filename (must fail)"
$ZSTD tmp -of tmpCompressed && die "-o must be followed by filename "
$ECHO "test : force write, correct order"
@@ -142,21 +142,21 @@ $ZSTD -q -f tmpro
rm -f tmpro tmpro.zst
$ECHO "test : file removal"
$ZSTD -f --rm tmp
-ls tmp && die "tmp should no longer be present"
+test ! -f tmp # tmp should no longer be present
$ZSTD -f -d --rm tmp.zst
-ls tmp.zst && die "tmp.zst should no longer be present"
+test ! -f tmp.zst # tmp.zst should no longer be present
$ECHO "test : --rm on stdin"
$ECHO a | $ZSTD --rm > $INTOVOID # --rm should remain silent
rm tmp
$ZSTD -f tmp && die "tmp not present : should have failed"
-ls tmp.zst && die "tmp.zst should not be created"
+test ! -f tmp.zst # tmp.zst should not be created
$ECHO "\n**** Advanced compression parameters **** "
$ECHO "Hello world!" | $ZSTD --zstd=windowLog=21, - -o tmp.zst && die "wrong parameters not detected!"
$ECHO "Hello world!" | $ZSTD --zstd=windowLo=21 - -o tmp.zst && die "wrong parameters not detected!"
$ECHO "Hello world!" | $ZSTD --zstd=windowLog=21,slog - -o tmp.zst && die "wrong parameters not detected!"
-ls tmp.zst && die "tmp.zst should not be created"
+test ! -f tmp.zst # tmp.zst should not be created
roundTripTest -g512K
roundTripTest -g512K " --zstd=slen=3,tlen=48,strat=6"
roundTripTest -g512K " --zstd=strat=6,wlog=23,clog=23,hlog=22,slog=6"
@@ -201,16 +201,17 @@ $ECHO foo | $ZSTD > /dev/full && die "write error not detected!"
$ECHO "$ECHO foo | $ZSTD | $ZSTD -d > /dev/full"
$ECHO foo | $ZSTD | $ZSTD -d > /dev/full && die "write error not detected!"
+
$ECHO "\n**** symbolic link test **** "
rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst
$ECHO "hello world" > hello.tmp
ln -s hello.tmp world.tmp
$ZSTD world.tmp hello.tmp
-ls hello.tmp.zst || die "regular file should have been compressed!"
-ls world.tmp.zst && die "symbolic link should not have been compressed!"
+test -f hello.tmp.zst # regular file should have been compressed!
+test ! -f world.tmp.zst # symbolic link should not have been compressed!
$ZSTD world.tmp hello.tmp -f
-ls world.tmp.zst || die "symbol link should have been compressed with --force"
+test -f world.tmp.zst # symbolic link should have been compressed with --force
rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst
fi
@@ -225,10 +226,10 @@ $ZSTD tmpSparse -c | $ZSTD -dv --sparse -c > tmpOutSparse
$DIFF -s tmpSparse tmpOutSparse
$ZSTD tmpSparse -c | $ZSTD -dv --no-sparse -c > tmpOutNoSparse
$DIFF -s tmpSparse tmpOutNoSparse
-ls -ls tmpSparse*
+ls -ls tmpSparse* # look at file size and block size on disk
./datagen -s1 -g1200007 -P100 | $ZSTD | $ZSTD -dv --sparse -c > tmpSparseOdd # Odd size file (to not finish on an exact nb of blocks)
./datagen -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd
-ls -ls tmpSparseOdd
+ls -ls tmpSparseOdd # look at file size and block size on disk
$ECHO "\n Sparse Compatibility with Console :"
$ECHO "Hello World 1 !" | $ZSTD | $ZSTD -d -c
$ECHO "Hello World 2 !" | $ZSTD | $ZSTD -d | cat
@@ -238,7 +239,7 @@ cat tmpSparse1M tmpSparse1M > tmpSparse2M
$ZSTD -v -f tmpSparse1M -o tmpSparseCompressed
$ZSTD -d -v -f tmpSparseCompressed -o tmpSparseRegenerated
$ZSTD -d -v -f tmpSparseCompressed -c >> tmpSparseRegenerated
-ls -ls tmpSparse*
+ls -ls tmpSparse* # look at file size and block size on disk
$DIFF tmpSparse2M tmpSparseRegenerated
rm tmpSparse*
@@ -257,11 +258,11 @@ $ZSTD -df *.zst
ls -ls tmp*
$ECHO "compress tmp* into stdout > tmpall : "
$ZSTD -c tmp1 tmp2 tmp3 > tmpall
-ls -ls tmp*
+ls -ls tmp* # check size of tmpall (should be tmp1.zst + tmp2.zst + tmp3.zst)
$ECHO "decompress tmpall* into stdout > tmpdec : "
cp tmpall tmpall2
$ZSTD -dc tmpall* > tmpdec
-ls -ls tmp*
+ls -ls tmp* # check size of tmpdec (should be 2*(tmp1 + tmp2 + tmp3))
$ECHO "compress multiple files including a missing one (notHere) : "
$ZSTD -f tmp1 notHere tmp2 && die "missing file not detected!"
@@ -379,7 +380,9 @@ $ZSTD -t tmp2.zst && die "bad file not detected !"
$ZSTD -t tmp3 && die "bad file not detected !" # detects 0-sized files as bad
$ECHO "test --rm and --test combined "
$ZSTD -t --rm tmp1.zst
-ls -ls tmp1.zst # check file is still present
+test -f tmp1.zst # check file is still present
+split -b16384 tmp1.zst tmpSplit.
+$ZSTD -t tmpSplit.* && die "bad file not detected !"
$ECHO "\n**** benchmark mode tests **** "
@@ -439,6 +442,7 @@ if [ $LZMAMODE -eq 1 ]; then
XZEXE=1
xz -V && lzma -V || XZEXE=0
if [ $XZEXE -eq 1 ]; then
+ $ECHO "Testing zstd xz and lzma support"
./datagen > tmp
$ZSTD --format=lzma -f tmp
$ZSTD --format=xz -f tmp
@@ -449,6 +453,24 @@ if [ $LZMAMODE -eq 1 ]; then
$ZSTD -d -f -v tmp.xz
$ZSTD -d -f -v tmp.lzma
rm tmp*
+ $ECHO "Creating symlinks"
+ ln -s $ZSTD ./xz
+ ln -s $ZSTD ./unxz
+ ln -s $ZSTD ./lzma
+ ln -s $ZSTD ./unlzma
+ $ECHO "Testing xz and lzma symlinks"
+ ./datagen > tmp
+ ./xz tmp
+ xz -d tmp.xz
+ ./lzma tmp
+ lzma -d tmp.lzma
+ $ECHO "Testing unxz and unlzma symlinks"
+ xz tmp
+ ./xz -d tmp.xz
+ lzma tmp
+ ./lzma -d tmp.lzma
+ rm xz unxz lzma unlzma
+ rm tmp*
else
$ECHO "xz binary not detected"
fi
@@ -534,6 +556,54 @@ fi
rm tmp*
+$ECHO "\n**** zstd --list/-l single frame tests ****"
+./datagen > tmp1
+./datagen > tmp2
+./datagen > tmp3
+./datagen > tmp4
+$ZSTD tmp*
+$ZSTD -l *.zst
+$ZSTD -lv *.zst
+$ZSTD --list *.zst
+$ZSTD --list -v *.zst
+
+$ECHO "\n**** zstd --list/-l multiple frame tests ****"
+cat tmp1.zst tmp2.zst > tmp12.zst
+cat tmp3.zst tmp4.zst > tmp34.zst
+cat tmp12.zst tmp34.zst > tmp1234.zst
+cat tmp12.zst tmp4.zst > tmp124.zst
+$ZSTD -l *.zst
+$ZSTD -lv *.zst
+$ZSTD --list *.zst
+$ZSTD --list -v *.zst
+
+$ECHO "\n**** zstd --list/-l error detection tests ****"
+! $ZSTD -l tmp1 tmp1.zst
+! $ZSTD --list tmp*
+! $ZSTD -lv tmp1*
+! $ZSTD --list -v tmp2 tmp23.zst
+
+$ECHO "\n**** zstd --list/-l test with null files ****"
+./datagen -g0 > tmp5
+$ZSTD tmp5
+$ZSTD -l tmp5.zst
+! $ZSTD -l tmp5*
+$ZSTD -lv tmp5.zst
+! $ZSTD -lv tmp5*
+
+$ECHO "\n**** zstd --list/-l test with no content size field ****"
+./datagen -g1MB | $ZSTD > tmp6.zst
+$ZSTD -l tmp6.zst
+$ZSTD -lv tmp6.zst
+
+$ECHO "\n**** zstd --list/-l test with no checksum ****"
+$ZSTD -f --no-check tmp1
+$ZSTD -l tmp1.zst
+$ZSTD -lv tmp1.zst
+
+rm tmp*
+
+
if [ "$1" != "--test-large-data" ]; then
$ECHO "Skipping large data tests"
exit 0
diff --git a/tests/roundTripCrash.c b/tests/roundTripCrash.c
index a296d4160e55d..77c6737eebdb2 100644
--- a/tests/roundTripCrash.c
+++ b/tests/roundTripCrash.c
@@ -68,13 +68,20 @@ static size_t checkBuffers(const void* buff1, const void* buff2, size_t buffSize
return pos;
}
+static void crash(int errorCode){
+ /* abort if AFL/libfuzzer, exit otherwise */
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* could also use __AFL_COMPILER */
+ abort();
+ #else
+ exit(errorCode);
+ #endif
+}
static void roundTripCheck(const void* srcBuff, size_t srcBuffSize)
{
size_t const cBuffSize = ZSTD_compressBound(srcBuffSize);
void* cBuff = malloc(cBuffSize);
void* rBuff = malloc(cBuffSize);
- #define CRASH { free(cBuff); free(cBuff); } /* double free, to crash program */
if (!cBuff || !rBuff) {
fprintf(stderr, "not enough memory ! \n");
@@ -84,15 +91,15 @@ static void roundTripCheck(const void* srcBuff, size_t srcBuffSize)
{ size_t const result = roundTripTest(rBuff, cBuffSize, cBuff, cBuffSize, srcBuff, srcBuffSize);
if (ZSTD_isError(result)) {
fprintf(stderr, "roundTripTest error : %s \n", ZSTD_getErrorName(result));
- CRASH;
+ crash(1);
}
if (result != srcBuffSize) {
fprintf(stderr, "Incorrect regenerated size : %u != %u\n", (unsigned)result, (unsigned)srcBuffSize);
- CRASH;
+ crash(1);
}
if (checkBuffers(srcBuff, rBuff, srcBuffSize) != srcBuffSize) {
fprintf(stderr, "Silent decoding corruption !!!");
- CRASH;
+ crash(1);
}
}
diff --git a/tests/symbols.c b/tests/symbols.c
index 7dacfc05892d5..8920187f37f76 100644
--- a/tests/symbols.c
+++ b/tests/symbols.c
@@ -88,14 +88,14 @@ static const void *symbols[] = {
&ZSTD_copyCCtx,
&ZSTD_compressContinue,
&ZSTD_compressEnd,
- &ZSTD_getFrameParams,
+ &ZSTD_getFrameHeader,
&ZSTD_decompressBegin,
&ZSTD_decompressBegin_usingDict,
&ZSTD_copyDCtx,
&ZSTD_nextSrcSizeToDecompress,
&ZSTD_decompressContinue,
&ZSTD_nextInputType,
- &ZSTD_getBlockSizeMax,
+ &ZSTD_getBlockSize,
&ZSTD_compressBlock,
&ZSTD_decompressBlock,
&ZSTD_insertBlock,
@@ -131,7 +131,10 @@ static const void *symbols[] = {
&ZDICT_isError,
&ZDICT_getErrorName,
/* zdict.h: advanced functions */
- &ZDICT_trainFromBuffer_advanced,
+ &ZDICT_trainFromBuffer_cover,
+ &ZDICT_optimizeTrainFromBuffer_cover,
+ &ZDICT_finalizeDictionary,
+ &ZDICT_trainFromBuffer_legacy,
&ZDICT_addEntropyTablesFromBuffer,
NULL,
};
diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c
index 0e09e185642be..9b2b8eaf81b74 100644
--- a/tests/zstreamtest.c
+++ b/tests/zstreamtest.c
@@ -12,9 +12,9 @@
* Compiler specific
**************************************/
#ifdef _MSC_VER /* Visual Studio */
-# define _CRT_SECURE_NO_WARNINGS /* fgets */
-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
+# define _CRT_SECURE_NO_WARNINGS /* fgets */
+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
+# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
#endif
@@ -25,8 +25,9 @@
#include <stdio.h> /* fgets, sscanf */
#include <time.h> /* clock_t, clock() */
#include <string.h> /* strcmp */
+#include <assert.h> /* assert */
#include "mem.h"
-#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel, ZSTD_customMem, ZSTD_getDictID_fromFrame */
+#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel, ZSTD_customMem, ZSTD_getDictID_fromFrame */
#include "zstd.h" /* ZSTD_compressBound */
#include "zstd_errors.h" /* ZSTD_error_srcSize_wrong */
#include "zstdmt_compress.h"
@@ -44,6 +45,7 @@
#define GB *(1U<<30)
static const U32 nbTestsDefault = 10000;
+static const U32 g_cLevelMax_smallTests = 10;
#define COMPRESSIBLE_NOISE_LENGTH (10 MB)
#define FUZ_COMPRESSIBILITY_DEFAULT 50
static const U32 prime32 = 2654435761U;
@@ -53,13 +55,15 @@ static const U32 prime32 = 2654435761U;
* Display Macros
**************************************/
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
-#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
+#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { \
+ DISPLAY(__VA_ARGS__); \
+ if (g_displayLevel>=4) fflush(stderr); }
static U32 g_displayLevel = 2;
#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
if ((FUZ_GetClockSpan(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \
{ g_displayClock = clock(); DISPLAY(__VA_ARGS__); \
- if (g_displayLevel>=4) fflush(stderr); } }
+ if (g_displayLevel>=4) fflush(stderr); } }
static const clock_t g_refreshRate = CLOCKS_PER_SEC / 6;
static clock_t g_displayClock = 0;
@@ -155,12 +159,13 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
void* decodedBuffer = malloc(decodedBufferSize);
size_t cSize;
int testResult = 0;
- U32 testNb=0;
+ U32 testNb = 1;
ZSTD_CStream* zc = ZSTD_createCStream_advanced(customMem);
ZSTD_DStream* zd = ZSTD_createDStream_advanced(customMem);
ZSTD_inBuffer inBuff, inBuff2;
ZSTD_outBuffer outBuff;
buffer_t dictionary = g_nullBuffer;
+ size_t const dictSize = 128 KB;
unsigned dictID = 0;
/* Create compressible test buffer */
@@ -186,7 +191,8 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
/* Basic compression test */
DISPLAYLEVEL(3, "test%3i : compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
- ZSTD_initCStream_usingDict(zc, CNBuffer, 128 KB, 1);
+ { size_t const r = ZSTD_initCStream_usingDict(zc, CNBuffer, dictSize, 1);
+ if (ZSTD_isError(r)) goto _output_error; }
outBuff.dst = (char*)(compressedBuffer)+cSize;
outBuff.size = compressedBufferSize;
outBuff.pos = 0;
@@ -201,10 +207,20 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
cSize += outBuff.pos;
DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
- DISPLAYLEVEL(3, "test%3i : check CStream size : ", testNb++);
- { size_t const s = ZSTD_sizeof_CStream(zc);
- if (ZSTD_isError(s)) goto _output_error;
- DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
+ /* context size functions */
+ DISPLAYLEVEL(3, "test%3i : estimate CStream size : ", testNb++);
+ { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictSize);
+ size_t const s = ZSTD_estimateCStreamSize_advanced(cParams)
+ /* uses ZSTD_initCStream_usingDict() */
+ + ZSTD_estimateCDictSize_advanced(dictSize, cParams, 0);
+ if (ZSTD_isError(s)) goto _output_error;
+ DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
+ }
+
+ DISPLAYLEVEL(3, "test%3i : check actual CStream size : ", testNb++);
+ { size_t const s = ZSTD_sizeof_CStream(zc);
+ if (ZSTD_isError(s)) goto _output_error;
+ DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
}
/* Attempt bad compression parameters */
@@ -219,22 +235,25 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
/* skippable frame test */
DISPLAYLEVEL(3, "test%3i : decompress skippable frame : ", testNb++);
- ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
+ if (ZSTD_isError( ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize) ))
+ goto _output_error;
inBuff.src = compressedBuffer;
inBuff.size = cSize;
inBuff.pos = 0;
outBuff.dst = decodedBuffer;
outBuff.size = CNBufferSize;
outBuff.pos = 0;
- { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);
- if (r != 0) goto _output_error; }
+ { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);
+ DISPLAYLEVEL(5, " ( ZSTD_decompressStream => %u ) ", (U32)r);
+ if (r != 0) goto _output_error;
+ }
if (outBuff.pos != 0) goto _output_error; /* skippable frame output len is 0 */
DISPLAYLEVEL(3, "OK \n");
/* Basic decompression test */
inBuff2 = inBuff;
DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
- ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
+ ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
{ size_t const r = ZSTD_setDStreamParameter(zd, DStream_p_maxWindowSize, 1000000000); /* large limit */
if (ZSTD_isError(r)) goto _output_error; }
{ size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff);
@@ -260,7 +279,21 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
} }
DISPLAYLEVEL(3, "OK \n");
- DISPLAYLEVEL(3, "test%3i : check DStream size : ", testNb++);
+ /* context size functions */
+ DISPLAYLEVEL(3, "test%3i : estimate DStream size : ", testNb++);
+ { ZSTD_frameHeader fhi;
+ const void* cStart = (char*)compressedBuffer + (skippableFrameSize + 8);
+ size_t const gfhError = ZSTD_getFrameHeader(&fhi, cStart, cSize);
+ if (gfhError!=0) goto _output_error;
+ DISPLAYLEVEL(5, " (windowSize : %u) ", (U32)fhi.windowSize);
+ { size_t const s = ZSTD_estimateDStreamSize(fhi.windowSize)
+ /* uses ZSTD_initDStream_usingDict() */
+ + ZSTD_estimateDDictSize(dictSize, 0);
+ if (ZSTD_isError(s)) goto _output_error;
+ DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
+ } }
+
+ DISPLAYLEVEL(3, "test%3i : check actual DStream size : ", testNb++);
{ size_t const s = ZSTD_sizeof_DStream(zd);
if (ZSTD_isError(s)) goto _output_error;
DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
@@ -270,7 +303,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
DISPLAYLEVEL(3, "test%3i : decompress byte-by-byte : ", testNb++);
{ /* skippable frame */
size_t r = 1;
- ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
+ ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
inBuff.src = compressedBuffer;
outBuff.dst = decodedBuffer;
inBuff.pos = 0;
@@ -282,7 +315,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
if (ZSTD_isError(r)) goto _output_error;
}
/* normal frame */
- ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
+ ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
r=1;
while (r) {
inBuff.size = inBuff.pos + 1;
@@ -344,6 +377,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
if (zc==NULL) goto _output_error; /* memory allocation issue */
/* use 1 */
{ size_t const inSize = 513;
+ DISPLAYLEVEL(5, "use1 ");
ZSTD_initCStream_advanced(zc, NULL, 0, ZSTD_getParams(19, inSize, 0), inSize); /* needs btopt + search3 to trigger hashLog3 */
inBuff.src = CNBuffer;
inBuff.size = inSize;
@@ -351,14 +385,17 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
outBuff.dst = (char*)(compressedBuffer)+cSize;
outBuff.size = ZSTD_compressBound(inSize);
outBuff.pos = 0;
+ DISPLAYLEVEL(5, "compress1 ");
{ size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff);
if (ZSTD_isError(r)) goto _output_error; }
if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
+ DISPLAYLEVEL(5, "end1 ");
{ size_t const r = ZSTD_endStream(zc, &outBuff);
if (r != 0) goto _output_error; } /* error, or some data not flushed */
}
/* use 2 */
{ size_t const inSize = 1025; /* will not continue, because tables auto-adjust and are therefore different size */
+ DISPLAYLEVEL(5, "use2 ");
ZSTD_initCStream_advanced(zc, NULL, 0, ZSTD_getParams(19, inSize, 0), inSize); /* needs btopt + search3 to trigger hashLog3 */
inBuff.src = CNBuffer;
inBuff.size = inSize;
@@ -366,9 +403,11 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
outBuff.dst = (char*)(compressedBuffer)+cSize;
outBuff.size = ZSTD_compressBound(inSize);
outBuff.pos = 0;
+ DISPLAYLEVEL(5, "compress2 ");
{ size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff);
if (ZSTD_isError(r)) goto _output_error; }
if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
+ DISPLAYLEVEL(5, "end2 ");
{ size_t const r = ZSTD_endStream(zc, &outBuff);
if (r != 0) goto _output_error; } /* error, or some data not flushed */
}
@@ -376,7 +415,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
/* CDict scenario */
DISPLAYLEVEL(3, "test%3i : digested dictionary : ", testNb++);
- { ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, 1);
+ { ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, 1 /*byRef*/ );
size_t const initError = ZSTD_initCStream_usingCDict(zc, cdict);
if (ZSTD_isError(initError)) goto _output_error;
cSize = 0;
@@ -435,7 +474,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
/* Memory restriction */
DISPLAYLEVEL(3, "test%3i : maxWindowSize < frame requirement : ", testNb++);
- ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
+ ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
{ size_t const r = ZSTD_setDStreamParameter(zd, DStream_p_maxWindowSize, 1000); /* too small limit */
if (ZSTD_isError(r)) goto _output_error; }
inBuff.src = compressedBuffer;
@@ -451,8 +490,8 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_usingCDict_advanced with masked dictID : ", testNb++);
{ ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictionary.filled);
ZSTD_frameParameters const fParams = { 1 /* contentSize */, 1 /* checksum */, 1 /* noDictID */};
- ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, 1 /* byReference */, cParams, customMem);
- size_t const initError = ZSTD_initCStream_usingCDict_advanced(zc, cdict, CNBufferSize, fParams);
+ ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, 1 /* byReference */, ZSTD_dm_auto, cParams, customMem);
+ size_t const initError = ZSTD_initCStream_usingCDict_advanced(zc, cdict, fParams, CNBufferSize);
if (ZSTD_isError(initError)) goto _output_error;
cSize = 0;
outBuff.dst = compressedBuffer;
@@ -463,7 +502,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
inBuff.pos = 0;
{ size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff);
if (ZSTD_isError(r)) goto _output_error; }
- if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
+ if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
{ size_t const r = ZSTD_endStream(zc, &outBuff);
if (r != 0) goto _output_error; } /* error, or some data not flushed */
cSize = outBuff.pos;
@@ -483,6 +522,55 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
DISPLAYLEVEL(3, "OK (%s)\n", ZSTD_getErrorName(r));
}
+ DISPLAYLEVEL(3, "test%3i : compress with ZSTD_CCtx_refPrefix : ", testNb++);
+ { size_t const refErr = ZSTD_CCtx_refPrefix(zc, dictionary.start, dictionary.filled);
+ if (ZSTD_isError(refErr)) goto _output_error; }
+ outBuff.dst = compressedBuffer;
+ outBuff.size = compressedBufferSize;
+ outBuff.pos = 0;
+ inBuff.src = CNBuffer;
+ inBuff.size = CNBufferSize;
+ inBuff.pos = 0;
+ { size_t const r = ZSTD_compress_generic(zc, &outBuff, &inBuff, ZSTD_e_end);
+ if (ZSTD_isError(r)) goto _output_error; }
+ if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
+ cSize = outBuff.pos;
+ DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBufferSize*100);
+
+ DISPLAYLEVEL(3, "test%3i : decompress with dictionary : ", testNb++);
+ { size_t const r = ZSTD_decompress_usingDict(zd,
+ decodedBuffer, CNBufferSize,
+ compressedBuffer, cSize,
+ dictionary.start, dictionary.filled);
+ if (ZSTD_isError(r)) goto _output_error; /* must fail : dictionary not used */
+ DISPLAYLEVEL(3, "OK \n");
+ }
+
+ DISPLAYLEVEL(3, "test%3i : decompress without dictionary (should fail): ", testNb++);
+ { size_t const r = ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize);
+ if (!ZSTD_isError(r)) goto _output_error; /* must fail : dictionary not used */
+ DISPLAYLEVEL(3, "OK (%s)\n", ZSTD_getErrorName(r));
+ }
+
+ DISPLAYLEVEL(3, "test%3i : compress again with ZSTD_compress_generic : ", testNb++);
+ outBuff.dst = compressedBuffer;
+ outBuff.size = compressedBufferSize;
+ outBuff.pos = 0;
+ inBuff.src = CNBuffer;
+ inBuff.size = CNBufferSize;
+ inBuff.pos = 0;
+ { size_t const r = ZSTD_compress_generic(zc, &outBuff, &inBuff, ZSTD_e_end);
+ if (ZSTD_isError(r)) goto _output_error; }
+ if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
+ cSize = outBuff.pos;
+ DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBufferSize*100);
+
+ DISPLAYLEVEL(3, "test%3i : decompress without dictionary (should work): ", testNb++);
+ { size_t const r = ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize);
+ if (ZSTD_isError(r)) goto _output_error; /* must fail : dictionary not used */
+ DISPLAYLEVEL(3, "OK \n");
+ }
+
/* Empty srcSize */
DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_advanced with pledgedSrcSize=0 and dict : ", testNb++);
{ ZSTD_parameters params = ZSTD_getParams(5, 0, 0);
@@ -612,12 +700,26 @@ static size_t FUZ_randomLength(U32* seed, U32 maxLog)
#define MIN(a,b) ( (a) < (b) ? (a) : (b) )
-#define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
- DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
+#define CHECK(cond, ...) { \
+ if (cond) { \
+ DISPLAY("Error => "); \
+ DISPLAY(__VA_ARGS__); \
+ DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); \
+ goto _output_error; \
+} }
+
+#define CHECK_Z(f) { \
+ size_t const err = f; \
+ if (ZSTD_isError(err)) { \
+ DISPLAY("Error => %s : %s ", \
+ #f, ZSTD_getErrorName(err)); \
+ DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); \
+ goto _output_error; \
+} }
static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibility, int bigTests)
{
- static const U32 maxSrcLog = 24;
+ U32 const maxSrcLog = bigTests ? 24 : 22;
static const U32 maxSampleLog = 19;
size_t const srcBufferSize = (size_t)1<<maxSrcLog;
BYTE* cNoiseBuffer[5];
@@ -637,7 +739,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
const BYTE* dict=NULL; /* can keep same dict on 2 consecutive tests */
size_t dictSize = 0;
U32 oldTestLog = 0;
- int const cLevelLimiter = bigTests ? 3 : 2;
+ U32 const cLevelMax = bigTests ? (U32)ZSTD_maxCLevel() : g_cLevelMax_smallTests;
/* allocations */
cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
@@ -680,8 +782,18 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
/* states full reset (deliberately not synchronized) */
/* some issues can only happen when reusing states */
- if ((FUZ_rand(&lseed) & 0xFF) == 131) { ZSTD_freeCStream(zc); zc = ZSTD_createCStream(); resetAllowed=0; }
- if ((FUZ_rand(&lseed) & 0xFF) == 132) { ZSTD_freeDStream(zd); zd = ZSTD_createDStream(); ZSTD_initDStream_usingDict(zd, NULL, 0); /* ensure at least one init */ }
+ if ((FUZ_rand(&lseed) & 0xFF) == 131) {
+ ZSTD_freeCStream(zc);
+ zc = ZSTD_createCStream();
+ CHECK(zc==NULL, "ZSTD_createCStream : allocation error");
+ resetAllowed=0;
+ }
+ if ((FUZ_rand(&lseed) & 0xFF) == 132) {
+ ZSTD_freeDStream(zd);
+ zd = ZSTD_createDStream();
+ CHECK(zd==NULL, "ZSTD_createDStream : allocation error");
+ CHECK_Z( ZSTD_initDStream_usingDict(zd, NULL, 0) ); /* ensure at least one init */
+ }
/* srcBuffer selection [0-4] */
{ U32 buffNb = FUZ_rand(&lseed) & 0x7F;
@@ -705,20 +817,20 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
if (maxTestSize >= srcBufferSize)
maxTestSize = srcBufferSize-1;
{ U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? 0 : maxTestSize;
- size_t const resetError = ZSTD_resetCStream(zc, pledgedSrcSize);
- CHECK(ZSTD_isError(resetError), "ZSTD_resetCStream error : %s", ZSTD_getErrorName(resetError));
+ CHECK_Z( ZSTD_resetCStream(zc, pledgedSrcSize) );
}
} else {
U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;
- U32 const cLevel = ( FUZ_rand(&lseed) %
+ U32 const cLevelCandidate = ( FUZ_rand(&lseed) %
(ZSTD_maxCLevel() -
- (MAX(testLog, dictLog) / cLevelLimiter)))
+ (MAX(testLog, dictLog) / 3)))
+ 1;
+ U32 const cLevel = MIN(cLevelCandidate, cLevelMax);
maxTestSize = FUZ_rLogLength(&lseed, testLog);
oldTestLog = testLog;
/* random dictionary selection */
- dictSize = ((FUZ_rand(&lseed)&1)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0;
+ dictSize = ((FUZ_rand(&lseed)&7)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0;
{ size_t const dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize);
dict = srcBuffer + dictStart;
}
@@ -726,9 +838,8 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
ZSTD_parameters params = ZSTD_getParams(cLevel, pledgedSrcSize, dictSize);
params.fParams.checksumFlag = FUZ_rand(&lseed) & 1;
params.fParams.noDictIDFlag = FUZ_rand(&lseed) & 1;
- { size_t const initError = ZSTD_initCStream_advanced(zc, dict, dictSize, params, pledgedSrcSize);
- CHECK (ZSTD_isError(initError),"ZSTD_initCStream_advanced error : %s", ZSTD_getErrorName(initError));
- } } }
+ CHECK_Z ( ZSTD_initCStream_advanced(zc, dict, dictSize, params, pledgedSrcSize) );
+ } }
/* multi-segments compression test */
XXH64_reset(&xxhState, 0);
@@ -744,8 +855,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
ZSTD_inBuffer inBuff = { srcBuffer+srcStart, srcSize, 0 };
outBuff.size = outBuff.pos + dstBuffSize;
- { size_t const compressionError = ZSTD_compressStream(zc, &outBuff, &inBuff);
- CHECK (ZSTD_isError(compressionError), "compression error : %s", ZSTD_getErrorName(compressionError)); }
+ CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );
XXH64_update(&xxhState, srcBuffer+srcStart, inBuff.pos);
memcpy(copyBuffer+totalTestSize, srcBuffer+srcStart, inBuff.pos);
@@ -757,20 +867,17 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize);
outBuff.size = outBuff.pos + adjustedDstSize;
- { size_t const flushError = ZSTD_flushStream(zc, &outBuff);
- CHECK (ZSTD_isError(flushError), "flush error : %s", ZSTD_getErrorName(flushError));
- } } }
+ CHECK_Z( ZSTD_flushStream(zc, &outBuff) );
+ } }
/* final frame epilogue */
{ size_t remainingToFlush = (size_t)(-1);
while (remainingToFlush) {
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize);
- U32 const enoughDstSize = (adjustedDstSize >= remainingToFlush);
outBuff.size = outBuff.pos + adjustedDstSize;
remainingToFlush = ZSTD_endStream(zc, &outBuff);
- CHECK (ZSTD_isError(remainingToFlush), "flush error : %s", ZSTD_getErrorName(remainingToFlush));
- CHECK (enoughDstSize && remainingToFlush, "ZSTD_endStream() not fully flushed (%u remaining), but enough space available", (U32)remainingToFlush);
+ CHECK (ZSTD_isError(remainingToFlush), "end error : %s", ZSTD_getErrorName(remainingToFlush));
} }
crcOrig = XXH64_digest(&xxhState);
cSize = outBuff.pos;
@@ -778,9 +885,9 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
/* multi - fragments decompression test */
if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {
- CHECK (ZSTD_isError(ZSTD_resetDStream(zd)), "ZSTD_resetDStream failed");
+ CHECK_Z ( ZSTD_resetDStream(zd) );
} else {
- ZSTD_initDStream_usingDict(zd, dict, dictSize);
+ CHECK_Z ( ZSTD_initDStream_usingDict(zd, dict, dictSize) );
}
{ size_t decompressionResult = 1;
ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
@@ -815,7 +922,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
} }
/* try decompression on noisy data */
- ZSTD_initDStream(zd_noise); /* note : no dictionary */
+ CHECK_Z( ZSTD_initDStream(zd_noise) ); /* note : no dictionary */
{ ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
while (outBuff.pos < dstBufferSize) {
@@ -855,7 +962,7 @@ _output_error:
/* Multi-threading version of fuzzer Tests */
static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double compressibility, int bigTests)
{
- static const U32 maxSrcLog = 24;
+ const U32 maxSrcLog = bigTests ? 24 : 22;
static const U32 maxSampleLog = 19;
size_t const srcBufferSize = (size_t)1<<maxSrcLog;
BYTE* cNoiseBuffer[5];
@@ -875,7 +982,8 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
const BYTE* dict=NULL; /* can keep same dict on 2 consecutive tests */
size_t dictSize = 0;
U32 oldTestLog = 0;
- int const cLevelLimiter = bigTests ? 3 : 2;
+ U32 const cLevelMax = bigTests ? (U32)ZSTD_maxCLevel() : g_cLevelMax_smallTests;
+ U32 const nbThreadsMax = bigTests ? 5 : 2;
/* allocations */
cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
@@ -919,15 +1027,18 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
/* states full reset (deliberately not synchronized) */
/* some issues can only happen when reusing states */
if ((FUZ_rand(&lseed) & 0xFF) == 131) {
- U32 const nbThreads = (FUZ_rand(&lseed) % 6) + 1;
+ U32 const nbThreadsCandidate = (FUZ_rand(&lseed) % 6) + 1;
+ U32 const nbThreads = MIN(nbThreadsCandidate, nbThreadsMax);
DISPLAYLEVEL(5, "Creating new context with %u threads \n", nbThreads);
ZSTDMT_freeCCtx(zc);
zc = ZSTDMT_createCCtx(nbThreads);
+ CHECK(zc==NULL, "ZSTDMT_createCCtx allocation error")
resetAllowed=0;
}
if ((FUZ_rand(&lseed) & 0xFF) == 132) {
ZSTD_freeDStream(zd);
zd = ZSTD_createDStream();
+ CHECK(zd==NULL, "ZSTDMT_createCCtx allocation error")
ZSTD_initDStream_usingDict(zd, NULL, 0); /* ensure at least one init */
}
@@ -952,16 +1063,16 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
maxTestSize = FUZ_randomLength(&lseed, oldTestLog+2);
if (maxTestSize >= srcBufferSize) maxTestSize = srcBufferSize-1;
{ int const compressionLevel = (FUZ_rand(&lseed) % 5) + 1;
- size_t const resetError = ZSTDMT_initCStream(zc, compressionLevel);
- CHECK(ZSTD_isError(resetError), "ZSTDMT_initCStream error : %s", ZSTD_getErrorName(resetError));
+ CHECK_Z( ZSTDMT_initCStream(zc, compressionLevel) );
}
} else {
U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;
- U32 const cLevel = (FUZ_rand(&lseed) %
- (ZSTD_maxCLevel() -
- (MAX(testLog, dictLog) / cLevelLimiter))) +
+ U32 const cLevelCandidate = (FUZ_rand(&lseed) %
+ (ZSTD_maxCLevel() -
+ (MAX(testLog, dictLog) / 3))) +
1;
+ U32 const cLevel = MIN(cLevelCandidate, cLevelMax);
maxTestSize = FUZ_rLogLength(&lseed, testLog);
oldTestLog = testLog;
/* random dictionary selection */
@@ -977,10 +1088,9 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
params.fParams.noDictIDFlag = FUZ_rand(&lseed) & 1;
params.fParams.contentSizeFlag = pledgedSrcSize>0;
DISPLAYLEVEL(5, "checksumFlag : %u \n", params.fParams.checksumFlag);
- { size_t const initError = ZSTDMT_initCStream_advanced(zc, dict, dictSize, params, pledgedSrcSize);
- CHECK (ZSTD_isError(initError),"ZSTDMT_initCStream_advanced error : %s", ZSTD_getErrorName(initError)); }
- ZSTDMT_setMTCtxParameter(zc, ZSTDMT_p_overlapSectionLog, FUZ_rand(&lseed) % 12);
- ZSTDMT_setMTCtxParameter(zc, ZSTDMT_p_sectionSize, FUZ_rand(&lseed) % (2*maxTestSize+1));
+ CHECK_Z( ZSTDMT_initCStream_advanced(zc, dict, dictSize, params, pledgedSrcSize) );
+ CHECK_Z( ZSTDMT_setMTCtxParameter(zc, ZSTDMT_p_overlapSectionLog, FUZ_rand(&lseed) % 12) );
+ CHECK_Z( ZSTDMT_setMTCtxParameter(zc, ZSTDMT_p_sectionSize, FUZ_rand(&lseed) % (2*maxTestSize+1)) );
} }
/* multi-segments compression test */
@@ -998,8 +1108,7 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
outBuff.size = outBuff.pos + dstBuffSize;
DISPLAYLEVEL(5, "Sending %u bytes to compress \n", (U32)srcSize);
- { size_t const compressionError = ZSTDMT_compressStream(zc, &outBuff, &inBuff);
- CHECK (ZSTD_isError(compressionError), "compression error : %s", ZSTD_getErrorName(compressionError)); }
+ CHECK_Z( ZSTDMT_compressStream(zc, &outBuff, &inBuff) );
DISPLAYLEVEL(5, "%u bytes read by ZSTDMT_compressStream \n", (U32)inBuff.pos);
XXH64_update(&xxhState, srcBuffer+srcStart, inBuff.pos);
@@ -1013,9 +1122,8 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize);
outBuff.size = outBuff.pos + adjustedDstSize;
DISPLAYLEVEL(5, "Flushing into dst buffer of size %u \n", (U32)adjustedDstSize);
- { size_t const flushError = ZSTDMT_flushStream(zc, &outBuff);
- CHECK (ZSTD_isError(flushError), "ZSTDMT_flushStream error : %s", ZSTD_getErrorName(flushError));
- } } }
+ CHECK_Z( ZSTDMT_flushStream(zc, &outBuff) );
+ } }
/* final frame epilogue */
{ size_t remainingToFlush = (size_t)(-1);
@@ -1035,9 +1143,9 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
/* multi - fragments decompression test */
if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {
- CHECK (ZSTD_isError(ZSTD_resetDStream(zd)), "ZSTD_resetDStream failed");
+ CHECK_Z( ZSTD_resetDStream(zd) );
} else {
- ZSTD_initDStream_usingDict(zd, dict, dictSize);
+ CHECK_Z( ZSTD_initDStream_usingDict(zd, dict, dictSize) );
}
{ size_t decompressionResult = 1;
ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
@@ -1073,7 +1181,7 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
} }
/* try decompression on noisy data */
- ZSTD_initDStream(zd_noise); /* note : no dictionary */
+ CHECK_Z( ZSTD_initDStream(zd_noise) ); /* note : no dictionary */
{ ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
while (outBuff.pos < dstBufferSize) {
@@ -1110,6 +1218,297 @@ _output_error:
}
+/* Tests for ZSTD_compress_generic() API */
+static int fuzzerTests_newAPI(U32 seed, U32 nbTests, unsigned startTest, double compressibility, int bigTests)
+{
+ U32 const maxSrcLog = bigTests ? 24 : 22;
+ static const U32 maxSampleLog = 19;
+ size_t const srcBufferSize = (size_t)1<<maxSrcLog;
+ BYTE* cNoiseBuffer[5];
+ size_t const copyBufferSize= srcBufferSize + (1<<maxSampleLog);
+ BYTE* const copyBuffer = (BYTE*)malloc (copyBufferSize);
+ size_t const cBufferSize = ZSTD_compressBound(srcBufferSize);
+ BYTE* const cBuffer = (BYTE*)malloc (cBufferSize);
+ size_t const dstBufferSize = srcBufferSize;
+ BYTE* const dstBuffer = (BYTE*)malloc (dstBufferSize);
+ U32 result = 0;
+ U32 testNb = 0;
+ U32 coreSeed = seed;
+ ZSTD_CCtx* zc = ZSTD_createCCtx(); /* will be reset sometimes */
+ ZSTD_DStream* zd = ZSTD_createDStream(); /* will be reset sometimes */
+ ZSTD_DStream* const zd_noise = ZSTD_createDStream();
+ clock_t const startClock = clock();
+ const BYTE* dict = NULL; /* can keep same dict on 2 consecutive tests */
+ size_t dictSize = 0;
+ U32 oldTestLog = 0;
+ U32 const cLevelMax = bigTests ? (U32)ZSTD_maxCLevel() : g_cLevelMax_smallTests;
+ U32 const nbThreadsMax = bigTests ? 5 : 1;
+
+ /* allocations */
+ cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
+ cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize);
+ cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize);
+ cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize);
+ cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize);
+ CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4] ||
+ !copyBuffer || !dstBuffer || !cBuffer || !zc || !zd || !zd_noise ,
+ "Not enough memory, fuzzer tests cancelled");
+
+ /* Create initial samples */
+ RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed); /* pure noise */
+ RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed); /* barely compressible */
+ RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);
+ RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */
+ RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */
+ memset(copyBuffer, 0x65, copyBufferSize); /* make copyBuffer considered initialized */
+ CHECK_Z( ZSTD_initDStream_usingDict(zd, NULL, 0) ); /* ensure at least one init */
+
+ /* catch up testNb */
+ for (testNb=1; testNb < startTest; testNb++)
+ FUZ_rand(&coreSeed);
+
+ /* test loop */
+ for ( ; (testNb <= nbTests) || (FUZ_GetClockSpan(startClock) < g_clockTime) ; testNb++ ) {
+ U32 lseed;
+ const BYTE* srcBuffer;
+ size_t totalTestSize, totalGenSize, cSize;
+ XXH64_state_t xxhState;
+ U64 crcOrig;
+ U32 resetAllowed = 1;
+ size_t maxTestSize;
+
+ /* init */
+ if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); }
+ else { DISPLAYUPDATE(2, "\r%6u ", testNb); }
+ FUZ_rand(&coreSeed);
+ lseed = coreSeed ^ prime32;
+
+ /* states full reset (deliberately not synchronized) */
+ /* some issues can only happen when reusing states */
+ if ((FUZ_rand(&lseed) & 0xFF) == 131) {
+ DISPLAYLEVEL(5, "Creating new context \n");
+ ZSTD_freeCCtx(zc);
+ zc = ZSTD_createCCtx();
+ CHECK(zc==NULL, "ZSTD_createCCtx allocation error");
+ resetAllowed=0;
+ }
+ if ((FUZ_rand(&lseed) & 0xFF) == 132) {
+ ZSTD_freeDStream(zd);
+ zd = ZSTD_createDStream();
+ CHECK(zd==NULL, "ZSTD_createDStream allocation error");
+ ZSTD_initDStream_usingDict(zd, NULL, 0); /* ensure at least one init */
+ }
+
+ /* srcBuffer selection [0-4] */
+ { U32 buffNb = FUZ_rand(&lseed) & 0x7F;
+ if (buffNb & 7) buffNb=2; /* most common : compressible (P) */
+ else {
+ buffNb >>= 3;
+ if (buffNb & 7) {
+ const U32 tnb[2] = { 1, 3 }; /* barely/highly compressible */
+ buffNb = tnb[buffNb >> 3];
+ } else {
+ const U32 tnb[2] = { 0, 4 }; /* not compressible / sparse */
+ buffNb = tnb[buffNb >> 3];
+ } }
+ srcBuffer = cNoiseBuffer[buffNb];
+ }
+
+ /* compression init */
+ CHECK_Z( ZSTD_CCtx_loadDictionary(zc, NULL, 0) ); /* cancel previous dict /*/
+ if ((FUZ_rand(&lseed)&1) /* at beginning, to keep same nb of rand */
+ && oldTestLog /* at least one test happened */ && resetAllowed) {
+ maxTestSize = FUZ_randomLength(&lseed, oldTestLog+2);
+ if (maxTestSize >= srcBufferSize) maxTestSize = srcBufferSize-1;
+ { int const compressionLevel = (FUZ_rand(&lseed) % 5) + 1;
+ CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_compressionLevel, compressionLevel) );
+ }
+ } else {
+ U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
+ U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;
+ U32 const cLevelCandidate = (FUZ_rand(&lseed) %
+ (ZSTD_maxCLevel() -
+ (MAX(testLog, dictLog) / 3))) +
+ 1;
+ U32 const cLevel = MIN(cLevelCandidate, cLevelMax);
+ maxTestSize = FUZ_rLogLength(&lseed, testLog);
+ oldTestLog = testLog;
+ /* random dictionary selection */
+ dictSize = ((FUZ_rand(&lseed)&63)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0;
+ { size_t const dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize);
+ dict = srcBuffer + dictStart;
+ if (!dictSize) dict=NULL;
+ }
+ { U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? ZSTD_CONTENTSIZE_UNKNOWN : maxTestSize;
+ ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, pledgedSrcSize, dictSize);
+
+ /* mess with compression parameters */
+ cParams.windowLog += (FUZ_rand(&lseed) & 3) - 1;
+ cParams.hashLog += (FUZ_rand(&lseed) & 3) - 1;
+ cParams.chainLog += (FUZ_rand(&lseed) & 3) - 1;
+ cParams.searchLog += (FUZ_rand(&lseed) & 3) - 1;
+ cParams.searchLength += (FUZ_rand(&lseed) & 3) - 1;
+ cParams.targetLength = (U32)(cParams.targetLength * (0.5 + ((double)(FUZ_rand(&lseed) & 127) / 128)));
+ cParams = ZSTD_adjustCParams(cParams, 0, 0);
+
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_windowLog, cParams.windowLog) );
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_hashLog, cParams.hashLog) );
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_chainLog, cParams.chainLog) );
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_searchLog, cParams.searchLog) );
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_minMatch, cParams.searchLength) );
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_targetLength, cParams.targetLength) );
+
+ /* unconditionally set, to be sync with decoder */
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_refDictContent, FUZ_rand(&lseed) & 1) );
+ if (FUZ_rand(&lseed) & 1) {
+ CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dict, dictSize) );
+ if (dict && dictSize) {
+ /* test that compression parameters are rejected (correctly) after loading a non-NULL dictionary */
+ size_t const setError = ZSTD_CCtx_setParameter(zc, ZSTD_p_windowLog, cParams.windowLog-1) ;
+ CHECK(!ZSTD_isError(setError), "ZSTD_CCtx_setParameter should have failed");
+ } } else {
+ CHECK_Z( ZSTD_CCtx_refPrefix(zc, dict, dictSize) );
+ }
+
+ /* mess with frame parameters */
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_checksumFlag, FUZ_rand(&lseed) & 1) );
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_dictIDFlag, FUZ_rand(&lseed) & 1) );
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_contentSizeFlag, FUZ_rand(&lseed) & 1) );
+ if (FUZ_rand(&lseed) & 1) CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) );
+ DISPLAYLEVEL(5, "pledgedSrcSize : %u \n", (U32)pledgedSrcSize);
+
+ /* multi-threading parameters */
+ { U32 const nbThreadsCandidate = (FUZ_rand(&lseed) & 4) + 1;
+ U32 const nbThreads = MIN(nbThreadsCandidate, nbThreadsMax);
+ CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_nbThreads, nbThreads) );
+ if (nbThreads > 1) {
+ U32 const jobLog = FUZ_rand(&lseed) % (testLog+1);
+ CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_overlapSizeLog, FUZ_rand(&lseed) % 10) );
+ CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_p_jobSize, (U32)FUZ_rLogLength(&lseed, jobLog)) );
+ } } } }
+
+ /* multi-segments compression test */
+ XXH64_reset(&xxhState, 0);
+ { ZSTD_outBuffer outBuff = { cBuffer, cBufferSize, 0 } ;
+ U32 n;
+ for (n=0, cSize=0, totalTestSize=0 ; totalTestSize < maxTestSize ; n++) {
+ /* compress random chunks into randomly sized dst buffers */
+ size_t const randomSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
+ size_t const srcSize = MIN(maxTestSize-totalTestSize, randomSrcSize);
+ size_t const srcStart = FUZ_rand(&lseed) % (srcBufferSize - srcSize);
+ size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
+ size_t const dstBuffSize = MIN(cBufferSize - cSize, randomDstSize);
+ ZSTD_EndDirective const flush = (FUZ_rand(&lseed) & 15) ? ZSTD_e_continue : ZSTD_e_flush;
+ ZSTD_inBuffer inBuff = { srcBuffer+srcStart, srcSize, 0 };
+ outBuff.size = outBuff.pos + dstBuffSize;
+
+ CHECK_Z( ZSTD_compress_generic(zc, &outBuff, &inBuff, flush) );
+ DISPLAYLEVEL(5, "compress consumed %u bytes (total : %u) \n",
+ (U32)inBuff.pos, (U32)(totalTestSize + inBuff.pos));
+
+ XXH64_update(&xxhState, srcBuffer+srcStart, inBuff.pos);
+ memcpy(copyBuffer+totalTestSize, srcBuffer+srcStart, inBuff.pos);
+ totalTestSize += inBuff.pos;
+ }
+
+ /* final frame epilogue */
+ { size_t remainingToFlush = (size_t)(-1);
+ while (remainingToFlush) {
+ ZSTD_inBuffer inBuff = { NULL, 0, 0 };
+ size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
+ size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize);
+ outBuff.size = outBuff.pos + adjustedDstSize;
+ DISPLAYLEVEL(5, "End-flush into dst buffer of size %u \n", (U32)adjustedDstSize);
+ remainingToFlush = ZSTD_compress_generic(zc, &outBuff, &inBuff, ZSTD_e_end);
+ CHECK(ZSTD_isError(remainingToFlush),
+ "ZSTD_compress_generic w/ ZSTD_e_end error : %s",
+ ZSTD_getErrorName(remainingToFlush) );
+ } }
+ crcOrig = XXH64_digest(&xxhState);
+ cSize = outBuff.pos;
+ DISPLAYLEVEL(5, "Frame completed : %u bytes \n", (U32)cSize);
+ }
+
+ /* multi - fragments decompression test */
+ if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {
+ DISPLAYLEVEL(5, "resetting DCtx (dict:%08X) \n", (U32)(size_t)dict);
+ CHECK_Z( ZSTD_resetDStream(zd) );
+ } else {
+ DISPLAYLEVEL(5, "using dict of size %u \n", (U32)dictSize);
+ CHECK_Z( ZSTD_initDStream_usingDict(zd, dict, dictSize) );
+ }
+ { size_t decompressionResult = 1;
+ ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
+ ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
+ for (totalGenSize = 0 ; decompressionResult ; ) {
+ size_t const readCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
+ size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
+ size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);
+ inBuff.size = inBuff.pos + readCSrcSize;
+ outBuff.size = inBuff.pos + dstBuffSize;
+ DISPLAYLEVEL(5, "ZSTD_decompressStream input %u bytes (pos:%u/%u)\n",
+ (U32)readCSrcSize, (U32)inBuff.pos, (U32)cSize);
+ decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff);
+ CHECK (ZSTD_isError(decompressionResult), "decompression error : %s", ZSTD_getErrorName(decompressionResult));
+ DISPLAYLEVEL(5, "inBuff.pos = %u \n", (U32)readCSrcSize);
+ }
+ CHECK (outBuff.pos != totalTestSize, "decompressed data : wrong size (%u != %u)", (U32)outBuff.pos, (U32)totalTestSize);
+ CHECK (inBuff.pos != cSize, "compressed data should be fully read (%u != %u)", (U32)inBuff.pos, (U32)cSize);
+ { U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0);
+ if (crcDest!=crcOrig) findDiff(copyBuffer, dstBuffer, totalTestSize);
+ CHECK (crcDest!=crcOrig, "decompressed data corrupted");
+ } }
+
+ /*===== noisy/erroneous src decompression test =====*/
+
+ /* add some noise */
+ { U32 const nbNoiseChunks = (FUZ_rand(&lseed) & 7) + 2;
+ U32 nn; for (nn=0; nn<nbNoiseChunks; nn++) {
+ size_t const randomNoiseSize = FUZ_randomLength(&lseed, maxSampleLog);
+ size_t const noiseSize = MIN((cSize/3) , randomNoiseSize);
+ size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseSize);
+ size_t const cStart = FUZ_rand(&lseed) % (cSize - noiseSize);
+ memcpy(cBuffer+cStart, srcBuffer+noiseStart, noiseSize);
+ } }
+
+ /* try decompression on noisy data */
+ CHECK_Z( ZSTD_initDStream(zd_noise) ); /* note : no dictionary */
+ { ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
+ ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
+ while (outBuff.pos < dstBufferSize) {
+ size_t const randomCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
+ size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
+ size_t const adjustedDstSize = MIN(dstBufferSize - outBuff.pos, randomDstSize);
+ size_t const adjustedCSrcSize = MIN(cSize - inBuff.pos, randomCSrcSize);
+ outBuff.size = outBuff.pos + adjustedDstSize;
+ inBuff.size = inBuff.pos + adjustedCSrcSize;
+ { size_t const decompressError = ZSTD_decompressStream(zd, &outBuff, &inBuff);
+ if (ZSTD_isError(decompressError)) break; /* error correctly detected */
+ /* Good so far, but no more progress possible */
+ if (outBuff.pos < outBuff.size && inBuff.pos == cSize) break;
+ } } } }
+ DISPLAY("\r%u fuzzer tests completed \n", testNb-1);
+
+_cleanup:
+ ZSTD_freeCCtx(zc);
+ ZSTD_freeDStream(zd);
+ ZSTD_freeDStream(zd_noise);
+ free(cNoiseBuffer[0]);
+ free(cNoiseBuffer[1]);
+ free(cNoiseBuffer[2]);
+ free(cNoiseBuffer[3]);
+ free(cNoiseBuffer[4]);
+ free(copyBuffer);
+ free(cBuffer);
+ free(dstBuffer);
+ return result;
+
+_output_error:
+ result = 1;
+ goto _cleanup;
+}
+
+
/*-*******************************************************
* Command line
*********************************************************/
@@ -1129,6 +1528,7 @@ int FUZ_usage(const char* programName)
return 0;
}
+typedef enum { simple_api, mt_api, advanced_api } e_api;
int main(int argc, const char** argv)
{
@@ -1140,11 +1540,11 @@ int main(int argc, const char** argv)
int proba = FUZ_COMPRESSIBILITY_DEFAULT;
int result=0;
int mainPause = 0;
- int mtOnly = 0;
- int bigTests = 1;
+ int bigTests = (sizeof(size_t) == 8);
+ e_api selected_api = simple_api;
const char* const programName = argv[0];
ZSTD_customMem const customMem = { allocFunction, freeFunction, NULL };
- ZSTD_customMem const customNULL = { NULL, NULL, NULL };
+ ZSTD_customMem const customNULL = ZSTD_defaultCMem;
/* Check command line */
for(argNb=1; argNb<argc; argNb++) {
@@ -1154,7 +1554,8 @@ int main(int argc, const char** argv)
/* Parsing commands. Aggregated commands are allowed */
if (argument[0]=='-') {
- if (!strcmp(argument, "--mt")) { mtOnly=1; continue; }
+ if (!strcmp(argument, "--mt")) { selected_api=mt_api; continue; }
+ if (!strcmp(argument, "--newapi")) { selected_api=advanced_api; continue; }
if (!strcmp(argument, "--no-big-tests")) { bigTests=0; continue; }
argument++;
@@ -1261,8 +1662,22 @@ int main(int argc, const char** argv)
result = basicUnitTests(0, ((double)proba) / 100, customMem); /* use custom memory allocation functions */
} }
- if (!result && !mtOnly) result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100, bigTests);
- if (!result) result = fuzzerTests_MT(seed, nbTests, testNb, ((double)proba) / 100, bigTests);
+ if (!result) {
+ switch(selected_api)
+ {
+ case simple_api :
+ result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100, bigTests);
+ break;
+ case mt_api :
+ result = fuzzerTests_MT(seed, nbTests, testNb, ((double)proba) / 100, bigTests);
+ break;
+ case advanced_api :
+ result = fuzzerTests_newAPI(seed, nbTests, testNb, ((double)proba) / 100, bigTests);
+ break;
+ default :
+ assert(0); /* impossible */
+ }
+ }
if (mainPause) {
int unused;