mirror of
https://github.com/facebook/zstd.git
synced 2025-07-29 11:21:22 +03:00
Add unit tests for HIST_count_wksp
The following tests are included: - Empty input scenario test. - Workspace size and alignment tests. - Symbol out-of-range tests. - Cover multiple input sizes, vary permitted maximum symbol values, and include diverse symbol distributions. These tests verifies count table correctness, maxSymbolValuePtr updates, and error-handling paths. It enables automated regression of core histogram logic as well.
This commit is contained in:
2
.github/workflows/dev-short-tests.yml
vendored
2
.github/workflows/dev-short-tests.yml
vendored
@ -435,6 +435,8 @@ jobs:
|
|||||||
make clean
|
make clean
|
||||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j check
|
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j check
|
||||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j -C tests test-cli-tests
|
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j -C tests test-cli-tests
|
||||||
|
CFLAGS="-march=armv8.2-a+sve2" LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j check
|
||||||
|
CFLAGS="-march=armv8.2-a+sve2" LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j -C tests test-cli-tests
|
||||||
# This test is only compatible with standard libraries that support BTI (Branch Target Identification).
|
# This test is only compatible with standard libraries that support BTI (Branch Target Identification).
|
||||||
# Unfortunately, the standard library provided on Ubuntu 24.04 does not have this feature enabled.
|
# Unfortunately, the standard library provided on Ubuntu 24.04 does not have this feature enabled.
|
||||||
# make clean
|
# make clean
|
||||||
|
@ -640,7 +640,7 @@ if __name__ == "__main__":
|
|||||||
help="Preserve the scratch directory TEST_DIR/scratch/ for debugging purposes."
|
help="Preserve the scratch directory TEST_DIR/scratch/ for debugging purposes."
|
||||||
)
|
)
|
||||||
parser.add_argument("--verbose", action="store_true", help="Verbose test output.")
|
parser.add_argument("--verbose", action="store_true", help="Verbose test output.")
|
||||||
parser.add_argument("--timeout", default=200, type=int, help="Test case timeout in seconds. Set to 0 to disable timeouts.")
|
parser.add_argument("--timeout", default=800, type=int, help="Test case timeout in seconds. Set to 0 to disable timeouts.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--exec-prefix",
|
"--exec-prefix",
|
||||||
default=None,
|
default=None,
|
||||||
|
126
tests/fuzzer.c
126
tests/fuzzer.c
@ -44,6 +44,13 @@
|
|||||||
/* must be included after util.h, due to ERROR macro redefinition issue on Visual Studio */
|
/* must be included after util.h, due to ERROR macro redefinition issue on Visual Studio */
|
||||||
#include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */
|
#include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */
|
||||||
#include "threading.h" /* ZSTD_pthread_create, ZSTD_pthread_join */
|
#include "threading.h" /* ZSTD_pthread_create, ZSTD_pthread_join */
|
||||||
|
#include "compress/hist.h" /* HIST_count_wksp */
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Macros
|
||||||
|
**************************************/
|
||||||
|
#define COUNTOF(array) (sizeof(array) / sizeof(*(array)))
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
@ -567,6 +574,123 @@ static void test_decompressBound(unsigned tnb)
|
|||||||
DISPLAYLEVEL(3, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned test_histCountWksp(unsigned seed, unsigned testNb)
|
||||||
|
{
|
||||||
|
static const unsigned symLowLimits[] = { 0, 27, 0, 0, 27, 42, 0, 0, 27, 42, 27, 42 };
|
||||||
|
static const unsigned symHighLimits[] = { 255, 255, 210, 110, 42, 42, 210, 110, 42, 42, 42, 42 };
|
||||||
|
static const unsigned symMaxLimits[] = { 255, 255, 255, 255, 255, 255, 230, 130, 99, 99, 42, 42 };
|
||||||
|
static const size_t inputSizes[] = { 3367, 1761, 893, 117 };
|
||||||
|
unsigned workspace[HIST_WKSP_SIZE_U32];
|
||||||
|
size_t res, i, is, il;
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3u : HIST_count_wksp with empty source : ", testNb++);
|
||||||
|
{
|
||||||
|
/* With NULL source UBSan of older Clang could fail: applying zero offset to null pointer. */
|
||||||
|
static const unsigned char source[4] = { 0 };
|
||||||
|
unsigned count[1] = { 0 };
|
||||||
|
unsigned maxSym = 0;
|
||||||
|
res = HIST_count_wksp(count, &maxSym, source, 0, workspace, sizeof(workspace));
|
||||||
|
CHECK_EQ(res, 0);
|
||||||
|
CHECK_EQ(maxSym, 0);
|
||||||
|
CHECK_EQ(count[0], 0);
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
#if HIST_WKSP_SIZE_U32
|
||||||
|
DISPLAYLEVEL(3, "test%3u : HIST_count_wksp with small workspace : ", testNb++);
|
||||||
|
{
|
||||||
|
unsigned count[1] = { 0 };
|
||||||
|
unsigned maxSym = 0;
|
||||||
|
res = HIST_count_wksp(count, &maxSym, NULL, 0, workspace, sizeof(workspace) - 1);
|
||||||
|
CHECK_EQ(res, ERROR(workSpace_tooSmall));
|
||||||
|
CHECK_EQ(maxSym, 0);
|
||||||
|
CHECK_EQ(count[0], 0);
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3u : HIST_count_wksp with wrong workspace alignment : ", testNb++);
|
||||||
|
{
|
||||||
|
unsigned count[1] = { 0 };
|
||||||
|
unsigned maxSym = 0;
|
||||||
|
res = HIST_count_wksp(count, &maxSym, NULL, 0, (unsigned*)(void*)((char*)workspace + 1), sizeof(workspace));
|
||||||
|
CHECK_EQ(res, ERROR(GENERIC));
|
||||||
|
CHECK_EQ(maxSym, 0);
|
||||||
|
CHECK_EQ(count[0], 0);
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3u : HIST_count_wksp with symbol out of range, small size : ", testNb++);
|
||||||
|
{
|
||||||
|
/* For less elements HIST_count_parallel_wksp would fail. */
|
||||||
|
static const unsigned char source[4] = { 1, 4, 0, 2 };
|
||||||
|
static const unsigned expected[6] = { 0 };
|
||||||
|
unsigned count[6] = { 0 };
|
||||||
|
unsigned maxSym = 2;
|
||||||
|
res = HIST_count_wksp(count, &maxSym, source, sizeof(source), workspace, sizeof(workspace));
|
||||||
|
CHECK_EQ(res, ERROR(maxSymbolValue_tooSmall));
|
||||||
|
CHECK_EQ(maxSym, 2);
|
||||||
|
for (i = 0; i < COUNTOF(expected); ++i) CHECK_EQ(count[i], expected[i]);
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3u : HIST_count_wksp with symbol out of range, medium size : ", testNb++);
|
||||||
|
{
|
||||||
|
unsigned char source[3407];
|
||||||
|
unsigned count[6] = { 0 };
|
||||||
|
unsigned maxSym = 2;
|
||||||
|
for (i = 0; i < COUNTOF(source); ++i) {
|
||||||
|
source[i] = (48271 * (i + 1)) & 3;
|
||||||
|
}
|
||||||
|
res = HIST_count_wksp(count, &maxSym, source, sizeof(source), workspace, sizeof(workspace));
|
||||||
|
CHECK_EQ(res, ERROR(maxSymbolValue_tooSmall));
|
||||||
|
CHECK_EQ(maxSym, 2);
|
||||||
|
for (i = 0; i < COUNTOF(count); ++i) CHECK_EQ(count[i], 0);
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
for (il = 0; il < COUNTOF(symMaxLimits); ++il) {
|
||||||
|
unsigned symMax = symMaxLimits[il];
|
||||||
|
unsigned symLow = symLowLimits[il];
|
||||||
|
unsigned symHigh = symHighLimits[il];
|
||||||
|
unsigned symRange = symHigh - symLow + 1;
|
||||||
|
|
||||||
|
for (is = 0; is < COUNTOF(inputSizes); ++is) {
|
||||||
|
unsigned char source[4000];
|
||||||
|
size_t inputSize = inputSizes[is];
|
||||||
|
assert(inputSize <= sizeof(source));
|
||||||
|
DISPLAYLEVEL(3, "test%3u : HIST_count_wksp test in [%u..%u], symMax: %u, inputSize: %u : ",
|
||||||
|
testNb++, symLow, symHigh, symMax, (unsigned)inputSize);
|
||||||
|
{
|
||||||
|
unsigned count[260] = { 0 };
|
||||||
|
unsigned expected[COUNTOF(count)] = { 0 };
|
||||||
|
unsigned maxSym = symMax;
|
||||||
|
unsigned realMaxSym = symMax;
|
||||||
|
unsigned maxCount = 0;
|
||||||
|
for (i = 0; i < inputSize; ++i) {
|
||||||
|
unsigned prng = (48271 * (i + seed)) % symRange + symLow;
|
||||||
|
source[i] = (unsigned char)prng;
|
||||||
|
++expected[prng];
|
||||||
|
}
|
||||||
|
/* for basic buffer overwrite checks */
|
||||||
|
for (i = maxSym + 1; i < COUNTOF(count); ++i) expected[i] = count[i] = ~0u;
|
||||||
|
for (i = 0; i <= maxSym; ++i) maxCount = MAX(maxCount, expected[i]);
|
||||||
|
for (i = realMaxSym; i > 0; --i) {
|
||||||
|
if (expected[i]) break;
|
||||||
|
--realMaxSym;
|
||||||
|
}
|
||||||
|
res = HIST_count_wksp(count, &maxSym, source, inputSize, workspace, sizeof(workspace));
|
||||||
|
CHECK_EQ(res, maxCount);
|
||||||
|
CHECK_EQ(maxSym, realMaxSym);
|
||||||
|
for (i = 0; i < COUNTOF(expected); ++i) CHECK_EQ(count[i], expected[i]);
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return testNb;
|
||||||
|
}
|
||||||
|
|
||||||
static void test_setCParams(unsigned tnb)
|
static void test_setCParams(unsigned tnb)
|
||||||
{
|
{
|
||||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||||
@ -712,6 +836,8 @@ static int basicUnitTests(U32 const seed, double compressibility)
|
|||||||
}
|
}
|
||||||
DISPLAYLEVEL(3, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
testNb = test_histCountWksp(seed, testNb);
|
||||||
|
|
||||||
DISPLAYLEVEL(3, "test%3u : compress %u bytes : ", testNb++, (unsigned)CNBuffSize);
|
DISPLAYLEVEL(3, "test%3u : compress %u bytes : ", testNb++, (unsigned)CNBuffSize);
|
||||||
{ ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
{ ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||||
if (cctx==NULL) goto _output_error;
|
if (cctx==NULL) goto _output_error;
|
||||||
|
Reference in New Issue
Block a user