diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /src/zstd/contrib/linux-kernel/test | |
parent | Initial commit. (diff) | |
download | ceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip |
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
14 files changed, 1257 insertions, 0 deletions
diff --git a/src/zstd/contrib/linux-kernel/test/.gitignore b/src/zstd/contrib/linux-kernel/test/.gitignore new file mode 100644 index 000000000..4fc10228d --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/.gitignore @@ -0,0 +1 @@ +*Test diff --git a/src/zstd/contrib/linux-kernel/test/DecompressCrash.c b/src/zstd/contrib/linux-kernel/test/DecompressCrash.c new file mode 100644 index 000000000..2ab7dfe52 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/DecompressCrash.c @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + */ + +/* + This program takes a file in input, + performs a zstd round-trip test (compression - decompress) + compares the result with original + and generates a crash (double free) on corruption detection. +*/ + +/*=========================================== +* Dependencies +*==========================================*/ +#include <stddef.h> /* size_t */ +#include <stdlib.h> /* malloc, free, exit */ +#include <stdio.h> /* fprintf */ +#include <linux/zstd.h> + +/*=========================================== +* Macros +*==========================================*/ +#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) + +static ZSTD_DCtx *dctx = NULL; +void *dws = NULL; +static void* rBuff = NULL; +static size_t buffSize = 0; + +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 decompressCheck(const void* srcBuff, size_t srcBuffSize) +{ + size_t const neededBuffSize = 20 * srcBuffSize; + + /* Allocate all buffers and contexts if not already allocated */ + if (neededBuffSize > buffSize) { + free(rBuff); + buffSize = 0; + + rBuff = malloc(neededBuffSize); + if (!rBuff) { + fprintf(stderr, "not enough memory ! \n"); + crash(1); + } + buffSize = neededBuffSize; + } + if (!dctx) { + size_t const workspaceSize = ZSTD_DCtxWorkspaceBound(); + dws = malloc(workspaceSize); + if (!dws) { + fprintf(stderr, "not enough memory ! \n"); + crash(1); + } + dctx = ZSTD_initDCtx(dws, workspaceSize); + if (!dctx) { + fprintf(stderr, "not enough memory ! \n"); + crash(1); + } + } + ZSTD_decompressDCtx(dctx, rBuff, buffSize, srcBuff, srcBuffSize); + +#ifndef SKIP_FREE + free(dws); dws = NULL; dctx = NULL; + free(rBuff); rBuff = NULL; + buffSize = 0; +#endif +} + +int LLVMFuzzerTestOneInput(const unsigned char *srcBuff, size_t srcBuffSize) { + decompressCheck(srcBuff, srcBuffSize); + return 0; +} diff --git a/src/zstd/contrib/linux-kernel/test/Makefile b/src/zstd/contrib/linux-kernel/test/Makefile new file mode 100644 index 000000000..8411462c9 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/Makefile @@ -0,0 +1,43 @@ + +IFLAGS := -isystem include/ -I ../include/ -I ../lib/zstd/ -isystem googletest/googletest/include -isystem ../../../lib/common/ + +SOURCES := $(wildcard ../lib/zstd/*.c) +OBJECTS := $(patsubst %.c,%.o,$(SOURCES)) + +ARFLAGS := rcs +CXXFLAGS += -std=c++11 -g -O3 -Wcast-align +CFLAGS += -g -O3 -Wframe-larger-than=400 -Wcast-align +CPPFLAGS += $(IFLAGS) + +../lib/zstd/libzstd.a: $(OBJECTS) + $(AR) $(ARFLAGS) $@ $^ + +DecompressCrash: DecompressCrash.o $(OBJECTS) libFuzzer.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ + +RoundTripCrash: RoundTripCrash.o $(OBJECTS) ../lib/xxhash.o libFuzzer.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ + +UserlandTest: UserlandTest.cpp ../lib/zstd/libzstd.a ../lib/xxhash.o + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ googletest/build/googlemock/gtest/libgtest.a googletest/build/googlemock/gtest/libgtest_main.a -o $@ + +XXHashUserlandTest: XXHashUserlandTest.cpp ../lib/xxhash.o ../../../lib/common/xxhash.o + $(CXX) $(CXXFLAGS) $(CFLAGS) $(CPPFLAGS) $^ googletest/build/googlemock/gtest/libgtest.a googletest/build/googlemock/gtest/libgtest_main.a -o $@ + +# Install libfuzzer +libFuzzer.a: + @$(RM) -rf Fuzzer + @git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer + @./Fuzzer/build.sh + +# Install googletest +.PHONY: googletest +googletest: + @$(RM) -rf googletest + @git clone https://github.com/google/googletest + @mkdir -p googletest/build + @cd googletest/build && cmake .. && $(MAKE) + +clean: + $(RM) -f *.{o,a} ../lib/zstd/*.{o,a} ../lib/*.o + $(RM) -f DecompressCrash RoundTripCrash UserlandTest XXHashUserlandTest diff --git a/src/zstd/contrib/linux-kernel/test/RoundTripCrash.c b/src/zstd/contrib/linux-kernel/test/RoundTripCrash.c new file mode 100644 index 000000000..4f968023d --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/RoundTripCrash.c @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + */ + +/* + This program takes a file in input, + performs a zstd round-trip test (compression - decompress) + compares the result with original + and generates a crash (double free) on corruption detection. +*/ + +/*=========================================== +* Dependencies +*==========================================*/ +#include <stddef.h> /* size_t */ +#include <stdlib.h> /* malloc, free, exit */ +#include <stdio.h> /* fprintf */ +#include <linux/xxhash.h> +#include <linux/zstd.h> + +/*=========================================== +* Macros +*==========================================*/ +#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) + +static const int kMaxClevel = 22; + +static ZSTD_CCtx *cctx = NULL; +void *cws = NULL; +static ZSTD_DCtx *dctx = NULL; +void *dws = NULL; +static void* cBuff = NULL; +static void* rBuff = NULL; +static size_t buffSize = 0; + + +/** roundTripTest() : +* Compresses `srcBuff` into `compressedBuff`, +* then decompresses `compressedBuff` into `resultBuff`. +* Compression level used is derived from first content byte. +* @return : result of decompression, which should be == `srcSize` +* or an error code if either compression or decompression fails. +* Note : `compressedBuffCapacity` should be `>= ZSTD_compressBound(srcSize)` +* for compression to be guaranteed to work */ +static size_t roundTripTest(void* resultBuff, size_t resultBuffCapacity, + void* compressedBuff, size_t compressedBuffCapacity, + const void* srcBuff, size_t srcBuffSize) +{ + size_t const hashLength = MIN(128, srcBuffSize); + unsigned const h32 = xxh32(srcBuff, hashLength, 0); + int const cLevel = h32 % kMaxClevel; + ZSTD_parameters const params = ZSTD_getParams(cLevel, srcBuffSize, 0); + size_t const cSize = ZSTD_compressCCtx(cctx, compressedBuff, compressedBuffCapacity, srcBuff, srcBuffSize, params); + if (ZSTD_isError(cSize)) { + fprintf(stderr, "Compression error : %u \n", ZSTD_getErrorCode(cSize)); + return cSize; + } + return ZSTD_decompressDCtx(dctx, resultBuff, resultBuffCapacity, compressedBuff, cSize); +} + + +static size_t checkBuffers(const void* buff1, const void* buff2, size_t buffSize) +{ + const char* ip1 = (const char*)buff1; + const char* ip2 = (const char*)buff2; + size_t pos; + + for (pos=0; pos<buffSize; pos++) + if (ip1[pos]!=ip2[pos]) + break; + + 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 neededBuffSize = ZSTD_compressBound(srcBuffSize); + + /* Allocate all buffers and contexts if not already allocated */ + if (neededBuffSize > buffSize) { + free(cBuff); + free(rBuff); + buffSize = 0; + + cBuff = malloc(neededBuffSize); + rBuff = malloc(neededBuffSize); + if (!cBuff || !rBuff) { + fprintf(stderr, "not enough memory ! \n"); + crash(1); + } + buffSize = neededBuffSize; + } + if (!cctx) { + ZSTD_compressionParameters const params = ZSTD_getCParams(kMaxClevel, 0, 0); + size_t const workspaceSize = ZSTD_CCtxWorkspaceBound(params); + cws = malloc(workspaceSize); + if (!cws) { + fprintf(stderr, "not enough memory ! \n"); + crash(1); + } + cctx = ZSTD_initCCtx(cws, workspaceSize); + if (!cctx) { + fprintf(stderr, "not enough memory ! \n"); + crash(1); + } + } + if (!dctx) { + size_t const workspaceSize = ZSTD_DCtxWorkspaceBound(); + dws = malloc(workspaceSize); + if (!dws) { + fprintf(stderr, "not enough memory ! \n"); + crash(1); + } + dctx = ZSTD_initDCtx(dws, workspaceSize); + if (!dctx) { + fprintf(stderr, "not enough memory ! \n"); + crash(1); + } + } + + { size_t const result = roundTripTest(rBuff, buffSize, cBuff, buffSize, srcBuff, srcBuffSize); + if (ZSTD_isError(result)) { + fprintf(stderr, "roundTripTest error : %u \n", ZSTD_getErrorCode(result)); + crash(1); + } + if (result != srcBuffSize) { + fprintf(stderr, "Incorrect regenerated size : %u != %u\n", (unsigned)result, (unsigned)srcBuffSize); + crash(1); + } + if (checkBuffers(srcBuff, rBuff, srcBuffSize) != srcBuffSize) { + fprintf(stderr, "Silent decoding corruption !!!"); + crash(1); + } + } + +#ifndef SKIP_FREE + free(cws); cws = NULL; cctx = NULL; + free(dws); dws = NULL; dctx = NULL; + free(cBuff); cBuff = NULL; + free(rBuff); rBuff = NULL; + buffSize = 0; +#endif +} + +int LLVMFuzzerTestOneInput(const unsigned char *srcBuff, size_t srcBuffSize) { + roundTripCheck(srcBuff, srcBuffSize); + return 0; +} diff --git a/src/zstd/contrib/linux-kernel/test/UserlandTest.cpp b/src/zstd/contrib/linux-kernel/test/UserlandTest.cpp new file mode 100644 index 000000000..03058382f --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/UserlandTest.cpp @@ -0,0 +1,565 @@ +extern "C" { +#include <linux/zstd.h> +} +#include <gtest/gtest.h> +#include <memory> +#include <string> +#include <iostream> + +using namespace std; + +namespace { +struct WorkspaceDeleter { + void *memory; + + template <typename T> void operator()(T const *) { free(memory); } +}; + +std::unique_ptr<ZSTD_CCtx, WorkspaceDeleter> +createCCtx(ZSTD_compressionParameters cParams) { + size_t const workspaceSize = ZSTD_CCtxWorkspaceBound(cParams); + void *workspace = malloc(workspaceSize); + std::unique_ptr<ZSTD_CCtx, WorkspaceDeleter> cctx{ + ZSTD_initCCtx(workspace, workspaceSize), WorkspaceDeleter{workspace}}; + if (!cctx) { + throw std::runtime_error{"Bad cctx"}; + } + return cctx; +} + +std::unique_ptr<ZSTD_CCtx, WorkspaceDeleter> +createCCtx(int level, unsigned long long estimatedSrcSize = 0, + size_t dictSize = 0) { + auto const cParams = ZSTD_getCParams(level, estimatedSrcSize, dictSize); + return createCCtx(cParams); +} + +std::unique_ptr<ZSTD_DCtx, WorkspaceDeleter> +createDCtx() { + size_t const workspaceSize = ZSTD_DCtxWorkspaceBound(); + void *workspace = malloc(workspaceSize); + std::unique_ptr<ZSTD_DCtx, WorkspaceDeleter> dctx{ + ZSTD_initDCtx(workspace, workspaceSize), WorkspaceDeleter{workspace}}; + if (!dctx) { + throw std::runtime_error{"Bad dctx"}; + } + return dctx; +} + +std::unique_ptr<ZSTD_CDict, WorkspaceDeleter> +createCDict(std::string const& dict, ZSTD_parameters params) { + size_t const workspaceSize = ZSTD_CDictWorkspaceBound(params.cParams); + void *workspace = malloc(workspaceSize); + std::unique_ptr<ZSTD_CDict, WorkspaceDeleter> cdict{ + ZSTD_initCDict(dict.data(), dict.size(), params, workspace, + workspaceSize), + WorkspaceDeleter{workspace}}; + if (!cdict) { + throw std::runtime_error{"Bad cdict"}; + } + return cdict; +} + +std::unique_ptr<ZSTD_CDict, WorkspaceDeleter> +createCDict(std::string const& dict, int level) { + auto const params = ZSTD_getParams(level, 0, dict.size()); + return createCDict(dict, params); +} + +std::unique_ptr<ZSTD_DDict, WorkspaceDeleter> +createDDict(std::string const& dict) { + size_t const workspaceSize = ZSTD_DDictWorkspaceBound(); + void *workspace = malloc(workspaceSize); + std::unique_ptr<ZSTD_DDict, WorkspaceDeleter> ddict{ + ZSTD_initDDict(dict.data(), dict.size(), workspace, workspaceSize), + WorkspaceDeleter{workspace}}; + if (!ddict) { + throw std::runtime_error{"Bad ddict"}; + } + return ddict; +} + +std::unique_ptr<ZSTD_CStream, WorkspaceDeleter> +createCStream(ZSTD_parameters params, unsigned long long pledgedSrcSize = 0) { + size_t const workspaceSize = ZSTD_CStreamWorkspaceBound(params.cParams); + void *workspace = malloc(workspaceSize); + std::unique_ptr<ZSTD_CStream, WorkspaceDeleter> zcs{ + ZSTD_initCStream(params, pledgedSrcSize, workspace, workspaceSize)}; + if (!zcs) { + throw std::runtime_error{"bad cstream"}; + } + return zcs; +} + +std::unique_ptr<ZSTD_CStream, WorkspaceDeleter> +createCStream(ZSTD_compressionParameters cParams, ZSTD_CDict const &cdict, + unsigned long long pledgedSrcSize = 0) { + size_t const workspaceSize = ZSTD_CStreamWorkspaceBound(cParams); + void *workspace = malloc(workspaceSize); + std::unique_ptr<ZSTD_CStream, WorkspaceDeleter> zcs{ + ZSTD_initCStream_usingCDict(&cdict, pledgedSrcSize, workspace, + workspaceSize)}; + if (!zcs) { + throw std::runtime_error{"bad cstream"}; + } + return zcs; +} + +std::unique_ptr<ZSTD_CStream, WorkspaceDeleter> +createCStream(int level, unsigned long long pledgedSrcSize = 0) { + auto const params = ZSTD_getParams(level, pledgedSrcSize, 0); + return createCStream(params, pledgedSrcSize); +} + +std::unique_ptr<ZSTD_DStream, WorkspaceDeleter> +createDStream(size_t maxWindowSize = (1ULL << ZSTD_WINDOWLOG_MAX), + ZSTD_DDict const *ddict = nullptr) { + size_t const workspaceSize = ZSTD_DStreamWorkspaceBound(maxWindowSize); + void *workspace = malloc(workspaceSize); + std::unique_ptr<ZSTD_DStream, WorkspaceDeleter> zds{ + ddict == nullptr + ? ZSTD_initDStream(maxWindowSize, workspace, workspaceSize) + : ZSTD_initDStream_usingDDict(maxWindowSize, ddict, workspace, + workspaceSize)}; + if (!zds) { + throw std::runtime_error{"bad dstream"}; + } + return zds; +} + +std::string compress(ZSTD_CCtx &cctx, std::string const &data, + ZSTD_parameters params, std::string const &dict = "") { + std::string compressed; + compressed.resize(ZSTD_compressBound(data.size())); + size_t const rc = + dict.empty() + ? ZSTD_compressCCtx(&cctx, &compressed[0], compressed.size(), + data.data(), data.size(), params) + : ZSTD_compress_usingDict(&cctx, &compressed[0], compressed.size(), + data.data(), data.size(), dict.data(), + dict.size(), params); + if (ZSTD_isError(rc)) { + throw std::runtime_error{"compression error"}; + } + compressed.resize(rc); + return compressed; +} + +std::string compress(ZSTD_CCtx& cctx, std::string const& data, int level, std::string const& dict = "") { + auto const params = ZSTD_getParams(level, 0, dict.size()); + return compress(cctx, data, params, dict); +} + +std::string decompress(ZSTD_DCtx& dctx, std::string const& compressed, size_t decompressedSize, std::string const& dict = "") { + std::string decompressed; + decompressed.resize(decompressedSize); + size_t const rc = + dict.empty() + ? ZSTD_decompressDCtx(&dctx, &decompressed[0], decompressed.size(), + compressed.data(), compressed.size()) + : ZSTD_decompress_usingDict( + &dctx, &decompressed[0], decompressed.size(), compressed.data(), + compressed.size(), dict.data(), dict.size()); + if (ZSTD_isError(rc)) { + throw std::runtime_error{"decompression error"}; + } + decompressed.resize(rc); + return decompressed; +} + +std::string compress(ZSTD_CCtx& cctx, std::string const& data, ZSTD_CDict& cdict) { + std::string compressed; + compressed.resize(ZSTD_compressBound(data.size())); + size_t const rc = + ZSTD_compress_usingCDict(&cctx, &compressed[0], compressed.size(), + data.data(), data.size(), &cdict); + if (ZSTD_isError(rc)) { + throw std::runtime_error{"compression error"}; + } + compressed.resize(rc); + return compressed; +} + +std::string decompress(ZSTD_DCtx& dctx, std::string const& compressed, size_t decompressedSize, ZSTD_DDict& ddict) { + std::string decompressed; + decompressed.resize(decompressedSize); + size_t const rc = + ZSTD_decompress_usingDDict(&dctx, &decompressed[0], decompressed.size(), + compressed.data(), compressed.size(), &ddict); + if (ZSTD_isError(rc)) { + throw std::runtime_error{"decompression error"}; + } + decompressed.resize(rc); + return decompressed; +} + +std::string compress(ZSTD_CStream& zcs, std::string const& data) { + std::string compressed; + compressed.resize(ZSTD_compressBound(data.size())); + ZSTD_inBuffer in = {data.data(), data.size(), 0}; + ZSTD_outBuffer out = {&compressed[0], compressed.size(), 0}; + while (in.pos != in.size) { + size_t const rc = ZSTD_compressStream(&zcs, &out, &in); + if (ZSTD_isError(rc)) { + throw std::runtime_error{"compress stream failed"}; + } + } + size_t const rc = ZSTD_endStream(&zcs, &out); + if (rc != 0) { + throw std::runtime_error{"compress end failed"}; + } + compressed.resize(out.pos); + return compressed; +} + +std::string decompress(ZSTD_DStream &zds, std::string const &compressed, + size_t decompressedSize) { + std::string decompressed; + decompressed.resize(decompressedSize); + ZSTD_inBuffer in = {compressed.data(), compressed.size(), 0}; + ZSTD_outBuffer out = {&decompressed[0], decompressed.size(), 0}; + while (in.pos != in.size) { + size_t const rc = ZSTD_decompressStream(&zds, &out, &in); + if (ZSTD_isError(rc)) { + throw std::runtime_error{"decompress stream failed"}; + } + } + decompressed.resize(out.pos); + return decompressed; +} + +std::string makeData(size_t size) { + std::string result; + result.reserve(size + 20); + while (result.size() < size) { + result += "Hello world"; + } + return result; +} + +std::string const kData = "Hello world"; +std::string const kPlainDict = makeData(10000); +std::string const kZstdDict{ + "\x37\xA4\x30\xEC\x99\x69\x58\x1C\x21\x10\xD8\x4A\x84\x01\xCC\xF3" + "\x3C\xCF\x9B\x25\xBB\xC9\x6E\xB2\x9B\xEC\x26\xAD\xCF\xDF\x4E\xCD" + "\xF3\x2C\x3A\x21\x84\x10\x42\x08\x21\x01\x33\xF1\x78\x3C\x1E\x8F" + "\xC7\xE3\xF1\x78\x3C\xCF\xF3\xBC\xF7\xD4\x42\x41\x41\x41\x41\x41" + "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" + "\x41\x41\x41\x41\xA1\x50\x28\x14\x0A\x85\x42\xA1\x50\x28\x14\x0A" + "\x85\xA2\x28\x8A\xA2\x28\x4A\x29\x7D\x74\xE1\xE1\xE1\xE1\xE1\xE1" + "\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xF1\x78\x3C" + "\x1E\x8F\xC7\xE3\xF1\x78\x9E\xE7\x79\xEF\x01\x01\x00\x00\x00\x04" + "\x00\x00\x00\x08\x00\x00\x00" + "0123456789", + 161}; +} + +TEST(Block, CCtx) { + auto cctx = createCCtx(1); + auto const compressed = compress(*cctx, kData, 1); + auto dctx = createDCtx(); + auto const decompressed = decompress(*dctx, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); +} + +TEST(Block, NoContentSize) { + auto cctx = createCCtx(1); + auto const c = compress(*cctx, kData, 1); + auto const size = ZSTD_findDecompressedSize(c.data(), c.size()); + EXPECT_EQ(ZSTD_CONTENTSIZE_UNKNOWN, size); +} + +TEST(Block, ContentSize) { + auto cctx = createCCtx(1); + auto params = ZSTD_getParams(1, 0, 0); + params.fParams.contentSizeFlag = 1; + auto const c = compress(*cctx, kData, params); + auto const size = ZSTD_findDecompressedSize(c.data(), c.size()); + EXPECT_EQ(kData.size(), size); +} + +TEST(Block, CCtxLevelIncrease) { + std::string c; + auto cctx = createCCtx(22); + auto dctx = createDCtx(); + for (int level = 1; level <= 22; ++level) { + auto compressed = compress(*cctx, kData, level); + auto const decompressed = decompress(*dctx, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); + } +} + +TEST(Block, PlainDict) { + auto cctx = createCCtx(1); + auto const compressed = compress(*cctx, kData, 1, kPlainDict); + auto dctx = createDCtx(); + EXPECT_ANY_THROW(decompress(*dctx, compressed, kData.size())); + auto const decompressed = + decompress(*dctx, compressed, kData.size(), kPlainDict); + EXPECT_EQ(kData, decompressed); +} + +TEST(Block, ZstdDict) { + auto cctx = createCCtx(1); + auto const compressed = compress(*cctx, kData, 1, kZstdDict); + auto dctx = createDCtx(); + EXPECT_ANY_THROW(decompress(*dctx, compressed, kData.size())); + auto const decompressed = + decompress(*dctx, compressed, kData.size(), kZstdDict); + EXPECT_EQ(kData, decompressed); +} + +TEST(Block, PreprocessedPlainDict) { + auto cctx = createCCtx(1); + auto const cdict = createCDict(kPlainDict, 1); + auto const compressed = compress(*cctx, kData, *cdict); + auto dctx = createDCtx(); + auto const ddict = createDDict(kPlainDict); + EXPECT_ANY_THROW(decompress(*dctx, compressed, kData.size())); + auto const decompressed = + decompress(*dctx, compressed, kData.size(), *ddict); + EXPECT_EQ(kData, decompressed); +} + +TEST(Block, PreprocessedZstdDict) { + auto cctx = createCCtx(1); + auto const cdict = createCDict(kZstdDict, 1); + auto const compressed = compress(*cctx, kData, *cdict); + auto dctx = createDCtx(); + auto const ddict = createDDict(kZstdDict); + EXPECT_ANY_THROW(decompress(*dctx, compressed, kData.size())); + auto const decompressed = + decompress(*dctx, compressed, kData.size(), *ddict); + EXPECT_EQ(kData, decompressed); +} + +TEST(Block, ReinitializeCCtx) { + auto cctx = createCCtx(1); + { + auto const compressed = compress(*cctx, kData, 1); + auto dctx = createDCtx(); + auto const decompressed = decompress(*dctx, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); + } + // Create the cctx with the same memory + auto d = cctx.get_deleter(); + auto raw = cctx.release(); + auto params = ZSTD_getParams(1, 0, 0); + cctx.reset( + ZSTD_initCCtx(d.memory, ZSTD_CCtxWorkspaceBound(params.cParams))); + // Repeat + { + auto const compressed = compress(*cctx, kData, 1); + auto dctx = createDCtx(); + auto const decompressed = decompress(*dctx, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); + } +} + +TEST(Block, ReinitializeDCtx) { + auto dctx = createDCtx(); + { + auto cctx = createCCtx(1); + auto const compressed = compress(*cctx, kData, 1); + auto const decompressed = decompress(*dctx, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); + } + // Create the cctx with the same memory + auto d = dctx.get_deleter(); + auto raw = dctx.release(); + dctx.reset(ZSTD_initDCtx(d.memory, ZSTD_DCtxWorkspaceBound())); + // Repeat + { + auto cctx = createCCtx(1); + auto const compressed = compress(*cctx, kData, 1); + auto dctx = createDCtx(); + auto const decompressed = decompress(*dctx, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); + } +} + +TEST(Stream, Basic) { + auto zcs = createCStream(1); + auto const compressed = compress(*zcs, kData); + auto zds = createDStream(); + auto const decompressed = decompress(*zds, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); +} + +TEST(Stream, PlainDict) { + auto params = ZSTD_getParams(1, kData.size(), kPlainDict.size()); + params.cParams.windowLog = 17; + auto cdict = createCDict(kPlainDict, params); + auto zcs = createCStream(params.cParams, *cdict, kData.size()); + auto const compressed = compress(*zcs, kData); + auto const contentSize = + ZSTD_findDecompressedSize(compressed.data(), compressed.size()); + EXPECT_ANY_THROW(decompress(*createDStream(), compressed, kData.size())); + auto ddict = createDDict(kPlainDict); + auto zds = createDStream(1 << 17, ddict.get()); + auto const decompressed = decompress(*zds, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); +} + +TEST(Stream, ZstdDict) { + auto params = ZSTD_getParams(1, 0, 0); + params.cParams.windowLog = 17; + auto cdict = createCDict(kZstdDict, 1); + auto zcs = createCStream(params.cParams, *cdict); + auto const compressed = compress(*zcs, kData); + EXPECT_ANY_THROW(decompress(*createDStream(), compressed, kData.size())); + auto ddict = createDDict(kZstdDict); + auto zds = createDStream(1 << 17, ddict.get()); + auto const decompressed = decompress(*zds, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); +} + +TEST(Stream, ResetCStream) { + auto zcs = createCStream(1); + auto zds = createDStream(); + { + auto const compressed = compress(*zcs, kData); + auto const decompressed = decompress(*zds, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); + } + { + ZSTD_resetCStream(zcs.get(), 0); + auto const compressed = compress(*zcs, kData); + auto const decompressed = decompress(*zds, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); + } +} + +TEST(Stream, ResetDStream) { + auto zcs = createCStream(1); + auto zds = createDStream(); + auto const compressed = compress(*zcs, kData); + EXPECT_ANY_THROW(decompress(*zds, kData, kData.size())); + EXPECT_ANY_THROW(decompress(*zds, compressed, kData.size())); + ZSTD_resetDStream(zds.get()); + auto const decompressed = decompress(*zds, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); +} + +TEST(Stream, Flush) { + auto zcs = createCStream(1); + auto zds = createDStream(); + std::string compressed; + { + compressed.resize(ZSTD_compressBound(kData.size())); + ZSTD_inBuffer in = {kData.data(), kData.size(), 0}; + ZSTD_outBuffer out = {&compressed[0], compressed.size(), 0}; + while (in.pos != in.size) { + size_t const rc = ZSTD_compressStream(zcs.get(), &out, &in); + if (ZSTD_isError(rc)) { + throw std::runtime_error{"compress stream failed"}; + } + } + EXPECT_EQ(0, out.pos); + size_t const rc = ZSTD_flushStream(zcs.get(), &out); + if (rc != 0) { + throw std::runtime_error{"compress end failed"}; + } + compressed.resize(out.pos); + EXPECT_LT(0, out.pos); + } + std::string decompressed; + { + decompressed.resize(kData.size()); + ZSTD_inBuffer in = {compressed.data(), compressed.size(), 0}; + ZSTD_outBuffer out = {&decompressed[0], decompressed.size(), 0}; + while (in.pos != in.size) { + size_t const rc = ZSTD_decompressStream(zds.get(), &out, &in); + if (ZSTD_isError(rc)) { + throw std::runtime_error{"decompress stream failed"}; + } + } + } + EXPECT_EQ(kData, decompressed); +} + +TEST(Stream, DStreamLevelIncrease) { + auto zds = createDStream(); + for (int level = 1; level <= 22; ++level) { + auto zcs = createCStream(level); + auto compressed = compress(*zcs, kData); + ZSTD_resetDStream(zds.get()); + auto const decompressed = decompress(*zds, compressed, kData.size()); + EXPECT_EQ(kData, decompressed); + } +} + +#define TEST_SYMBOL(symbol) \ + do { \ + extern void *__##symbol; \ + EXPECT_NE((void *)0, __##symbol); \ + } while (0) + +TEST(API, Symbols) { + TEST_SYMBOL(ZSTD_CCtxWorkspaceBound); + TEST_SYMBOL(ZSTD_initCCtx); + TEST_SYMBOL(ZSTD_compressCCtx); + TEST_SYMBOL(ZSTD_compress_usingDict); + TEST_SYMBOL(ZSTD_DCtxWorkspaceBound); + TEST_SYMBOL(ZSTD_initDCtx); + TEST_SYMBOL(ZSTD_decompressDCtx); + TEST_SYMBOL(ZSTD_decompress_usingDict); + + TEST_SYMBOL(ZSTD_CDictWorkspaceBound); + TEST_SYMBOL(ZSTD_initCDict); + TEST_SYMBOL(ZSTD_compress_usingCDict); + TEST_SYMBOL(ZSTD_DDictWorkspaceBound); + TEST_SYMBOL(ZSTD_initDDict); + TEST_SYMBOL(ZSTD_decompress_usingDDict); + + TEST_SYMBOL(ZSTD_CStreamWorkspaceBound); + TEST_SYMBOL(ZSTD_initCStream); + TEST_SYMBOL(ZSTD_initCStream_usingCDict); + TEST_SYMBOL(ZSTD_resetCStream); + TEST_SYMBOL(ZSTD_compressStream); + TEST_SYMBOL(ZSTD_flushStream); + TEST_SYMBOL(ZSTD_endStream); + TEST_SYMBOL(ZSTD_CStreamInSize); + TEST_SYMBOL(ZSTD_CStreamOutSize); + TEST_SYMBOL(ZSTD_DStreamWorkspaceBound); + TEST_SYMBOL(ZSTD_initDStream); + TEST_SYMBOL(ZSTD_initDStream_usingDDict); + TEST_SYMBOL(ZSTD_resetDStream); + TEST_SYMBOL(ZSTD_decompressStream); + TEST_SYMBOL(ZSTD_DStreamInSize); + TEST_SYMBOL(ZSTD_DStreamOutSize); + + TEST_SYMBOL(ZSTD_findFrameCompressedSize); + TEST_SYMBOL(ZSTD_getFrameContentSize); + TEST_SYMBOL(ZSTD_findDecompressedSize); + + TEST_SYMBOL(ZSTD_getCParams); + TEST_SYMBOL(ZSTD_getParams); + TEST_SYMBOL(ZSTD_checkCParams); + TEST_SYMBOL(ZSTD_adjustCParams); + + TEST_SYMBOL(ZSTD_isFrame); + TEST_SYMBOL(ZSTD_getDictID_fromDict); + TEST_SYMBOL(ZSTD_getDictID_fromDDict); + TEST_SYMBOL(ZSTD_getDictID_fromFrame); + + TEST_SYMBOL(ZSTD_compressBegin); + TEST_SYMBOL(ZSTD_compressBegin_usingDict); + TEST_SYMBOL(ZSTD_compressBegin_advanced); + TEST_SYMBOL(ZSTD_copyCCtx); + TEST_SYMBOL(ZSTD_compressBegin_usingCDict); + TEST_SYMBOL(ZSTD_compressContinue); + TEST_SYMBOL(ZSTD_compressEnd); + TEST_SYMBOL(ZSTD_getFrameParams); + TEST_SYMBOL(ZSTD_decompressBegin); + TEST_SYMBOL(ZSTD_decompressBegin_usingDict); + TEST_SYMBOL(ZSTD_copyDCtx); + TEST_SYMBOL(ZSTD_nextSrcSizeToDecompress); + TEST_SYMBOL(ZSTD_decompressContinue); + TEST_SYMBOL(ZSTD_nextInputType); + + TEST_SYMBOL(ZSTD_getBlockSizeMax); + TEST_SYMBOL(ZSTD_compressBlock); + TEST_SYMBOL(ZSTD_decompressBlock); + TEST_SYMBOL(ZSTD_insertBlock); +} diff --git a/src/zstd/contrib/linux-kernel/test/XXHashUserlandTest.cpp b/src/zstd/contrib/linux-kernel/test/XXHashUserlandTest.cpp new file mode 100644 index 000000000..f50401a2e --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/XXHashUserlandTest.cpp @@ -0,0 +1,166 @@ +extern "C" { +#include <linux/errno.h> +#include <linux/xxhash.h> +} +#include <gtest/gtest.h> +#include <array> +#include <iostream> +#include <memory> +#include <string> +#define XXH_STATIC_LINKING_ONLY +#include <xxhash.h> + +using namespace std; + +namespace { +const std::array<std::string, 11> kTestInputs = { + "", + "0", + "01234", + "0123456789abcde", + "0123456789abcdef", + "0123456789abcdef0", + "0123456789abcdef0123", + "0123456789abcdef0123456789abcde", + "0123456789abcdef0123456789abcdef", + "0123456789abcdef0123456789abcdef0", + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", +}; + +bool testXXH32(const void *input, const size_t length, uint32_t seed) { + return XXH32(input, length, seed) == xxh32(input, length, seed); +} + +bool testXXH64(const void *input, const size_t length, uint32_t seed) { + return XXH64(input, length, seed) == xxh64(input, length, seed); +} + +class XXH32State { + struct xxh32_state kernelState; + XXH32_state_t state; + +public: + explicit XXH32State(const uint32_t seed) { reset(seed); } + XXH32State(XXH32State const& other) noexcept { + xxh32_copy_state(&kernelState, &other.kernelState); + XXH32_copyState(&state, &other.state); + } + XXH32State& operator=(XXH32State const& other) noexcept { + xxh32_copy_state(&kernelState, &other.kernelState); + XXH32_copyState(&state, &other.state); + return *this; + } + + void reset(const uint32_t seed) { + xxh32_reset(&kernelState, seed); + EXPECT_EQ(0, XXH32_reset(&state, seed)); + } + + void update(const void *input, const size_t length) { + EXPECT_EQ(0, xxh32_update(&kernelState, input, length)); + EXPECT_EQ(0, (int)XXH32_update(&state, input, length)); + } + + bool testDigest() const { + return xxh32_digest(&kernelState) == XXH32_digest(&state); + } +}; + +class XXH64State { + struct xxh64_state kernelState; + XXH64_state_t state; + +public: + explicit XXH64State(const uint64_t seed) { reset(seed); } + XXH64State(XXH64State const& other) noexcept { + xxh64_copy_state(&kernelState, &other.kernelState); + XXH64_copyState(&state, &other.state); + } + XXH64State& operator=(XXH64State const& other) noexcept { + xxh64_copy_state(&kernelState, &other.kernelState); + XXH64_copyState(&state, &other.state); + return *this; + } + + void reset(const uint64_t seed) { + xxh64_reset(&kernelState, seed); + EXPECT_EQ(0, XXH64_reset(&state, seed)); + } + + void update(const void *input, const size_t length) { + EXPECT_EQ(0, xxh64_update(&kernelState, input, length)); + EXPECT_EQ(0, (int)XXH64_update(&state, input, length)); + } + + bool testDigest() const { + return xxh64_digest(&kernelState) == XXH64_digest(&state); + } +}; +} + +TEST(Simple, Null) { + EXPECT_TRUE(testXXH32(NULL, 0, 0)); + EXPECT_TRUE(testXXH64(NULL, 0, 0)); +} + +TEST(Stream, Null) { + struct xxh32_state state32; + xxh32_reset(&state32, 0); + EXPECT_EQ(-EINVAL, xxh32_update(&state32, NULL, 0)); + + struct xxh64_state state64; + xxh64_reset(&state64, 0); + EXPECT_EQ(-EINVAL, xxh64_update(&state64, NULL, 0)); +} + +TEST(Simple, TestInputs) { + for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { + for (auto const input : kTestInputs) { + EXPECT_TRUE(testXXH32(input.data(), input.size(), seed)); + EXPECT_TRUE(testXXH64(input.data(), input.size(), (uint64_t)seed)); + } + } +} + +TEST(Stream, TestInputs) { + for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { + for (auto const input : kTestInputs) { + XXH32State s32(seed); + XXH64State s64(seed); + s32.update(input.data(), input.size()); + s64.update(input.data(), input.size()); + EXPECT_TRUE(s32.testDigest()); + EXPECT_TRUE(s64.testDigest()); + } + } +} + +TEST(Stream, MultipleTestInputs) { + for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { + XXH32State s32(seed); + XXH64State s64(seed); + for (auto const input : kTestInputs) { + s32.update(input.data(), input.size()); + s64.update(input.data(), input.size()); + } + EXPECT_TRUE(s32.testDigest()); + EXPECT_TRUE(s64.testDigest()); + } +} + +TEST(Stream, CopyState) { + for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { + XXH32State s32(seed); + XXH64State s64(seed); + for (auto const input : kTestInputs) { + auto t32(s32); + t32.update(input.data(), input.size()); + s32 = t32; + auto t64(s64); + t64.update(input.data(), input.size()); + s64 = t64; + } + EXPECT_TRUE(s32.testDigest()); + EXPECT_TRUE(s64.testDigest()); + } +} diff --git a/src/zstd/contrib/linux-kernel/test/include/asm/unaligned.h b/src/zstd/contrib/linux-kernel/test/include/asm/unaligned.h new file mode 100644 index 000000000..4f4828126 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/include/asm/unaligned.h @@ -0,0 +1,177 @@ +#ifndef ASM_UNALIGNED_H +#define ASM_UNALIGNED_H + +#include <assert.h> +#include <linux/string.h> +#include <linux/types.h> + +#define _LITTLE_ENDIAN 1 + +static unsigned _isLittleEndian(void) +{ + const union { uint32_t u; uint8_t c[4]; } one = { 1 }; + assert(_LITTLE_ENDIAN == one.c[0]); + return _LITTLE_ENDIAN; +} + +static uint16_t _swap16(uint16_t in) +{ + return ((in & 0xF) << 8) + ((in & 0xF0) >> 8); +} + +static uint32_t _swap32(uint32_t in) +{ + return __builtin_bswap32(in); +} + +static uint64_t _swap64(uint64_t in) +{ + return __builtin_bswap64(in); +} + +/* Little endian */ +static uint16_t get_unaligned_le16(const void* memPtr) +{ + uint16_t val; + memcpy(&val, memPtr, sizeof(val)); + if (!_isLittleEndian()) _swap16(val); + return val; +} + +static uint32_t get_unaligned_le32(const void* memPtr) +{ + uint32_t val; + memcpy(&val, memPtr, sizeof(val)); + if (!_isLittleEndian()) _swap32(val); + return val; +} + +static uint64_t get_unaligned_le64(const void* memPtr) +{ + uint64_t val; + memcpy(&val, memPtr, sizeof(val)); + if (!_isLittleEndian()) _swap64(val); + return val; +} + +static void put_unaligned_le16(uint16_t value, void* memPtr) +{ + if (!_isLittleEndian()) value = _swap16(value); + memcpy(memPtr, &value, sizeof(value)); +} + +static void put_unaligned_le32(uint32_t value, void* memPtr) +{ + if (!_isLittleEndian()) value = _swap32(value); + memcpy(memPtr, &value, sizeof(value)); +} + +static void put_unaligned_le64(uint64_t value, void* memPtr) +{ + if (!_isLittleEndian()) value = _swap64(value); + memcpy(memPtr, &value, sizeof(value)); +} + +/* big endian */ +static uint32_t get_unaligned_be32(const void* memPtr) +{ + uint32_t val; + memcpy(&val, memPtr, sizeof(val)); + if (_isLittleEndian()) _swap32(val); + return val; +} + +static uint64_t get_unaligned_be64(const void* memPtr) +{ + uint64_t val; + memcpy(&val, memPtr, sizeof(val)); + if (_isLittleEndian()) _swap64(val); + return val; +} + +static void put_unaligned_be32(uint32_t value, void* memPtr) +{ + if (_isLittleEndian()) value = _swap32(value); + memcpy(memPtr, &value, sizeof(value)); +} + +static void put_unaligned_be64(uint64_t value, void* memPtr) +{ + if (_isLittleEndian()) value = _swap64(value); + memcpy(memPtr, &value, sizeof(value)); +} + +/* generic */ +extern void __bad_unaligned_access_size(void); + +#define __get_unaligned_le(ptr) ((typeof(*(ptr)))({ \ + __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \ + __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)), \ + __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)), \ + __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)), \ + __bad_unaligned_access_size())))); \ + })) + +#define __get_unaligned_be(ptr) ((typeof(*(ptr)))({ \ + __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \ + __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)), \ + __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)), \ + __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)), \ + __bad_unaligned_access_size())))); \ + })) + +#define __put_unaligned_le(val, ptr) \ + ({ \ + void *__gu_p = (ptr); \ + switch (sizeof(*(ptr))) { \ + case 1: \ + *(uint8_t *)__gu_p = (uint8_t)(val); \ + break; \ + case 2: \ + put_unaligned_le16((uint16_t)(val), __gu_p); \ + break; \ + case 4: \ + put_unaligned_le32((uint32_t)(val), __gu_p); \ + break; \ + case 8: \ + put_unaligned_le64((uint64_t)(val), __gu_p); \ + break; \ + default: \ + __bad_unaligned_access_size(); \ + break; \ + } \ + (void)0; \ + }) + +#define __put_unaligned_be(val, ptr) \ + ({ \ + void *__gu_p = (ptr); \ + switch (sizeof(*(ptr))) { \ + case 1: \ + *(uint8_t *)__gu_p = (uint8_t)(val); \ + break; \ + case 2: \ + put_unaligned_be16((uint16_t)(val), __gu_p); \ + break; \ + case 4: \ + put_unaligned_be32((uint32_t)(val), __gu_p); \ + break; \ + case 8: \ + put_unaligned_be64((uint64_t)(val), __gu_p); \ + break; \ + default: \ + __bad_unaligned_access_size(); \ + break; \ + } \ + (void)0; \ + }) + +#if _LITTLE_ENDIAN +# define get_unaligned __get_unaligned_le +# define put_unaligned __put_unaligned_le +#else +# define get_unaligned __get_unaligned_be +# define put_unaligned __put_unaligned_be +#endif + +#endif // ASM_UNALIGNED_H diff --git a/src/zstd/contrib/linux-kernel/test/include/linux/compiler.h b/src/zstd/contrib/linux-kernel/test/include/linux/compiler.h new file mode 100644 index 000000000..4fb4f42e2 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/include/linux/compiler.h @@ -0,0 +1,12 @@ +#ifndef LINUX_COMPILER_H_ +#define LINUX_COMPILER_H_ + +#ifndef __always_inline +# define __always_inline inline +#endif + +#ifndef noinline +# define noinline __attribute__((__noinline__)) +#endif + +#endif // LINUX_COMPILER_H_ diff --git a/src/zstd/contrib/linux-kernel/test/include/linux/errno.h b/src/zstd/contrib/linux-kernel/test/include/linux/errno.h new file mode 100644 index 000000000..b9db08524 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/include/linux/errno.h @@ -0,0 +1,6 @@ +#ifndef LINUX_ERRNO_H_ +#define LINUX_ERRNO_H_ + +#define EINVAL 22 + +#endif // LINUX_ERRNO_H_ diff --git a/src/zstd/contrib/linux-kernel/test/include/linux/kernel.h b/src/zstd/contrib/linux-kernel/test/include/linux/kernel.h new file mode 100644 index 000000000..3ef2f7fe8 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/include/linux/kernel.h @@ -0,0 +1,16 @@ +#ifndef LINUX_KERNEL_H_ +#define LINUX_KERNEL_H_ + +#define ALIGN(x, a) ({ \ + typeof(x) const __xe = (x); \ + typeof(a) const __ae = (a); \ + typeof(a) const __m = __ae - 1; \ + typeof(x) const __r = __xe & __m; \ + __xe + (__r ? (__ae - __r) : 0); \ + }) + +#define PTR_ALIGN(p, a) (typeof(p))ALIGN((unsigned long long)(p), (a)) + +#define current Something that doesn't compile :) + +#endif // LINUX_KERNEL_H_ diff --git a/src/zstd/contrib/linux-kernel/test/include/linux/math64.h b/src/zstd/contrib/linux-kernel/test/include/linux/math64.h new file mode 100644 index 000000000..3d0ae72d5 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/include/linux/math64.h @@ -0,0 +1,11 @@ +#ifndef LINUX_MATH64_H +#define LINUX_MATH64_H + +#include <stdint.h> + +static uint64_t div_u64(uint64_t n, uint32_t d) +{ + return n / d; +} + +#endif diff --git a/src/zstd/contrib/linux-kernel/test/include/linux/module.h b/src/zstd/contrib/linux-kernel/test/include/linux/module.h new file mode 100644 index 000000000..ef514c349 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/include/linux/module.h @@ -0,0 +1,10 @@ +#ifndef LINUX_MODULE_H_ +#define LINUX_MODULE_H_ + +#define EXPORT_SYMBOL(symbol) \ + void* __##symbol = symbol +#define MODULE_LICENSE(license) static char const *const LICENSE = license +#define MODULE_DESCRIPTION(description) \ + static char const *const DESCRIPTION = description + +#endif // LINUX_MODULE_H_ diff --git a/src/zstd/contrib/linux-kernel/test/include/linux/string.h b/src/zstd/contrib/linux-kernel/test/include/linux/string.h new file mode 100644 index 000000000..3b2f59002 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/include/linux/string.h @@ -0,0 +1 @@ +#include <string.h> diff --git a/src/zstd/contrib/linux-kernel/test/include/linux/types.h b/src/zstd/contrib/linux-kernel/test/include/linux/types.h new file mode 100644 index 000000000..c2d4f4b72 --- /dev/null +++ b/src/zstd/contrib/linux-kernel/test/include/linux/types.h @@ -0,0 +1,2 @@ +#include <stddef.h> +#include <stdint.h> |