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 16using namespace llvm; 17using namespace llvm::opt; 18 19enum 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 32enum OptionFlags { 33 OptFlag1 = (1 << 4), 34 OptFlag2 = (1 << 5), 35 OptFlag3 = (1 << 6) 36}; 37 38static 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 47namespace { 48class TestOptTable : public OptTable { 49public: 50 TestOptTable(bool IgnoreCase = false) 51 : OptTable(InfoTable, IgnoreCase) {} 52}; 53} 54 55const 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 67TEST(Option, OptionParsing) { 68 TestOptTable T; 69 unsigned MAI, MAC; 70 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("hi", AL.getLastArgValue(OPT_B)); 83 EXPECT_EQ("bye", AL.getLastArgValue(OPT_C)); 84 EXPECT_EQ("adena", AL.getLastArgValue(OPT_D)); 85 std::vector<std::string> Es = AL.getAllArgValues(OPT_E); 86 EXPECT_EQ("apple", Es[0]); 87 EXPECT_EQ("bloom", Es[1]); 88 EXPECT_EQ("42", AL.getLastArgValue(OPT_F)); 89 std::vector<std::string> Gs = AL.getAllArgValues(OPT_G); 90 EXPECT_EQ("chuu", Gs[0]); 91 EXPECT_EQ("2", Gs[1]); 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(std::string::npos, Help.find("-A")); 98 99 // Test aliases. 100 arg_iterator Cs = AL.filtered_begin(OPT_C); 101 ASSERT_NE(AL.filtered_end(), Cs); 102 EXPECT_EQ("desu", StringRef((*Cs)->getValue())); 103 ArgStringList ASL; 104 (*Cs)->render(AL, ASL); 105 ASSERT_EQ(2u, ASL.size()); 106 EXPECT_EQ("-C", StringRef(ASL[0])); 107 EXPECT_EQ("desu", StringRef(ASL[1])); 108} 109 110TEST(Option, ParseWithFlagExclusions) { 111 TestOptTable T; 112 unsigned MAI, MAC; 113 114 // Exclude flag3 to avoid parsing as OPT_SLASH_C. 115 InputArgList AL = T.ParseArgs(Args, MAI, MAC, 116 /*FlagsToInclude=*/0, 117 /*FlagsToExclude=*/OptFlag3); 118 EXPECT_TRUE(AL.hasArg(OPT_A)); 119 EXPECT_TRUE(AL.hasArg(OPT_C)); 120 EXPECT_FALSE(AL.hasArg(OPT_SLASH_C)); 121 122 // Exclude flag1 to avoid parsing as OPT_C. 123 AL = T.ParseArgs(Args, MAI, MAC, 124 /*FlagsToInclude=*/0, 125 /*FlagsToExclude=*/OptFlag1); 126 EXPECT_TRUE(AL.hasArg(OPT_B)); 127 EXPECT_FALSE(AL.hasArg(OPT_C)); 128 EXPECT_TRUE(AL.hasArg(OPT_SLASH_C)); 129 130 const char *NewArgs[] = { "/C", "foo", "--C=bar" }; 131 AL = T.ParseArgs(NewArgs, MAI, MAC); 132 EXPECT_TRUE(AL.hasArg(OPT_SLASH_C)); 133 EXPECT_TRUE(AL.hasArg(OPT_C)); 134 EXPECT_EQ("foo", AL.getLastArgValue(OPT_SLASH_C)); 135 EXPECT_EQ("bar", AL.getLastArgValue(OPT_C)); 136} 137 138TEST(Option, ParseAliasInGroup) { 139 TestOptTable T; 140 unsigned MAI, MAC; 141 142 const char *MyArgs[] = { "-I" }; 143 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 144 EXPECT_TRUE(AL.hasArg(OPT_H)); 145} 146 147TEST(Option, AliasArgs) { 148 TestOptTable T; 149 unsigned MAI, MAC; 150 151 const char *MyArgs[] = { "-J", "-Joo" }; 152 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 153 EXPECT_TRUE(AL.hasArg(OPT_B)); 154 EXPECT_EQ("foo", AL.getAllArgValues(OPT_B)[0]); 155 EXPECT_EQ("bar", AL.getAllArgValues(OPT_B)[1]); 156} 157 158TEST(Option, IgnoreCase) { 159 TestOptTable T(true); 160 unsigned MAI, MAC; 161 162 const char *MyArgs[] = { "-a", "-joo" }; 163 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 164 EXPECT_TRUE(AL.hasArg(OPT_A)); 165 EXPECT_TRUE(AL.hasArg(OPT_B)); 166} 167 168TEST(Option, DoNotIgnoreCase) { 169 TestOptTable T; 170 unsigned MAI, MAC; 171 172 const char *MyArgs[] = { "-a", "-joo" }; 173 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 174 EXPECT_FALSE(AL.hasArg(OPT_A)); 175 EXPECT_FALSE(AL.hasArg(OPT_B)); 176} 177 178TEST(Option, SlurpEmpty) { 179 TestOptTable T; 180 unsigned MAI, MAC; 181 182 const char *MyArgs[] = { "-A", "-slurp" }; 183 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 184 EXPECT_TRUE(AL.hasArg(OPT_A)); 185 EXPECT_TRUE(AL.hasArg(OPT_Slurp)); 186 EXPECT_EQ(0U, AL.getAllArgValues(OPT_Slurp).size()); 187} 188 189TEST(Option, Slurp) { 190 TestOptTable T; 191 unsigned MAI, MAC; 192 193 const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" }; 194 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 195 EXPECT_EQ(AL.size(), 2U); 196 EXPECT_TRUE(AL.hasArg(OPT_A)); 197 EXPECT_FALSE(AL.hasArg(OPT_B)); 198 EXPECT_TRUE(AL.hasArg(OPT_Slurp)); 199 EXPECT_EQ(3U, AL.getAllArgValues(OPT_Slurp).size()); 200 EXPECT_EQ("-B", AL.getAllArgValues(OPT_Slurp)[0]); 201 EXPECT_EQ("--", AL.getAllArgValues(OPT_Slurp)[1]); 202 EXPECT_EQ("foo", AL.getAllArgValues(OPT_Slurp)[2]); 203} 204 205TEST(Option, SlurpJoinedEmpty) { 206 TestOptTable T; 207 unsigned MAI, MAC; 208 209 const char *MyArgs[] = { "-A", "-slurpjoined" }; 210 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 211 EXPECT_TRUE(AL.hasArg(OPT_A)); 212 EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined)); 213 EXPECT_EQ(AL.getAllArgValues(OPT_SlurpJoined).size(), 0U); 214} 215 216TEST(Option, SlurpJoinedOneJoined) { 217 TestOptTable T; 218 unsigned MAI, MAC; 219 220 const char *MyArgs[] = { "-A", "-slurpjoinedfoo" }; 221 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 222 EXPECT_TRUE(AL.hasArg(OPT_A)); 223 EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined)); 224 EXPECT_EQ(AL.getAllArgValues(OPT_SlurpJoined).size(), 1U); 225 EXPECT_EQ(AL.getAllArgValues(OPT_SlurpJoined)[0], "foo"); 226} 227 228TEST(Option, SlurpJoinedAndSeparate) { 229 TestOptTable T; 230 unsigned MAI, MAC; 231 232 const char *MyArgs[] = { "-A", "-slurpjoinedfoo", "bar", "baz" }; 233 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 234 EXPECT_TRUE(AL.hasArg(OPT_A)); 235 EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined)); 236 EXPECT_EQ(3U, AL.getAllArgValues(OPT_SlurpJoined).size()); 237 EXPECT_EQ("foo", AL.getAllArgValues(OPT_SlurpJoined)[0]); 238 EXPECT_EQ("bar", AL.getAllArgValues(OPT_SlurpJoined)[1]); 239 EXPECT_EQ("baz", AL.getAllArgValues(OPT_SlurpJoined)[2]); 240} 241 242TEST(Option, SlurpJoinedButSeparate) { 243 TestOptTable T; 244 unsigned MAI, MAC; 245 246 const char *MyArgs[] = { "-A", "-slurpjoined", "foo", "bar", "baz" }; 247 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 248 EXPECT_TRUE(AL.hasArg(OPT_A)); 249 EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined)); 250 EXPECT_EQ(3U, AL.getAllArgValues(OPT_SlurpJoined).size()); 251 EXPECT_EQ("foo", AL.getAllArgValues(OPT_SlurpJoined)[0]); 252 EXPECT_EQ("bar", AL.getAllArgValues(OPT_SlurpJoined)[1]); 253 EXPECT_EQ("baz", AL.getAllArgValues(OPT_SlurpJoined)[2]); 254} 255 256TEST(Option, FlagAliasToJoined) { 257 TestOptTable T; 258 unsigned MAI, MAC; 259 260 // Check that a flag alias provides an empty argument to a joined option. 261 const char *MyArgs[] = { "-K" }; 262 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); 263 EXPECT_EQ(AL.size(), 1U); 264 EXPECT_TRUE(AL.hasArg(OPT_B)); 265 EXPECT_EQ(1U, AL.getAllArgValues(OPT_B).size()); 266 EXPECT_EQ("", AL.getAllArgValues(OPT_B)[0]); 267} 268