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

source code of llvm/unittests/Option/OptionParsingTest.cpp