llvm-project

Форк
0
/
OptionParsingTest.cpp 
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

16
using namespace llvm;
17
using namespace llvm::opt;
18

19
#if defined(__clang__)
20
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
21
#endif
22

23
enum 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

38
static constexpr const StringLiteral PrefixTable_init[] =
39
#define PREFIX_UNION(VALUES) VALUES
40
#include "Opts.inc"
41
#undef PREFIX_UNION
42
    ;
43
static constexpr const ArrayRef<StringLiteral>
44
    PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1);
45

46
enum OptionFlags {
47
  OptFlag1 = (1 << 4),
48
  OptFlag2 = (1 << 5),
49
  OptFlag3 = (1 << 6)
50
};
51

52
enum OptionVisibility {
53
  SubtoolVis = (1 << 2),
54
  MultiLineVis = (1 << 3),
55
};
56

57
static constexpr OptTable::Info InfoTable[] = {
58
#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
59
#include "Opts.inc"
60
#undef OPTION
61
};
62

63
namespace {
64
class TestOptTable : public GenericOptTable {
65
public:
66
  TestOptTable(bool IgnoreCase = false)
67
      : GenericOptTable(InfoTable, IgnoreCase) {}
68
};
69

70
class TestPrecomputedOptTable : public PrecomputedOptTable {
71
public:
72
  TestPrecomputedOptTable(bool IgnoreCase = false)
73
      : PrecomputedOptTable(InfoTable, PrefixTable, IgnoreCase) {}
74
};
75
}
76

77
const 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
90
template <typename T> class OptTableTest : public ::testing::Test {};
91

92
template <typename T> class DISABLED_OptTableTest : public ::testing::Test {};
93

94
// Test both precomputed and computed OptTables with the same suite of tests.
95
using OptTableTestTypes =
96
    ::testing::Types<TestOptTable, TestPrecomputedOptTable>;
97

98
TYPED_TEST_SUITE(OptTableTest, OptTableTestTypes, );
99
TYPED_TEST_SUITE(DISABLED_OptTableTest, OptTableTestTypes, );
100

101
TYPED_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(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(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

148
TYPED_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

176
TYPED_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

213
TYPED_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

222
TYPED_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

233
TYPED_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

249
TYPED_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

270
TYPED_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

280
TYPED_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

291
TYPED_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

307
TYPED_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

318
TYPED_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

330
TYPED_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

344
TYPED_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

358
TYPED_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

371
TYPED_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

430
TYPED_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

441
TYPED_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

471
TYPED_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

504
TYPED_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

518
TYPED_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

530
TYPED_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

544
TYPED_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

552
USAGE: usage
553

554
OPTIONS:
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.