Home | History | Annotate | Download | only in Option
      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 
     16 using namespace llvm;
     17 using namespace llvm::opt;
     18 
     19 enum 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 
     32 enum OptionFlags {
     33   OptFlag1 = (1 << 4),
     34   OptFlag2 = (1 << 5),
     35   OptFlag3 = (1 << 6)
     36 };
     37 
     38 static 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 
     47 namespace {
     48 class TestOptTable : public OptTable {
     49 public:
     50   TestOptTable(bool IgnoreCase = false)
     51     : OptTable(InfoTable, IgnoreCase) {}
     52 };
     53 }
     54 
     55 const 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 
     67 TEST(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(AL.getLastArgValue(OPT_B), "hi");
     83   EXPECT_EQ(AL.getLastArgValue(OPT_C), "bye");
     84   EXPECT_EQ(AL.getLastArgValue(OPT_D), "adena");
     85   std::vector<std::string> Es = AL.getAllArgValues(OPT_E);
     86   EXPECT_EQ(Es[0], "apple");
     87   EXPECT_EQ(Es[1], "bloom");
     88   EXPECT_EQ(AL.getLastArgValue(OPT_F), "42");
     89   std::vector<std::string> Gs = AL.getAllArgValues(OPT_G);
     90   EXPECT_EQ(Gs[0], "chuu");
     91   EXPECT_EQ(Gs[1], "2");
     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(Help.find("-A"), std::string::npos);
     98 
     99   // Test aliases.
    100   arg_iterator Cs = AL.filtered_begin(OPT_C);
    101   ASSERT_NE(Cs, AL.filtered_end());
    102   EXPECT_EQ(StringRef((*Cs)->getValue()), "desu");
    103   ArgStringList ASL;
    104   (*Cs)->render(AL, ASL);
    105   ASSERT_EQ(ASL.size(), 2u);
    106   EXPECT_EQ(StringRef(ASL[0]), "-C");
    107   EXPECT_EQ(StringRef(ASL[1]), "desu");
    108 }
    109 
    110 TEST(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(AL.getLastArgValue(OPT_SLASH_C), "foo");
    135   EXPECT_EQ(AL.getLastArgValue(OPT_C), "bar");
    136 }
    137 
    138 TEST(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 
    147 TEST(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(AL.getAllArgValues(OPT_B)[0], "foo");
    155   EXPECT_EQ(AL.getAllArgValues(OPT_B)[1], "bar");
    156 }
    157 
    158 TEST(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 
    168 TEST(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 
    178 TEST(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(AL.getAllArgValues(OPT_Slurp).size(), 0U);
    187 }
    188 
    189 TEST(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(AL.getAllArgValues(OPT_Slurp).size(), 3U);
    200   EXPECT_EQ(AL.getAllArgValues(OPT_Slurp)[0], "-B");
    201   EXPECT_EQ(AL.getAllArgValues(OPT_Slurp)[1], "--");
    202   EXPECT_EQ(AL.getAllArgValues(OPT_Slurp)[2], "foo");
    203 }
    204 
    205 TEST(Option, FlagAliasToJoined) {
    206   TestOptTable T;
    207   unsigned MAI, MAC;
    208 
    209   // Check that a flag alias provides an empty argument to a joined option.
    210   const char *MyArgs[] = { "-K" };
    211   InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
    212   EXPECT_EQ(AL.size(), 1U);
    213   EXPECT_TRUE(AL.hasArg(OPT_B));
    214   EXPECT_EQ(AL.getAllArgValues(OPT_B).size(), 1U);
    215   EXPECT_EQ(AL.getAllArgValues(OPT_B)[0], "");
    216 }
    217