OptionsTest.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*
  2. * Copyright (c) 2016-present, Facebook, Inc.
  3. * All rights reserved.
  4. *
  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).
  8. */
  9. #include "Options.h"
  10. #include <array>
  11. #include <gtest/gtest.h>
  12. using namespace pzstd;
  13. namespace pzstd {
  14. bool operator==(const Options &lhs, const Options &rhs) {
  15. return lhs.numThreads == rhs.numThreads &&
  16. lhs.maxWindowLog == rhs.maxWindowLog &&
  17. lhs.compressionLevel == rhs.compressionLevel &&
  18. lhs.decompress == rhs.decompress && lhs.inputFiles == rhs.inputFiles &&
  19. lhs.outputFile == rhs.outputFile && lhs.overwrite == rhs.overwrite &&
  20. lhs.keepSource == rhs.keepSource && lhs.writeMode == rhs.writeMode &&
  21. lhs.checksum == rhs.checksum && lhs.verbosity == rhs.verbosity;
  22. }
  23. std::ostream &operator<<(std::ostream &out, const Options &opt) {
  24. out << "{";
  25. {
  26. out << "\n\t"
  27. << "numThreads: " << opt.numThreads;
  28. out << ",\n\t"
  29. << "maxWindowLog: " << opt.maxWindowLog;
  30. out << ",\n\t"
  31. << "compressionLevel: " << opt.compressionLevel;
  32. out << ",\n\t"
  33. << "decompress: " << opt.decompress;
  34. out << ",\n\t"
  35. << "inputFiles: {";
  36. {
  37. bool first = true;
  38. for (const auto &file : opt.inputFiles) {
  39. if (!first) {
  40. out << ",";
  41. }
  42. first = false;
  43. out << "\n\t\t" << file;
  44. }
  45. }
  46. out << "\n\t}";
  47. out << ",\n\t"
  48. << "outputFile: " << opt.outputFile;
  49. out << ",\n\t"
  50. << "overwrite: " << opt.overwrite;
  51. out << ",\n\t"
  52. << "keepSource: " << opt.keepSource;
  53. out << ",\n\t"
  54. << "writeMode: " << static_cast<int>(opt.writeMode);
  55. out << ",\n\t"
  56. << "checksum: " << opt.checksum;
  57. out << ",\n\t"
  58. << "verbosity: " << opt.verbosity;
  59. }
  60. out << "\n}";
  61. return out;
  62. }
  63. }
  64. namespace {
  65. #ifdef _WIN32
  66. const char nullOutput[] = "nul";
  67. #else
  68. const char nullOutput[] = "/dev/null";
  69. #endif
  70. constexpr auto autoMode = Options::WriteMode::Auto;
  71. } // anonymous namespace
  72. #define EXPECT_SUCCESS(...) EXPECT_EQ(Options::Status::Success, __VA_ARGS__)
  73. #define EXPECT_FAILURE(...) EXPECT_EQ(Options::Status::Failure, __VA_ARGS__)
  74. #define EXPECT_MESSAGE(...) EXPECT_EQ(Options::Status::Message, __VA_ARGS__)
  75. template <typename... Args>
  76. std::array<const char *, sizeof...(Args) + 1> makeArray(Args... args) {
  77. return {{nullptr, args...}};
  78. }
  79. TEST(Options, ValidInputs) {
  80. {
  81. Options options;
  82. auto args = makeArray("--processes", "5", "-o", "x", "y", "-f");
  83. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  84. Options expected = {5, 23, 3, false, {"y"}, "x",
  85. true, true, autoMode, true, 2};
  86. EXPECT_EQ(expected, options);
  87. }
  88. {
  89. Options options;
  90. auto args = makeArray("-p", "1", "input", "-19");
  91. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  92. Options expected = {1, 23, 19, false, {"input"}, "",
  93. false, true, autoMode, true, 2};
  94. EXPECT_EQ(expected, options);
  95. }
  96. {
  97. Options options;
  98. auto args =
  99. makeArray("--ultra", "-22", "-p", "1", "-o", "x", "-d", "x.zst", "-f");
  100. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  101. Options expected = {1, 0, 22, true, {"x.zst"}, "x",
  102. true, true, autoMode, true, 2};
  103. EXPECT_EQ(expected, options);
  104. }
  105. {
  106. Options options;
  107. auto args = makeArray("--processes", "100", "hello.zst", "--decompress",
  108. "--force");
  109. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  110. Options expected = {100, 23, 3, true, {"hello.zst"}, "", true,
  111. true, autoMode, true, 2};
  112. EXPECT_EQ(expected, options);
  113. }
  114. {
  115. Options options;
  116. auto args = makeArray("x", "-dp", "1", "-c");
  117. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  118. Options expected = {1, 23, 3, true, {"x"}, "-",
  119. false, true, autoMode, true, 2};
  120. EXPECT_EQ(expected, options);
  121. }
  122. {
  123. Options options;
  124. auto args = makeArray("x", "-dp", "1", "--stdout");
  125. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  126. Options expected = {1, 23, 3, true, {"x"}, "-",
  127. false, true, autoMode, true, 2};
  128. EXPECT_EQ(expected, options);
  129. }
  130. {
  131. Options options;
  132. auto args = makeArray("-p", "1", "x", "-5", "-fo", "-", "--ultra", "-d");
  133. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  134. Options expected = {1, 0, 5, true, {"x"}, "-",
  135. true, true, autoMode, true, 2};
  136. EXPECT_EQ(expected, options);
  137. }
  138. {
  139. Options options;
  140. auto args = makeArray("silesia.tar", "-o", "silesia.tar.pzstd", "-p", "2");
  141. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  142. Options expected = {2,
  143. 23,
  144. 3,
  145. false,
  146. {"silesia.tar"},
  147. "silesia.tar.pzstd",
  148. false,
  149. true,
  150. autoMode,
  151. true,
  152. 2};
  153. EXPECT_EQ(expected, options);
  154. }
  155. {
  156. Options options;
  157. auto args = makeArray("x", "-p", "1");
  158. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  159. }
  160. {
  161. Options options;
  162. auto args = makeArray("x", "-p", "1");
  163. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  164. }
  165. }
  166. TEST(Options, GetOutputFile) {
  167. {
  168. Options options;
  169. auto args = makeArray("x");
  170. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  171. EXPECT_EQ("x.zst", options.getOutputFile(options.inputFiles[0]));
  172. }
  173. {
  174. Options options;
  175. auto args = makeArray("x", "y", "-o", nullOutput);
  176. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  177. EXPECT_EQ(nullOutput, options.getOutputFile(options.inputFiles[0]));
  178. }
  179. {
  180. Options options;
  181. auto args = makeArray("x.zst", "-do", nullOutput);
  182. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  183. EXPECT_EQ(nullOutput, options.getOutputFile(options.inputFiles[0]));
  184. }
  185. {
  186. Options options;
  187. auto args = makeArray("x.zst", "-d");
  188. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  189. EXPECT_EQ("x", options.getOutputFile(options.inputFiles[0]));
  190. }
  191. {
  192. Options options;
  193. auto args = makeArray("xzst", "-d");
  194. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  195. EXPECT_EQ("", options.getOutputFile(options.inputFiles[0]));
  196. }
  197. {
  198. Options options;
  199. auto args = makeArray("xzst", "-doxx");
  200. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  201. EXPECT_EQ("xx", options.getOutputFile(options.inputFiles[0]));
  202. }
  203. }
  204. TEST(Options, MultipleFiles) {
  205. {
  206. Options options;
  207. auto args = makeArray("x", "y", "z");
  208. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  209. Options expected;
  210. expected.inputFiles = {"x", "y", "z"};
  211. expected.verbosity = 1;
  212. EXPECT_EQ(expected, options);
  213. }
  214. {
  215. Options options;
  216. auto args = makeArray("x", "y", "z", "-o", nullOutput);
  217. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  218. Options expected;
  219. expected.inputFiles = {"x", "y", "z"};
  220. expected.outputFile = nullOutput;
  221. expected.verbosity = 1;
  222. EXPECT_EQ(expected, options);
  223. }
  224. {
  225. Options options;
  226. auto args = makeArray("x", "y", "-o-");
  227. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  228. }
  229. {
  230. Options options;
  231. auto args = makeArray("x", "y", "-o", "file");
  232. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  233. }
  234. {
  235. Options options;
  236. auto args = makeArray("-qqvd12qp4", "-f", "x", "--", "--rm", "-c");
  237. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  238. Options expected = {4, 23, 12, true, {"x", "--rm", "-c"},
  239. "", true, true, autoMode, true,
  240. 0};
  241. EXPECT_EQ(expected, options);
  242. }
  243. }
  244. TEST(Options, NumThreads) {
  245. {
  246. Options options;
  247. auto args = makeArray("x", "-dfo", "-");
  248. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  249. }
  250. {
  251. Options options;
  252. auto args = makeArray("x", "-p", "0", "-fo", "-");
  253. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  254. }
  255. {
  256. Options options;
  257. auto args = makeArray("-f", "-p", "-o", "-");
  258. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  259. }
  260. }
  261. TEST(Options, BadCompressionLevel) {
  262. {
  263. Options options;
  264. auto args = makeArray("x", "-20");
  265. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  266. }
  267. {
  268. Options options;
  269. auto args = makeArray("x", "--ultra", "-23");
  270. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  271. }
  272. {
  273. Options options;
  274. auto args = makeArray("x", "--1"); // negative 1?
  275. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  276. }
  277. }
  278. TEST(Options, InvalidOption) {
  279. {
  280. Options options;
  281. auto args = makeArray("x", "-x");
  282. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  283. }
  284. }
  285. TEST(Options, BadOutputFile) {
  286. {
  287. Options options;
  288. auto args = makeArray("notzst", "-d", "-p", "1");
  289. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  290. EXPECT_EQ("", options.getOutputFile(options.inputFiles.front()));
  291. }
  292. }
  293. TEST(Options, BadOptionsWithArguments) {
  294. {
  295. Options options;
  296. auto args = makeArray("x", "-pf");
  297. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  298. }
  299. {
  300. Options options;
  301. auto args = makeArray("x", "-p", "10f");
  302. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  303. }
  304. {
  305. Options options;
  306. auto args = makeArray("x", "-p");
  307. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  308. }
  309. {
  310. Options options;
  311. auto args = makeArray("x", "-o");
  312. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  313. }
  314. {
  315. Options options;
  316. auto args = makeArray("x", "-o");
  317. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  318. }
  319. }
  320. TEST(Options, KeepSource) {
  321. {
  322. Options options;
  323. auto args = makeArray("x", "--rm", "-k");
  324. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  325. EXPECT_EQ(true, options.keepSource);
  326. }
  327. {
  328. Options options;
  329. auto args = makeArray("x", "--rm", "--keep");
  330. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  331. EXPECT_EQ(true, options.keepSource);
  332. }
  333. {
  334. Options options;
  335. auto args = makeArray("x");
  336. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  337. EXPECT_EQ(true, options.keepSource);
  338. }
  339. {
  340. Options options;
  341. auto args = makeArray("x", "--rm");
  342. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  343. EXPECT_EQ(false, options.keepSource);
  344. }
  345. }
  346. TEST(Options, Verbosity) {
  347. {
  348. Options options;
  349. auto args = makeArray("x");
  350. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  351. EXPECT_EQ(2, options.verbosity);
  352. }
  353. {
  354. Options options;
  355. auto args = makeArray("--quiet", "-qq", "x");
  356. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  357. EXPECT_EQ(-1, options.verbosity);
  358. }
  359. {
  360. Options options;
  361. auto args = makeArray("x", "y");
  362. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  363. EXPECT_EQ(1, options.verbosity);
  364. }
  365. {
  366. Options options;
  367. auto args = makeArray("--", "x", "y");
  368. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  369. EXPECT_EQ(1, options.verbosity);
  370. }
  371. {
  372. Options options;
  373. auto args = makeArray("-qv", "x", "y");
  374. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  375. EXPECT_EQ(1, options.verbosity);
  376. }
  377. {
  378. Options options;
  379. auto args = makeArray("-v", "x", "y");
  380. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  381. EXPECT_EQ(3, options.verbosity);
  382. }
  383. {
  384. Options options;
  385. auto args = makeArray("-v", "x");
  386. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  387. EXPECT_EQ(3, options.verbosity);
  388. }
  389. }
  390. TEST(Options, TestMode) {
  391. {
  392. Options options;
  393. auto args = makeArray("x", "-t");
  394. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  395. EXPECT_EQ(true, options.keepSource);
  396. EXPECT_EQ(true, options.decompress);
  397. EXPECT_EQ(nullOutput, options.outputFile);
  398. }
  399. {
  400. Options options;
  401. auto args = makeArray("x", "--test", "--rm", "-ohello");
  402. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  403. EXPECT_EQ(true, options.keepSource);
  404. EXPECT_EQ(true, options.decompress);
  405. EXPECT_EQ(nullOutput, options.outputFile);
  406. }
  407. }
  408. TEST(Options, Checksum) {
  409. {
  410. Options options;
  411. auto args = makeArray("x.zst", "--no-check", "-Cd");
  412. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  413. EXPECT_EQ(true, options.checksum);
  414. }
  415. {
  416. Options options;
  417. auto args = makeArray("x");
  418. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  419. EXPECT_EQ(true, options.checksum);
  420. }
  421. {
  422. Options options;
  423. auto args = makeArray("x", "--no-check", "--check");
  424. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  425. EXPECT_EQ(true, options.checksum);
  426. }
  427. {
  428. Options options;
  429. auto args = makeArray("x", "--no-check");
  430. EXPECT_SUCCESS(options.parse(args.size(), args.data()));
  431. EXPECT_EQ(false, options.checksum);
  432. }
  433. }
  434. TEST(Options, InputFiles) {
  435. {
  436. Options options;
  437. auto args = makeArray("-cd");
  438. options.parse(args.size(), args.data());
  439. EXPECT_EQ(1, options.inputFiles.size());
  440. EXPECT_EQ("-", options.inputFiles[0]);
  441. EXPECT_EQ("-", options.outputFile);
  442. }
  443. {
  444. Options options;
  445. auto args = makeArray();
  446. options.parse(args.size(), args.data());
  447. EXPECT_EQ(1, options.inputFiles.size());
  448. EXPECT_EQ("-", options.inputFiles[0]);
  449. EXPECT_EQ("-", options.outputFile);
  450. }
  451. {
  452. Options options;
  453. auto args = makeArray("-d");
  454. options.parse(args.size(), args.data());
  455. EXPECT_EQ(1, options.inputFiles.size());
  456. EXPECT_EQ("-", options.inputFiles[0]);
  457. EXPECT_EQ("-", options.outputFile);
  458. }
  459. {
  460. Options options;
  461. auto args = makeArray("x", "-");
  462. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  463. }
  464. }
  465. TEST(Options, InvalidOptions) {
  466. {
  467. Options options;
  468. auto args = makeArray("-ibasdf");
  469. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  470. }
  471. {
  472. Options options;
  473. auto args = makeArray("- ");
  474. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  475. }
  476. {
  477. Options options;
  478. auto args = makeArray("-n15");
  479. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  480. }
  481. {
  482. Options options;
  483. auto args = makeArray("-0", "x");
  484. EXPECT_FAILURE(options.parse(args.size(), args.data()));
  485. }
  486. }
  487. TEST(Options, Extras) {
  488. {
  489. Options options;
  490. auto args = makeArray("-h");
  491. EXPECT_MESSAGE(options.parse(args.size(), args.data()));
  492. }
  493. {
  494. Options options;
  495. auto args = makeArray("-H");
  496. EXPECT_MESSAGE(options.parse(args.size(), args.data()));
  497. }
  498. {
  499. Options options;
  500. auto args = makeArray("-V");
  501. EXPECT_MESSAGE(options.parse(args.size(), args.data()));
  502. }
  503. {
  504. Options options;
  505. auto args = makeArray("--help");
  506. EXPECT_MESSAGE(options.parse(args.size(), args.data()));
  507. }
  508. {
  509. Options options;
  510. auto args = makeArray("--version");
  511. EXPECT_MESSAGE(options.parse(args.size(), args.data()));
  512. }
  513. }