parse_test.cc
Go to the documentation of this file.
00001 //
00002 // Copyright 2019 The Abseil Authors.
00003 //
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //
00008 //      https://www.apache.org/licenses/LICENSE-2.0
00009 //
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
00015 
00016 #include "absl/flags/parse.h"
00017 
00018 #include <fstream>
00019 
00020 #include "gmock/gmock.h"
00021 #include "gtest/gtest.h"
00022 #include "absl/base/internal/raw_logging.h"
00023 #include "absl/base/internal/scoped_set_env.h"
00024 #include "absl/flags/flag.h"
00025 #include "absl/strings/str_cat.h"
00026 #include "absl/strings/substitute.h"
00027 #include "absl/types/span.h"
00028 
00029 #ifdef _WIN32
00030 #include <windows.h>
00031 #endif
00032 
00033 namespace {
00034 
00035 using absl::base_internal::ScopedSetEnv;
00036 
00037 struct UDT {
00038   UDT() = default;
00039   UDT(const UDT&) = default;
00040   UDT(int v) : value(v) {}  // NOLINT
00041 
00042   int value;
00043 };
00044 
00045 bool AbslParseFlag(absl::string_view in, UDT* udt, std::string* err) {
00046   if (in == "A") {
00047     udt->value = 1;
00048     return true;
00049   }
00050   if (in == "AAA") {
00051     udt->value = 10;
00052     return true;
00053   }
00054 
00055   *err = "Use values A, AAA instead";
00056   return false;
00057 }
00058 std::string AbslUnparseFlag(const UDT& udt) {
00059   return udt.value == 1 ? "A" : "AAA";
00060 }
00061 
00062 std::string GetTestTmpDirEnvVar(const char* const env_var_name) {
00063 #ifdef _WIN32
00064   char buf[MAX_PATH];
00065   auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf));
00066   if (get_res >= sizeof(buf) || get_res == 0) {
00067     return "";
00068   }
00069 
00070   return std::string(buf, get_res);
00071 #else
00072   const char* val = ::getenv(env_var_name);
00073   if (val == nullptr) {
00074     return "";
00075   }
00076 
00077   return val;
00078 #endif
00079 }
00080 
00081 const std::string& GetTestTempDir() {
00082   static std::string* temp_dir_name = []() -> std::string* {
00083     std::string* res = new std::string(GetTestTmpDirEnvVar("TEST_TMPDIR"));
00084 
00085     if (res->empty()) {
00086       *res = GetTestTmpDirEnvVar("TMPDIR");
00087     }
00088 
00089     if (res->empty()) {
00090 #ifdef _WIN32
00091       char temp_path_buffer[MAX_PATH];
00092 
00093       auto len = GetTempPathA(MAX_PATH, temp_path_buffer);
00094       if (len < MAX_PATH && len != 0) {
00095         std::string temp_dir_name = absl::StrCat(
00096             temp_path_buffer, "\\parse_test.", GetCurrentProcessId());
00097         if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {
00098           *res = temp_dir_name;
00099         }
00100       }
00101 #else
00102       char temp_dir_template[] = "/tmp/parse_test.XXXXXX";
00103       if (auto* unique_name = ::mkdtemp(temp_dir_template)) {
00104         *res = unique_name;
00105       }
00106 #endif
00107 
00108       if (res->empty()) {
00109         ABSL_INTERNAL_LOG(FATAL,
00110                           "Failed to make temporary directory for data files");
00111       }
00112     }
00113 
00114 #ifdef _WIN32
00115     *res += "\\";
00116 #else
00117     *res += "/";
00118 #endif
00119 
00120     return res;
00121   }();
00122 
00123   return *temp_dir_name;
00124 }
00125 
00126 struct FlagfileData {
00127   const absl::string_view file_name;
00128   const absl::Span<const char* const> file_lines;
00129 };
00130 
00131 // clang-format off
00132 constexpr const char* const ff1_data[] = {
00133     "# comment    ",
00134     "  # comment  ",
00135     "",
00136     "     ",
00137     "--int_flag=-1",
00138     "  --string_flag=q2w2  ",
00139     "  ##   ",
00140     "  --double_flag=0.1",
00141     "--bool_flag=Y  "
00142 };
00143 
00144 constexpr const char* const ff2_data[] = {
00145     "# Setting legacy flag",
00146     "--legacy_int=1111",
00147     "--legacy_bool",
00148     "--nobool_flag",
00149     "--legacy_str=aqsw",
00150     "--int_flag=100",
00151     "   ## ============="
00152 };
00153 // clang-format on
00154 
00155 // Builds flagfile flag in the flagfile_flag buffer and returns it. This
00156 // function also creates a temporary flagfile based on FlagfileData input.
00157 // We create a flagfile in a temporary directory with the name specified in
00158 // FlagfileData and populate it with lines specifed in FlagfileData. If $0 is
00159 // referenced in any of the lines in FlagfileData they are replaced with
00160 // temporary directory location. This way we can test inclusion of one flagfile
00161 // from another flagfile.
00162 const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
00163                             std::string* flagfile_flag) {
00164   *flagfile_flag = "--flagfile=";
00165   absl::string_view separator;
00166   for (const auto& flagfile_data : ffd) {
00167     std::string flagfile_name =
00168         absl::StrCat(GetTestTempDir(), flagfile_data.file_name);
00169 
00170     std::ofstream flagfile_out(flagfile_name);
00171     for (auto line : flagfile_data.file_lines) {
00172       flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
00173     }
00174 
00175     absl::StrAppend(flagfile_flag, separator, flagfile_name);
00176     separator = ",";
00177   }
00178 
00179   return flagfile_flag->c_str();
00180 }
00181 
00182 }  // namespace
00183 
00184 ABSL_FLAG(int, int_flag, 1, "");
00185 ABSL_FLAG(double, double_flag, 1.1, "");
00186 ABSL_FLAG(std::string, string_flag, "a", "");
00187 ABSL_FLAG(bool, bool_flag, false, "");
00188 ABSL_FLAG(UDT, udt_flag, -1, "");
00189 ABSL_RETIRED_FLAG(int, legacy_int, 1, "");
00190 ABSL_RETIRED_FLAG(bool, legacy_bool, false, "");
00191 ABSL_RETIRED_FLAG(std::string, legacy_str, "l", "");
00192 
00193 namespace {
00194 
00195 namespace flags = absl::flags_internal;
00196 using testing::ElementsAreArray;
00197 
00198 class ParseTest : public testing::Test {
00199  private:
00200   flags::FlagSaver flag_saver_;
00201 };
00202 
00203 // --------------------------------------------------------------------
00204 
00205 template <int N>
00206 std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
00207   return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
00208 }
00209 
00210 // --------------------------------------------------------------------
00211 
00212 template <int N>
00213 void TestParse(const char* (&in_argv)[N], int int_flag_value,
00214                double double_flag_val, absl::string_view string_flag_val,
00215                bool bool_flag_val, int exp_position_args = 0) {
00216   auto out_args = InvokeParse(in_argv);
00217 
00218   EXPECT_EQ(out_args.size(), 1 + exp_position_args);
00219   EXPECT_STREQ(out_args[0], "testbin");
00220 
00221   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value);
00222   EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001);
00223   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val);
00224   EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val);
00225 }
00226 
00227 // --------------------------------------------------------------------
00228 
00229 TEST_F(ParseTest, TestEmptyArgv) {
00230   const char* in_argv[] = {"testbin"};
00231 
00232   auto out_args = InvokeParse(in_argv);
00233 
00234   EXPECT_EQ(out_args.size(), 1);
00235   EXPECT_STREQ(out_args[0], "testbin");
00236 }
00237 
00238 // --------------------------------------------------------------------
00239 
00240 TEST_F(ParseTest, TestValidIntArg) {
00241   const char* in_args1[] = {
00242       "testbin",
00243       "--int_flag=10",
00244   };
00245   TestParse(in_args1, 10, 1.1, "a", false);
00246 
00247   const char* in_args2[] = {
00248       "testbin",
00249       "-int_flag=020",
00250   };
00251   TestParse(in_args2, 20, 1.1, "a", false);
00252 
00253   const char* in_args3[] = {
00254       "testbin",
00255       "--int_flag",
00256       "-30",
00257   };
00258   TestParse(in_args3, -30, 1.1, "a", false);
00259 
00260   const char* in_args4[] = {
00261       "testbin",
00262       "-int_flag",
00263       "0x21",
00264   };
00265   TestParse(in_args4, 33, 1.1, "a", false);
00266 }
00267 
00268 // --------------------------------------------------------------------
00269 
00270 TEST_F(ParseTest, TestValidDoubleArg) {
00271   const char* in_args1[] = {
00272       "testbin",
00273       "--double_flag=2.3",
00274   };
00275   TestParse(in_args1, 1, 2.3, "a", false);
00276 
00277   const char* in_args2[] = {
00278       "testbin",
00279       "--double_flag=0x1.2",
00280   };
00281   TestParse(in_args2, 1, 1.125, "a", false);
00282 
00283   const char* in_args3[] = {
00284       "testbin",
00285       "--double_flag",
00286       "99.7",
00287   };
00288   TestParse(in_args3, 1, 99.7, "a", false);
00289 
00290   const char* in_args4[] = {
00291       "testbin",
00292       "--double_flag",
00293       "0x20.1",
00294   };
00295   TestParse(in_args4, 1, 32.0625, "a", false);
00296 }
00297 
00298 // --------------------------------------------------------------------
00299 
00300 TEST_F(ParseTest, TestValidStringArg) {
00301   const char* in_args1[] = {
00302       "testbin",
00303       "--string_flag=aqswde",
00304   };
00305   TestParse(in_args1, 1, 1.1, "aqswde", false);
00306 
00307   const char* in_args2[] = {
00308       "testbin",
00309       "-string_flag=a=b=c",
00310   };
00311   TestParse(in_args2, 1, 1.1, "a=b=c", false);
00312 
00313   const char* in_args3[] = {
00314       "testbin",
00315       "--string_flag",
00316       "zaxscd",
00317   };
00318   TestParse(in_args3, 1, 1.1, "zaxscd", false);
00319 
00320   const char* in_args4[] = {
00321       "testbin",
00322       "-string_flag",
00323       "--int_flag",
00324   };
00325   TestParse(in_args4, 1, 1.1, "--int_flag", false);
00326 
00327   const char* in_args5[] = {
00328       "testbin",
00329       "--string_flag",
00330       "--no_a_flag=11",
00331   };
00332   TestParse(in_args5, 1, 1.1, "--no_a_flag=11", false);
00333 }
00334 
00335 // --------------------------------------------------------------------
00336 
00337 TEST_F(ParseTest, TestValidBoolArg) {
00338   const char* in_args1[] = {
00339       "testbin",
00340       "--bool_flag",
00341   };
00342   TestParse(in_args1, 1, 1.1, "a", true);
00343 
00344   const char* in_args2[] = {
00345       "testbin",
00346       "--nobool_flag",
00347   };
00348   TestParse(in_args2, 1, 1.1, "a", false);
00349 
00350   const char* in_args3[] = {
00351       "testbin",
00352       "--bool_flag=true",
00353   };
00354   TestParse(in_args3, 1, 1.1, "a", true);
00355 
00356   const char* in_args4[] = {
00357       "testbin",
00358       "-bool_flag=false",
00359   };
00360   TestParse(in_args4, 1, 1.1, "a", false);
00361 }
00362 
00363 // --------------------------------------------------------------------
00364 
00365 TEST_F(ParseTest, TestValidUDTArg) {
00366   const char* in_args1[] = {
00367       "testbin",
00368       "--udt_flag=A",
00369   };
00370   InvokeParse(in_args1);
00371 
00372   EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1);
00373 
00374   const char* in_args2[] = {"testbin", "--udt_flag", "AAA"};
00375   InvokeParse(in_args2);
00376 
00377   EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10);
00378 }
00379 
00380 // --------------------------------------------------------------------
00381 
00382 TEST_F(ParseTest, TestValidMultipleArg) {
00383   const char* in_args1[] = {
00384       "testbin",           "--bool_flag",       "--int_flag=2",
00385       "--double_flag=0.1", "--string_flag=asd",
00386   };
00387   TestParse(in_args1, 2, 0.1, "asd", true);
00388 
00389   const char* in_args2[] = {
00390       "testbin", "--string_flag=", "--nobool_flag", "--int_flag",
00391       "-011",    "--double_flag",  "-1e-2",
00392   };
00393   TestParse(in_args2, -11, -0.01, "", false);
00394 
00395   const char* in_args3[] = {
00396       "testbin",          "--int_flag",         "-0", "--string_flag", "\"\"",
00397       "--bool_flag=true", "--double_flag=1e18",
00398   };
00399   TestParse(in_args3, 0, 1e18, "\"\"", true);
00400 }
00401 
00402 // --------------------------------------------------------------------
00403 
00404 TEST_F(ParseTest, TestPositionalArgs) {
00405   const char* in_args1[] = {
00406       "testbin",
00407       "p1",
00408       "p2",
00409   };
00410   TestParse(in_args1, 1, 1.1, "a", false, 2);
00411 
00412   auto out_args1 = InvokeParse(in_args1);
00413 
00414   EXPECT_STREQ(out_args1[1], "p1");
00415   EXPECT_STREQ(out_args1[2], "p2");
00416 
00417   const char* in_args2[] = {
00418       "testbin",
00419       "--int_flag=2",
00420       "p1",
00421   };
00422   TestParse(in_args2, 2, 1.1, "a", false, 1);
00423 
00424   auto out_args2 = InvokeParse(in_args2);
00425 
00426   EXPECT_STREQ(out_args2[1], "p1");
00427 
00428   const char* in_args3[] = {"testbin", "p1",          "--int_flag=3",
00429                             "p2",      "--bool_flag", "true"};
00430   TestParse(in_args3, 3, 1.1, "a", true, 3);
00431 
00432   auto out_args3 = InvokeParse(in_args3);
00433 
00434   EXPECT_STREQ(out_args3[1], "p1");
00435   EXPECT_STREQ(out_args3[2], "p2");
00436   EXPECT_STREQ(out_args3[3], "true");
00437 
00438   const char* in_args4[] = {
00439       "testbin",
00440       "--",
00441       "p1",
00442       "p2",
00443   };
00444   TestParse(in_args4, 3, 1.1, "a", true, 2);
00445 
00446   auto out_args4 = InvokeParse(in_args4);
00447 
00448   EXPECT_STREQ(out_args4[1], "p1");
00449   EXPECT_STREQ(out_args4[2], "p2");
00450 
00451   const char* in_args5[] = {
00452       "testbin", "p1", "--int_flag=4", "--", "--bool_flag", "false", "p2",
00453   };
00454   TestParse(in_args5, 4, 1.1, "a", true, 4);
00455 
00456   auto out_args5 = InvokeParse(in_args5);
00457 
00458   EXPECT_STREQ(out_args5[1], "p1");
00459   EXPECT_STREQ(out_args5[2], "--bool_flag");
00460   EXPECT_STREQ(out_args5[3], "false");
00461   EXPECT_STREQ(out_args5[4], "p2");
00462 }
00463 
00464 // --------------------------------------------------------------------
00465 
00466 using ParseDeathTest = ParseTest;
00467 
00468 TEST_F(ParseDeathTest, TestUndefinedArg) {
00469   const char* in_args1[] = {
00470       "testbin",
00471       "--undefined_flag",
00472   };
00473   EXPECT_DEATH(InvokeParse(in_args1),
00474                "Unknown command line flag 'undefined_flag'");
00475 
00476   const char* in_args2[] = {
00477       "testbin",
00478       "--noprefixed_flag",
00479   };
00480   EXPECT_DEATH(InvokeParse(in_args2),
00481                "Unknown command line flag 'noprefixed_flag'");
00482 
00483   const char* in_args3[] = {
00484       "testbin",
00485       "--Int_flag=1",
00486   };
00487   EXPECT_DEATH(InvokeParse(in_args3), "Unknown command line flag 'Int_flag'");
00488 }
00489 
00490 // --------------------------------------------------------------------
00491 
00492 TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {
00493   const char* in_args1[] = {
00494       "testbin",
00495       "--bool_flag=",
00496   };
00497   EXPECT_DEATH(
00498       InvokeParse(in_args1),
00499       "Missing the value after assignment for the boolean flag 'bool_flag'");
00500 
00501   const char* in_args2[] = {
00502       "testbin",
00503       "--nobool_flag=true",
00504   };
00505   EXPECT_DEATH(InvokeParse(in_args2),
00506                "Negative form with assignment is not valid for the boolean "
00507                "flag 'bool_flag'");
00508 }
00509 
00510 // --------------------------------------------------------------------
00511 
00512 TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) {
00513   const char* in_args1[] = {
00514       "testbin",
00515       "--nostring_flag",
00516   };
00517   EXPECT_DEATH(InvokeParse(in_args1),
00518                "Negative form is not valid for the flag 'string_flag'");
00519 
00520   const char* in_args2[] = {
00521       "testbin",
00522       "--int_flag",
00523   };
00524   EXPECT_DEATH(InvokeParse(in_args2),
00525                "Missing the value for the flag 'int_flag'");
00526 }
00527 
00528 // --------------------------------------------------------------------
00529 
00530 TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {
00531   const char* in_args1[] = {
00532       "testbin",
00533       "--udt_flag=1",
00534   };
00535   EXPECT_DEATH(InvokeParse(in_args1),
00536                "Illegal value '1' specified for flag 'udt_flag'; Use values A, "
00537                "AAA instead");
00538 
00539   const char* in_args2[] = {
00540       "testbin",
00541       "--udt_flag",
00542       "AA",
00543   };
00544   EXPECT_DEATH(InvokeParse(in_args2),
00545                "Illegal value 'AA' specified for flag 'udt_flag'; Use values "
00546                "A, AAA instead");
00547 }
00548 
00549 // --------------------------------------------------------------------
00550 
00551 TEST_F(ParseTest, TestLegacyFlags) {
00552   const char* in_args1[] = {
00553       "testbin",
00554       "--legacy_int=11",
00555   };
00556   TestParse(in_args1, 1, 1.1, "a", false);
00557 
00558   const char* in_args2[] = {
00559       "testbin",
00560       "--legacy_bool",
00561   };
00562   TestParse(in_args2, 1, 1.1, "a", false);
00563 
00564   const char* in_args3[] = {
00565       "testbin",       "--legacy_int", "22",           "--int_flag=2",
00566       "--legacy_bool", "true",         "--legacy_str", "--string_flag=qwe",
00567   };
00568   TestParse(in_args3, 2, 1.1, "a", false, 1);
00569 }
00570 
00571 // --------------------------------------------------------------------
00572 
00573 TEST_F(ParseTest, TestSimpleValidFlagfile) {
00574   std::string flagfile_flag;
00575 
00576   const char* in_args1[] = {
00577       "testbin",
00578       GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
00579                       &flagfile_flag),
00580   };
00581   TestParse(in_args1, -1, 0.1, "q2w2  ", true);
00582 
00583   const char* in_args2[] = {
00584       "testbin",
00585       GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}},
00586                       &flagfile_flag),
00587   };
00588   TestParse(in_args2, 100, 0.1, "q2w2  ", false);
00589 }
00590 
00591 // --------------------------------------------------------------------
00592 
00593 TEST_F(ParseTest, TestValidMultiFlagfile) {
00594   std::string flagfile_flag;
00595 
00596   const char* in_args1[] = {
00597       "testbin",
00598       GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
00599                        {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
00600                       &flagfile_flag),
00601   };
00602   TestParse(in_args1, -1, 0.1, "q2w2  ", true);
00603 }
00604 
00605 // --------------------------------------------------------------------
00606 
00607 TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
00608   std::string flagfile_flag;
00609 
00610   const char* in_args1[] = {
00611       "testbin", "--int_flag=3",
00612       GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
00613                       &flagfile_flag),
00614       "-double_flag=0.2"};
00615   TestParse(in_args1, -1, 0.2, "q2w2  ", true);
00616 }
00617 
00618 // --------------------------------------------------------------------
00619 
00620 TEST_F(ParseTest, TestFlagfileInFlagfile) {
00621   std::string flagfile_flag;
00622 
00623   constexpr const char* const ff3_data[] = {
00624       "--flagfile=$0/parse_test.ff1",
00625       "--flagfile=$0/parse_test.ff2",
00626   };
00627 
00628   const char* in_args1[] = {
00629       "testbin",
00630       GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
00631                       &flagfile_flag),
00632   };
00633   TestParse(in_args1, 100, 0.1, "q2w2  ", false);
00634 }
00635 
00636 // --------------------------------------------------------------------
00637 
00638 TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
00639   std::string flagfile_flag;
00640 
00641   constexpr const char* const ff4_data[] = {
00642     "--unknown_flag=10"
00643   };
00644 
00645   const char* in_args1[] = {
00646       "testbin",
00647       GetFlagfileFlag({{"parse_test.ff4",
00648                         absl::MakeConstSpan(ff4_data)}}, &flagfile_flag),
00649   };
00650   EXPECT_DEATH(InvokeParse(in_args1),
00651                "Unknown command line flag 'unknown_flag'");
00652 
00653   constexpr const char* const ff5_data[] = {
00654     "--int_flag 10",
00655   };
00656 
00657   const char* in_args2[] = {
00658       "testbin",
00659       GetFlagfileFlag({{"parse_test.ff5",
00660                         absl::MakeConstSpan(ff5_data)}}, &flagfile_flag),
00661   };
00662   EXPECT_DEATH(InvokeParse(in_args2),
00663                "Unknown command line flag 'int_flag 10'");
00664 
00665   constexpr const char* const ff6_data[] = {
00666       "--int_flag=10", "--", "arg1", "arg2", "arg3",
00667   };
00668 
00669   const char* in_args3[] = {
00670       "testbin",
00671       GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
00672                       &flagfile_flag),
00673   };
00674   EXPECT_DEATH(InvokeParse(in_args3),
00675                "Flagfile can't contain position arguments or --");
00676 
00677   const char* in_args4[] = {
00678       "testbin",
00679       "--flagfile=invalid_flag_file",
00680   };
00681   EXPECT_DEATH(InvokeParse(in_args4), "Can't open flagfile invalid_flag_file");
00682 
00683   constexpr const char* const ff7_data[] = {
00684       "--int_flag=10",
00685       "*bin*",
00686       "--str_flag=aqsw",
00687   };
00688 
00689   const char* in_args5[] = {
00690       "testbin",
00691       GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
00692                       &flagfile_flag),
00693   };
00694   EXPECT_DEATH(InvokeParse(in_args5),
00695                "Unexpected line in the flagfile .*: \\*bin\\*");
00696 }
00697 
00698 // --------------------------------------------------------------------
00699 
00700 TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) {
00701   const char* in_args1[] = {"testbin",
00702                             "--fromenv=int_flag,bool_flag,string_flag"};
00703 
00704   ScopedSetEnv set_int_flag("FLAGS_int_flag", "33");
00705   ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "True");
00706   ScopedSetEnv set_string_flag("FLAGS_string_flag", "AQ12");
00707 
00708   TestParse(in_args1, 33, 1.1, "AQ12", true);
00709 }
00710 
00711 // --------------------------------------------------------------------
00712 
00713 TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {
00714   const char* in_args1[] = {"testbin", "--fromenv=int_flag"};
00715 
00716   EXPECT_DEATH(InvokeParse(in_args1),
00717                "FLAGS_int_flag not found in environment");
00718 }
00719 
00720 // --------------------------------------------------------------------
00721 
00722 TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) {
00723   const char* in_args1[] = {"testbin", "--fromenv=tryfromenv"};
00724 
00725   ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag");
00726 
00727   EXPECT_DEATH(InvokeParse(in_args1), "Infinite recursion on flag tryfromenv");
00728 }
00729 
00730 // --------------------------------------------------------------------
00731 
00732 TEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) {
00733   const char* in_args1[] = {
00734       "testbin", "--tryfromenv=int_flag,bool_flag,string_flag,other_flag"};
00735 
00736   ScopedSetEnv set_int_flag("FLAGS_int_flag", "17");
00737   ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "Y");
00738 
00739   TestParse(in_args1, 17, 1.1, "a", true);
00740 }
00741 
00742 // --------------------------------------------------------------------
00743 
00744 TEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) {
00745   const char* in_args1[] = {
00746       "testbin",
00747       "--bool_flag=T",
00748       "--tryfromenv=int_flag,bool_flag",
00749       "--int_flag=-21",
00750   };
00751 
00752   ScopedSetEnv set_int_flag("FLAGS_int_flag", "-15");
00753   ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "F");
00754 
00755   TestParse(in_args1, -21, 1.1, "a", false);
00756 }
00757 
00758 // --------------------------------------------------------------------
00759 
00760 TEST_F(ParseTest, TestKeepParsedArgs) {
00761   const char* in_args1[] = {
00762       "testbin",        "arg1", "--bool_flag",
00763       "--int_flag=211", "arg2", "--double_flag=1.1",
00764       "--string_flag",  "asd",  "--",
00765       "arg3",           "arg4",
00766   };
00767 
00768   auto out_args1 = InvokeParse(in_args1);
00769 
00770   EXPECT_THAT(
00771       out_args1,
00772       ElementsAreArray({absl::string_view("testbin"), absl::string_view("arg1"),
00773                         absl::string_view("arg2"), absl::string_view("arg3"),
00774                         absl::string_view("arg4")}));
00775 
00776   auto out_args2 = flags::ParseCommandLineImpl(
00777       11, const_cast<char**>(in_args1), flags::ArgvListAction::kKeepParsedArgs,
00778       flags::UsageFlagsAction::kHandleUsage,
00779       flags::OnUndefinedFlag::kAbortIfUndefined);
00780 
00781   EXPECT_THAT(
00782       out_args2,
00783       ElementsAreArray({absl::string_view("testbin"),
00784                         absl::string_view("--bool_flag"),
00785                         absl::string_view("--int_flag=211"),
00786                         absl::string_view("--double_flag=1.1"),
00787                         absl::string_view("--string_flag"),
00788                         absl::string_view("asd"), absl::string_view("--"),
00789                         absl::string_view("arg1"), absl::string_view("arg2"),
00790                         absl::string_view("arg3"), absl::string_view("arg4")}));
00791 }
00792 
00793 // --------------------------------------------------------------------
00794 
00795 TEST_F(ParseTest, TestIgnoreUndefinedFlags) {
00796   const char* in_args1[] = {
00797       "testbin",
00798       "arg1",
00799       "--undef_flag=aa",
00800       "--int_flag=21",
00801   };
00802 
00803   auto out_args1 = flags::ParseCommandLineImpl(
00804       4, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
00805       flags::UsageFlagsAction::kHandleUsage,
00806       flags::OnUndefinedFlag::kIgnoreUndefined);
00807 
00808   EXPECT_THAT(out_args1, ElementsAreArray({absl::string_view("testbin"),
00809                                            absl::string_view("arg1")}));
00810 
00811   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 21);
00812 
00813   const char* in_args2[] = {
00814       "testbin",
00815       "arg1",
00816       "--undef_flag=aa",
00817       "--string_flag=AA",
00818   };
00819 
00820   auto out_args2 = flags::ParseCommandLineImpl(
00821       4, const_cast<char**>(in_args2), flags::ArgvListAction::kKeepParsedArgs,
00822       flags::UsageFlagsAction::kHandleUsage,
00823       flags::OnUndefinedFlag::kIgnoreUndefined);
00824 
00825   EXPECT_THAT(
00826       out_args2,
00827       ElementsAreArray(
00828           {absl::string_view("testbin"), absl::string_view("--undef_flag=aa"),
00829            absl::string_view("--string_flag=AA"), absl::string_view("arg1")}));
00830 
00831   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "AA");
00832 }
00833 
00834 // --------------------------------------------------------------------
00835 
00836 TEST_F(ParseDeathTest, TestHelpFlagHandling) {
00837   const char* in_args1[] = {
00838       "testbin",
00839       "--help",
00840   };
00841 
00842   EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), "");
00843 
00844   const char* in_args2[] = {
00845       "testbin",
00846       "--help",
00847       "--int_flag=3",
00848   };
00849 
00850   auto out_args2 = flags::ParseCommandLineImpl(
00851       3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
00852       flags::UsageFlagsAction::kIgnoreUsage,
00853       flags::OnUndefinedFlag::kAbortIfUndefined);
00854 
00855   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
00856 }
00857 
00858 }  // namespace


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15