xref: /openbmc/bmcweb/test/http/zstd_decompressor_test.cpp (revision b25390694f7015224fbf02de247faec4c50429aa)
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 
TEST(Zstd,EmptyFile)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 
TEST(Zstd,ZerosFile)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 
TEST(Zstd,OnesFile)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