aboutsummaryrefslogtreecommitdiff
path: root/tests/unit/libutil/compression.cc
blob: f629fb0a319f2b54124a566b23ec0951e2927750 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "compression.hh"
#include <gtest/gtest.h>

namespace nix {

/* ----------------------------------------------------------------------------
 * compress / decompress
 * --------------------------------------------------------------------------*/

TEST(compress, compressWithUnknownMethod)
{
    ASSERT_THROW(compress("invalid-method", "something-to-compress"), UnknownCompressionMethod);
}

TEST(compress, noneMethodDoesNothingToTheInput)
{
    auto o = compress("none", "this-is-a-test");

    ASSERT_EQ(o, "this-is-a-test");
}

TEST(decompress, decompressEmptyString)
{
    // Empty-method decompression used e.g. by S3 store
    // (Content-Encoding == "").
    auto o = decompress("", "this-is-a-test");

    ASSERT_EQ(o, "this-is-a-test");
}

/* ----------------------------------------------------------------------------
 * compression sinks
 * --------------------------------------------------------------------------*/

TEST(makeCompressionSink, noneSinkDoesNothingToInput)
{
    auto method = "none";
    StringSink strSink;
    auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf";
    auto sink = makeCompressionSink(method, strSink);
    (*sink)(inputString);
    sink->finish();

    ASSERT_STREQ(strSink.s.c_str(), inputString);
}

/** Tests applied to all compression types */
class PerTypeCompressionTest : public testing::TestWithParam<const char *>
{};

/** Tests applied to non-passthrough compression types */
class PerTypeNonNullCompressionTest : public testing::TestWithParam<const char *>
{};

constexpr const char * COMPRESSION_TYPES_NONNULL[] = {
    // libarchive
    "bzip2",
    "compress",
    "gzip",
    "lzip",
    "lzma",
    "xz",
    "zstd",
    // Uses external program via libarchive so cannot be used :(
    /*
    "grzip",
    "lrzip",
    "lzop",
    "lz4",
    */
    // custom
    "br",
};

INSTANTIATE_TEST_SUITE_P(
    compressionNonNull, PerTypeNonNullCompressionTest, testing::ValuesIn(COMPRESSION_TYPES_NONNULL)
);
INSTANTIATE_TEST_SUITE_P(
    compressionNonNull, PerTypeCompressionTest, testing::ValuesIn(COMPRESSION_TYPES_NONNULL)
);

INSTANTIATE_TEST_SUITE_P(
    compressionNull, PerTypeCompressionTest, testing::Values("none")
);

/* ---------------------------------------
 * All compression types
 * --------------------------------------- */

TEST_P(PerTypeCompressionTest, roundTrips)
{
    auto method = GetParam();
    auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf";
    auto o = decompress(method, compress(method, str));

    ASSERT_EQ(o, str);
}

TEST_P(PerTypeCompressionTest, longerThanBuffer)
{
    // This is targeted originally at regression testing a brotli bug, but we might as well do it to
    // everything
    auto method = GetParam();
    auto str = std::string(65536, 'a');
    auto o = decompress(method, compress(method, str));

    // This is just to not print 64k of "a" for most failures
    ASSERT_EQ(o.length(), str.length());
    ASSERT_EQ(o, str);
}

TEST_P(PerTypeCompressionTest, sinkAndSource)
{
    auto method = GetParam();
    auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf";

    StringSink strSink;
    auto sink = makeCompressionSink(method, strSink);
    (*sink)(inputString);
    sink->finish();

    StringSource strSource{strSink.s};
    auto decompressionSource = makeDecompressionSource(method, strSource);

    ASSERT_STREQ(decompressionSource->drain().c_str(), inputString);
}

/* ---------------------------------------
 * Non null compression types
 * --------------------------------------- */

TEST_P(PerTypeNonNullCompressionTest, bogusInputDecompression)
{
    auto param = GetParam();

    auto bogus = "this data is bogus and should throw when decompressing";
    ASSERT_THROW(decompress(param, bogus), CompressionError);
}
}