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, array_lengthof(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   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 
    111 TEST(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 
    140 TEST(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 
    150 TEST(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 
    162 TEST(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 
    173 TEST(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 
    184 TEST(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 
    196 TEST(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