bloaty/third_party/abseil-cpp/absl/flags/parse_test.cc
Go to the documentation of this file.
1 //
2 // Copyright 2019 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "absl/flags/parse.h"
17 
18 #include <stdlib.h>
19 
20 #include <fstream>
21 #include <string>
22 #include <vector>
23 
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "absl/base/internal/raw_logging.h"
27 #include "absl/base/internal/scoped_set_env.h"
28 #include "absl/flags/declare.h"
29 #include "absl/flags/flag.h"
30 #include "absl/flags/internal/parse.h"
31 #include "absl/flags/internal/usage.h"
32 #include "absl/flags/reflection.h"
33 #include "absl/strings/str_cat.h"
34 #include "absl/strings/string_view.h"
35 #include "absl/strings/substitute.h"
36 #include "absl/types/span.h"
37 
38 #ifdef _WIN32
39 #include <windows.h>
40 #endif
41 
42 namespace {
43 
45 
46 struct UDT {
47  UDT() = default;
48  UDT(const UDT&) = default;
49  UDT(int v) : value(v) {} // NOLINT
50 
51  int value;
52 };
53 
55  if (in == "A") {
56  udt->value = 1;
57  return true;
58  }
59  if (in == "AAA") {
60  udt->value = 10;
61  return true;
62  }
63 
64  *err = "Use values A, AAA instead";
65  return false;
66 }
67 std::string AbslUnparseFlag(const UDT& udt) {
68  return udt.value == 1 ? "A" : "AAA";
69 }
70 
71 std::string GetTestTmpDirEnvVar(const char* const env_var_name) {
72 #ifdef _WIN32
73  char buf[MAX_PATH];
74  auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf));
75  if (get_res >= sizeof(buf) || get_res == 0) {
76  return "";
77  }
78 
79  return std::string(buf, get_res);
80 #else
81  const char* val = ::getenv(env_var_name);
82  if (val == nullptr) {
83  return "";
84  }
85 
86  return val;
87 #endif
88 }
89 
90 const std::string& GetTestTempDir() {
91  static std::string* temp_dir_name = []() -> std::string* {
92  std::string* res = new std::string(GetTestTmpDirEnvVar("TEST_TMPDIR"));
93 
94  if (res->empty()) {
95  *res = GetTestTmpDirEnvVar("TMPDIR");
96  }
97 
98  if (res->empty()) {
99 #ifdef _WIN32
100  char temp_path_buffer[MAX_PATH];
101 
102  auto len = GetTempPathA(MAX_PATH, temp_path_buffer);
103  if (len < MAX_PATH && len != 0) {
104  std::string temp_dir_name = temp_path_buffer;
105  if (!absl::EndsWith(temp_dir_name, "\\")) {
106  temp_dir_name.push_back('\\');
107  }
108  absl::StrAppend(&temp_dir_name, "parse_test.", GetCurrentProcessId());
109  if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {
110  *res = temp_dir_name;
111  }
112  }
113 #else
114  char temp_dir_template[] = "/tmp/parse_test.XXXXXX";
115  if (auto* unique_name = ::mkdtemp(temp_dir_template)) {
116  *res = unique_name;
117  }
118 #endif
119  }
120 
121  if (res->empty()) {
123  "Failed to make temporary directory for data files");
124  }
125 
126 #ifdef _WIN32
127  *res += "\\";
128 #else
129  *res += "/";
130 #endif
131 
132  return res;
133  }();
134 
135  return *temp_dir_name;
136 }
137 
138 struct FlagfileData {
139  const absl::string_view file_name;
140  const absl::Span<const char* const> file_lines;
141 };
142 
143 // clang-format off
144 constexpr const char* const ff1_data[] = {
145  "# comment ",
146  " # comment ",
147  "",
148  " ",
149  "--int_flag=-1",
150  " --string_flag=q2w2 ",
151  " ## ",
152  " --double_flag=0.1",
153  "--bool_flag=Y "
154 };
155 
156 constexpr const char* const ff2_data[] = {
157  "# Setting legacy flag",
158  "--legacy_int=1111",
159  "--legacy_bool",
160  "--nobool_flag",
161  "--legacy_str=aqsw",
162  "--int_flag=100",
163  " ## ============="
164 };
165 // clang-format on
166 
167 // Builds flagfile flag in the flagfile_flag buffer and returns it. This
168 // function also creates a temporary flagfile based on FlagfileData input.
169 // We create a flagfile in a temporary directory with the name specified in
170 // FlagfileData and populate it with lines specifed in FlagfileData. If $0 is
171 // referenced in any of the lines in FlagfileData they are replaced with
172 // temporary directory location. This way we can test inclusion of one flagfile
173 // from another flagfile.
174 const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
175  std::string& flagfile_flag) {
176  flagfile_flag = "--flagfile=";
177  absl::string_view separator;
178  for (const auto& flagfile_data : ffd) {
179  std::string flagfile_name =
180  absl::StrCat(GetTestTempDir(), flagfile_data.file_name);
181 
182  std::ofstream flagfile_out(flagfile_name);
183  for (auto line : flagfile_data.file_lines) {
184  flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
185  }
186 
187  absl::StrAppend(&flagfile_flag, separator, flagfile_name);
188  separator = ",";
189  }
190 
191  return flagfile_flag.c_str();
192 }
193 
194 } // namespace
195 
196 ABSL_FLAG(int, int_flag, 1, "");
197 ABSL_FLAG(double, double_flag, 1.1, "");
198 ABSL_FLAG(std::string, string_flag, "a", "");
199 ABSL_FLAG(bool, bool_flag, false, "");
200 ABSL_FLAG(UDT, udt_flag, -1, "");
201 ABSL_RETIRED_FLAG(int, legacy_int, 1, "");
202 ABSL_RETIRED_FLAG(bool, legacy_bool, false, "");
203 ABSL_RETIRED_FLAG(std::string, legacy_str, "l", "");
204 
205 namespace {
206 
207 namespace flags = absl::flags_internal;
209 
210 class ParseTest : public testing::Test {
211  public:
213 
214  private:
215  absl::FlagSaver flag_saver_;
216 };
217 
218 // --------------------------------------------------------------------
219 
220 template <int N>
221 std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
222  return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
223 }
224 
225 // --------------------------------------------------------------------
226 
227 template <int N>
228 void TestParse(const char* (&in_argv)[N], int int_flag_value,
229  double double_flag_val, absl::string_view string_flag_val,
230  bool bool_flag_val, int exp_position_args = 0) {
231  auto out_args = InvokeParse(in_argv);
232 
233  EXPECT_EQ(out_args.size(), 1 + exp_position_args);
234  EXPECT_STREQ(out_args[0], "testbin");
235 
236  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value);
237  EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001);
238  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val);
239  EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val);
240 }
241 
242 // --------------------------------------------------------------------
243 
244 TEST_F(ParseTest, TestEmptyArgv) {
245  const char* in_argv[] = {"testbin"};
246 
247  auto out_args = InvokeParse(in_argv);
248 
249  EXPECT_EQ(out_args.size(), 1);
250  EXPECT_STREQ(out_args[0], "testbin");
251 }
252 
253 // --------------------------------------------------------------------
254 
255 TEST_F(ParseTest, TestValidIntArg) {
256  const char* in_args1[] = {
257  "testbin",
258  "--int_flag=10",
259  };
260  TestParse(in_args1, 10, 1.1, "a", false);
261 
262  const char* in_args2[] = {
263  "testbin",
264  "-int_flag=020",
265  };
266  TestParse(in_args2, 20, 1.1, "a", false);
267 
268  const char* in_args3[] = {
269  "testbin",
270  "--int_flag",
271  "-30",
272  };
273  TestParse(in_args3, -30, 1.1, "a", false);
274 
275  const char* in_args4[] = {
276  "testbin",
277  "-int_flag",
278  "0x21",
279  };
280  TestParse(in_args4, 33, 1.1, "a", false);
281 }
282 
283 // --------------------------------------------------------------------
284 
285 TEST_F(ParseTest, TestValidDoubleArg) {
286  const char* in_args1[] = {
287  "testbin",
288  "--double_flag=2.3",
289  };
290  TestParse(in_args1, 1, 2.3, "a", false);
291 
292  const char* in_args2[] = {
293  "testbin",
294  "--double_flag=0x1.2",
295  };
296  TestParse(in_args2, 1, 1.125, "a", false);
297 
298  const char* in_args3[] = {
299  "testbin",
300  "--double_flag",
301  "99.7",
302  };
303  TestParse(in_args3, 1, 99.7, "a", false);
304 
305  const char* in_args4[] = {
306  "testbin",
307  "--double_flag",
308  "0x20.1",
309  };
310  TestParse(in_args4, 1, 32.0625, "a", false);
311 }
312 
313 // --------------------------------------------------------------------
314 
315 TEST_F(ParseTest, TestValidStringArg) {
316  const char* in_args1[] = {
317  "testbin",
318  "--string_flag=aqswde",
319  };
320  TestParse(in_args1, 1, 1.1, "aqswde", false);
321 
322  const char* in_args2[] = {
323  "testbin",
324  "-string_flag=a=b=c",
325  };
326  TestParse(in_args2, 1, 1.1, "a=b=c", false);
327 
328  const char* in_args3[] = {
329  "testbin",
330  "--string_flag",
331  "zaxscd",
332  };
333  TestParse(in_args3, 1, 1.1, "zaxscd", false);
334 
335  const char* in_args4[] = {
336  "testbin",
337  "-string_flag",
338  "--int_flag",
339  };
340  TestParse(in_args4, 1, 1.1, "--int_flag", false);
341 
342  const char* in_args5[] = {
343  "testbin",
344  "--string_flag",
345  "--no_a_flag=11",
346  };
347  TestParse(in_args5, 1, 1.1, "--no_a_flag=11", false);
348 }
349 
350 // --------------------------------------------------------------------
351 
352 TEST_F(ParseTest, TestValidBoolArg) {
353  const char* in_args1[] = {
354  "testbin",
355  "--bool_flag",
356  };
357  TestParse(in_args1, 1, 1.1, "a", true);
358 
359  const char* in_args2[] = {
360  "testbin",
361  "--nobool_flag",
362  };
363  TestParse(in_args2, 1, 1.1, "a", false);
364 
365  const char* in_args3[] = {
366  "testbin",
367  "--bool_flag=true",
368  };
369  TestParse(in_args3, 1, 1.1, "a", true);
370 
371  const char* in_args4[] = {
372  "testbin",
373  "-bool_flag=false",
374  };
375  TestParse(in_args4, 1, 1.1, "a", false);
376 }
377 
378 // --------------------------------------------------------------------
379 
380 TEST_F(ParseTest, TestValidUDTArg) {
381  const char* in_args1[] = {
382  "testbin",
383  "--udt_flag=A",
384  };
385  InvokeParse(in_args1);
386 
387  EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1);
388 
389  const char* in_args2[] = {"testbin", "--udt_flag", "AAA"};
390  InvokeParse(in_args2);
391 
392  EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10);
393 }
394 
395 // --------------------------------------------------------------------
396 
397 TEST_F(ParseTest, TestValidMultipleArg) {
398  const char* in_args1[] = {
399  "testbin", "--bool_flag", "--int_flag=2",
400  "--double_flag=0.1", "--string_flag=asd",
401  };
402  TestParse(in_args1, 2, 0.1, "asd", true);
403 
404  const char* in_args2[] = {
405  "testbin", "--string_flag=", "--nobool_flag", "--int_flag",
406  "-011", "--double_flag", "-1e-2",
407  };
408  TestParse(in_args2, -11, -0.01, "", false);
409 
410  const char* in_args3[] = {
411  "testbin", "--int_flag", "-0", "--string_flag", "\"\"",
412  "--bool_flag=true", "--double_flag=1e18",
413  };
414  TestParse(in_args3, 0, 1e18, "\"\"", true);
415 }
416 
417 // --------------------------------------------------------------------
418 
419 TEST_F(ParseTest, TestPositionalArgs) {
420  const char* in_args1[] = {
421  "testbin",
422  "p1",
423  "p2",
424  };
425  TestParse(in_args1, 1, 1.1, "a", false, 2);
426 
427  auto out_args1 = InvokeParse(in_args1);
428 
429  EXPECT_STREQ(out_args1[1], "p1");
430  EXPECT_STREQ(out_args1[2], "p2");
431 
432  const char* in_args2[] = {
433  "testbin",
434  "--int_flag=2",
435  "p1",
436  };
437  TestParse(in_args2, 2, 1.1, "a", false, 1);
438 
439  auto out_args2 = InvokeParse(in_args2);
440 
441  EXPECT_STREQ(out_args2[1], "p1");
442 
443  const char* in_args3[] = {"testbin", "p1", "--int_flag=3",
444  "p2", "--bool_flag", "true"};
445  TestParse(in_args3, 3, 1.1, "a", true, 3);
446 
447  auto out_args3 = InvokeParse(in_args3);
448 
449  EXPECT_STREQ(out_args3[1], "p1");
450  EXPECT_STREQ(out_args3[2], "p2");
451  EXPECT_STREQ(out_args3[3], "true");
452 
453  const char* in_args4[] = {
454  "testbin",
455  "--",
456  "p1",
457  "p2",
458  };
459  TestParse(in_args4, 3, 1.1, "a", true, 2);
460 
461  auto out_args4 = InvokeParse(in_args4);
462 
463  EXPECT_STREQ(out_args4[1], "p1");
464  EXPECT_STREQ(out_args4[2], "p2");
465 
466  const char* in_args5[] = {
467  "testbin", "p1", "--int_flag=4", "--", "--bool_flag", "false", "p2",
468  };
469  TestParse(in_args5, 4, 1.1, "a", true, 4);
470 
471  auto out_args5 = InvokeParse(in_args5);
472 
473  EXPECT_STREQ(out_args5[1], "p1");
474  EXPECT_STREQ(out_args5[2], "--bool_flag");
475  EXPECT_STREQ(out_args5[3], "false");
476  EXPECT_STREQ(out_args5[4], "p2");
477 }
478 
479 // --------------------------------------------------------------------
480 
481 using ParseDeathTest = ParseTest;
482 
483 TEST_F(ParseDeathTest, TestUndefinedArg) {
484  const char* in_args1[] = {
485  "testbin",
486  "--undefined_flag",
487  };
488  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
489  "Unknown command line flag 'undefined_flag'");
490 
491  const char* in_args2[] = {
492  "testbin",
493  "--noprefixed_flag",
494  };
495  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
496  "Unknown command line flag 'noprefixed_flag'");
497 
498  const char* in_args3[] = {
499  "testbin",
500  "--Int_flag=1",
501  };
502  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
503  "Unknown command line flag 'Int_flag'");
504 }
505 
506 // --------------------------------------------------------------------
507 
508 TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {
509  const char* in_args1[] = {
510  "testbin",
511  "--bool_flag=",
512  };
514  InvokeParse(in_args1),
515  "Missing the value after assignment for the boolean flag 'bool_flag'");
516 
517  const char* in_args2[] = {
518  "testbin",
519  "--nobool_flag=true",
520  };
521  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
522  "Negative form with assignment is not valid for the boolean "
523  "flag 'bool_flag'");
524 }
525 
526 // --------------------------------------------------------------------
527 
528 TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) {
529  const char* in_args1[] = {
530  "testbin",
531  "--nostring_flag",
532  };
533  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
534  "Negative form is not valid for the flag 'string_flag'");
535 
536  const char* in_args2[] = {
537  "testbin",
538  "--int_flag",
539  };
540  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
541  "Missing the value for the flag 'int_flag'");
542 }
543 
544 // --------------------------------------------------------------------
545 
546 TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {
547  const char* in_args1[] = {
548  "testbin",
549  "--udt_flag=1",
550  };
551  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
552  "Illegal value '1' specified for flag 'udt_flag'; Use values A, "
553  "AAA instead");
554 
555  const char* in_args2[] = {
556  "testbin",
557  "--udt_flag",
558  "AA",
559  };
560  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
561  "Illegal value 'AA' specified for flag 'udt_flag'; Use values "
562  "A, AAA instead");
563 }
564 
565 // --------------------------------------------------------------------
566 
567 TEST_F(ParseTest, TestLegacyFlags) {
568  const char* in_args1[] = {
569  "testbin",
570  "--legacy_int=11",
571  };
572  TestParse(in_args1, 1, 1.1, "a", false);
573 
574  const char* in_args2[] = {
575  "testbin",
576  "--legacy_bool",
577  };
578  TestParse(in_args2, 1, 1.1, "a", false);
579 
580  const char* in_args3[] = {
581  "testbin", "--legacy_int", "22", "--int_flag=2",
582  "--legacy_bool", "true", "--legacy_str", "--string_flag=qwe",
583  };
584  TestParse(in_args3, 2, 1.1, "a", false, 1);
585 }
586 
587 // --------------------------------------------------------------------
588 
589 TEST_F(ParseTest, TestSimpleValidFlagfile) {
590  std::string flagfile_flag;
591 
592  const char* in_args1[] = {
593  "testbin",
594  GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
595  flagfile_flag),
596  };
597  TestParse(in_args1, -1, 0.1, "q2w2 ", true);
598 
599  const char* in_args2[] = {
600  "testbin",
601  GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}},
602  flagfile_flag),
603  };
604  TestParse(in_args2, 100, 0.1, "q2w2 ", false);
605 }
606 
607 // --------------------------------------------------------------------
608 
609 TEST_F(ParseTest, TestValidMultiFlagfile) {
610  std::string flagfile_flag;
611 
612  const char* in_args1[] = {
613  "testbin",
614  GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
615  {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
616  flagfile_flag),
617  };
618  TestParse(in_args1, -1, 0.1, "q2w2 ", true);
619 }
620 
621 // --------------------------------------------------------------------
622 
623 TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
624  std::string flagfile_flag;
625 
626  const char* in_args1[] = {
627  "testbin", "--int_flag=3",
628  GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
629  flagfile_flag),
630  "-double_flag=0.2"};
631  TestParse(in_args1, -1, 0.2, "q2w2 ", true);
632 }
633 
634 // --------------------------------------------------------------------
635 
636 TEST_F(ParseTest, TestFlagfileInFlagfile) {
637  std::string flagfile_flag;
638 
639  constexpr const char* const ff3_data[] = {
640  "--flagfile=$0/parse_test.ff1",
641  "--flagfile=$0/parse_test.ff2",
642  };
643 
644  GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
645  {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
646  flagfile_flag);
647 
648  const char* in_args1[] = {
649  "testbin",
650  GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
651  flagfile_flag),
652  };
653  TestParse(in_args1, 100, 0.1, "q2w2 ", false);
654 }
655 
656 // --------------------------------------------------------------------
657 
658 TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
659  std::string flagfile_flag;
660 
661  constexpr const char* const ff4_data[] = {
662  "--unknown_flag=10"
663  };
664 
665  const char* in_args1[] = {
666  "testbin",
667  GetFlagfileFlag({{"parse_test.ff4",
668  absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
669  };
670  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
671  "Unknown command line flag 'unknown_flag'");
672 
673  constexpr const char* const ff5_data[] = {
674  "--int_flag 10",
675  };
676 
677  const char* in_args2[] = {
678  "testbin",
679  GetFlagfileFlag({{"parse_test.ff5",
680  absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
681  };
682  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
683  "Unknown command line flag 'int_flag 10'");
684 
685  constexpr const char* const ff6_data[] = {
686  "--int_flag=10", "--", "arg1", "arg2", "arg3",
687  };
688 
689  const char* in_args3[] = {
690  "testbin",
691  GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
692  flagfile_flag),
693  };
694  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
695  "Flagfile can't contain position arguments or --");
696 
697  const char* in_args4[] = {
698  "testbin",
699  "--flagfile=invalid_flag_file",
700  };
701  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args4),
702  "Can't open flagfile invalid_flag_file");
703 
704  constexpr const char* const ff7_data[] = {
705  "--int_flag=10",
706  "*bin*",
707  "--str_flag=aqsw",
708  };
709 
710  const char* in_args5[] = {
711  "testbin",
712  GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
713  flagfile_flag),
714  };
715  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
716  "Unexpected line in the flagfile .*: \\*bin\\*");
717 }
718 
719 // --------------------------------------------------------------------
720 
721 TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) {
722  const char* in_args1[] = {"testbin",
723  "--fromenv=int_flag,bool_flag,string_flag"};
724 
725  ScopedSetEnv set_int_flag("FLAGS_int_flag", "33");
726  ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "True");
727  ScopedSetEnv set_string_flag("FLAGS_string_flag", "AQ12");
728 
729  TestParse(in_args1, 33, 1.1, "AQ12", true);
730 }
731 
732 // --------------------------------------------------------------------
733 
734 TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {
735  const char* in_args1[] = {"testbin", "--fromenv=int_flag"};
736 
737  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
738  "FLAGS_int_flag not found in environment");
739 }
740 
741 // --------------------------------------------------------------------
742 
743 TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) {
744  const char* in_args1[] = {"testbin", "--fromenv=tryfromenv"};
745 
746  ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag");
747 
748  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
749  "Infinite recursion on flag tryfromenv");
750 }
751 
752 // --------------------------------------------------------------------
753 
754 TEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) {
755  const char* in_args1[] = {
756  "testbin", "--tryfromenv=int_flag,bool_flag,string_flag,other_flag"};
757 
758  ScopedSetEnv set_int_flag("FLAGS_int_flag", "17");
759  ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "Y");
760 
761  TestParse(in_args1, 17, 1.1, "a", true);
762 }
763 
764 // --------------------------------------------------------------------
765 
766 TEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) {
767  const char* in_args1[] = {
768  "testbin",
769  "--bool_flag=T",
770  "--tryfromenv=int_flag,bool_flag",
771  "--int_flag=-21",
772  };
773 
774  ScopedSetEnv set_int_flag("FLAGS_int_flag", "-15");
775  ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "F");
776 
777  TestParse(in_args1, -21, 1.1, "a", false);
778 }
779 
780 // --------------------------------------------------------------------
781 
782 TEST_F(ParseTest, TestKeepParsedArgs) {
783  const char* in_args1[] = {
784  "testbin", "arg1", "--bool_flag",
785  "--int_flag=211", "arg2", "--double_flag=1.1",
786  "--string_flag", "asd", "--",
787  "arg3", "arg4",
788  };
789 
790  auto out_args1 = InvokeParse(in_args1);
791 
792  EXPECT_THAT(
793  out_args1,
795  absl::string_view("arg2"), absl::string_view("arg3"),
796  absl::string_view("arg4")}));
797 
798  auto out_args2 = flags::ParseCommandLineImpl(
799  11, const_cast<char**>(in_args1), flags::ArgvListAction::kKeepParsedArgs,
800  flags::UsageFlagsAction::kHandleUsage,
801  flags::OnUndefinedFlag::kAbortIfUndefined);
802 
803  EXPECT_THAT(
804  out_args2,
806  absl::string_view("--bool_flag"),
807  absl::string_view("--int_flag=211"),
808  absl::string_view("--double_flag=1.1"),
809  absl::string_view("--string_flag"),
810  absl::string_view("asd"), absl::string_view("--"),
811  absl::string_view("arg1"), absl::string_view("arg2"),
812  absl::string_view("arg3"), absl::string_view("arg4")}));
813 }
814 
815 // --------------------------------------------------------------------
816 
817 TEST_F(ParseTest, TestIgnoreUndefinedFlags) {
818  const char* in_args1[] = {
819  "testbin",
820  "arg1",
821  "--undef_flag=aa",
822  "--int_flag=21",
823  };
824 
825  auto out_args1 = flags::ParseCommandLineImpl(
826  4, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
827  flags::UsageFlagsAction::kHandleUsage,
828  flags::OnUndefinedFlag::kIgnoreUndefined);
829 
830  EXPECT_THAT(out_args1, ElementsAreArray({absl::string_view("testbin"),
831  absl::string_view("arg1")}));
832 
833  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 21);
834 
835  const char* in_args2[] = {
836  "testbin",
837  "arg1",
838  "--undef_flag=aa",
839  "--string_flag=AA",
840  };
841 
842  auto out_args2 = flags::ParseCommandLineImpl(
843  4, const_cast<char**>(in_args2), flags::ArgvListAction::kKeepParsedArgs,
844  flags::UsageFlagsAction::kHandleUsage,
845  flags::OnUndefinedFlag::kIgnoreUndefined);
846 
847  EXPECT_THAT(
848  out_args2,
850  {absl::string_view("testbin"), absl::string_view("--undef_flag=aa"),
851  absl::string_view("--string_flag=AA"), absl::string_view("arg1")}));
852 
853  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "AA");
854 }
855 
856 // --------------------------------------------------------------------
857 
858 TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
859  const char* in_args1[] = {
860  "testbin",
861  "--help",
862  };
863 
864  EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), "");
865 
866  const char* in_args2[] = {
867  "testbin",
868  "--help",
869  "--int_flag=3",
870  };
871 
872  auto out_args2 = flags::ParseCommandLineImpl(
873  3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
874  flags::UsageFlagsAction::kIgnoreUsage,
875  flags::OnUndefinedFlag::kAbortIfUndefined);
876 
877  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
878  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
879 }
880 
881 // --------------------------------------------------------------------
882 
883 TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) {
884  const char* in_args1[] = {
885  "testbin",
886  "--help=abcd",
887  };
888 
889  auto out_args1 = flags::ParseCommandLineImpl(
890  2, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
891  flags::UsageFlagsAction::kIgnoreUsage,
892  flags::OnUndefinedFlag::kAbortIfUndefined);
893 
896 
897  const char* in_args2[] = {"testbin", "--help", "some_positional_arg"};
898 
899  auto out_args2 = flags::ParseCommandLineImpl(
900  3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
901  flags::UsageFlagsAction::kIgnoreUsage,
902  flags::OnUndefinedFlag::kAbortIfUndefined);
903 
904  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
905 }
906 
907 // --------------------------------------------------------------------
908 
910  const char* in_args1[] = {
911  "testbin", "arg1", "--bool_flag",
912  "--int_flag=211", "arg2", "--double_flag=1.1",
913  "--string_flag", "asd", "--",
914  "--some_flag", "arg4",
915  };
916 
917  InvokeParse(in_args1);
918 
925 }
926 
927 // --------------------------------------------------------------------
928 
929 } // namespace
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
absl::StrAppend
void StrAppend(std::string *dest, const AlphaNum &a)
Definition: abseil-cpp/absl/strings/str_cat.cc:193
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
EXPECT_THAT
#define EXPECT_THAT(value, matcher)
absl::Span
Definition: abseil-cpp/absl/types/span.h:152
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
absl::flags_internal::SetFlagsHelpMode
void SetFlagsHelpMode(HelpMode mode)
Definition: abseil-cpp/absl/flags/internal/usage.cc:449
error_ref_leak.err
err
Definition: error_ref_leak.py:35
absl::ParseCommandLine
std::vector< char * > ParseCommandLine(int argc, char *argv[])
Definition: abseil-cpp/absl/flags/parse.cc:815
ABSL_FLAG
ABSL_FLAG(int, int_flag, 1, "")
mkdtemp
char * mkdtemp(char *path)
Definition: os390-syscalls.c:425
absl::flags_internal::HelpMode::kNone
@ kNone
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
testing::ElementsAreArray
internal::ElementsAreArrayMatcher< typename ::std::iterator_traits< Iter >::value_type > ElementsAreArray(Iter first, Iter last)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8465
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
absl::flags_internal::ParseCommandLineImpl
std::vector< char * > ParseCommandLineImpl(int argc, char *argv[], ArgvListAction arg_list_act, UsageFlagsAction usage_flag_act, OnUndefinedFlag on_undef_flag)
Definition: abseil-cpp/absl/flags/parse.cc:608
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
absl::base_internal::ScopedSetEnv
Definition: abseil-cpp/absl/base/internal/scoped_set_env.h:28
AbslUnparseFlag
std::string AbslUnparseFlag(const UDT &)
Definition: bloaty/third_party/abseil-cpp/absl/flags/internal/usage_test.cc:50
UDT::UDT
UDT()=default
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
ParseTest
Definition: hpack_parser_test.cc:48
absl::GetFlag
ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag< T > &flag)
Definition: abseil-cpp/absl/flags/flag.h:98
EXPECT_DEATH_IF_SUPPORTED
#define EXPECT_DEATH_IF_SUPPORTED(statement, regex)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-death-test.h:335
absl::flags_internal::GetFlagsHelpMode
HelpMode GetFlagsHelpMode()
Definition: abseil-cpp/absl/flags/internal/usage.cc:444
value
const char * value
Definition: hpack_parser_table.cc:165
EXPECT_STREQ
#define EXPECT_STREQ(s1, s2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2095
absl::flags_internal::GetFlagsHelpMatchSubstr
std::string GetFlagsHelpMatchSubstr()
Definition: abseil-cpp/absl/flags/internal/usage.cc:432
FATAL
#define FATAL(msg)
Definition: task.h:88
ABSL_RETIRED_FLAG
ABSL_RETIRED_FLAG(int, legacy_int, 1, "")
absl::FlagSaver
Definition: abseil-cpp/absl/flags/reflection.h:73
N
#define N
Definition: sync_test.cc:37
absl::flags_internal
Definition: abseil-cpp/absl/flags/commandlineflag.h:40
testing::internal::edit_distance::kMatch
@ kMatch
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h:156
string_view
absl::string_view string_view
Definition: attr.cc:22
AbslParseFlag
bool AbslParseFlag(absl::string_view, UDT *, std::string *)
Definition: bloaty/third_party/abseil-cpp/absl/flags/internal/usage_test.cc:49
regen-readme.line
line
Definition: regen-readme.py:30
absl::Substitute
ABSL_MUST_USE_RESULT std::string Substitute(absl::string_view format)
Definition: abseil-cpp/absl/strings/substitute.h:506
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
EXPECT_NEAR
#define EXPECT_NEAR(val1, val2, abs_error)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2143
absl::flags_internal::WasPresentOnCommandLine
bool WasPresentOnCommandLine(absl::string_view flag_name)
Definition: abseil-cpp/absl/flags/parse.cc:597
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
ABSL_INTERNAL_LOG
#define ABSL_INTERNAL_LOG(severity, message)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:75
getenv
#define getenv(ptr)
Definition: ares_private.h:106
re2::TestParse
void TestParse(const Test *tests, int ntests, Regexp::ParseFlags flags, const std::string &title)
Definition: bloaty/third_party/re2/re2/testing/parse_test.cc:230
absl::EndsWith
bool EndsWith(absl::string_view text, absl::string_view suffix) noexcept
Definition: third_party/abseil-cpp/absl/strings/match.h:68
TEST_F
#define TEST_F(test_fixture, test_name)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2367
ParseTest::~ParseTest
~ParseTest() override
Definition: hpack_parser_test.cc:55
absl::MakeConstSpan
constexpr Span< const T > MakeConstSpan(T *ptr, size_t size) noexcept
Definition: abseil-cpp/absl/types/span.h:707


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:39