1*01826a49SYabin Cui /*
2*01826a49SYabin Cui * Copyright (c) Meta Platforms, Inc. and affiliates.
3*01826a49SYabin Cui * All rights reserved.
4*01826a49SYabin Cui *
5*01826a49SYabin Cui * This source code is licensed under both the BSD-style license (found in the
6*01826a49SYabin Cui * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7*01826a49SYabin Cui * in the COPYING file in the root directory of this source tree).
8*01826a49SYabin Cui */
9*01826a49SYabin Cui #include "Pzstd.h"
10*01826a49SYabin Cui extern "C" {
11*01826a49SYabin Cui #include "datagen.h"
12*01826a49SYabin Cui }
13*01826a49SYabin Cui #include "test/RoundTrip.h"
14*01826a49SYabin Cui #include "utils/ScopeGuard.h"
15*01826a49SYabin Cui
16*01826a49SYabin Cui #include <cstddef>
17*01826a49SYabin Cui #include <cstdio>
18*01826a49SYabin Cui #include <gtest/gtest.h>
19*01826a49SYabin Cui #include <memory>
20*01826a49SYabin Cui #include <random>
21*01826a49SYabin Cui
22*01826a49SYabin Cui using namespace std;
23*01826a49SYabin Cui using namespace pzstd;
24*01826a49SYabin Cui
TEST(Pzstd,SmallSizes)25*01826a49SYabin Cui TEST(Pzstd, SmallSizes) {
26*01826a49SYabin Cui unsigned seed = std::random_device{}();
27*01826a49SYabin Cui std::fprintf(stderr, "Pzstd.SmallSizes seed: %u\n", seed);
28*01826a49SYabin Cui std::mt19937 gen(seed);
29*01826a49SYabin Cui
30*01826a49SYabin Cui for (unsigned len = 1; len < 256; ++len) {
31*01826a49SYabin Cui if (len % 16 == 0) {
32*01826a49SYabin Cui std::fprintf(stderr, "%u / 16\n", len / 16);
33*01826a49SYabin Cui }
34*01826a49SYabin Cui std::string inputFile = std::tmpnam(nullptr);
35*01826a49SYabin Cui auto guard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
36*01826a49SYabin Cui {
37*01826a49SYabin Cui static uint8_t buf[256];
38*01826a49SYabin Cui RDG_genBuffer(buf, len, 0.5, 0.0, gen());
39*01826a49SYabin Cui auto fd = std::fopen(inputFile.c_str(), "wb");
40*01826a49SYabin Cui auto written = std::fwrite(buf, 1, len, fd);
41*01826a49SYabin Cui std::fclose(fd);
42*01826a49SYabin Cui ASSERT_EQ(written, len);
43*01826a49SYabin Cui }
44*01826a49SYabin Cui for (unsigned numThreads = 1; numThreads <= 2; ++numThreads) {
45*01826a49SYabin Cui for (unsigned level = 1; level <= 4; level *= 4) {
46*01826a49SYabin Cui auto errorGuard = makeScopeGuard([&] {
47*01826a49SYabin Cui std::fprintf(stderr, "# threads: %u\n", numThreads);
48*01826a49SYabin Cui std::fprintf(stderr, "compression level: %u\n", level);
49*01826a49SYabin Cui });
50*01826a49SYabin Cui Options options;
51*01826a49SYabin Cui options.overwrite = true;
52*01826a49SYabin Cui options.inputFiles = {inputFile};
53*01826a49SYabin Cui options.numThreads = numThreads;
54*01826a49SYabin Cui options.compressionLevel = level;
55*01826a49SYabin Cui options.verbosity = 1;
56*01826a49SYabin Cui ASSERT_TRUE(roundTrip(options));
57*01826a49SYabin Cui errorGuard.dismiss();
58*01826a49SYabin Cui }
59*01826a49SYabin Cui }
60*01826a49SYabin Cui }
61*01826a49SYabin Cui }
62*01826a49SYabin Cui
TEST(Pzstd,LargeSizes)63*01826a49SYabin Cui TEST(Pzstd, LargeSizes) {
64*01826a49SYabin Cui unsigned seed = std::random_device{}();
65*01826a49SYabin Cui std::fprintf(stderr, "Pzstd.LargeSizes seed: %u\n", seed);
66*01826a49SYabin Cui std::mt19937 gen(seed);
67*01826a49SYabin Cui
68*01826a49SYabin Cui for (unsigned len = 1 << 20; len <= (1 << 24); len *= 2) {
69*01826a49SYabin Cui std::string inputFile = std::tmpnam(nullptr);
70*01826a49SYabin Cui auto guard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
71*01826a49SYabin Cui {
72*01826a49SYabin Cui std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
73*01826a49SYabin Cui RDG_genBuffer(buf.get(), len, 0.5, 0.0, gen());
74*01826a49SYabin Cui auto fd = std::fopen(inputFile.c_str(), "wb");
75*01826a49SYabin Cui auto written = std::fwrite(buf.get(), 1, len, fd);
76*01826a49SYabin Cui std::fclose(fd);
77*01826a49SYabin Cui ASSERT_EQ(written, len);
78*01826a49SYabin Cui }
79*01826a49SYabin Cui for (unsigned numThreads = 1; numThreads <= 16; numThreads *= 4) {
80*01826a49SYabin Cui for (unsigned level = 1; level <= 4; level *= 4) {
81*01826a49SYabin Cui auto errorGuard = makeScopeGuard([&] {
82*01826a49SYabin Cui std::fprintf(stderr, "# threads: %u\n", numThreads);
83*01826a49SYabin Cui std::fprintf(stderr, "compression level: %u\n", level);
84*01826a49SYabin Cui });
85*01826a49SYabin Cui Options options;
86*01826a49SYabin Cui options.overwrite = true;
87*01826a49SYabin Cui options.inputFiles = {inputFile};
88*01826a49SYabin Cui options.numThreads = std::min(numThreads, options.numThreads);
89*01826a49SYabin Cui options.compressionLevel = level;
90*01826a49SYabin Cui options.verbosity = 1;
91*01826a49SYabin Cui ASSERT_TRUE(roundTrip(options));
92*01826a49SYabin Cui errorGuard.dismiss();
93*01826a49SYabin Cui }
94*01826a49SYabin Cui }
95*01826a49SYabin Cui }
96*01826a49SYabin Cui }
97*01826a49SYabin Cui
TEST(Pzstd,DISABLED_ExtremelyLargeSize)98*01826a49SYabin Cui TEST(Pzstd, DISABLED_ExtremelyLargeSize) {
99*01826a49SYabin Cui unsigned seed = std::random_device{}();
100*01826a49SYabin Cui std::fprintf(stderr, "Pzstd.ExtremelyLargeSize seed: %u\n", seed);
101*01826a49SYabin Cui std::mt19937 gen(seed);
102*01826a49SYabin Cui
103*01826a49SYabin Cui std::string inputFile = std::tmpnam(nullptr);
104*01826a49SYabin Cui auto guard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
105*01826a49SYabin Cui
106*01826a49SYabin Cui {
107*01826a49SYabin Cui // Write 4GB + 64 MB
108*01826a49SYabin Cui constexpr size_t kLength = 1 << 26;
109*01826a49SYabin Cui std::unique_ptr<uint8_t[]> buf(new uint8_t[kLength]);
110*01826a49SYabin Cui auto fd = std::fopen(inputFile.c_str(), "wb");
111*01826a49SYabin Cui auto closeGuard = makeScopeGuard([&] { std::fclose(fd); });
112*01826a49SYabin Cui for (size_t i = 0; i < (1 << 6) + 1; ++i) {
113*01826a49SYabin Cui RDG_genBuffer(buf.get(), kLength, 0.5, 0.0, gen());
114*01826a49SYabin Cui auto written = std::fwrite(buf.get(), 1, kLength, fd);
115*01826a49SYabin Cui if (written != kLength) {
116*01826a49SYabin Cui std::fprintf(stderr, "Failed to write file, skipping test\n");
117*01826a49SYabin Cui return;
118*01826a49SYabin Cui }
119*01826a49SYabin Cui }
120*01826a49SYabin Cui }
121*01826a49SYabin Cui
122*01826a49SYabin Cui Options options;
123*01826a49SYabin Cui options.overwrite = true;
124*01826a49SYabin Cui options.inputFiles = {inputFile};
125*01826a49SYabin Cui options.compressionLevel = 1;
126*01826a49SYabin Cui if (options.numThreads == 0) {
127*01826a49SYabin Cui options.numThreads = 1;
128*01826a49SYabin Cui }
129*01826a49SYabin Cui ASSERT_TRUE(roundTrip(options));
130*01826a49SYabin Cui }
131*01826a49SYabin Cui
TEST(Pzstd,ExtremelyCompressible)132*01826a49SYabin Cui TEST(Pzstd, ExtremelyCompressible) {
133*01826a49SYabin Cui std::string inputFile = std::tmpnam(nullptr);
134*01826a49SYabin Cui auto guard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
135*01826a49SYabin Cui {
136*01826a49SYabin Cui std::unique_ptr<uint8_t[]> buf(new uint8_t[10000]);
137*01826a49SYabin Cui std::memset(buf.get(), 'a', 10000);
138*01826a49SYabin Cui auto fd = std::fopen(inputFile.c_str(), "wb");
139*01826a49SYabin Cui auto written = std::fwrite(buf.get(), 1, 10000, fd);
140*01826a49SYabin Cui std::fclose(fd);
141*01826a49SYabin Cui ASSERT_EQ(written, 10000);
142*01826a49SYabin Cui }
143*01826a49SYabin Cui Options options;
144*01826a49SYabin Cui options.overwrite = true;
145*01826a49SYabin Cui options.inputFiles = {inputFile};
146*01826a49SYabin Cui options.numThreads = 1;
147*01826a49SYabin Cui options.compressionLevel = 1;
148*01826a49SYabin Cui ASSERT_TRUE(roundTrip(options));
149*01826a49SYabin Cui }
150