1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 #ifdef HAVE_ZSTD 4 #include "zstd_decompressor.hpp" 5 6 #include <boost/asio/buffer.hpp> 7 8 #include <algorithm> 9 #include <array> 10 #include <cstddef> 11 #include <optional> 12 #include <span> 13 14 #include <gmock/gmock.h> 15 #include <gtest/gtest.h> 16 17 using ::testing::Each; 18 using ::testing::Eq; 19 20 namespace zstd 21 { 22 namespace 23 { 24 25 TEST(Zstd, EmptyFile) 26 { 27 std::array<unsigned char, 13> empty{0x28, 0xb5, 0x2f, 0xfd, 0x24, 28 0x00, 0x01, 0x00, 0x00, 0x99, 29 0xe9, 0xd8, 0x51}; 30 31 ZstdDecompressor comp; 32 std::optional<boost::asio::const_buffer> out = 33 comp.decompress(boost::asio::buffer(empty)); 34 ASSERT_TRUE(out); 35 if (!out) 36 { 37 return; 38 } 39 EXPECT_TRUE(out->size() == 0); 40 } 41 42 TEST(Zstd, ZerosFile) 43 { 44 // A 1MB file of all zeros created using 45 // dd if=/dev/zero of=zeros-file bs=1024 count=1024 46 // zstd -c zeros-file | xxd -i 47 std::array<unsigned char, 54> zeros = { 48 0x28, 0xb5, 0x2f, 0xfd, 0xa4, 0x00, 0x00, 0x10, 0x00, 0x54, 0x00, 49 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0xfb, 0xff, 0x39, 0xc0, 0x02, 50 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x10, 51 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 52 0x10, 0x00, 0x03, 0x00, 0x10, 0x00, 0xf1, 0x3e, 0x16, 0xe1}; 53 54 for (size_t chunkSize : 55 std::to_array<size_t>({1U, 2U, 4U, 8U, 16U, zeros.size()})) 56 { 57 ZstdDecompressor comp; 58 std::span<unsigned char> data = std::span(zeros); 59 size_t read = 0; 60 while (!data.empty()) 61 { 62 std::span<unsigned char> chunk = 63 data.subspan(0, std::min(chunkSize, data.size())); 64 std::optional<boost::asio::const_buffer> out = comp.decompress( 65 boost::asio::buffer(chunk.data(), chunk.size())); 66 ASSERT_TRUE(out); 67 if (out) 68 { 69 EXPECT_THAT( 70 std::span(static_cast<const unsigned char*>(out->data()), 71 out->size()), 72 Each(Eq(0))); 73 read += out->size(); 74 } 75 data = data.subspan(chunk.size()); 76 } 77 78 EXPECT_EQ(read, 1024 * 1024); 79 } 80 } 81 82 TEST(Zstd, OnesFile) 83 { 84 // A 1MB file of all ones created using 85 // dd if=/dev/zero bs=1024 count=1024 | tr "\000" "\377" > ones.txt 86 // zstd -c ones-file | xxd -i 87 std::array<unsigned char, 54> ones = { 88 0x28, 0xb5, 0x2f, 0xfd, 0xa4, 0x00, 0x00, 0x10, 0x00, 0x54, 0x00, 89 0x00, 0x10, 0xff, 0xff, 0x01, 0x00, 0xfb, 0xff, 0x39, 0xc0, 0x02, 90 0x02, 0x00, 0x10, 0xff, 0x02, 0x00, 0x10, 0xff, 0x02, 0x00, 0x10, 91 0xff, 0x02, 0x00, 0x10, 0xff, 0x02, 0x00, 0x10, 0xff, 0x02, 0x00, 92 0x10, 0xff, 0x03, 0x00, 0x10, 0xff, 0xb4, 0xc8, 0xba, 0x13}; 93 94 for (size_t chunkSize : 95 std::to_array<size_t>({1U, 2U, 4U, 8U, 16U, ones.size()})) 96 { 97 ZstdDecompressor comp; 98 std::span<unsigned char> data = std::span(ones); 99 size_t read = 0; 100 while (!data.empty()) 101 { 102 std::span<unsigned char> chunk = 103 data.subspan(0, std::min(chunkSize, data.size())); 104 std::optional<boost::asio::const_buffer> out = comp.decompress( 105 boost::asio::buffer(chunk.data(), chunk.size())); 106 ASSERT_TRUE(out); 107 if (out) 108 { 109 EXPECT_THAT( 110 std::span(static_cast<const unsigned char*>(out->data()), 111 out->size()), 112 Each(Eq(0xFF))); 113 read += out->size(); 114 } 115 data = data.subspan(chunk.size()); 116 } 117 118 EXPECT_EQ(read, 1024 * 1024); 119 } 120 } 121 122 } // namespace 123 } // namespace zstd 124 #endif 125