2 * Copyright (c) Meta Platforms, Inc. and affiliates.
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
12 #include <gtest/gtest.h>
14 using namespace pzstd;
17 bool operator==(const Options &lhs, const Options &rhs) {
18 return lhs.numThreads == rhs.numThreads &&
19 lhs.maxWindowLog == rhs.maxWindowLog &&
20 lhs.compressionLevel == rhs.compressionLevel &&
21 lhs.decompress == rhs.decompress && lhs.inputFiles == rhs.inputFiles &&
22 lhs.outputFile == rhs.outputFile && lhs.overwrite == rhs.overwrite &&
23 lhs.keepSource == rhs.keepSource && lhs.writeMode == rhs.writeMode &&
24 lhs.checksum == rhs.checksum && lhs.verbosity == rhs.verbosity;
27 std::ostream &operator<<(std::ostream &out, const Options &opt) {
31 << "numThreads: " << opt.numThreads;
33 << "maxWindowLog: " << opt.maxWindowLog;
35 << "compressionLevel: " << opt.compressionLevel;
37 << "decompress: " << opt.decompress;
42 for (const auto &file : opt.inputFiles) {
47 out << "\n\t\t" << file;
52 << "outputFile: " << opt.outputFile;
54 << "overwrite: " << opt.overwrite;
56 << "keepSource: " << opt.keepSource;
58 << "writeMode: " << static_cast<int>(opt.writeMode);
60 << "checksum: " << opt.checksum;
62 << "verbosity: " << opt.verbosity;
71 const char nullOutput[] = "nul";
73 const char nullOutput[] = "/dev/null";
76 constexpr auto autoMode = Options::WriteMode::Auto;
77 } // anonymous namespace
79 #define EXPECT_SUCCESS(...) EXPECT_EQ(Options::Status::Success, __VA_ARGS__)
80 #define EXPECT_FAILURE(...) EXPECT_EQ(Options::Status::Failure, __VA_ARGS__)
81 #define EXPECT_MESSAGE(...) EXPECT_EQ(Options::Status::Message, __VA_ARGS__)
83 template <typename... Args>
84 std::array<const char *, sizeof...(Args) + 1> makeArray(Args... args) {
85 return {{nullptr, args...}};
88 TEST(Options, ValidInputs) {
91 auto args = makeArray("--processes", "5", "-o", "x", "y", "-f");
92 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
93 Options expected = {5, 23, 3, false, {"y"}, "x",
94 true, true, autoMode, true, 2};
95 EXPECT_EQ(expected, options);
99 auto args = makeArray("-p", "1", "input", "-19");
100 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
101 Options expected = {1, 23, 19, false, {"input"}, "",
102 false, true, autoMode, true, 2};
103 EXPECT_EQ(expected, options);
108 makeArray("--ultra", "-22", "-p", "1", "-o", "x", "-d", "x.zst", "-f");
109 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
110 Options expected = {1, 0, 22, true, {"x.zst"}, "x",
111 true, true, autoMode, true, 2};
112 EXPECT_EQ(expected, options);
116 auto args = makeArray("--processes", "100", "hello.zst", "--decompress",
118 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
119 Options expected = {100, 23, 3, true, {"hello.zst"}, "", true,
120 true, autoMode, true, 2};
121 EXPECT_EQ(expected, options);
125 auto args = makeArray("x", "-dp", "1", "-c");
126 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
127 Options expected = {1, 23, 3, true, {"x"}, "-",
128 false, true, autoMode, true, 2};
129 EXPECT_EQ(expected, options);
133 auto args = makeArray("x", "-dp", "1", "--stdout");
134 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
135 Options expected = {1, 23, 3, true, {"x"}, "-",
136 false, true, autoMode, true, 2};
137 EXPECT_EQ(expected, options);
141 auto args = makeArray("-p", "1", "x", "-5", "-fo", "-", "--ultra", "-d");
142 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
143 Options expected = {1, 0, 5, true, {"x"}, "-",
144 true, true, autoMode, true, 2};
145 EXPECT_EQ(expected, options);
149 auto args = makeArray("silesia.tar", "-o", "silesia.tar.pzstd", "-p", "2");
150 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
151 Options expected = {2,
162 EXPECT_EQ(expected, options);
166 auto args = makeArray("x", "-p", "1");
167 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
171 auto args = makeArray("x", "-p", "1");
172 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
176 TEST(Options, GetOutputFile) {
179 auto args = makeArray("x");
180 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
181 EXPECT_EQ("x.zst", options.getOutputFile(options.inputFiles[0]));
185 auto args = makeArray("x", "y", "-o", nullOutput);
186 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
187 EXPECT_EQ(nullOutput, options.getOutputFile(options.inputFiles[0]));
191 auto args = makeArray("x.zst", "-do", nullOutput);
192 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
193 EXPECT_EQ(nullOutput, options.getOutputFile(options.inputFiles[0]));
197 auto args = makeArray("x.zst", "-d");
198 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
199 EXPECT_EQ("x", options.getOutputFile(options.inputFiles[0]));
203 auto args = makeArray("xzst", "-d");
204 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
205 EXPECT_EQ("", options.getOutputFile(options.inputFiles[0]));
209 auto args = makeArray("xzst", "-doxx");
210 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
211 EXPECT_EQ("xx", options.getOutputFile(options.inputFiles[0]));
215 TEST(Options, MultipleFiles) {
218 auto args = makeArray("x", "y", "z");
219 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
221 expected.inputFiles = {"x", "y", "z"};
222 expected.verbosity = 1;
223 EXPECT_EQ(expected, options);
227 auto args = makeArray("x", "y", "z", "-o", nullOutput);
228 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
230 expected.inputFiles = {"x", "y", "z"};
231 expected.outputFile = nullOutput;
232 expected.verbosity = 1;
233 EXPECT_EQ(expected, options);
237 auto args = makeArray("x", "y", "-o-");
238 EXPECT_FAILURE(options.parse(args.size(), args.data()));
242 auto args = makeArray("x", "y", "-o", "file");
243 EXPECT_FAILURE(options.parse(args.size(), args.data()));
247 auto args = makeArray("-qqvd12qp4", "-f", "x", "--", "--rm", "-c");
248 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
249 Options expected = {4, 23, 12, true, {"x", "--rm", "-c"},
250 "", true, true, autoMode, true,
252 EXPECT_EQ(expected, options);
256 TEST(Options, NumThreads) {
259 auto args = makeArray("x", "-dfo", "-");
260 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
264 auto args = makeArray("x", "-p", "0", "-fo", "-");
265 EXPECT_FAILURE(options.parse(args.size(), args.data()));
269 auto args = makeArray("-f", "-p", "-o", "-");
270 EXPECT_FAILURE(options.parse(args.size(), args.data()));
274 TEST(Options, BadCompressionLevel) {
277 auto args = makeArray("x", "-20");
278 EXPECT_FAILURE(options.parse(args.size(), args.data()));
282 auto args = makeArray("x", "--ultra", "-23");
283 EXPECT_FAILURE(options.parse(args.size(), args.data()));
287 auto args = makeArray("x", "--1"); // negative 1?
288 EXPECT_FAILURE(options.parse(args.size(), args.data()));
292 TEST(Options, InvalidOption) {
295 auto args = makeArray("x", "-x");
296 EXPECT_FAILURE(options.parse(args.size(), args.data()));
300 TEST(Options, BadOutputFile) {
303 auto args = makeArray("notzst", "-d", "-p", "1");
304 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
305 EXPECT_EQ("", options.getOutputFile(options.inputFiles.front()));
309 TEST(Options, BadOptionsWithArguments) {
312 auto args = makeArray("x", "-pf");
313 EXPECT_FAILURE(options.parse(args.size(), args.data()));
317 auto args = makeArray("x", "-p", "10f");
318 EXPECT_FAILURE(options.parse(args.size(), args.data()));
322 auto args = makeArray("x", "-p");
323 EXPECT_FAILURE(options.parse(args.size(), args.data()));
327 auto args = makeArray("x", "-o");
328 EXPECT_FAILURE(options.parse(args.size(), args.data()));
332 auto args = makeArray("x", "-o");
333 EXPECT_FAILURE(options.parse(args.size(), args.data()));
337 TEST(Options, KeepSource) {
340 auto args = makeArray("x", "--rm", "-k");
341 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
342 EXPECT_EQ(true, options.keepSource);
346 auto args = makeArray("x", "--rm", "--keep");
347 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
348 EXPECT_EQ(true, options.keepSource);
352 auto args = makeArray("x");
353 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
354 EXPECT_EQ(true, options.keepSource);
358 auto args = makeArray("x", "--rm");
359 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
360 EXPECT_EQ(false, options.keepSource);
364 TEST(Options, Verbosity) {
367 auto args = makeArray("x");
368 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
369 EXPECT_EQ(2, options.verbosity);
373 auto args = makeArray("--quiet", "-qq", "x");
374 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
375 EXPECT_EQ(-1, options.verbosity);
379 auto args = makeArray("x", "y");
380 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
381 EXPECT_EQ(1, options.verbosity);
385 auto args = makeArray("--", "x", "y");
386 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
387 EXPECT_EQ(1, options.verbosity);
391 auto args = makeArray("-qv", "x", "y");
392 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
393 EXPECT_EQ(1, options.verbosity);
397 auto args = makeArray("-v", "x", "y");
398 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
399 EXPECT_EQ(3, options.verbosity);
403 auto args = makeArray("-v", "x");
404 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
405 EXPECT_EQ(3, options.verbosity);
409 TEST(Options, TestMode) {
412 auto args = makeArray("x", "-t");
413 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
414 EXPECT_EQ(true, options.keepSource);
415 EXPECT_EQ(true, options.decompress);
416 EXPECT_EQ(nullOutput, options.outputFile);
420 auto args = makeArray("x", "--test", "--rm", "-ohello");
421 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
422 EXPECT_EQ(true, options.keepSource);
423 EXPECT_EQ(true, options.decompress);
424 EXPECT_EQ(nullOutput, options.outputFile);
428 TEST(Options, Checksum) {
431 auto args = makeArray("x.zst", "--no-check", "-Cd");
432 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
433 EXPECT_EQ(true, options.checksum);
437 auto args = makeArray("x");
438 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
439 EXPECT_EQ(true, options.checksum);
443 auto args = makeArray("x", "--no-check", "--check");
444 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
445 EXPECT_EQ(true, options.checksum);
449 auto args = makeArray("x", "--no-check");
450 EXPECT_SUCCESS(options.parse(args.size(), args.data()));
451 EXPECT_EQ(false, options.checksum);
455 TEST(Options, InputFiles) {
458 auto args = makeArray("-cd");
459 options.parse(args.size(), args.data());
460 EXPECT_EQ(1, options.inputFiles.size());
461 EXPECT_EQ("-", options.inputFiles[0]);
462 EXPECT_EQ("-", options.outputFile);
466 auto args = makeArray();
467 options.parse(args.size(), args.data());
468 EXPECT_EQ(1, options.inputFiles.size());
469 EXPECT_EQ("-", options.inputFiles[0]);
470 EXPECT_EQ("-", options.outputFile);
474 auto args = makeArray("-d");
475 options.parse(args.size(), args.data());
476 EXPECT_EQ(1, options.inputFiles.size());
477 EXPECT_EQ("-", options.inputFiles[0]);
478 EXPECT_EQ("-", options.outputFile);
482 auto args = makeArray("x", "-");
483 EXPECT_FAILURE(options.parse(args.size(), args.data()));
487 TEST(Options, InvalidOptions) {
490 auto args = makeArray("-ibasdf");
491 EXPECT_FAILURE(options.parse(args.size(), args.data()));
495 auto args = makeArray("- ");
496 EXPECT_FAILURE(options.parse(args.size(), args.data()));
500 auto args = makeArray("-n15");
501 EXPECT_FAILURE(options.parse(args.size(), args.data()));
505 auto args = makeArray("-0", "x");
506 EXPECT_FAILURE(options.parse(args.size(), args.data()));
510 TEST(Options, Extras) {
513 auto args = makeArray("-h");
514 EXPECT_MESSAGE(options.parse(args.size(), args.data()));
518 auto args = makeArray("-H");
519 EXPECT_MESSAGE(options.parse(args.size(), args.data()));
523 auto args = makeArray("-V");
524 EXPECT_MESSAGE(options.parse(args.size(), args.data()));
528 auto args = makeArray("--help");
529 EXPECT_MESSAGE(options.parse(args.size(), args.data()));
533 auto args = makeArray("--version");
534 EXPECT_MESSAGE(options.parse(args.size(), args.data()));