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