562 lines · cpp
1//===- unittest/Support/OptionParsingTest.cpp - OptTable tests ------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/STLExtras.h"10#include "llvm/Option/Arg.h"11#include "llvm/Option/ArgList.h"12#include "llvm/Option/OptTable.h"13#include "llvm/Option/Option.h"14#include "gtest/gtest.h"15 16using namespace llvm;17using namespace llvm::opt;18 19#if defined(__clang__)20#pragma clang diagnostic ignored "-Wdeprecated-declarations"21#endif22 23#define OPTTABLE_STR_TABLE_CODE24#include "Opts.inc"25#undef OPTTABLE_STR_TABLE_CODE26 27enum ID {28 OPT_INVALID = 0, // This is not an option ID.29#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),30#include "Opts.inc"31 LastOption32#undef OPTION33};34 35#define OPTTABLE_PREFIXES_TABLE_CODE36#include "Opts.inc"37#undef OPTTABLE_PREFIXES_TABLE_CODE38 39#define OPTTABLE_PREFIXES_UNION_CODE40#include "Opts.inc"41#undef OPTTABLE_PREFIXES_UNION_CODE42 43enum OptionFlags {44 OptFlag1 = (1 << 4),45 OptFlag2 = (1 << 5),46 OptFlag3 = (1 << 6)47};48 49enum OptionVisibility {50 SubtoolVis = (1 << 2),51 MultiLineVis = (1 << 3),52};53 54static constexpr OptTable::Info InfoTable[] = {55#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),56#include "Opts.inc"57#undef OPTION58};59 60namespace {61class TestOptTable : public GenericOptTable {62public:63 TestOptTable(bool IgnoreCase = false)64 : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable,65 IgnoreCase) {}66};67 68class TestPrecomputedOptTable : public PrecomputedOptTable {69public:70 TestPrecomputedOptTable(bool IgnoreCase = false)71 : PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, InfoTable,72 OptionPrefixesUnion, IgnoreCase) {}73};74}75 76const char *Args[] = {77 "-A",78 "-Bhi",79 "--C=desu",80 "-C", "bye",81 "-D,adena",82 "-E", "apple", "bloom",83 "-Fblarg",84 "-F", "42",85 "-Gchuu", "2"86 };87 88// Test fixture89template <typename T> class OptTableTest : public ::testing::Test {};90 91template <typename T> class DISABLED_OptTableTest : public ::testing::Test {};92 93// Test both precomputed and computed OptTables with the same suite of tests.94using OptTableTestTypes =95 ::testing::Types<TestOptTable, TestPrecomputedOptTable>;96 97TYPED_TEST_SUITE(OptTableTest, OptTableTestTypes, );98TYPED_TEST_SUITE(DISABLED_OptTableTest, OptTableTestTypes, );99 100TYPED_TEST(OptTableTest, OptionParsing) {101 TypeParam T;102 unsigned MAI, MAC;103 InputArgList AL = T.ParseArgs(Args, MAI, MAC);104 105 // Check they all exist.106 EXPECT_TRUE(AL.hasArg(OPT_A));107 EXPECT_TRUE(AL.hasArg(OPT_B));108 EXPECT_TRUE(AL.hasArg(OPT_C));109 EXPECT_TRUE(AL.hasArg(OPT_D));110 EXPECT_TRUE(AL.hasArg(OPT_E));111 EXPECT_TRUE(AL.hasArg(OPT_F));112 EXPECT_TRUE(AL.hasArg(OPT_G));113 114 // Check the values.115 EXPECT_EQ("hi", AL.getLastArgValue(OPT_B));116 EXPECT_EQ("bye", AL.getLastArgValue(OPT_C));117 EXPECT_EQ("adena", AL.getLastArgValue(OPT_D));118 std::vector<std::string> Es = AL.getAllArgValues(OPT_E);119 EXPECT_EQ("apple", Es[0]);120 EXPECT_EQ("bloom", Es[1]);121 EXPECT_EQ("42", AL.getLastArgValue(OPT_F));122 std::vector<std::string> Gs = AL.getAllArgValues(OPT_G);123 EXPECT_EQ("chuu", Gs[0]);124 EXPECT_EQ("2", Gs[1]);125 126 // Check the help text.127 std::string Help;128 raw_string_ostream RSO(Help);129 T.printHelp(RSO, "test", "title!");130 EXPECT_NE(std::string::npos, Help.find("-A"));131 132 // Check usage line.133 T.printHelp(RSO, "name [options] file...", "title!");134 EXPECT_NE(std::string::npos, Help.find("USAGE: name [options] file...\n"));135 136 // Test aliases.137 auto Cs = AL.filtered(OPT_C);138 ASSERT_NE(Cs.begin(), Cs.end());139 EXPECT_EQ("desu", StringRef((*Cs.begin())->getValue()));140 ArgStringList ASL;141 (*Cs.begin())->render(AL, ASL);142 ASSERT_EQ(2u, ASL.size());143 EXPECT_EQ("-C", StringRef(ASL[0]));144 EXPECT_EQ("desu", StringRef(ASL[1]));145}146 147TYPED_TEST(OptTableTest, ParseWithFlagExclusions) {148 TypeParam T;149 unsigned MAI, MAC;150 151 // Exclude flag3 to avoid parsing as OPT_SLASH_C.152 InputArgList AL = T.ParseArgs(Args, MAI, MAC,153 /*FlagsToInclude=*/0,154 /*FlagsToExclude=*/OptFlag3);155 EXPECT_TRUE(AL.hasArg(OPT_A));156 EXPECT_TRUE(AL.hasArg(OPT_C));157 EXPECT_FALSE(AL.hasArg(OPT_SLASH_C));158 159 // Exclude flag1 to avoid parsing as OPT_C.160 AL = T.ParseArgs(Args, MAI, MAC,161 /*FlagsToInclude=*/0,162 /*FlagsToExclude=*/OptFlag1);163 EXPECT_TRUE(AL.hasArg(OPT_B));164 EXPECT_FALSE(AL.hasArg(OPT_C));165 EXPECT_TRUE(AL.hasArg(OPT_SLASH_C));166 167 const char *NewArgs[] = { "/C", "foo", "--C=bar" };168 AL = T.ParseArgs(NewArgs, MAI, MAC);169 EXPECT_TRUE(AL.hasArg(OPT_SLASH_C));170 EXPECT_TRUE(AL.hasArg(OPT_C));171 EXPECT_EQ("foo", AL.getLastArgValue(OPT_SLASH_C));172 EXPECT_EQ("bar", AL.getLastArgValue(OPT_C));173}174 175TYPED_TEST(OptTableTest, ParseWithVisibility) {176 TypeParam T;177 unsigned MAI, MAC;178 179 const char *STArgs[] = {"-A", "-Q", "-R"};180 181 // With no visibility specified, we find all of the arguments.182 InputArgList AL = T.ParseArgs(STArgs, MAI, MAC);183 EXPECT_TRUE(AL.hasArg(OPT_A));184 EXPECT_TRUE(AL.hasArg(OPT_Q));185 EXPECT_TRUE(AL.hasArg(OPT_R));186 187 // Default visibility omits SubtoolVis.188 AL = T.ParseArgs(STArgs, MAI, MAC, Visibility(DefaultVis));189 EXPECT_TRUE(AL.hasArg(OPT_A));190 EXPECT_FALSE(AL.hasArg(OPT_Q));191 EXPECT_TRUE(AL.hasArg(OPT_R));192 193 // ~SubtoolVis still finds arguments that are visible in Default.194 AL = T.ParseArgs(STArgs, MAI, MAC, Visibility(~SubtoolVis));195 EXPECT_TRUE(AL.hasArg(OPT_A));196 EXPECT_FALSE(AL.hasArg(OPT_Q));197 EXPECT_TRUE(AL.hasArg(OPT_R));198 199 // Only SubtoolVis.200 AL = T.ParseArgs(STArgs, MAI, MAC, Visibility(SubtoolVis));201 EXPECT_FALSE(AL.hasArg(OPT_A));202 EXPECT_TRUE(AL.hasArg(OPT_Q));203 EXPECT_TRUE(AL.hasArg(OPT_R));204 205 // Both Default and SubtoolVis are found.206 AL = T.ParseArgs(STArgs, MAI, MAC, Visibility(DefaultVis | SubtoolVis));207 EXPECT_TRUE(AL.hasArg(OPT_A));208 EXPECT_TRUE(AL.hasArg(OPT_Q));209 EXPECT_TRUE(AL.hasArg(OPT_R));210}211 212TYPED_TEST(OptTableTest, ParseAliasInGroup) {213 TypeParam T;214 unsigned MAI, MAC;215 216 const char *MyArgs[] = { "-I" };217 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);218 EXPECT_TRUE(AL.hasArg(OPT_H));219}220 221TYPED_TEST(OptTableTest, AliasArgs) {222 TypeParam T;223 unsigned MAI, MAC;224 225 const char *MyArgs[] = { "-J", "-Joo" };226 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);227 EXPECT_TRUE(AL.hasArg(OPT_B));228 EXPECT_EQ("foo", AL.getAllArgValues(OPT_B)[0]);229 EXPECT_EQ("bar", AL.getAllArgValues(OPT_B)[1]);230}231 232TYPED_TEST(OptTableTest, IgnoreCase) {233 TypeParam T(true);234 unsigned MAI, MAC;235 236 const char *MyArgs[] = { "-a", "-joo" };237 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);238 EXPECT_TRUE(AL.hasArg(OPT_A));239 EXPECT_TRUE(AL.hasArg(OPT_B));240}241 242#if defined(__clang__)243// Disable the warning that triggers on exactly what is being tested.244#pragma clang diagnostic push245#pragma clang diagnostic ignored "-Wself-move"246#endif247 248TYPED_TEST(OptTableTest, InputArgListSelfAssign) {249 TypeParam T;250 unsigned MAI, MAC;251 InputArgList AL = T.ParseArgs(Args, MAI, MAC,252 /*FlagsToInclude=*/0,253 /*FlagsToExclude=*/OptFlag3);254 EXPECT_TRUE(AL.hasArg(OPT_A));255 EXPECT_TRUE(AL.hasArg(OPT_C));256 EXPECT_FALSE(AL.hasArg(OPT_SLASH_C));257 258 AL = std::move(AL);259 260 EXPECT_TRUE(AL.hasArg(OPT_A));261 EXPECT_TRUE(AL.hasArg(OPT_C));262 EXPECT_FALSE(AL.hasArg(OPT_SLASH_C));263}264 265#if defined(__clang__)266#pragma clang diagnostic pop267#endif268 269TYPED_TEST(OptTableTest, DoNotIgnoreCase) {270 TypeParam T;271 unsigned MAI, MAC;272 273 const char *MyArgs[] = { "-a", "-joo" };274 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);275 EXPECT_FALSE(AL.hasArg(OPT_A));276 EXPECT_FALSE(AL.hasArg(OPT_B));277}278 279TYPED_TEST(OptTableTest, SlurpEmpty) {280 TypeParam T;281 unsigned MAI, MAC;282 283 const char *MyArgs[] = { "-A", "-slurp" };284 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);285 EXPECT_TRUE(AL.hasArg(OPT_A));286 EXPECT_TRUE(AL.hasArg(OPT_Slurp));287 EXPECT_EQ(0U, AL.getAllArgValues(OPT_Slurp).size());288}289 290TYPED_TEST(OptTableTest, Slurp) {291 TypeParam T;292 unsigned MAI, MAC;293 294 const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" };295 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);296 EXPECT_EQ(AL.size(), 2U);297 EXPECT_TRUE(AL.hasArg(OPT_A));298 EXPECT_FALSE(AL.hasArg(OPT_B));299 EXPECT_TRUE(AL.hasArg(OPT_Slurp));300 EXPECT_EQ(3U, AL.getAllArgValues(OPT_Slurp).size());301 EXPECT_EQ("-B", AL.getAllArgValues(OPT_Slurp)[0]);302 EXPECT_EQ("--", AL.getAllArgValues(OPT_Slurp)[1]);303 EXPECT_EQ("foo", AL.getAllArgValues(OPT_Slurp)[2]);304}305 306TYPED_TEST(OptTableTest, SlurpJoinedEmpty) {307 TypeParam T;308 unsigned MAI, MAC;309 310 const char *MyArgs[] = { "-A", "-slurpjoined" };311 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);312 EXPECT_TRUE(AL.hasArg(OPT_A));313 EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined));314 EXPECT_EQ(AL.getAllArgValues(OPT_SlurpJoined).size(), 0U);315}316 317TYPED_TEST(OptTableTest, SlurpJoinedOneJoined) {318 TypeParam T;319 unsigned MAI, MAC;320 321 const char *MyArgs[] = { "-A", "-slurpjoinedfoo" };322 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);323 EXPECT_TRUE(AL.hasArg(OPT_A));324 EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined));325 EXPECT_EQ(AL.getAllArgValues(OPT_SlurpJoined).size(), 1U);326 EXPECT_EQ(AL.getAllArgValues(OPT_SlurpJoined)[0], "foo");327}328 329TYPED_TEST(OptTableTest, SlurpJoinedAndSeparate) {330 TypeParam T;331 unsigned MAI, MAC;332 333 const char *MyArgs[] = { "-A", "-slurpjoinedfoo", "bar", "baz" };334 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);335 EXPECT_TRUE(AL.hasArg(OPT_A));336 EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined));337 EXPECT_EQ(3U, AL.getAllArgValues(OPT_SlurpJoined).size());338 EXPECT_EQ("foo", AL.getAllArgValues(OPT_SlurpJoined)[0]);339 EXPECT_EQ("bar", AL.getAllArgValues(OPT_SlurpJoined)[1]);340 EXPECT_EQ("baz", AL.getAllArgValues(OPT_SlurpJoined)[2]);341}342 343TYPED_TEST(OptTableTest, SlurpJoinedButSeparate) {344 TypeParam T;345 unsigned MAI, MAC;346 347 const char *MyArgs[] = { "-A", "-slurpjoined", "foo", "bar", "baz" };348 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);349 EXPECT_TRUE(AL.hasArg(OPT_A));350 EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined));351 EXPECT_EQ(3U, AL.getAllArgValues(OPT_SlurpJoined).size());352 EXPECT_EQ("foo", AL.getAllArgValues(OPT_SlurpJoined)[0]);353 EXPECT_EQ("bar", AL.getAllArgValues(OPT_SlurpJoined)[1]);354 EXPECT_EQ("baz", AL.getAllArgValues(OPT_SlurpJoined)[2]);355}356 357TYPED_TEST(OptTableTest, FlagAliasToJoined) {358 TypeParam T;359 unsigned MAI, MAC;360 361 // Check that a flag alias provides an empty argument to a joined option.362 const char *MyArgs[] = { "-K" };363 InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);364 EXPECT_EQ(AL.size(), 1U);365 EXPECT_TRUE(AL.hasArg(OPT_B));366 EXPECT_EQ(1U, AL.getAllArgValues(OPT_B).size());367 EXPECT_EQ("", AL.getAllArgValues(OPT_B)[0]);368}369 370TYPED_TEST(OptTableTest, FindNearest) {371 TypeParam T;372 std::string Nearest;373 374 // Options that are too short should not be considered375 // "near" other short options.376 EXPECT_GT(T.findNearest("-A", Nearest), 4U);377 EXPECT_GT(T.findNearest("/C", Nearest), 4U);378 EXPECT_GT(T.findNearest("--C=foo", Nearest), 4U);379 380 // The nearest candidate should mirror the amount of prefix381 // characters used in the original string.382 EXPECT_EQ(1U, T.findNearest("-blorb", Nearest));383 EXPECT_EQ(Nearest, "-blorp");384 EXPECT_EQ(1U, T.findNearest("--blorm", Nearest));385 EXPECT_EQ(Nearest, "--blorp");386 EXPECT_EQ(1U, T.findNearest("-blarg", Nearest));387 EXPECT_EQ(Nearest, "-blarn");388 EXPECT_EQ(1U, T.findNearest("--blarm", Nearest));389 EXPECT_EQ(Nearest, "--blarn");390 EXPECT_EQ(1U, T.findNearest("-fjormp", Nearest));391 EXPECT_EQ(Nearest, "--fjormp");392 393 // The nearest candidate respects the prefix and value delimiter394 // of the original string.395 EXPECT_EQ(1U, T.findNearest("/framb:foo", Nearest));396 EXPECT_EQ(Nearest, "/cramb:foo");397 398 // `--glormp` should have an editing distance > 0 from `--glormp=`.399 EXPECT_GT(T.findNearest("--glorrmp", Nearest), 0U);400 EXPECT_EQ(Nearest, "--glorrmp=");401 EXPECT_EQ(0U, T.findNearest("--glorrmp=foo", Nearest));402 403 // `--blurmps` should correct to `--blurmp`, not `--blurmp=`, even though404 // both naively have an editing distance of 1.405 EXPECT_EQ(1U, T.findNearest("--blurmps", Nearest));406 EXPECT_EQ(Nearest, "--blurmp");407 408 // ...but `--blurmps=foo` should correct to `--blurmp=foo`.409 EXPECT_EQ(1U, T.findNearest("--blurmps=foo", Nearest));410 EXPECT_EQ(Nearest, "--blurmp=foo");411 412 // Flags should be included and excluded as specified.413 EXPECT_EQ(1U, T.findNearest("-doopf", Nearest,414 /*FlagsToInclude=*/OptFlag2,415 /*FlagsToExclude=*/0));416 EXPECT_EQ(Nearest, "-doopf2");417 EXPECT_EQ(1U, T.findNearest("-doopf", Nearest,418 /*FlagsToInclude=*/0,419 /*FlagsToExclude=*/OptFlag2));420 EXPECT_EQ(Nearest, "-doopf1");421 422 // Spelling should respect visibility.423 EXPECT_EQ(1U, T.findNearest("-xyzzy", Nearest, Visibility(DefaultVis)));424 EXPECT_EQ(Nearest, "-xyzzy2");425 EXPECT_EQ(1U, T.findNearest("-xyzzy", Nearest, Visibility(SubtoolVis)));426 EXPECT_EQ(Nearest, "-xyzzy1");427}428 429TYPED_TEST(DISABLED_OptTableTest, FindNearestFIXME) {430 TypeParam T;431 std::string Nearest;432 433 // FIXME: Options with joined values should not have those values considered434 // when calculating distance. The test below would fail if run, but it should435 // succeed.436 EXPECT_EQ(1U, T.findNearest("--erbghFoo", Nearest));437 EXPECT_EQ(Nearest, "--ermghFoo");438}439 440TYPED_TEST(OptTableTest, ParseGroupedShortOptions) {441 TypeParam T;442 T.setGroupedShortOptions(true);443 unsigned MAI, MAC;444 445 // Grouped short options can be followed by a long Flag (-Joo), or a non-Flag446 // option (-C=1).447 const char *Args1[] = {"-AIJ", "-AIJoo", "-AC=1"};448 InputArgList AL = T.ParseArgs(Args1, MAI, MAC);449 EXPECT_TRUE(AL.hasArg(OPT_A));450 EXPECT_TRUE(AL.hasArg(OPT_H));451 ASSERT_EQ((size_t)2, AL.getAllArgValues(OPT_B).size());452 EXPECT_EQ("foo", AL.getAllArgValues(OPT_B)[0]);453 EXPECT_EQ("bar", AL.getAllArgValues(OPT_B)[1]);454 ASSERT_TRUE(AL.hasArg(OPT_C));455 EXPECT_EQ("1", AL.getAllArgValues(OPT_C)[0]);456 457 // Prefer a long option to a short option.458 const char *Args2[] = {"-AB"};459 InputArgList AL2 = T.ParseArgs(Args2, MAI, MAC);460 EXPECT_TRUE(!AL2.hasArg(OPT_A));461 EXPECT_TRUE(AL2.hasArg(OPT_AB));462 463 // Short options followed by a long option. We probably should disallow this.464 const char *Args3[] = {"-AIblorp"};465 InputArgList AL3 = T.ParseArgs(Args3, MAI, MAC);466 EXPECT_TRUE(AL3.hasArg(OPT_A));467 EXPECT_TRUE(AL3.hasArg(OPT_Blorp));468}469 470TYPED_TEST(OptTableTest, ParseDashDash) {471 TypeParam T;472 T.setDashDashParsing(true);473 unsigned MAI, MAC;474 475 const char *Args1[] = {"-A", "--"};476 InputArgList AL = T.ParseArgs(Args1, MAI, MAC);477 EXPECT_TRUE(AL.hasArg(OPT_A));478 EXPECT_EQ(size_t(0), AL.getAllArgValues(OPT_INPUT).size());479 EXPECT_EQ(size_t(0), AL.getAllArgValues(OPT_UNKNOWN).size());480 481 const char *Args2[] = {"-A", "--", "-A", "--", "-B"};482 AL = T.ParseArgs(Args2, MAI, MAC);483 EXPECT_TRUE(AL.hasArg(OPT_A));484 EXPECT_FALSE(AL.hasArg(OPT_B));485 const std::vector<std::string> Input = AL.getAllArgValues(OPT_INPUT);486 ASSERT_EQ(size_t(3), Input.size());487 EXPECT_EQ("-A", Input[0]);488 EXPECT_EQ("--", Input[1]);489 EXPECT_EQ("-B", Input[2]);490 EXPECT_EQ(size_t(0), AL.getAllArgValues(OPT_UNKNOWN).size());491 492 T.setDashDashParsing(false);493 AL = T.ParseArgs(Args2, MAI, MAC);494 EXPECT_TRUE(AL.hasArg(OPT_A));495 EXPECT_TRUE(AL.hasArg(OPT_B));496 EXPECT_EQ(size_t(0), AL.getAllArgValues(OPT_INPUT).size());497 const std::vector<std::string> Unknown = AL.getAllArgValues(OPT_UNKNOWN);498 ASSERT_EQ(size_t(2), Unknown.size());499 EXPECT_EQ("--", Unknown[0]);500 EXPECT_EQ("--", Unknown[1]);501}502 503TYPED_TEST(OptTableTest, UnknownOptions) {504 TypeParam T;505 unsigned MAI, MAC;506 const char *Args[] = {"-u", "--long", "0"};507 for (int I = 0; I < 2; ++I) {508 T.setGroupedShortOptions(I != 0);509 InputArgList AL = T.ParseArgs(Args, MAI, MAC);510 const std::vector<std::string> Unknown = AL.getAllArgValues(OPT_UNKNOWN);511 ASSERT_EQ((size_t)2, Unknown.size());512 EXPECT_EQ("-u", Unknown[0]);513 EXPECT_EQ("--long", Unknown[1]);514 }515}516 517TYPED_TEST(OptTableTest, FlagsWithoutValues) {518 TypeParam T;519 T.setGroupedShortOptions(true);520 unsigned MAI, MAC;521 const char *Args[] = {"-A=1", "-A="};522 InputArgList AL = T.ParseArgs(Args, MAI, MAC);523 const std::vector<std::string> Unknown = AL.getAllArgValues(OPT_UNKNOWN);524 ASSERT_EQ((size_t)2, Unknown.size());525 EXPECT_EQ("-A=1", Unknown[0]);526 EXPECT_EQ("-A=", Unknown[1]);527}528 529TYPED_TEST(OptTableTest, UnknownGroupedShortOptions) {530 TypeParam T;531 T.setGroupedShortOptions(true);532 unsigned MAI, MAC;533 const char *Args[] = {"-AuzK", "-AuzK"};534 InputArgList AL = T.ParseArgs(Args, MAI, MAC);535 const std::vector<std::string> Unknown = AL.getAllArgValues(OPT_UNKNOWN);536 ASSERT_EQ((size_t)4, Unknown.size());537 EXPECT_EQ("-u", Unknown[0]);538 EXPECT_EQ("-z", Unknown[1]);539 EXPECT_EQ("-u", Unknown[2]);540 EXPECT_EQ("-z", Unknown[3]);541}542 543TYPED_TEST(OptTableTest, PrintMultilineHelpText) {544 TypeParam T;545 std::string Help;546 raw_string_ostream RSO(Help);547 T.printHelp(RSO, "usage", "title", /*ShowHidden=*/false,548 /*ShowAllAliases=*/false, Visibility(MultiLineVis));549 EXPECT_STREQ(Help.c_str(), R"(OVERVIEW: title550 551USAGE: usage552 553OPTIONS:554 -multiline-help-with-long-name555 This a help text that has556 multiple lines in it557 and a long name558 -multiline-help This a help text that has559 multiple lines in it560)");561}562