initial commit
This commit is contained in:
+537
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdlib.h> /* free */
|
||||
#include <stdio.h> /* fgets, sscanf */
|
||||
#include <string.h> /* strcmp */
|
||||
#include <time.h> /* time_t, time(), to randomize seed */
|
||||
#include <assert.h> /* assert */
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_getTime */
|
||||
#include "mem.h"
|
||||
@@ -39,7 +40,7 @@
|
||||
#include "seqgen.h"
|
||||
#include "util.h"
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */
|
||||
|
||||
#include "external_matchfinder.h" /* zstreamExternalMatchFinder, EMF_testCase */
|
||||
|
||||
/*-************************************
|
||||
* Constants
|
||||
@@ -259,7 +260,7 @@ static U32 badParameters(ZSTD_CCtx* zc, ZSTD_parameters const savedParams)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int basicUnitTests(U32 seed, double compressibility)
|
||||
static int basicUnitTests(U32 seed, double compressibility, int bigTests)
|
||||
{
|
||||
size_t const CNBufferSize = COMPRESSIBLE_NOISE_LENGTH;
|
||||
void* CNBuffer = malloc(CNBufferSize);
|
||||
@@ -1565,6 +1566,84 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
CHECK(!ZSTD_isError(ZSTD_CCtx_setParameter(zc, ZSTD_c_srcSizeHint, -1)), "Out of range doesn't error");
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_lazy compress with hashLog = 29 and searchLog = 4 : ", testNb++);
|
||||
if (MEM_64bits()) {
|
||||
ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 };
|
||||
ZSTD_inBuffer in = { CNBuffer, CNBufferSize, 0 };
|
||||
CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_strategy, ZSTD_lazy));
|
||||
/* Force enable the row based match finder */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_useRowMatchFinder, ZSTD_ps_enable));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_searchLog, 4));
|
||||
/* Set windowLog to 29 so the hashLog doesn't get sized down */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_windowLog, 29));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_hashLog, 29));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, 1));
|
||||
/* Compress with continue first so the hashLog doesn't get sized down */
|
||||
CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_continue));
|
||||
CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_end));
|
||||
cSize = out.pos;
|
||||
CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize));
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Test offset == windowSize : ", testNb++);
|
||||
{
|
||||
int windowLog;
|
||||
int const kMaxWindowLog = bigTests ? 29 : 26;
|
||||
size_t const kNbSequences = 10000;
|
||||
size_t const kMaxSrcSize = (1u << kMaxWindowLog) + 10 * kNbSequences;
|
||||
char* src = calloc(kMaxSrcSize, 1);
|
||||
ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);
|
||||
for (windowLog = ZSTD_WINDOWLOG_MIN; windowLog <= kMaxWindowLog; ++windowLog) {
|
||||
size_t const srcSize = ((size_t)1 << windowLog) + 10 * (kNbSequences - 1);
|
||||
|
||||
sequences[0].offset = 32;
|
||||
sequences[0].litLength = 32;
|
||||
sequences[0].matchLength = (1u << windowLog) - 32;
|
||||
sequences[0].rep = 0;
|
||||
{
|
||||
size_t i;
|
||||
for (i = 1; i < kNbSequences; ++i) {
|
||||
sequences[i].offset = (1u << windowLog) - (FUZ_rand(&seed) % 8);
|
||||
sequences[i].litLength = FUZ_rand(&seed) & 7;
|
||||
sequences[i].matchLength = 10 - sequences[i].litLength;
|
||||
sequences[i].rep = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, 1));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_minMatch, 3));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_validateSequences, 1));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_windowLog, windowLog));
|
||||
assert(srcSize <= kMaxSrcSize);
|
||||
cSize = ZSTD_compressSequences(zc, compressedBuffer, compressedBufferSize, sequences, kNbSequences, src, srcSize);
|
||||
CHECK_Z(cSize);
|
||||
CHECK_Z(ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters));
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, windowLog))
|
||||
{
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
size_t decompressedBytes = 0;
|
||||
for (;;) {
|
||||
ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
size_t const ret = ZSTD_decompressStream(zd, &out, &in);
|
||||
CHECK_Z(ret);
|
||||
CHECK(decompressedBytes + out.pos > srcSize, "Output too large");
|
||||
CHECK(memcmp(out.dst, src + decompressedBytes, out.pos), "Corrupted");
|
||||
decompressedBytes += out.pos;
|
||||
if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK(decompressedBytes != srcSize, "Output wrong size");
|
||||
}
|
||||
}
|
||||
free(sequences);
|
||||
free(src);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
/* Overlen overwriting window data bug */
|
||||
DISPLAYLEVEL(3, "test%3i : wildcopy doesn't overwrite potential match data : ", testNb++);
|
||||
{ /* This test has a window size of 1024 bytes and consists of 3 blocks:
|
||||
@@ -1777,6 +1856,445 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : External matchfinder API: ", testNb++);
|
||||
{
|
||||
size_t const dstBufSize = ZSTD_compressBound(CNBufferSize);
|
||||
BYTE* const dstBuf = (BYTE*)malloc(ZSTD_compressBound(dstBufSize));
|
||||
size_t const checkBufSize = CNBufferSize;
|
||||
BYTE* const checkBuf = (BYTE*)malloc(checkBufSize);
|
||||
int enableFallback;
|
||||
EMF_testCase externalMatchState;
|
||||
|
||||
CHECK(dstBuf == NULL || checkBuf == NULL, "allocation failed");
|
||||
|
||||
CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));
|
||||
|
||||
/* Reference external matchfinder outside the test loop to
|
||||
* check that the reference is preserved across compressions */
|
||||
ZSTD_registerExternalMatchFinder(zc, &externalMatchState, zstreamExternalMatchFinder);
|
||||
|
||||
for (enableFallback = 0; enableFallback <= 1; enableFallback++) {
|
||||
size_t testCaseId;
|
||||
size_t const numTestCases = 9;
|
||||
|
||||
EMF_testCase const testCases[] = {
|
||||
EMF_ONE_BIG_SEQ,
|
||||
EMF_LOTS_OF_SEQS,
|
||||
EMF_ZERO_SEQS,
|
||||
EMF_BIG_ERROR,
|
||||
EMF_SMALL_ERROR,
|
||||
EMF_INVALID_OFFSET,
|
||||
EMF_INVALID_MATCHLEN,
|
||||
EMF_INVALID_LITLEN,
|
||||
EMF_INVALID_LAST_LITS
|
||||
};
|
||||
|
||||
ZSTD_ErrorCode const errorCodes[] = {
|
||||
ZSTD_error_no_error,
|
||||
ZSTD_error_no_error,
|
||||
ZSTD_error_externalMatchFinder_failed,
|
||||
ZSTD_error_externalMatchFinder_failed,
|
||||
ZSTD_error_externalMatchFinder_failed,
|
||||
ZSTD_error_externalSequences_invalid,
|
||||
ZSTD_error_externalSequences_invalid,
|
||||
ZSTD_error_externalSequences_invalid,
|
||||
ZSTD_error_externalSequences_invalid
|
||||
};
|
||||
|
||||
for (testCaseId = 0; testCaseId < numTestCases; testCaseId++) {
|
||||
size_t res;
|
||||
|
||||
int const compressionShouldSucceed = (
|
||||
(errorCodes[testCaseId] == ZSTD_error_no_error) ||
|
||||
(enableFallback && errorCodes[testCaseId] == ZSTD_error_externalMatchFinder_failed)
|
||||
);
|
||||
|
||||
int const testWithSequenceValidation = (
|
||||
testCases[testCaseId] == EMF_INVALID_OFFSET
|
||||
);
|
||||
|
||||
externalMatchState = testCases[testCaseId];
|
||||
|
||||
ZSTD_CCtx_reset(zc, ZSTD_reset_session_only);
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_validateSequences, testWithSequenceValidation));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableMatchFinderFallback, enableFallback));
|
||||
res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize);
|
||||
|
||||
if (compressionShouldSucceed) {
|
||||
CHECK(ZSTD_isError(res), "EMF: Compression error: %s", ZSTD_getErrorName(res));
|
||||
CHECK_Z(ZSTD_decompress(checkBuf, checkBufSize, dstBuf, res));
|
||||
CHECK(memcmp(CNBuffer, checkBuf, CNBufferSize) != 0, "EMF: Corruption!");
|
||||
} else {
|
||||
CHECK(!ZSTD_isError(res), "EMF: Should have raised an error!");
|
||||
CHECK(
|
||||
ZSTD_getErrorCode(res) != errorCodes[testCaseId],
|
||||
"EMF: Wrong error code: %s", ZSTD_getErrorName(res)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test compression with external matchfinder + empty src buffer */
|
||||
{
|
||||
size_t res;
|
||||
externalMatchState = EMF_ZERO_SEQS;
|
||||
ZSTD_CCtx_reset(zc, ZSTD_reset_session_only);
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableMatchFinderFallback, enableFallback));
|
||||
res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, 0);
|
||||
CHECK(ZSTD_isError(res), "EMF: Compression error: %s", ZSTD_getErrorName(res));
|
||||
CHECK(ZSTD_decompress(checkBuf, checkBufSize, dstBuf, res) != 0, "EMF: Empty src round trip failed!");
|
||||
}
|
||||
}
|
||||
|
||||
/* Test that reset clears the external matchfinder */
|
||||
CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));
|
||||
externalMatchState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder wasn't cleared */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableMatchFinderFallback, 0));
|
||||
CHECK_Z(ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize));
|
||||
|
||||
/* Test that registering mFinder == NULL clears the external matchfinder */
|
||||
ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters);
|
||||
ZSTD_registerExternalMatchFinder(zc, &externalMatchState, zstreamExternalMatchFinder);
|
||||
externalMatchState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder wasn't cleared */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableMatchFinderFallback, 0));
|
||||
ZSTD_registerExternalMatchFinder(zc, NULL, NULL); /* clear the external matchfinder */
|
||||
CHECK_Z(ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize));
|
||||
|
||||
/* Test that external matchfinder doesn't interact with older APIs */
|
||||
ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters);
|
||||
ZSTD_registerExternalMatchFinder(zc, &externalMatchState, zstreamExternalMatchFinder);
|
||||
externalMatchState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder is used */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableMatchFinderFallback, 0));
|
||||
CHECK_Z(ZSTD_compressCCtx(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize, 3));
|
||||
|
||||
/* Test that compression returns the correct error with LDM */
|
||||
CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));
|
||||
{
|
||||
size_t res;
|
||||
ZSTD_registerExternalMatchFinder(zc, &externalMatchState, zstreamExternalMatchFinder);
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));
|
||||
res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize);
|
||||
CHECK(!ZSTD_isError(res), "EMF: Should have raised an error!");
|
||||
CHECK(
|
||||
ZSTD_getErrorCode(res) != ZSTD_error_parameter_combination_unsupported,
|
||||
"EMF: Wrong error code: %s", ZSTD_getErrorName(res)
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
/* Test that compression returns the correct error with nbWorkers > 0 */
|
||||
CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));
|
||||
{
|
||||
size_t res;
|
||||
ZSTD_registerExternalMatchFinder(zc, &externalMatchState, zstreamExternalMatchFinder);
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_nbWorkers, 1));
|
||||
res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize);
|
||||
CHECK(!ZSTD_isError(res), "EMF: Should have raised an error!");
|
||||
CHECK(
|
||||
ZSTD_getErrorCode(res) != ZSTD_error_parameter_combination_unsupported,
|
||||
"EMF: Wrong error code: %s", ZSTD_getErrorName(res)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(dstBuf);
|
||||
free(checkBuf);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
|
||||
/* Test maxBlockSize cctx param functionality */
|
||||
DISPLAYLEVEL(3, "test%3i : Testing maxBlockSize PR#3418: ", testNb++);
|
||||
{
|
||||
ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
|
||||
/* Quick test to make sure maxBlockSize bounds are enforced */
|
||||
assert(ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX_MIN - 1)));
|
||||
assert(ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX + 1)));
|
||||
|
||||
/* Test maxBlockSize < windowSize and windowSize < maxBlockSize*/
|
||||
{
|
||||
size_t srcSize = 2 << 10;
|
||||
void* const src = CNBuffer;
|
||||
size_t dstSize = ZSTD_compressBound(srcSize);
|
||||
void* const dst1 = compressedBuffer;
|
||||
void* const dst2 = (BYTE*)compressedBuffer + dstSize;
|
||||
size_t size1, size2;
|
||||
void* const checkBuf = malloc(srcSize);
|
||||
memset(src, 'x', srcSize);
|
||||
|
||||
/* maxBlockSize = 1KB */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 1u << 10));
|
||||
size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize);
|
||||
|
||||
if (ZSTD_isError(size1)) goto _output_error;
|
||||
CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1));
|
||||
CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!");
|
||||
|
||||
/* maxBlockSize = 3KB */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 3u << 10));
|
||||
size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize);
|
||||
|
||||
if (ZSTD_isError(size2)) goto _output_error;
|
||||
CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2));
|
||||
CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!");
|
||||
|
||||
assert(size1 - size2 == 4); /* We add another RLE block with header + character */
|
||||
assert(memcmp(dst1, dst2, size2) != 0); /* Compressed output should not be equal */
|
||||
|
||||
/* maxBlockSize = 1KB, windowLog = 10 */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 1u << 10));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 10));
|
||||
size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize);
|
||||
|
||||
if (ZSTD_isError(size1)) goto _output_error;
|
||||
CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1));
|
||||
CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!");
|
||||
|
||||
/* maxBlockSize = 3KB, windowLog = 10 */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 3u << 10));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 10));
|
||||
size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize);
|
||||
|
||||
if (ZSTD_isError(size2)) goto _output_error;
|
||||
CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2));
|
||||
CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!");
|
||||
|
||||
assert(size1 == size2);
|
||||
assert(memcmp(dst1, dst2, size1) == 0); /* Compressed output should be equal */
|
||||
|
||||
free(checkBuf);
|
||||
}
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
|
||||
/* Test maxBlockSize = 0 is valid */
|
||||
{ size_t srcSize = 256 << 10;
|
||||
void* const src = CNBuffer;
|
||||
size_t dstSize = ZSTD_compressBound(srcSize);
|
||||
void* const dst1 = compressedBuffer;
|
||||
void* const dst2 = (BYTE*)compressedBuffer + dstSize;
|
||||
size_t size1, size2;
|
||||
void* const checkBuf = malloc(srcSize);
|
||||
|
||||
/* maxBlockSize = 0 */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 0));
|
||||
size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize);
|
||||
|
||||
if (ZSTD_isError(size1)) goto _output_error;
|
||||
CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1));
|
||||
CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!");
|
||||
|
||||
/* maxBlockSize = ZSTD_BLOCKSIZE_MAX */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX));
|
||||
size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize);
|
||||
|
||||
if (ZSTD_isError(size2)) goto _output_error;
|
||||
CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2));
|
||||
CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!");
|
||||
|
||||
assert(size1 == size2);
|
||||
assert(memcmp(dst1, dst2, size1) == 0); /* Compressed output should be equal */
|
||||
free(checkBuf);
|
||||
}
|
||||
ZSTD_freeCCtx(cctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
/* Test Sequence Validation */
|
||||
DISPLAYLEVEL(3, "test%3i : Testing sequence validation: ", testNb++);
|
||||
{
|
||||
ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
|
||||
/* Test minMatch >= 4, matchLength < 4 */
|
||||
{
|
||||
size_t srcSize = 11;
|
||||
void* const src = CNBuffer;
|
||||
size_t dstSize = ZSTD_compressBound(srcSize);
|
||||
void* const dst = compressedBuffer;
|
||||
size_t const kNbSequences = 4;
|
||||
ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);
|
||||
|
||||
memset(src, 'x', srcSize);
|
||||
|
||||
sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0};
|
||||
sequences[1] = (ZSTD_Sequence) {1, 0, 3, 0};
|
||||
sequences[2] = (ZSTD_Sequence) {1, 0, 3, 0};
|
||||
sequences[3] = (ZSTD_Sequence) {0, 1, 0, 0};
|
||||
|
||||
/* Test with sequence validation */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1));
|
||||
|
||||
cSize = ZSTD_compressSequences(cctx, dst, dstSize,
|
||||
sequences, kNbSequences,
|
||||
src, srcSize);
|
||||
|
||||
CHECK(!ZSTD_isError(cSize), "Should throw an error"); /* maxNbSeq is too small and an assert will fail */
|
||||
CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, "Wrong error code: %s", ZSTD_getErrorName(cSize)); /* fails sequence validation */
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
|
||||
/* Test without sequence validation */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 0));
|
||||
|
||||
cSize = ZSTD_compressSequences(cctx, dst, dstSize,
|
||||
sequences, kNbSequences,
|
||||
src, srcSize);
|
||||
|
||||
CHECK(!ZSTD_isError(cSize), "Should throw an error"); /* maxNbSeq is too small and an assert will fail */
|
||||
CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, "Wrong error code: %s", ZSTD_getErrorName(cSize)); /* fails sequence validation */
|
||||
|
||||
free(sequences);
|
||||
}
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
|
||||
|
||||
/* Test with no block delim */
|
||||
{
|
||||
size_t srcSize = 4;
|
||||
void* const src = CNBuffer;
|
||||
size_t dstSize = ZSTD_compressBound(srcSize);
|
||||
void* const dst = compressedBuffer;
|
||||
size_t const kNbSequences = 1;
|
||||
ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);
|
||||
void* const checkBuf = malloc(srcSize);
|
||||
|
||||
memset(src, 'x', srcSize);
|
||||
|
||||
sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0};
|
||||
|
||||
/* Test with sequence validation */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 3));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_noBlockDelimiters));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1));
|
||||
|
||||
cSize = ZSTD_compressSequences(cctx, dst, dstSize,
|
||||
sequences, kNbSequences,
|
||||
src, srcSize);
|
||||
|
||||
CHECK(ZSTD_isError(cSize), "Should not throw an error");
|
||||
CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst, cSize));
|
||||
CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!");
|
||||
|
||||
free(sequences);
|
||||
free(checkBuf);
|
||||
}
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
|
||||
{ /* Test case with two additional sequences */
|
||||
size_t srcSize = 19;
|
||||
void* const src = CNBuffer;
|
||||
size_t dstSize = ZSTD_compressBound(srcSize);
|
||||
void* const dst = compressedBuffer;
|
||||
size_t const kNbSequences = 7;
|
||||
ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);
|
||||
|
||||
memset(src, 'x', srcSize);
|
||||
|
||||
sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0};
|
||||
sequences[1] = (ZSTD_Sequence) {1, 0, 3, 0};
|
||||
sequences[2] = (ZSTD_Sequence) {1, 0, 3, 0};
|
||||
sequences[3] = (ZSTD_Sequence) {1, 0, 3, 0};
|
||||
sequences[4] = (ZSTD_Sequence) {1, 0, 3, 0};
|
||||
sequences[5] = (ZSTD_Sequence) {1, 0, 3, 0};
|
||||
sequences[6] = (ZSTD_Sequence) {0, 0, 0, 0};
|
||||
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1));
|
||||
|
||||
cSize = ZSTD_compressSequences(cctx, dst, dstSize,
|
||||
sequences, kNbSequences,
|
||||
src, srcSize);
|
||||
|
||||
CHECK(!ZSTD_isError(cSize), "Should throw an error"); /* maxNbSeq is too small and an assert will fail */
|
||||
CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, "Wrong error code: %s", ZSTD_getErrorName(cSize)); /* fails sequence validation */
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
|
||||
/* Test without sequence validation */
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 0));
|
||||
|
||||
cSize = ZSTD_compressSequences(cctx, dst, dstSize,
|
||||
sequences, kNbSequences,
|
||||
src, srcSize);
|
||||
|
||||
CHECK(!ZSTD_isError(cSize), "Should throw an error"); /* maxNbSeq is too small and an assert will fail */
|
||||
CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, "Wrong error code: %s", ZSTD_getErrorName(cSize)); /* fails sequence validation */
|
||||
|
||||
free(sequences);
|
||||
}
|
||||
ZSTD_freeCCtx(cctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Testing large offset with small window size: ", testNb++);
|
||||
{
|
||||
ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
|
||||
/* Test large offset, small window size*/
|
||||
{
|
||||
size_t srcSize = 21;
|
||||
void* const src = CNBuffer;
|
||||
size_t dstSize = ZSTD_compressBound(srcSize);
|
||||
void* const dst = compressedBuffer;
|
||||
size_t const kNbSequences = 4;
|
||||
ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);
|
||||
void* const checkBuf = malloc(srcSize);
|
||||
const size_t largeDictSize = 1 << 25;
|
||||
ZSTD_CDict* cdict = NULL;
|
||||
ZSTD_DDict* ddict = NULL;
|
||||
|
||||
/* Generate large dictionary */
|
||||
void* dictBuffer = calloc(largeDictSize, 1);
|
||||
ZSTD_compressionParameters cParams = ZSTD_getCParams(1, srcSize, largeDictSize);
|
||||
cParams.minMatch = ZSTD_MINMATCH_MIN;
|
||||
cParams.hashLog = ZSTD_HASHLOG_MIN;
|
||||
cParams.chainLog = ZSTD_CHAINLOG_MIN;
|
||||
|
||||
cdict = ZSTD_createCDict_advanced(dictBuffer, largeDictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, cParams, ZSTD_defaultCMem);
|
||||
ddict = ZSTD_createDDict_advanced(dictBuffer, largeDictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, ZSTD_defaultCMem);
|
||||
|
||||
ZSTD_CCtx_refCDict(cctx, cdict);
|
||||
ZSTD_DCtx_refDDict(dctx, ddict);
|
||||
|
||||
sequences[0] = (ZSTD_Sequence) {3, 3, 3, 0};
|
||||
sequences[1] = (ZSTD_Sequence) {1 << 25, 0, 3, 0};
|
||||
sequences[2] = (ZSTD_Sequence) {1 << 25, 0, 9, 0};
|
||||
sequences[3] = (ZSTD_Sequence) {3, 0, 3, 0};
|
||||
|
||||
cSize = ZSTD_compressSequences(cctx, dst, dstSize,
|
||||
sequences, kNbSequences,
|
||||
src, srcSize);
|
||||
|
||||
CHECK(ZSTD_isError(cSize), "Should not throw an error");
|
||||
|
||||
{
|
||||
size_t dSize = ZSTD_decompressDCtx(dctx, checkBuf, srcSize, dst, cSize);
|
||||
CHECK(ZSTD_isError(dSize), "Should not throw an error");
|
||||
CHECK(memcmp(src, checkBuf, srcSize) != 0, "Corruption!");
|
||||
}
|
||||
|
||||
free(sequences);
|
||||
free(checkBuf);
|
||||
free(dictBuffer);
|
||||
ZSTD_freeCDict(cdict);
|
||||
ZSTD_freeDDict(ddict);
|
||||
}
|
||||
ZSTD_freeCCtx(cctx);
|
||||
ZSTD_freeDCtx(dctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
_end:
|
||||
FUZ_freeDictionary(dictionary);
|
||||
ZSTD_freeCStream(zc);
|
||||
@@ -2444,6 +2962,9 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
|
||||
CHECK(badParameters(zc, savedParams), "CCtx params are wrong");
|
||||
|
||||
/* multi - fragments decompression test */
|
||||
if (FUZ_rand(&lseed) & 1) {
|
||||
CHECK_Z(ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters));
|
||||
}
|
||||
if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {
|
||||
DISPLAYLEVEL(5, "resetting DCtx (dict:%p) \n", (void const*)dict);
|
||||
CHECK_Z( ZSTD_resetDStream(zd) );
|
||||
@@ -2452,6 +2973,9 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
|
||||
DISPLAYLEVEL(5, "using dictionary of size %zu \n", dictSize);
|
||||
CHECK_Z( ZSTD_initDStream_usingDict(zd, dict, dictSize) );
|
||||
}
|
||||
if (FUZ_rand(&lseed) & 1) {
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1));
|
||||
}
|
||||
{ size_t decompressionResult = 1;
|
||||
ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
|
||||
ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
|
||||
@@ -2493,7 +3017,14 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
|
||||
} }
|
||||
|
||||
/* try decompression on noisy data */
|
||||
CHECK_Z( ZSTD_initDStream(zd_noise) ); /* note : no dictionary */
|
||||
if (FUZ_rand(&lseed) & 1) {
|
||||
CHECK_Z(ZSTD_DCtx_reset(zd_noise, ZSTD_reset_session_and_parameters));
|
||||
} else {
|
||||
CHECK_Z(ZSTD_DCtx_reset(zd_noise, ZSTD_reset_session_only));
|
||||
}
|
||||
if (FUZ_rand(&lseed) & 1) {
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(zd_noise, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1));
|
||||
}
|
||||
{ ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
|
||||
ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
|
||||
while (outBuff.pos < dstBufferSize) {
|
||||
@@ -2576,6 +3107,7 @@ int main(int argc, const char** argv)
|
||||
|
||||
if (!strcmp(argument, "--newapi")) { selected_api=advanced_api; testNb += !testNb; continue; }
|
||||
if (!strcmp(argument, "--no-big-tests")) { bigTests=0; continue; }
|
||||
if (!strcmp(argument, "--big-tests")) { bigTests=1; continue; }
|
||||
|
||||
argument++;
|
||||
while (*argument!=0) {
|
||||
@@ -2677,7 +3209,7 @@ int main(int argc, const char** argv)
|
||||
if (nbTests<=0) nbTests=1;
|
||||
|
||||
if (testNb==0) {
|
||||
result = basicUnitTests(0, ((double)proba) / 100); /* constant seed for predictability */
|
||||
result = basicUnitTests(0, ((double)proba) / 100, bigTests); /* constant seed for predictability */
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
|
||||
Reference in New Issue
Block a user