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