CommandLineTest.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. //===- llvm/unittest/Support/CommandLineTest.cpp - CommandLine tests ------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/Support/CommandLine.h"
  10. #include "llvm/ADT/STLExtras.h"
  11. #include "llvm/ADT/SmallString.h"
  12. #include "llvm/Config/config.h"
  13. #include "llvm/Support/FileSystem.h"
  14. #include "llvm/Support/Path.h"
  15. #include "llvm/Support/Program.h"
  16. #include "llvm/Support/StringSaver.h"
  17. #include "gtest/gtest.h"
  18. #include <fstream>
  19. #include <stdlib.h>
  20. #include <string>
  21. using namespace llvm;
  22. namespace {
  23. class TempEnvVar {
  24. public:
  25. TempEnvVar(const char *name, const char *value)
  26. : name(name) {
  27. const char *old_value = getenv(name);
  28. EXPECT_EQ(nullptr, old_value) << old_value;
  29. #if HAVE_SETENV
  30. setenv(name, value, true);
  31. #else
  32. # define SKIP_ENVIRONMENT_TESTS
  33. #endif
  34. }
  35. ~TempEnvVar() {
  36. #if HAVE_SETENV
  37. // Assume setenv and unsetenv come together.
  38. unsetenv(name);
  39. #else
  40. (void)name; // Suppress -Wunused-private-field.
  41. #endif
  42. }
  43. private:
  44. const char *const name;
  45. };
  46. template <typename T>
  47. class StackOption : public cl::opt<T> {
  48. typedef cl::opt<T> Base;
  49. public:
  50. // One option...
  51. template<class M0t>
  52. explicit StackOption(const M0t &M0) : Base(M0) {}
  53. // Two options...
  54. template<class M0t, class M1t>
  55. StackOption(const M0t &M0, const M1t &M1) : Base(M0, M1) {}
  56. // Three options...
  57. template<class M0t, class M1t, class M2t>
  58. StackOption(const M0t &M0, const M1t &M1, const M2t &M2) : Base(M0, M1, M2) {}
  59. // Four options...
  60. template<class M0t, class M1t, class M2t, class M3t>
  61. StackOption(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
  62. : Base(M0, M1, M2, M3) {}
  63. ~StackOption() override { this->removeArgument(); }
  64. template <class DT> StackOption<T> &operator=(const DT &V) {
  65. this->setValue(V);
  66. return *this;
  67. }
  68. };
  69. class StackSubCommand : public cl::SubCommand {
  70. public:
  71. StackSubCommand(StringRef Name,
  72. StringRef Description = StringRef())
  73. : SubCommand(Name, Description) {}
  74. StackSubCommand() : SubCommand() {}
  75. ~StackSubCommand() { unregisterSubCommand(); }
  76. };
  77. cl::OptionCategory TestCategory("Test Options", "Description");
  78. TEST(CommandLineTest, ModifyExisitingOption) {
  79. StackOption<int> TestOption("test-option", cl::desc("old description"));
  80. const char Description[] = "New description";
  81. const char ArgString[] = "new-test-option";
  82. const char ValueString[] = "Integer";
  83. StringMap<cl::Option *> &Map =
  84. cl::getRegisteredOptions(*cl::TopLevelSubCommand);
  85. ASSERT_TRUE(Map.count("test-option") == 1) <<
  86. "Could not find option in map.";
  87. cl::Option *Retrieved = Map["test-option"];
  88. ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
  89. ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) <<
  90. "Incorrect default option category.";
  91. Retrieved->setCategory(TestCategory);
  92. ASSERT_EQ(&TestCategory,Retrieved->Category) <<
  93. "Failed to modify option's option category.";
  94. Retrieved->setDescription(Description);
  95. ASSERT_STREQ(Retrieved->HelpStr.data(), Description)
  96. << "Changing option description failed.";
  97. Retrieved->setArgStr(ArgString);
  98. ASSERT_STREQ(ArgString, Retrieved->ArgStr.data())
  99. << "Failed to modify option's Argument string.";
  100. Retrieved->setValueStr(ValueString);
  101. ASSERT_STREQ(Retrieved->ValueStr.data(), ValueString)
  102. << "Failed to modify option's Value string.";
  103. Retrieved->setHiddenFlag(cl::Hidden);
  104. ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) <<
  105. "Failed to modify option's hidden flag.";
  106. }
  107. #ifndef SKIP_ENVIRONMENT_TESTS
  108. const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS";
  109. cl::opt<std::string> EnvironmentTestOption("env-test-opt");
  110. TEST(CommandLineTest, ParseEnvironment) {
  111. TempEnvVar TEV(test_env_var, "-env-test-opt=hello");
  112. EXPECT_EQ("", EnvironmentTestOption);
  113. cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
  114. EXPECT_EQ("hello", EnvironmentTestOption);
  115. }
  116. // This test used to make valgrind complain
  117. // ("Conditional jump or move depends on uninitialised value(s)")
  118. //
  119. // Warning: Do not run any tests after this one that try to gain access to
  120. // registered command line options because this will likely result in a
  121. // SEGFAULT. This can occur because the cl::opt in the test below is declared
  122. // on the stack which will be destroyed after the test completes but the
  123. // command line system will still hold a pointer to a deallocated cl::Option.
  124. TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
  125. // Put cl::opt on stack to check for proper initialization of fields.
  126. StackOption<std::string> EnvironmentTestOptionLocal("env-test-opt-local");
  127. TempEnvVar TEV(test_env_var, "-env-test-opt-local=hello-local");
  128. EXPECT_EQ("", EnvironmentTestOptionLocal);
  129. cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
  130. EXPECT_EQ("hello-local", EnvironmentTestOptionLocal);
  131. }
  132. #endif // SKIP_ENVIRONMENT_TESTS
  133. TEST(CommandLineTest, UseOptionCategory) {
  134. StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
  135. ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option "
  136. "Category.";
  137. }
  138. typedef void ParserFunction(StringRef Source, StringSaver &Saver,
  139. SmallVectorImpl<const char *> &NewArgv,
  140. bool MarkEOLs);
  141. void testCommandLineTokenizer(ParserFunction *parse, StringRef Input,
  142. const char *const Output[], size_t OutputSize) {
  143. SmallVector<const char *, 0> Actual;
  144. BumpPtrAllocator A;
  145. StringSaver Saver(A);
  146. parse(Input, Saver, Actual, /*MarkEOLs=*/false);
  147. EXPECT_EQ(OutputSize, Actual.size());
  148. for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
  149. if (I < OutputSize) {
  150. EXPECT_STREQ(Output[I], Actual[I]);
  151. }
  152. }
  153. }
  154. TEST(CommandLineTest, TokenizeGNUCommandLine) {
  155. const char Input[] =
  156. "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' -DFOO=bar\\(\\) "
  157. "foo\"bar\"baz C:\\\\src\\\\foo.cpp \"C:\\src\\foo.cpp\"";
  158. const char *const Output[] = {
  159. "foo bar", "foo bar", "foo bar", "foo\\bar",
  160. "-DFOO=bar()", "foobarbaz", "C:\\src\\foo.cpp", "C:srcfoo.cpp"};
  161. testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
  162. array_lengthof(Output));
  163. }
  164. TEST(CommandLineTest, TokenizeWindowsCommandLine) {
  165. const char Input[] = "a\\b c\\\\d e\\\\\"f g\" h\\\"i j\\\\\\\"k \"lmn\" o pqr "
  166. "\"st \\\"u\" \\v";
  167. const char *const Output[] = { "a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k",
  168. "lmn", "o", "pqr", "st \"u", "\\v" };
  169. testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output,
  170. array_lengthof(Output));
  171. }
  172. TEST(CommandLineTest, AliasesWithArguments) {
  173. static const size_t ARGC = 3;
  174. const char *const Inputs[][ARGC] = {
  175. { "-tool", "-actual=x", "-extra" },
  176. { "-tool", "-actual", "x" },
  177. { "-tool", "-alias=x", "-extra" },
  178. { "-tool", "-alias", "x" }
  179. };
  180. for (size_t i = 0, e = array_lengthof(Inputs); i < e; ++i) {
  181. StackOption<std::string> Actual("actual");
  182. StackOption<bool> Extra("extra");
  183. StackOption<std::string> Input(cl::Positional);
  184. cl::alias Alias("alias", llvm::cl::aliasopt(Actual));
  185. cl::ParseCommandLineOptions(ARGC, Inputs[i]);
  186. EXPECT_EQ("x", Actual);
  187. EXPECT_EQ(0, Input.getNumOccurrences());
  188. Alias.removeArgument();
  189. }
  190. }
  191. void testAliasRequired(int argc, const char *const *argv) {
  192. StackOption<std::string> Option("option", cl::Required);
  193. cl::alias Alias("o", llvm::cl::aliasopt(Option));
  194. cl::ParseCommandLineOptions(argc, argv);
  195. EXPECT_EQ("x", Option);
  196. EXPECT_EQ(1, Option.getNumOccurrences());
  197. Alias.removeArgument();
  198. }
  199. TEST(CommandLineTest, AliasRequired) {
  200. const char *opts1[] = { "-tool", "-option=x" };
  201. const char *opts2[] = { "-tool", "-o", "x" };
  202. testAliasRequired(array_lengthof(opts1), opts1);
  203. testAliasRequired(array_lengthof(opts2), opts2);
  204. }
  205. TEST(CommandLineTest, HideUnrelatedOptions) {
  206. StackOption<int> TestOption1("hide-option-1");
  207. StackOption<int> TestOption2("hide-option-2", cl::cat(TestCategory));
  208. cl::HideUnrelatedOptions(TestCategory);
  209. ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag())
  210. << "Failed to hide extra option.";
  211. ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
  212. << "Hid extra option that should be visable.";
  213. StringMap<cl::Option *> &Map =
  214. cl::getRegisteredOptions(*cl::TopLevelSubCommand);
  215. ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
  216. << "Hid default option that should be visable.";
  217. }
  218. cl::OptionCategory TestCategory2("Test Options set 2", "Description");
  219. TEST(CommandLineTest, HideUnrelatedOptionsMulti) {
  220. StackOption<int> TestOption1("multi-hide-option-1");
  221. StackOption<int> TestOption2("multi-hide-option-2", cl::cat(TestCategory));
  222. StackOption<int> TestOption3("multi-hide-option-3", cl::cat(TestCategory2));
  223. const cl::OptionCategory *VisibleCategories[] = {&TestCategory,
  224. &TestCategory2};
  225. cl::HideUnrelatedOptions(makeArrayRef(VisibleCategories));
  226. ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag())
  227. << "Failed to hide extra option.";
  228. ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
  229. << "Hid extra option that should be visable.";
  230. ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag())
  231. << "Hid extra option that should be visable.";
  232. StringMap<cl::Option *> &Map =
  233. cl::getRegisteredOptions(*cl::TopLevelSubCommand);
  234. ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
  235. << "Hid default option that should be visable.";
  236. }
  237. TEST(CommandLineTest, SetValueInSubcategories) {
  238. cl::ResetCommandLineParser();
  239. StackSubCommand SC1("sc1", "First subcommand");
  240. StackSubCommand SC2("sc2", "Second subcommand");
  241. StackOption<bool> TopLevelOpt("top-level", cl::init(false));
  242. StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
  243. StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
  244. EXPECT_FALSE(TopLevelOpt);
  245. EXPECT_FALSE(SC1Opt);
  246. EXPECT_FALSE(SC2Opt);
  247. const char *args[] = {"prog", "-top-level"};
  248. EXPECT_TRUE(
  249. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  250. EXPECT_TRUE(TopLevelOpt);
  251. EXPECT_FALSE(SC1Opt);
  252. EXPECT_FALSE(SC2Opt);
  253. TopLevelOpt = false;
  254. cl::ResetAllOptionOccurrences();
  255. EXPECT_FALSE(TopLevelOpt);
  256. EXPECT_FALSE(SC1Opt);
  257. EXPECT_FALSE(SC2Opt);
  258. const char *args2[] = {"prog", "sc1", "-sc1"};
  259. EXPECT_TRUE(
  260. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  261. EXPECT_FALSE(TopLevelOpt);
  262. EXPECT_TRUE(SC1Opt);
  263. EXPECT_FALSE(SC2Opt);
  264. SC1Opt = false;
  265. cl::ResetAllOptionOccurrences();
  266. EXPECT_FALSE(TopLevelOpt);
  267. EXPECT_FALSE(SC1Opt);
  268. EXPECT_FALSE(SC2Opt);
  269. const char *args3[] = {"prog", "sc2", "-sc2"};
  270. EXPECT_TRUE(
  271. cl::ParseCommandLineOptions(3, args3, StringRef(), &llvm::nulls()));
  272. EXPECT_FALSE(TopLevelOpt);
  273. EXPECT_FALSE(SC1Opt);
  274. EXPECT_TRUE(SC2Opt);
  275. }
  276. TEST(CommandLineTest, LookupFailsInWrongSubCommand) {
  277. cl::ResetCommandLineParser();
  278. StackSubCommand SC1("sc1", "First subcommand");
  279. StackSubCommand SC2("sc2", "Second subcommand");
  280. StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
  281. StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
  282. std::string Errs;
  283. raw_string_ostream OS(Errs);
  284. const char *args[] = {"prog", "sc1", "-sc2"};
  285. EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
  286. OS.flush();
  287. EXPECT_FALSE(Errs.empty());
  288. }
  289. TEST(CommandLineTest, AddToAllSubCommands) {
  290. cl::ResetCommandLineParser();
  291. StackSubCommand SC1("sc1", "First subcommand");
  292. StackOption<bool> AllOpt("everywhere", cl::sub(*cl::AllSubCommands),
  293. cl::init(false));
  294. StackSubCommand SC2("sc2", "Second subcommand");
  295. const char *args[] = {"prog", "-everywhere"};
  296. const char *args2[] = {"prog", "sc1", "-everywhere"};
  297. const char *args3[] = {"prog", "sc2", "-everywhere"};
  298. std::string Errs;
  299. raw_string_ostream OS(Errs);
  300. EXPECT_FALSE(AllOpt);
  301. EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
  302. EXPECT_TRUE(AllOpt);
  303. AllOpt = false;
  304. cl::ResetAllOptionOccurrences();
  305. EXPECT_FALSE(AllOpt);
  306. EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS));
  307. EXPECT_TRUE(AllOpt);
  308. AllOpt = false;
  309. cl::ResetAllOptionOccurrences();
  310. EXPECT_FALSE(AllOpt);
  311. EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS));
  312. EXPECT_TRUE(AllOpt);
  313. // Since all parsing succeeded, the error message should be empty.
  314. OS.flush();
  315. EXPECT_TRUE(Errs.empty());
  316. }
  317. TEST(CommandLineTest, ReparseCommandLineOptions) {
  318. cl::ResetCommandLineParser();
  319. StackOption<bool> TopLevelOpt("top-level", cl::sub(*cl::TopLevelSubCommand),
  320. cl::init(false));
  321. const char *args[] = {"prog", "-top-level"};
  322. EXPECT_FALSE(TopLevelOpt);
  323. EXPECT_TRUE(
  324. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  325. EXPECT_TRUE(TopLevelOpt);
  326. TopLevelOpt = false;
  327. cl::ResetAllOptionOccurrences();
  328. EXPECT_FALSE(TopLevelOpt);
  329. EXPECT_TRUE(
  330. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  331. EXPECT_TRUE(TopLevelOpt);
  332. }
  333. TEST(CommandLineTest, RemoveFromRegularSubCommand) {
  334. cl::ResetCommandLineParser();
  335. StackSubCommand SC("sc", "Subcommand");
  336. StackOption<bool> RemoveOption("remove-option", cl::sub(SC), cl::init(false));
  337. StackOption<bool> KeepOption("keep-option", cl::sub(SC), cl::init(false));
  338. const char *args[] = {"prog", "sc", "-remove-option"};
  339. std::string Errs;
  340. raw_string_ostream OS(Errs);
  341. EXPECT_FALSE(RemoveOption);
  342. EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
  343. EXPECT_TRUE(RemoveOption);
  344. OS.flush();
  345. EXPECT_TRUE(Errs.empty());
  346. RemoveOption.removeArgument();
  347. cl::ResetAllOptionOccurrences();
  348. EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
  349. OS.flush();
  350. EXPECT_FALSE(Errs.empty());
  351. }
  352. TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
  353. cl::ResetCommandLineParser();
  354. StackOption<bool> TopLevelRemove(
  355. "top-level-remove", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
  356. StackOption<bool> TopLevelKeep(
  357. "top-level-keep", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
  358. const char *args[] = {"prog", "-top-level-remove"};
  359. EXPECT_FALSE(TopLevelRemove);
  360. EXPECT_TRUE(
  361. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  362. EXPECT_TRUE(TopLevelRemove);
  363. TopLevelRemove.removeArgument();
  364. cl::ResetAllOptionOccurrences();
  365. EXPECT_FALSE(
  366. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  367. }
  368. TEST(CommandLineTest, RemoveFromAllSubCommands) {
  369. cl::ResetCommandLineParser();
  370. StackSubCommand SC1("sc1", "First Subcommand");
  371. StackSubCommand SC2("sc2", "Second Subcommand");
  372. StackOption<bool> RemoveOption("remove-option", cl::sub(*cl::AllSubCommands),
  373. cl::init(false));
  374. StackOption<bool> KeepOption("keep-option", cl::sub(*cl::AllSubCommands),
  375. cl::init(false));
  376. const char *args0[] = {"prog", "-remove-option"};
  377. const char *args1[] = {"prog", "sc1", "-remove-option"};
  378. const char *args2[] = {"prog", "sc2", "-remove-option"};
  379. // It should work for all subcommands including the top-level.
  380. EXPECT_FALSE(RemoveOption);
  381. EXPECT_TRUE(
  382. cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
  383. EXPECT_TRUE(RemoveOption);
  384. RemoveOption = false;
  385. cl::ResetAllOptionOccurrences();
  386. EXPECT_FALSE(RemoveOption);
  387. EXPECT_TRUE(
  388. cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
  389. EXPECT_TRUE(RemoveOption);
  390. RemoveOption = false;
  391. cl::ResetAllOptionOccurrences();
  392. EXPECT_FALSE(RemoveOption);
  393. EXPECT_TRUE(
  394. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  395. EXPECT_TRUE(RemoveOption);
  396. RemoveOption.removeArgument();
  397. // It should not work for any subcommands including the top-level.
  398. cl::ResetAllOptionOccurrences();
  399. EXPECT_FALSE(
  400. cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
  401. cl::ResetAllOptionOccurrences();
  402. EXPECT_FALSE(
  403. cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
  404. cl::ResetAllOptionOccurrences();
  405. EXPECT_FALSE(
  406. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  407. }
  408. TEST(CommandLineTest, GetRegisteredSubcommands) {
  409. cl::ResetCommandLineParser();
  410. StackSubCommand SC1("sc1", "First Subcommand");
  411. StackOption<bool> Opt1("opt1", cl::sub(SC1), cl::init(false));
  412. StackSubCommand SC2("sc2", "Second subcommand");
  413. StackOption<bool> Opt2("opt2", cl::sub(SC2), cl::init(false));
  414. const char *args0[] = {"prog", "sc1"};
  415. const char *args1[] = {"prog", "sc2"};
  416. EXPECT_TRUE(
  417. cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
  418. EXPECT_FALSE(Opt1);
  419. EXPECT_FALSE(Opt2);
  420. for (auto *S : cl::getRegisteredSubcommands()) {
  421. if (*S) {
  422. EXPECT_EQ("sc1", S->getName());
  423. }
  424. }
  425. cl::ResetAllOptionOccurrences();
  426. EXPECT_TRUE(
  427. cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
  428. EXPECT_FALSE(Opt1);
  429. EXPECT_FALSE(Opt2);
  430. for (auto *S : cl::getRegisteredSubcommands()) {
  431. if (*S) {
  432. EXPECT_EQ("sc2", S->getName());
  433. }
  434. }
  435. }
  436. TEST(CommandLineTest, ArgumentLimit) {
  437. std::string args(32 * 4096, 'a');
  438. EXPECT_FALSE(llvm::sys::commandLineFitsWithinSystemLimits("cl", args.data()));
  439. }
  440. TEST(CommandLineTest, ResponseFiles) {
  441. llvm::SmallString<128> TestDir;
  442. std::error_code EC =
  443. llvm::sys::fs::createUniqueDirectory("unittest", TestDir);
  444. EXPECT_TRUE(!EC);
  445. // Create included response file of first level.
  446. llvm::SmallString<128> IncludedFileName;
  447. llvm::sys::path::append(IncludedFileName, TestDir, "resp1");
  448. std::ofstream IncludedFile(IncludedFileName.c_str());
  449. EXPECT_TRUE(IncludedFile.is_open());
  450. IncludedFile << "-option_1 -option_2\n"
  451. "@incdir/resp2\n"
  452. "-option_3=abcd\n";
  453. IncludedFile.close();
  454. // Directory for included file.
  455. llvm::SmallString<128> IncDir;
  456. llvm::sys::path::append(IncDir, TestDir, "incdir");
  457. EC = llvm::sys::fs::create_directory(IncDir);
  458. EXPECT_TRUE(!EC);
  459. // Create included response file of second level.
  460. llvm::SmallString<128> IncludedFileName2;
  461. llvm::sys::path::append(IncludedFileName2, IncDir, "resp2");
  462. std::ofstream IncludedFile2(IncludedFileName2.c_str());
  463. EXPECT_TRUE(IncludedFile2.is_open());
  464. IncludedFile2 << "-option_21 -option_22\n";
  465. IncludedFile2 << "-option_23=abcd\n";
  466. IncludedFile2.close();
  467. // Prepare 'file' with reference to response file.
  468. SmallString<128> IncRef;
  469. IncRef.append(1, '@');
  470. IncRef.append(IncludedFileName.c_str());
  471. llvm::SmallVector<const char *, 4> Argv =
  472. { "test/test", "-flag_1", IncRef.c_str(), "-flag_2" };
  473. // Expand response files.
  474. llvm::BumpPtrAllocator A;
  475. llvm::StringSaver Saver(A);
  476. bool Res = llvm::cl::ExpandResponseFiles(
  477. Saver, llvm::cl::TokenizeGNUCommandLine, Argv, false, true);
  478. EXPECT_TRUE(Res);
  479. EXPECT_EQ(Argv.size(), 9U);
  480. EXPECT_STREQ(Argv[0], "test/test");
  481. EXPECT_STREQ(Argv[1], "-flag_1");
  482. EXPECT_STREQ(Argv[2], "-option_1");
  483. EXPECT_STREQ(Argv[3], "-option_2");
  484. EXPECT_STREQ(Argv[4], "-option_21");
  485. EXPECT_STREQ(Argv[5], "-option_22");
  486. EXPECT_STREQ(Argv[6], "-option_23=abcd");
  487. EXPECT_STREQ(Argv[7], "-option_3=abcd");
  488. EXPECT_STREQ(Argv[8], "-flag_2");
  489. llvm::sys::fs::remove(IncludedFileName2);
  490. llvm::sys::fs::remove(IncDir);
  491. llvm::sys::fs::remove(IncludedFileName);
  492. llvm::sys::fs::remove(TestDir);
  493. }
  494. } // anonymous namespace