#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_STORAGE_SOURCE 1 #if defined(NUCLEX_STORAGE_HAVE_CSC) #include "../../../Source/Compression/Csc/CscCompressor.h" #include "../../../Source/Compression/Csc/CscDecompressor.h" #include "../CompressorTest.h" #include namespace { #if 0 class DummyOutputStream : public Nuclex::Storage::Binary::OutputStream { public: bool CanAcceptMoreData() const override { return true; } public: void WriteUpTo( const std::uint8_t *buffer, std::size_t &byteCount, std::size_t minimumByteCount = 1 ) override { } }; #endif } // anonymous namespace namespace Nuclex { namespace Storage { namespace Compression { namespace Csc { // ------------------------------------------------------------------------------------------- // TEST(CscCompressorTest, CanBeCreatedAndDestroyed) { EXPECT_NO_THROW( CscCompressor compressor; (void)compressor; ); } // ------------------------------------------------------------------------------------------- // TEST(CscCompressorTest, MemoryChunkCanBeCompressed) { // Message that will be compressed char message[] = u8"Hello World, this text will be compressed by CSC"; const std::uint8_t *input = reinterpret_cast(message); // Set up a buffer to hold the compressed data. We assume compression will not // make result in generated output that is more than twice the size of the input data :) std::vector outputBuffer; outputBuffer.resize(sizeof(message) * 2); // Now compress the data with the deflate compressor { CscCompressor compressor; std::size_t inputByteCount = sizeof(message); std::size_t outputByteCount = outputBuffer.size(); StopReason stopReason = compressor.Process( input, inputByteCount, &outputBuffer[0], outputByteCount ); EXPECT_EQ(stopReason, StopReason::InputBufferExhausted); std::size_t secondOutputByteCount = outputBuffer.size() - outputByteCount; stopReason = compressor.Finish(&outputBuffer[outputByteCount], secondOutputByteCount); EXPECT_EQ(stopReason, StopReason::Finished); outputBuffer.resize(outputByteCount + secondOutputByteCount); } // Output compressed bytes as hex codes for debugging //for(std::size_t index = 0; index < outputBuffer.size(); ++index) { // std::cout << std::hex << static_cast(outputBuffer[index]) << std::endl; //} } // ------------------------------------------------------------------------------------------- // TEST(CscCompressorTest, MemoryChunkSurvivesCompressionRoundTrip) { // Message that will be compressed char message[] = u8"This text will be compressed and then decompressed again by CSC"; const std::uint8_t *input = reinterpret_cast(message); // Set up a buffer to hold the compressed data. We assume compression will not // make result in generated output that is more than twice the size of the input data :) std::vector outputBuffer; outputBuffer.resize(sizeof(message) * 2); // Compress the data with the deflate compressor { CscCompressor compressor; std::size_t inputByteCount = sizeof(message); std::size_t outputByteCount = outputBuffer.size(); StopReason stopReason = compressor.Process( input, inputByteCount, &outputBuffer[0], outputByteCount ); EXPECT_EQ(stopReason, StopReason::InputBufferExhausted); std::size_t secondOutputByteCount = outputBuffer.size() - outputByteCount; stopReason = compressor.Finish(&outputBuffer[outputByteCount], secondOutputByteCount); EXPECT_EQ(stopReason, StopReason::Finished); outputBuffer.resize(outputByteCount + secondOutputByteCount); } // Now the output becomes the round trip's input std::vector inputBuffer; inputBuffer.swap(outputBuffer); // Set up a buffer to hold the decompressed data. Same logic as before. outputBuffer.resize(sizeof(message) * 2); // Compress the data with the deflate compressor { CscDecompressor decompressor; std::size_t inputByteCount = inputBuffer.size(); std::size_t outputByteCount = outputBuffer.size(); StopReason stopReason = decompressor.Process( &inputBuffer[0], inputByteCount, &outputBuffer[0], outputByteCount ); EXPECT_EQ(stopReason, StopReason::InputBufferExhausted); std::size_t secondOutputByteCount = outputBuffer.size() - outputByteCount; stopReason = decompressor.Finish(&outputBuffer[outputByteCount], secondOutputByteCount); EXPECT_EQ(stopReason, StopReason::Finished); outputBuffer.resize(outputByteCount + secondOutputByteCount); } ASSERT_EQ(outputBuffer.size(), sizeof(message)); for(std::size_t index = 0; index < sizeof(message); ++index) { EXPECT_EQ(static_cast(outputBuffer[index]), message[index]); } } // ------------------------------------------------------------------------------------------- // TEST(CscCompressorTest, LongStreamSurvivesCompressionRoundTrip) { const std::size_t totalByteCount = 262144 - 123; // 256 KiB minus a bit to confuse chunking std::vector compressedData; { CscCompressor compressor(4); checkStreamCompression(compressor, compressedData, totalByteCount); } { CscDecompressor decompressor; checkStreamDecompression(decompressor, compressedData, totalByteCount); } } // ------------------------------------------------------------------------------------------- // }}}} // namespace Nuclex::Storage::Compression::Csc #endif // defined(NUCLEX_STORAGE_HAVE_CSC)