blob: 6ac6283327bbc8949d9e6b8439ff2f5970b81abe [file] [log] [blame]
Michael J. Spencer41ee0412012-12-05 00:29:32 +00001//===- 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
Reid Klecknerdd44a362013-07-19 18:05:13 +000010#include "llvm/ADT/STLExtras.h"
Michael J. Spencer41ee0412012-12-05 00:29:32 +000011#include "llvm/Option/Arg.h"
12#include "llvm/Option/ArgList.h"
13#include "llvm/Option/Option.h"
Michael J. Spencer41ee0412012-12-05 00:29:32 +000014#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.
Yuka Takahashiba5d4af2017-06-20 16:31:31 +000021#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
22 HELPTEXT, METAVAR, VALUES) \
23 OPT_##ID,
Michael J. Spencer41ee0412012-12-05 00:29:32 +000024#include "Opts.inc"
25 LastOption
26#undef OPTION
27};
28
29#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
30#include "Opts.inc"
31#undef PREFIX
32
Reid Klecknerdd44a362013-07-19 18:05:13 +000033enum OptionFlags {
34 OptFlag1 = (1 << 4),
35 OptFlag2 = (1 << 5),
36 OptFlag3 = (1 << 6)
37};
38
Michael J. Spencer41ee0412012-12-05 00:29:32 +000039static const OptTable::Info InfoTable[] = {
Yuka Takahashiba5d4af2017-06-20 16:31:31 +000040#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},
Michael J. Spencer41ee0412012-12-05 00:29:32 +000044#include "Opts.inc"
45#undef OPTION
46};
47
48namespace {
49class TestOptTable : public OptTable {
50public:
Rui Ueyama8fb5a912013-08-28 20:04:31 +000051 TestOptTable(bool IgnoreCase = false)
Craig Topper8ea23902015-10-21 16:30:42 +000052 : OptTable(InfoTable, IgnoreCase) {}
Michael J. Spencer41ee0412012-12-05 00:29:32 +000053};
54}
55
56const char *Args[] = {
57 "-A",
58 "-Bhi",
59 "--C=desu",
60 "-C", "bye",
61 "-D,adena",
62 "-E", "apple", "bloom",
63 "-Fblarg",
64 "-F", "42",
65 "-Gchuu", "2"
66 };
67
Reid Klecknerdd44a362013-07-19 18:05:13 +000068TEST(Option, OptionParsing) {
Michael J. Spencer41ee0412012-12-05 00:29:32 +000069 TestOptTable T;
70 unsigned MAI, MAC;
David Blaikiedb3d31d2015-06-22 22:06:37 +000071 InputArgList AL = T.ParseArgs(Args, MAI, MAC);
NAKAMURA Takumi07d2f3f2013-01-23 08:30:15 +000072
Michael J. Spencer41ee0412012-12-05 00:29:32 +000073 // Check they all exist.
David Blaikiedb3d31d2015-06-22 22:06:37 +000074 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));
Michael J. Spencer41ee0412012-12-05 00:29:32 +000081
82 // Check the values.
Hans Wennborgc940f092016-04-15 00:23:15 +000083 EXPECT_EQ("hi", AL.getLastArgValue(OPT_B));
84 EXPECT_EQ("bye", AL.getLastArgValue(OPT_C));
85 EXPECT_EQ("adena", AL.getLastArgValue(OPT_D));
David Blaikiedb3d31d2015-06-22 22:06:37 +000086 std::vector<std::string> Es = AL.getAllArgValues(OPT_E);
Hans Wennborgc940f092016-04-15 00:23:15 +000087 EXPECT_EQ("apple", Es[0]);
88 EXPECT_EQ("bloom", Es[1]);
89 EXPECT_EQ("42", AL.getLastArgValue(OPT_F));
David Blaikiedb3d31d2015-06-22 22:06:37 +000090 std::vector<std::string> Gs = AL.getAllArgValues(OPT_G);
Hans Wennborgc940f092016-04-15 00:23:15 +000091 EXPECT_EQ("chuu", Gs[0]);
92 EXPECT_EQ("2", Gs[1]);
Michael J. Spencer41ee0412012-12-05 00:29:32 +000093
94 // Check the help text.
95 std::string Help;
96 raw_string_ostream RSO(Help);
97 T.PrintHelp(RSO, "test", "title!");
Hans Wennborgc940f092016-04-15 00:23:15 +000098 EXPECT_NE(std::string::npos, Help.find("-A"));
Michael J. Spencer41ee0412012-12-05 00:29:32 +000099
100 // Test aliases.
Richard Smith6fd4bc62017-04-12 23:43:58 +0000101 auto Cs = AL.filtered(OPT_C);
102 ASSERT_NE(Cs.begin(), Cs.end());
103 EXPECT_EQ("desu", StringRef((*Cs.begin())->getValue()));
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000104 ArgStringList ASL;
Richard Smith6fd4bc62017-04-12 23:43:58 +0000105 (*Cs.begin())->render(AL, ASL);
Hans Wennborgc940f092016-04-15 00:23:15 +0000106 ASSERT_EQ(2u, ASL.size());
107 EXPECT_EQ("-C", StringRef(ASL[0]));
108 EXPECT_EQ("desu", StringRef(ASL[1]));
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000109}
Reid Klecknerdd44a362013-07-19 18:05:13 +0000110
111TEST(Option, ParseWithFlagExclusions) {
112 TestOptTable T;
113 unsigned MAI, MAC;
Reid Klecknerdd44a362013-07-19 18:05:13 +0000114
115 // Exclude flag3 to avoid parsing as OPT_SLASH_C.
David Blaikiedb3d31d2015-06-22 22:06:37 +0000116 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));
Reid Klecknerdd44a362013-07-19 18:05:13 +0000122
123 // Exclude flag1 to avoid parsing as OPT_C.
David Blaikiedb3d31d2015-06-22 22:06:37 +0000124 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));
Reid Klecknerdd44a362013-07-19 18:05:13 +0000130
131 const char *NewArgs[] = { "/C", "foo", "--C=bar" };
David Blaikiedb3d31d2015-06-22 22:06:37 +0000132 AL = T.ParseArgs(NewArgs, MAI, MAC);
133 EXPECT_TRUE(AL.hasArg(OPT_SLASH_C));
134 EXPECT_TRUE(AL.hasArg(OPT_C));
Hans Wennborgc940f092016-04-15 00:23:15 +0000135 EXPECT_EQ("foo", AL.getLastArgValue(OPT_SLASH_C));
136 EXPECT_EQ("bar", AL.getLastArgValue(OPT_C));
Reid Klecknerdd44a362013-07-19 18:05:13 +0000137}
Hans Wennborg31d6fd82013-07-22 16:18:13 +0000138
139TEST(Option, ParseAliasInGroup) {
140 TestOptTable T;
141 unsigned MAI, MAC;
142
143 const char *MyArgs[] = { "-I" };
David Blaikiedb3d31d2015-06-22 22:06:37 +0000144 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
145 EXPECT_TRUE(AL.hasArg(OPT_H));
Hans Wennborg31d6fd82013-07-22 16:18:13 +0000146}
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000147
148TEST(Option, AliasArgs) {
149 TestOptTable T;
150 unsigned MAI, MAC;
151
152 const char *MyArgs[] = { "-J", "-Joo" };
David Blaikiedb3d31d2015-06-22 22:06:37 +0000153 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
154 EXPECT_TRUE(AL.hasArg(OPT_B));
Hans Wennborgc940f092016-04-15 00:23:15 +0000155 EXPECT_EQ("foo", AL.getAllArgValues(OPT_B)[0]);
156 EXPECT_EQ("bar", AL.getAllArgValues(OPT_B)[1]);
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000157}
Hans Wennborgb8f34202013-08-02 21:20:27 +0000158
Rui Ueyama8fb5a912013-08-28 20:04:31 +0000159TEST(Option, IgnoreCase) {
160 TestOptTable T(true);
161 unsigned MAI, MAC;
162
163 const char *MyArgs[] = { "-a", "-joo" };
David Blaikiedb3d31d2015-06-22 22:06:37 +0000164 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
165 EXPECT_TRUE(AL.hasArg(OPT_A));
166 EXPECT_TRUE(AL.hasArg(OPT_B));
Rui Ueyama8fb5a912013-08-28 20:04:31 +0000167}
168
169TEST(Option, DoNotIgnoreCase) {
170 TestOptTable T;
171 unsigned MAI, MAC;
172
173 const char *MyArgs[] = { "-a", "-joo" };
David Blaikiedb3d31d2015-06-22 22:06:37 +0000174 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
175 EXPECT_FALSE(AL.hasArg(OPT_A));
176 EXPECT_FALSE(AL.hasArg(OPT_B));
Rui Ueyama8fb5a912013-08-28 20:04:31 +0000177}
178
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000179TEST(Option, SlurpEmpty) {
180 TestOptTable T;
181 unsigned MAI, MAC;
182
183 const char *MyArgs[] = { "-A", "-slurp" };
David Blaikiedb3d31d2015-06-22 22:06:37 +0000184 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
185 EXPECT_TRUE(AL.hasArg(OPT_A));
186 EXPECT_TRUE(AL.hasArg(OPT_Slurp));
Hans Wennborgc940f092016-04-15 00:23:15 +0000187 EXPECT_EQ(0U, AL.getAllArgValues(OPT_Slurp).size());
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000188}
189
190TEST(Option, Slurp) {
191 TestOptTable T;
192 unsigned MAI, MAC;
193
194 const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" };
David Blaikiedb3d31d2015-06-22 22:06:37 +0000195 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));
Hans Wennborgc940f092016-04-15 00:23:15 +0000200 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]);
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000204}
Hans Wennborg8d8146f2015-05-04 18:00:13 +0000205
Hans Wennborg40cfde32016-04-15 00:23:30 +0000206TEST(Option, SlurpJoinedEmpty) {
207 TestOptTable T;
208 unsigned MAI, MAC;
209
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);
215}
216
217TEST(Option, SlurpJoinedOneJoined) {
218 TestOptTable T;
219 unsigned MAI, MAC;
220
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");
227}
228
229TEST(Option, SlurpJoinedAndSeparate) {
230 TestOptTable T;
231 unsigned MAI, MAC;
232
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]);
241}
242
243TEST(Option, SlurpJoinedButSeparate) {
244 TestOptTable T;
245 unsigned MAI, MAC;
246
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]);
255}
256
Hans Wennborg8d8146f2015-05-04 18:00:13 +0000257TEST(Option, FlagAliasToJoined) {
258 TestOptTable T;
259 unsigned MAI, MAC;
260
261 // Check that a flag alias provides an empty argument to a joined option.
262 const char *MyArgs[] = { "-K" };
David Blaikiedb3d31d2015-06-22 22:06:37 +0000263 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
264 EXPECT_EQ(AL.size(), 1U);
265 EXPECT_TRUE(AL.hasArg(OPT_B));
Hans Wennborgc940f092016-04-15 00:23:15 +0000266 EXPECT_EQ(1U, AL.getAllArgValues(OPT_B).size());
267 EXPECT_EQ("", AL.getAllArgValues(OPT_B)[0]);
Hans Wennborg8d8146f2015-05-04 18:00:13 +0000268}