diff --git a/core/zip/CMakeLists.txt b/core/zip/CMakeLists.txt index 0be3d6c0c5154..72d1bfb756dd8 100644 --- a/core/zip/CMakeLists.txt +++ b/core/zip/CMakeLists.txt @@ -22,3 +22,5 @@ target_include_directories(Core PUBLIC ) ROOT_INSTALL_HEADERS() + +ROOT_ADD_TEST_SUBDIRECTORY(test) diff --git a/core/zip/test/CMakeLists.txt b/core/zip/test/CMakeLists.txt new file mode 100644 index 0000000000000..61b10d7ef40c7 --- /dev/null +++ b/core/zip/test/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. +# All rights reserved. +# +# For the licensing terms see $ROOTSYS/LICENSE. +# For the list of contributors see $ROOTSYS/README/CREDITS. + +ROOT_ADD_GTEST(ZipTest ZipTest.cxx LIBRARIES Core) diff --git a/core/zip/test/ZipTest.cxx b/core/zip/test/ZipTest.cxx new file mode 100644 index 0000000000000..f1b40f7853950 --- /dev/null +++ b/core/zip/test/ZipTest.cxx @@ -0,0 +1,70 @@ +#include +#include + +#include + +#include + +static void testZipBufferSizes(ROOT::RCompressionSetting::EAlgorithm::EValues compressionAlgorithm) +{ + static constexpr size_t BufferSize = 256; + static constexpr size_t MaxBytes = 128; + static_assert(MaxBytes <= BufferSize, "MaxBytes must be smaller than BufferSize"); + static constexpr size_t StartOffset = (BufferSize - MaxBytes) / 2; + // For extra "safety", allocate the buffers on the heap to avoid corrupting the stack should anything go wrong. + std::unique_ptr source(new char[BufferSize]); + std::unique_ptr target(new char[BufferSize]); + + // Fill the buffers with monotonically increasing numbers. This is easy to compress, but that's fine because we scan + // through all possible sizes. + for (size_t i = 0; i < BufferSize; i++) { + source[i] = static_cast(i); + target[i] = static_cast(i); + } + + // Now test all possible combinations of target and source sizes. The outer loop is for the target sizes because that + // allows us to check that nothing got overwritten. + for (size_t targetSize = 1; targetSize <= MaxBytes; targetSize++) { + for (size_t sourceSize = 1; sourceSize <= MaxBytes; sourceSize++) { + for (int cxlevel = 1; cxlevel <= 9; cxlevel++) { + int srcsize = static_cast(sourceSize); + int tgtsize = static_cast(targetSize); + int irep = -1; + R__zipMultipleAlgorithm(cxlevel, &srcsize, source.get(), &tgtsize, target.get() + StartOffset, &irep, + compressionAlgorithm); + + for (size_t i = 0; i < StartOffset; i++) { + EXPECT_EQ(target[i], static_cast(i)); + } + for (size_t i = StartOffset + targetSize + 1; i < BufferSize; i++) { + EXPECT_EQ(target[i], static_cast(i)); + } + } + } + } +} + +TEST(RZip, ZipBufferSizesOld) +{ + testZipBufferSizes(ROOT::RCompressionSetting::EAlgorithm::kOldCompressionAlgo); +} + +TEST(RZip, ZipBufferSizesZLIB) +{ + testZipBufferSizes(ROOT::RCompressionSetting::EAlgorithm::kZLIB); +} + +TEST(RZip, ZipBufferSizesLZMA) +{ + testZipBufferSizes(ROOT::RCompressionSetting::EAlgorithm::kLZMA); +} + +TEST(RZip, ZipBufferSizesLZ4) +{ + testZipBufferSizes(ROOT::RCompressionSetting::EAlgorithm::kLZ4); +} + +TEST(RZip, ZipBufferSizesZSTD) +{ + testZipBufferSizes(ROOT::RCompressionSetting::EAlgorithm::kZSTD); +}