Option parsing: add support for alias arguments.
[oota-llvm.git] / unittests / Option / OptionParsingTest.cpp
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/OwningPtr.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Option/Arg.h"
13 #include "llvm/Option/ArgList.h"
14 #include "llvm/Option/Option.h"
15 #include "gtest/gtest.h"
16
17 using namespace llvm;
18 using namespace llvm::opt;
19
20 #define SUPPORT_ALIASARGS // FIXME: Remove when no longer necessary.
21
22 enum ID {
23   OPT_INVALID = 0, // This is not an option ID.
24 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
25               HELPTEXT, METAVAR) OPT_##ID,
26 #include "Opts.inc"
27   LastOption
28 #undef OPTION
29 };
30
31 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
32 #include "Opts.inc"
33 #undef PREFIX
34
35 enum OptionFlags {
36   OptFlag1 = (1 << 4),
37   OptFlag2 = (1 << 5),
38   OptFlag3 = (1 << 6)
39 };
40
41 static const OptTable::Info InfoTable[] = {
42 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
43                HELPTEXT, METAVAR)   \
44   { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
45     FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
46 #include "Opts.inc"
47 #undef OPTION
48 };
49
50 namespace {
51 class TestOptTable : public OptTable {
52 public:
53   TestOptTable()
54     : OptTable(InfoTable, array_lengthof(InfoTable)) {}
55 };
56 }
57
58 const char *Args[] = {
59   "-A",
60   "-Bhi",
61   "--C=desu",
62   "-C", "bye",
63   "-D,adena",
64   "-E", "apple", "bloom",
65   "-Fblarg",
66   "-F", "42",
67   "-Gchuu", "2"
68   };
69
70 TEST(Option, OptionParsing) {
71   TestOptTable T;
72   unsigned MAI, MAC;
73   OwningPtr<InputArgList> AL(T.ParseArgs(Args, array_endof(Args), MAI, MAC));
74
75   // Check they all exist.
76   EXPECT_TRUE(AL->hasArg(OPT_A));
77   EXPECT_TRUE(AL->hasArg(OPT_B));
78   EXPECT_TRUE(AL->hasArg(OPT_C));
79   EXPECT_TRUE(AL->hasArg(OPT_D));
80   EXPECT_TRUE(AL->hasArg(OPT_E));
81   EXPECT_TRUE(AL->hasArg(OPT_F));
82   EXPECT_TRUE(AL->hasArg(OPT_G));
83
84   // Check the values.
85   EXPECT_EQ(AL->getLastArgValue(OPT_B), "hi");
86   EXPECT_EQ(AL->getLastArgValue(OPT_C), "bye");
87   EXPECT_EQ(AL->getLastArgValue(OPT_D), "adena");
88   std::vector<std::string> Es = AL->getAllArgValues(OPT_E);
89   EXPECT_EQ(Es[0], "apple");
90   EXPECT_EQ(Es[1], "bloom");
91   EXPECT_EQ(AL->getLastArgValue(OPT_F), "42");
92   std::vector<std::string> Gs = AL->getAllArgValues(OPT_G);
93   EXPECT_EQ(Gs[0], "chuu");
94   EXPECT_EQ(Gs[1], "2");
95
96   // Check the help text.
97   std::string Help;
98   raw_string_ostream RSO(Help);
99   T.PrintHelp(RSO, "test", "title!");
100   EXPECT_NE(Help.find("-A"), std::string::npos);
101
102   // Test aliases.
103   arg_iterator Cs = AL->filtered_begin(OPT_C);
104   ASSERT_NE(Cs, AL->filtered_end());
105   EXPECT_EQ(StringRef((*Cs)->getValue()), "desu");
106   ArgStringList ASL;
107   (*Cs)->render(*AL, ASL);
108   ASSERT_EQ(ASL.size(), 2u);
109   EXPECT_EQ(StringRef(ASL[0]), "-C");
110   EXPECT_EQ(StringRef(ASL[1]), "desu");
111 }
112
113 TEST(Option, ParseWithFlagExclusions) {
114   TestOptTable T;
115   unsigned MAI, MAC;
116   OwningPtr<InputArgList> AL;
117
118   // Exclude flag3 to avoid parsing as OPT_SLASH_C.
119   AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC,
120                        /*FlagsToInclude=*/0,
121                        /*FlagsToExclude=*/OptFlag3));
122   EXPECT_TRUE(AL->hasArg(OPT_A));
123   EXPECT_TRUE(AL->hasArg(OPT_C));
124   EXPECT_FALSE(AL->hasArg(OPT_SLASH_C));
125
126   // Exclude flag1 to avoid parsing as OPT_C.
127   AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC,
128                        /*FlagsToInclude=*/0,
129                        /*FlagsToExclude=*/OptFlag1));
130   EXPECT_TRUE(AL->hasArg(OPT_B));
131   EXPECT_FALSE(AL->hasArg(OPT_C));
132   EXPECT_TRUE(AL->hasArg(OPT_SLASH_C));
133
134   const char *NewArgs[] = { "/C", "foo", "--C=bar" };
135   AL.reset(T.ParseArgs(NewArgs, array_endof(NewArgs), MAI, MAC));
136   EXPECT_TRUE(AL->hasArg(OPT_SLASH_C));
137   EXPECT_TRUE(AL->hasArg(OPT_C));
138   EXPECT_EQ(AL->getLastArgValue(OPT_SLASH_C), "foo");
139   EXPECT_EQ(AL->getLastArgValue(OPT_C), "bar");
140 }
141
142 TEST(Option, ParseAliasInGroup) {
143   TestOptTable T;
144   unsigned MAI, MAC;
145
146   const char *MyArgs[] = { "-I" };
147   OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
148   EXPECT_TRUE(AL->hasArg(OPT_H));
149 }
150
151 TEST(Option, AliasArgs) {
152   TestOptTable T;
153   unsigned MAI, MAC;
154
155   const char *MyArgs[] = { "-J", "-Joo" };
156   OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(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 }