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