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