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