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, array_lengthof(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  std::unique_ptr<InputArgList> AL(
71      T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC));
72
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));
81
82  // Check the values.
83  EXPECT_EQ(AL->getLastArgValue(OPT_B), "hi");
84  EXPECT_EQ(AL->getLastArgValue(OPT_C), "bye");
85  EXPECT_EQ(AL->getLastArgValue(OPT_D), "adena");
86  std::vector<std::string> Es = AL->getAllArgValues(OPT_E);
87  EXPECT_EQ(Es[0], "apple");
88  EXPECT_EQ(Es[1], "bloom");
89  EXPECT_EQ(AL->getLastArgValue(OPT_F), "42");
90  std::vector<std::string> Gs = AL->getAllArgValues(OPT_G);
91  EXPECT_EQ(Gs[0], "chuu");
92  EXPECT_EQ(Gs[1], "2");
93
94  // Check the help text.
95  std::string Help;
96  raw_string_ostream RSO(Help);
97  T.PrintHelp(RSO, "test", "title!");
98  EXPECT_NE(Help.find("-A"), std::string::npos);
99
100  // Test aliases.
101  arg_iterator Cs = AL->filtered_begin(OPT_C);
102  ASSERT_NE(Cs, AL->filtered_end());
103  EXPECT_EQ(StringRef((*Cs)->getValue()), "desu");
104  ArgStringList ASL;
105  (*Cs)->render(*AL, ASL);
106  ASSERT_EQ(ASL.size(), 2u);
107  EXPECT_EQ(StringRef(ASL[0]), "-C");
108  EXPECT_EQ(StringRef(ASL[1]), "desu");
109}
110
111TEST(Option, ParseWithFlagExclusions) {
112  TestOptTable T;
113  unsigned MAI, MAC;
114  std::unique_ptr<InputArgList> AL;
115
116  // Exclude flag3 to avoid parsing as OPT_SLASH_C.
117  AL.reset(T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC,
118                       /*FlagsToInclude=*/0,
119                       /*FlagsToExclude=*/OptFlag3));
120  EXPECT_TRUE(AL->hasArg(OPT_A));
121  EXPECT_TRUE(AL->hasArg(OPT_C));
122  EXPECT_FALSE(AL->hasArg(OPT_SLASH_C));
123
124  // Exclude flag1 to avoid parsing as OPT_C.
125  AL.reset(T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC,
126                       /*FlagsToInclude=*/0,
127                       /*FlagsToExclude=*/OptFlag1));
128  EXPECT_TRUE(AL->hasArg(OPT_B));
129  EXPECT_FALSE(AL->hasArg(OPT_C));
130  EXPECT_TRUE(AL->hasArg(OPT_SLASH_C));
131
132  const char *NewArgs[] = { "/C", "foo", "--C=bar" };
133  AL.reset(T.ParseArgs(std::begin(NewArgs), std::end(NewArgs), MAI, MAC));
134  EXPECT_TRUE(AL->hasArg(OPT_SLASH_C));
135  EXPECT_TRUE(AL->hasArg(OPT_C));
136  EXPECT_EQ(AL->getLastArgValue(OPT_SLASH_C), "foo");
137  EXPECT_EQ(AL->getLastArgValue(OPT_C), "bar");
138}
139
140TEST(Option, ParseAliasInGroup) {
141  TestOptTable T;
142  unsigned MAI, MAC;
143
144  const char *MyArgs[] = { "-I" };
145  std::unique_ptr<InputArgList> AL(
146      T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
147  EXPECT_TRUE(AL->hasArg(OPT_H));
148}
149
150TEST(Option, AliasArgs) {
151  TestOptTable T;
152  unsigned MAI, MAC;
153
154  const char *MyArgs[] = { "-J", "-Joo" };
155  std::unique_ptr<InputArgList> AL(
156      T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
157  EXPECT_TRUE(AL->hasArg(OPT_B));
158  EXPECT_EQ(AL->getAllArgValues(OPT_B)[0], "foo");
159  EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar");
160}
161
162TEST(Option, IgnoreCase) {
163  TestOptTable T(true);
164  unsigned MAI, MAC;
165
166  const char *MyArgs[] = { "-a", "-joo" };
167  std::unique_ptr<InputArgList> AL(
168      T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
169  EXPECT_TRUE(AL->hasArg(OPT_A));
170  EXPECT_TRUE(AL->hasArg(OPT_B));
171}
172
173TEST(Option, DoNotIgnoreCase) {
174  TestOptTable T;
175  unsigned MAI, MAC;
176
177  const char *MyArgs[] = { "-a", "-joo" };
178  std::unique_ptr<InputArgList> AL(
179      T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
180  EXPECT_FALSE(AL->hasArg(OPT_A));
181  EXPECT_FALSE(AL->hasArg(OPT_B));
182}
183
184TEST(Option, SlurpEmpty) {
185  TestOptTable T;
186  unsigned MAI, MAC;
187
188  const char *MyArgs[] = { "-A", "-slurp" };
189  std::unique_ptr<InputArgList> AL(
190      T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
191  EXPECT_TRUE(AL->hasArg(OPT_A));
192  EXPECT_TRUE(AL->hasArg(OPT_Slurp));
193  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 0U);
194}
195
196TEST(Option, Slurp) {
197  TestOptTable T;
198  unsigned MAI, MAC;
199
200  const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" };
201  std::unique_ptr<InputArgList> AL(
202      T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
203  EXPECT_EQ(AL->size(), 2U);
204  EXPECT_TRUE(AL->hasArg(OPT_A));
205  EXPECT_FALSE(AL->hasArg(OPT_B));
206  EXPECT_TRUE(AL->hasArg(OPT_Slurp));
207  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 3U);
208  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[0], "-B");
209  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[1], "--");
210  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[2], "foo");
211}
212