1 //===- unittest/Support/OptionParsingTest.cpp - OptTable tests ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
17 using namespace llvm::opt
;
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, VALUES) \
29 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
39 static const OptTable::Info InfoTable
[] = {
40 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
41 HELPTEXT, METAVAR, VALUES) \
42 {PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, \
43 PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES},
49 class TestOptTable
: public OptTable
{
51 TestOptTable(bool IgnoreCase
= false)
52 : OptTable(InfoTable
, IgnoreCase
) {}
56 const char *Args
[] = {
62 "-E", "apple", "bloom",
68 TEST(Option
, OptionParsing
) {
71 InputArgList AL
= T
.ParseArgs(Args
, MAI
, MAC
);
73 // Check they all exist.
74 EXPECT_TRUE(AL
.hasArg(OPT_A
));
75 EXPECT_TRUE(AL
.hasArg(OPT_B
));
76 EXPECT_TRUE(AL
.hasArg(OPT_C
));
77 EXPECT_TRUE(AL
.hasArg(OPT_D
));
78 EXPECT_TRUE(AL
.hasArg(OPT_E
));
79 EXPECT_TRUE(AL
.hasArg(OPT_F
));
80 EXPECT_TRUE(AL
.hasArg(OPT_G
));
83 EXPECT_EQ("hi", AL
.getLastArgValue(OPT_B
));
84 EXPECT_EQ("bye", AL
.getLastArgValue(OPT_C
));
85 EXPECT_EQ("adena", AL
.getLastArgValue(OPT_D
));
86 std::vector
<std::string
> Es
= AL
.getAllArgValues(OPT_E
);
87 EXPECT_EQ("apple", Es
[0]);
88 EXPECT_EQ("bloom", Es
[1]);
89 EXPECT_EQ("42", AL
.getLastArgValue(OPT_F
));
90 std::vector
<std::string
> Gs
= AL
.getAllArgValues(OPT_G
);
91 EXPECT_EQ("chuu", Gs
[0]);
92 EXPECT_EQ("2", Gs
[1]);
94 // Check the help text.
96 raw_string_ostream
RSO(Help
);
97 T
.PrintHelp(RSO
, "test", "title!");
98 EXPECT_NE(std::string::npos
, Help
.find("-A"));
101 auto Cs
= AL
.filtered(OPT_C
);
102 ASSERT_NE(Cs
.begin(), Cs
.end());
103 EXPECT_EQ("desu", StringRef((*Cs
.begin())->getValue()));
105 (*Cs
.begin())->render(AL
, ASL
);
106 ASSERT_EQ(2u, ASL
.size());
107 EXPECT_EQ("-C", StringRef(ASL
[0]));
108 EXPECT_EQ("desu", StringRef(ASL
[1]));
111 TEST(Option
, ParseWithFlagExclusions
) {
115 // Exclude flag3 to avoid parsing as OPT_SLASH_C.
116 InputArgList AL
= 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
));
123 // Exclude flag1 to avoid parsing as OPT_C.
124 AL
= 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
));
131 const char *NewArgs
[] = { "/C", "foo", "--C=bar" };
132 AL
= T
.ParseArgs(NewArgs
, MAI
, MAC
);
133 EXPECT_TRUE(AL
.hasArg(OPT_SLASH_C
));
134 EXPECT_TRUE(AL
.hasArg(OPT_C
));
135 EXPECT_EQ("foo", AL
.getLastArgValue(OPT_SLASH_C
));
136 EXPECT_EQ("bar", AL
.getLastArgValue(OPT_C
));
139 TEST(Option
, ParseAliasInGroup
) {
143 const char *MyArgs
[] = { "-I" };
144 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
145 EXPECT_TRUE(AL
.hasArg(OPT_H
));
148 TEST(Option
, AliasArgs
) {
152 const char *MyArgs
[] = { "-J", "-Joo" };
153 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
154 EXPECT_TRUE(AL
.hasArg(OPT_B
));
155 EXPECT_EQ("foo", AL
.getAllArgValues(OPT_B
)[0]);
156 EXPECT_EQ("bar", AL
.getAllArgValues(OPT_B
)[1]);
159 TEST(Option
, IgnoreCase
) {
160 TestOptTable
T(true);
163 const char *MyArgs
[] = { "-a", "-joo" };
164 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
165 EXPECT_TRUE(AL
.hasArg(OPT_A
));
166 EXPECT_TRUE(AL
.hasArg(OPT_B
));
169 TEST(Option
, DoNotIgnoreCase
) {
173 const char *MyArgs
[] = { "-a", "-joo" };
174 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
175 EXPECT_FALSE(AL
.hasArg(OPT_A
));
176 EXPECT_FALSE(AL
.hasArg(OPT_B
));
179 TEST(Option
, SlurpEmpty
) {
183 const char *MyArgs
[] = { "-A", "-slurp" };
184 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
185 EXPECT_TRUE(AL
.hasArg(OPT_A
));
186 EXPECT_TRUE(AL
.hasArg(OPT_Slurp
));
187 EXPECT_EQ(0U, AL
.getAllArgValues(OPT_Slurp
).size());
190 TEST(Option
, Slurp
) {
194 const char *MyArgs
[] = { "-A", "-slurp", "-B", "--", "foo" };
195 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(3U, AL
.getAllArgValues(OPT_Slurp
).size());
201 EXPECT_EQ("-B", AL
.getAllArgValues(OPT_Slurp
)[0]);
202 EXPECT_EQ("--", AL
.getAllArgValues(OPT_Slurp
)[1]);
203 EXPECT_EQ("foo", AL
.getAllArgValues(OPT_Slurp
)[2]);
206 TEST(Option
, SlurpJoinedEmpty
) {
210 const char *MyArgs
[] = { "-A", "-slurpjoined" };
211 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
212 EXPECT_TRUE(AL
.hasArg(OPT_A
));
213 EXPECT_TRUE(AL
.hasArg(OPT_SlurpJoined
));
214 EXPECT_EQ(AL
.getAllArgValues(OPT_SlurpJoined
).size(), 0U);
217 TEST(Option
, SlurpJoinedOneJoined
) {
221 const char *MyArgs
[] = { "-A", "-slurpjoinedfoo" };
222 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
223 EXPECT_TRUE(AL
.hasArg(OPT_A
));
224 EXPECT_TRUE(AL
.hasArg(OPT_SlurpJoined
));
225 EXPECT_EQ(AL
.getAllArgValues(OPT_SlurpJoined
).size(), 1U);
226 EXPECT_EQ(AL
.getAllArgValues(OPT_SlurpJoined
)[0], "foo");
229 TEST(Option
, SlurpJoinedAndSeparate
) {
233 const char *MyArgs
[] = { "-A", "-slurpjoinedfoo", "bar", "baz" };
234 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
235 EXPECT_TRUE(AL
.hasArg(OPT_A
));
236 EXPECT_TRUE(AL
.hasArg(OPT_SlurpJoined
));
237 EXPECT_EQ(3U, AL
.getAllArgValues(OPT_SlurpJoined
).size());
238 EXPECT_EQ("foo", AL
.getAllArgValues(OPT_SlurpJoined
)[0]);
239 EXPECT_EQ("bar", AL
.getAllArgValues(OPT_SlurpJoined
)[1]);
240 EXPECT_EQ("baz", AL
.getAllArgValues(OPT_SlurpJoined
)[2]);
243 TEST(Option
, SlurpJoinedButSeparate
) {
247 const char *MyArgs
[] = { "-A", "-slurpjoined", "foo", "bar", "baz" };
248 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
249 EXPECT_TRUE(AL
.hasArg(OPT_A
));
250 EXPECT_TRUE(AL
.hasArg(OPT_SlurpJoined
));
251 EXPECT_EQ(3U, AL
.getAllArgValues(OPT_SlurpJoined
).size());
252 EXPECT_EQ("foo", AL
.getAllArgValues(OPT_SlurpJoined
)[0]);
253 EXPECT_EQ("bar", AL
.getAllArgValues(OPT_SlurpJoined
)[1]);
254 EXPECT_EQ("baz", AL
.getAllArgValues(OPT_SlurpJoined
)[2]);
257 TEST(Option
, FlagAliasToJoined
) {
261 // Check that a flag alias provides an empty argument to a joined option.
262 const char *MyArgs
[] = { "-K" };
263 InputArgList AL
= T
.ParseArgs(MyArgs
, MAI
, MAC
);
264 EXPECT_EQ(AL
.size(), 1U);
265 EXPECT_TRUE(AL
.hasArg(OPT_B
));
266 EXPECT_EQ(1U, AL
.getAllArgValues(OPT_B
).size());
267 EXPECT_EQ("", AL
.getAllArgValues(OPT_B
)[0]);
270 TEST(Option
, FindNearest
) {
274 // Options that are too short should not be considered
275 // "near" other short options.
276 EXPECT_GT(T
.findNearest("-A", Nearest
), 4U);
277 EXPECT_GT(T
.findNearest("/C", Nearest
), 4U);
278 EXPECT_GT(T
.findNearest("--C=foo", Nearest
), 4U);
280 // The nearest candidate should mirror the amount of prefix
281 // characters used in the original string.
282 EXPECT_EQ(1U, T
.findNearest("-blorb", Nearest
));
283 EXPECT_EQ(Nearest
, "-blorp");
284 EXPECT_EQ(1U, T
.findNearest("--blorm", Nearest
));
285 EXPECT_EQ(Nearest
, "--blorp");
286 EXPECT_EQ(1U, T
.findNearest("-fjormp", Nearest
));
287 EXPECT_EQ(Nearest
, "--fjormp");
289 // The nearest candidate respects the prefix and value delimiter
290 // of the original string.
291 EXPECT_EQ(1U, T
.findNearest("/framb:foo", Nearest
));
292 EXPECT_EQ(Nearest
, "/cramb:foo");
294 // Flags should be included and excluded as specified.
295 EXPECT_EQ(1U, T
.findNearest("-doopf", Nearest
, /*FlagsToInclude=*/OptFlag2
));
296 EXPECT_EQ(Nearest
, "-doopf2");
297 EXPECT_EQ(1U, T
.findNearest("-doopf", Nearest
,
298 /*FlagsToInclude=*/0,
299 /*FlagsToExclude=*/OptFlag2
));
300 EXPECT_EQ(Nearest
, "-doopf1");
303 TEST(DISABLED_Option
, FindNearestFIXME
) {
307 // FIXME: Options with joined values should not have those values considered
308 // when calculating distance. The test below would fail if run, but it should
310 EXPECT_EQ(1U, T
.findNearest("--erbghFoo", Nearest
));
311 EXPECT_EQ(Nearest
, "--ermghFoo");