1*f4a2713aSLionel Sambuc //===- unittest/Support/OptionParsingTest.cpp - OptTable tests ------------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc 10*f4a2713aSLionel Sambuc #include "llvm/ADT/OwningPtr.h" 11*f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h" 12*f4a2713aSLionel Sambuc #include "llvm/Option/Arg.h" 13*f4a2713aSLionel Sambuc #include "llvm/Option/ArgList.h" 14*f4a2713aSLionel Sambuc #include "llvm/Option/Option.h" 15*f4a2713aSLionel Sambuc #include "gtest/gtest.h" 16*f4a2713aSLionel Sambuc 17*f4a2713aSLionel Sambuc using namespace llvm; 18*f4a2713aSLionel Sambuc using namespace llvm::opt; 19*f4a2713aSLionel Sambuc 20*f4a2713aSLionel Sambuc enum ID { 21*f4a2713aSLionel Sambuc OPT_INVALID = 0, // This is not an option ID. 22*f4a2713aSLionel Sambuc #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 23*f4a2713aSLionel Sambuc HELPTEXT, METAVAR) OPT_##ID, 24*f4a2713aSLionel Sambuc #include "Opts.inc" 25*f4a2713aSLionel Sambuc LastOption 26*f4a2713aSLionel Sambuc #undef OPTION 27*f4a2713aSLionel Sambuc }; 28*f4a2713aSLionel Sambuc 29*f4a2713aSLionel Sambuc #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 30*f4a2713aSLionel Sambuc #include "Opts.inc" 31*f4a2713aSLionel Sambuc #undef PREFIX 32*f4a2713aSLionel Sambuc 33*f4a2713aSLionel Sambuc enum OptionFlags { 34*f4a2713aSLionel Sambuc OptFlag1 = (1 << 4), 35*f4a2713aSLionel Sambuc OptFlag2 = (1 << 5), 36*f4a2713aSLionel Sambuc OptFlag3 = (1 << 6) 37*f4a2713aSLionel Sambuc }; 38*f4a2713aSLionel Sambuc 39*f4a2713aSLionel Sambuc static const OptTable::Info InfoTable[] = { 40*f4a2713aSLionel Sambuc #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 41*f4a2713aSLionel Sambuc HELPTEXT, METAVAR) \ 42*f4a2713aSLionel Sambuc { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \ 43*f4a2713aSLionel Sambuc FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS }, 44*f4a2713aSLionel Sambuc #include "Opts.inc" 45*f4a2713aSLionel Sambuc #undef OPTION 46*f4a2713aSLionel Sambuc }; 47*f4a2713aSLionel Sambuc 48*f4a2713aSLionel Sambuc namespace { 49*f4a2713aSLionel Sambuc class TestOptTable : public OptTable { 50*f4a2713aSLionel Sambuc public: 51*f4a2713aSLionel Sambuc TestOptTable(bool IgnoreCase = false) 52*f4a2713aSLionel Sambuc : OptTable(InfoTable, array_lengthof(InfoTable), IgnoreCase) {} 53*f4a2713aSLionel Sambuc }; 54*f4a2713aSLionel Sambuc } 55*f4a2713aSLionel Sambuc 56*f4a2713aSLionel Sambuc const char *Args[] = { 57*f4a2713aSLionel Sambuc "-A", 58*f4a2713aSLionel Sambuc "-Bhi", 59*f4a2713aSLionel Sambuc "--C=desu", 60*f4a2713aSLionel Sambuc "-C", "bye", 61*f4a2713aSLionel Sambuc "-D,adena", 62*f4a2713aSLionel Sambuc "-E", "apple", "bloom", 63*f4a2713aSLionel Sambuc "-Fblarg", 64*f4a2713aSLionel Sambuc "-F", "42", 65*f4a2713aSLionel Sambuc "-Gchuu", "2" 66*f4a2713aSLionel Sambuc }; 67*f4a2713aSLionel Sambuc 68*f4a2713aSLionel Sambuc TEST(Option, OptionParsing) { 69*f4a2713aSLionel Sambuc TestOptTable T; 70*f4a2713aSLionel Sambuc unsigned MAI, MAC; 71*f4a2713aSLionel Sambuc OwningPtr<InputArgList> AL(T.ParseArgs(Args, array_endof(Args), MAI, MAC)); 72*f4a2713aSLionel Sambuc 73*f4a2713aSLionel Sambuc // Check they all exist. 74*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_A)); 75*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_B)); 76*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_C)); 77*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_D)); 78*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_E)); 79*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_F)); 80*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_G)); 81*f4a2713aSLionel Sambuc 82*f4a2713aSLionel Sambuc // Check the values. 83*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getLastArgValue(OPT_B), "hi"); 84*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getLastArgValue(OPT_C), "bye"); 85*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getLastArgValue(OPT_D), "adena"); 86*f4a2713aSLionel Sambuc std::vector<std::string> Es = AL->getAllArgValues(OPT_E); 87*f4a2713aSLionel Sambuc EXPECT_EQ(Es[0], "apple"); 88*f4a2713aSLionel Sambuc EXPECT_EQ(Es[1], "bloom"); 89*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getLastArgValue(OPT_F), "42"); 90*f4a2713aSLionel Sambuc std::vector<std::string> Gs = AL->getAllArgValues(OPT_G); 91*f4a2713aSLionel Sambuc EXPECT_EQ(Gs[0], "chuu"); 92*f4a2713aSLionel Sambuc EXPECT_EQ(Gs[1], "2"); 93*f4a2713aSLionel Sambuc 94*f4a2713aSLionel Sambuc // Check the help text. 95*f4a2713aSLionel Sambuc std::string Help; 96*f4a2713aSLionel Sambuc raw_string_ostream RSO(Help); 97*f4a2713aSLionel Sambuc T.PrintHelp(RSO, "test", "title!"); 98*f4a2713aSLionel Sambuc EXPECT_NE(Help.find("-A"), std::string::npos); 99*f4a2713aSLionel Sambuc 100*f4a2713aSLionel Sambuc // Test aliases. 101*f4a2713aSLionel Sambuc arg_iterator Cs = AL->filtered_begin(OPT_C); 102*f4a2713aSLionel Sambuc ASSERT_NE(Cs, AL->filtered_end()); 103*f4a2713aSLionel Sambuc EXPECT_EQ(StringRef((*Cs)->getValue()), "desu"); 104*f4a2713aSLionel Sambuc ArgStringList ASL; 105*f4a2713aSLionel Sambuc (*Cs)->render(*AL, ASL); 106*f4a2713aSLionel Sambuc ASSERT_EQ(ASL.size(), 2u); 107*f4a2713aSLionel Sambuc EXPECT_EQ(StringRef(ASL[0]), "-C"); 108*f4a2713aSLionel Sambuc EXPECT_EQ(StringRef(ASL[1]), "desu"); 109*f4a2713aSLionel Sambuc } 110*f4a2713aSLionel Sambuc 111*f4a2713aSLionel Sambuc TEST(Option, ParseWithFlagExclusions) { 112*f4a2713aSLionel Sambuc TestOptTable T; 113*f4a2713aSLionel Sambuc unsigned MAI, MAC; 114*f4a2713aSLionel Sambuc OwningPtr<InputArgList> AL; 115*f4a2713aSLionel Sambuc 116*f4a2713aSLionel Sambuc // Exclude flag3 to avoid parsing as OPT_SLASH_C. 117*f4a2713aSLionel Sambuc AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC, 118*f4a2713aSLionel Sambuc /*FlagsToInclude=*/0, 119*f4a2713aSLionel Sambuc /*FlagsToExclude=*/OptFlag3)); 120*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_A)); 121*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_C)); 122*f4a2713aSLionel Sambuc EXPECT_FALSE(AL->hasArg(OPT_SLASH_C)); 123*f4a2713aSLionel Sambuc 124*f4a2713aSLionel Sambuc // Exclude flag1 to avoid parsing as OPT_C. 125*f4a2713aSLionel Sambuc AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC, 126*f4a2713aSLionel Sambuc /*FlagsToInclude=*/0, 127*f4a2713aSLionel Sambuc /*FlagsToExclude=*/OptFlag1)); 128*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_B)); 129*f4a2713aSLionel Sambuc EXPECT_FALSE(AL->hasArg(OPT_C)); 130*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_SLASH_C)); 131*f4a2713aSLionel Sambuc 132*f4a2713aSLionel Sambuc const char *NewArgs[] = { "/C", "foo", "--C=bar" }; 133*f4a2713aSLionel Sambuc AL.reset(T.ParseArgs(NewArgs, array_endof(NewArgs), MAI, MAC)); 134*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_SLASH_C)); 135*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_C)); 136*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getLastArgValue(OPT_SLASH_C), "foo"); 137*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getLastArgValue(OPT_C), "bar"); 138*f4a2713aSLionel Sambuc } 139*f4a2713aSLionel Sambuc 140*f4a2713aSLionel Sambuc TEST(Option, ParseAliasInGroup) { 141*f4a2713aSLionel Sambuc TestOptTable T; 142*f4a2713aSLionel Sambuc unsigned MAI, MAC; 143*f4a2713aSLionel Sambuc 144*f4a2713aSLionel Sambuc const char *MyArgs[] = { "-I" }; 145*f4a2713aSLionel Sambuc OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); 146*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_H)); 147*f4a2713aSLionel Sambuc } 148*f4a2713aSLionel Sambuc 149*f4a2713aSLionel Sambuc TEST(Option, AliasArgs) { 150*f4a2713aSLionel Sambuc TestOptTable T; 151*f4a2713aSLionel Sambuc unsigned MAI, MAC; 152*f4a2713aSLionel Sambuc 153*f4a2713aSLionel Sambuc const char *MyArgs[] = { "-J", "-Joo" }; 154*f4a2713aSLionel Sambuc OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); 155*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_B)); 156*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getAllArgValues(OPT_B)[0], "foo"); 157*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar"); 158*f4a2713aSLionel Sambuc } 159*f4a2713aSLionel Sambuc 160*f4a2713aSLionel Sambuc TEST(Option, IgnoreCase) { 161*f4a2713aSLionel Sambuc TestOptTable T(true); 162*f4a2713aSLionel Sambuc unsigned MAI, MAC; 163*f4a2713aSLionel Sambuc 164*f4a2713aSLionel Sambuc const char *MyArgs[] = { "-a", "-joo" }; 165*f4a2713aSLionel Sambuc OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); 166*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_A)); 167*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_B)); 168*f4a2713aSLionel Sambuc } 169*f4a2713aSLionel Sambuc 170*f4a2713aSLionel Sambuc TEST(Option, DoNotIgnoreCase) { 171*f4a2713aSLionel Sambuc TestOptTable T; 172*f4a2713aSLionel Sambuc unsigned MAI, MAC; 173*f4a2713aSLionel Sambuc 174*f4a2713aSLionel Sambuc const char *MyArgs[] = { "-a", "-joo" }; 175*f4a2713aSLionel Sambuc OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); 176*f4a2713aSLionel Sambuc EXPECT_FALSE(AL->hasArg(OPT_A)); 177*f4a2713aSLionel Sambuc EXPECT_FALSE(AL->hasArg(OPT_B)); 178*f4a2713aSLionel Sambuc } 179*f4a2713aSLionel Sambuc 180*f4a2713aSLionel Sambuc TEST(Option, SlurpEmpty) { 181*f4a2713aSLionel Sambuc TestOptTable T; 182*f4a2713aSLionel Sambuc unsigned MAI, MAC; 183*f4a2713aSLionel Sambuc 184*f4a2713aSLionel Sambuc const char *MyArgs[] = { "-A", "-slurp" }; 185*f4a2713aSLionel Sambuc OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); 186*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_A)); 187*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_Slurp)); 188*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 0U); 189*f4a2713aSLionel Sambuc } 190*f4a2713aSLionel Sambuc 191*f4a2713aSLionel Sambuc TEST(Option, Slurp) { 192*f4a2713aSLionel Sambuc TestOptTable T; 193*f4a2713aSLionel Sambuc unsigned MAI, MAC; 194*f4a2713aSLionel Sambuc 195*f4a2713aSLionel Sambuc const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" }; 196*f4a2713aSLionel Sambuc OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); 197*f4a2713aSLionel Sambuc EXPECT_EQ(AL->size(), 2U); 198*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_A)); 199*f4a2713aSLionel Sambuc EXPECT_FALSE(AL->hasArg(OPT_B)); 200*f4a2713aSLionel Sambuc EXPECT_TRUE(AL->hasArg(OPT_Slurp)); 201*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 3U); 202*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[0], "-B"); 203*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[1], "--"); 204*f4a2713aSLionel Sambuc EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[2], "foo"); 205*f4a2713aSLionel Sambuc } 206