123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 |
- //
- // Copyright 2019 The Abseil Authors.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // https://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "absl/flags/parse.h"
- #include <stdlib.h>
- #include <fstream>
- #include <string>
- #include <vector>
- #include "gmock/gmock.h"
- #include "gtest/gtest.h"
- #include "absl/base/internal/raw_logging.h"
- #include "absl/base/internal/scoped_set_env.h"
- #include "absl/flags/declare.h"
- #include "absl/flags/flag.h"
- #include "absl/flags/internal/parse.h"
- #include "absl/flags/internal/usage.h"
- #include "absl/flags/reflection.h"
- #include "absl/strings/str_cat.h"
- #include "absl/strings/string_view.h"
- #include "absl/strings/substitute.h"
- #include "absl/types/span.h"
- #ifdef _WIN32
- #include <windows.h>
- #endif
- namespace {
- using absl::base_internal::ScopedSetEnv;
- struct UDT {
- UDT() = default;
- UDT(const UDT&) = default;
- UDT& operator=(const UDT&) = default;
- UDT(int v) : value(v) {} // NOLINT
- int value;
- };
- bool AbslParseFlag(absl::string_view in, UDT* udt, std::string* err) {
- if (in == "A") {
- udt->value = 1;
- return true;
- }
- if (in == "AAA") {
- udt->value = 10;
- return true;
- }
- *err = "Use values A, AAA instead";
- return false;
- }
- std::string AbslUnparseFlag(const UDT& udt) {
- return udt.value == 1 ? "A" : "AAA";
- }
- std::string GetTestTmpDirEnvVar(const char* const env_var_name) {
- #ifdef _WIN32
- char buf[MAX_PATH];
- auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf));
- if (get_res >= sizeof(buf) || get_res == 0) {
- return "";
- }
- return std::string(buf, get_res);
- #else
- const char* val = ::getenv(env_var_name);
- if (val == nullptr) {
- return "";
- }
- return val;
- #endif
- }
- const std::string& GetTestTempDir() {
- static std::string* temp_dir_name = []() -> std::string* {
- std::string* res = new std::string(GetTestTmpDirEnvVar("TEST_TMPDIR"));
- if (res->empty()) {
- *res = GetTestTmpDirEnvVar("TMPDIR");
- }
- if (res->empty()) {
- #ifdef _WIN32
- char temp_path_buffer[MAX_PATH];
- auto len = GetTempPathA(MAX_PATH, temp_path_buffer);
- if (len < MAX_PATH && len != 0) {
- std::string temp_dir_name = temp_path_buffer;
- if (!absl::EndsWith(temp_dir_name, "\\")) {
- temp_dir_name.push_back('\\');
- }
- absl::StrAppend(&temp_dir_name, "parse_test.", GetCurrentProcessId());
- if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {
- *res = temp_dir_name;
- }
- }
- #else
- char temp_dir_template[] = "/tmp/parse_test.XXXXXX";
- if (auto* unique_name = ::mkdtemp(temp_dir_template)) {
- *res = unique_name;
- }
- #endif
- }
- if (res->empty()) {
- ABSL_INTERNAL_LOG(FATAL,
- "Failed to make temporary directory for data files");
- }
- #ifdef _WIN32
- *res += "\\";
- #else
- *res += "/";
- #endif
- return res;
- }();
- return *temp_dir_name;
- }
- struct FlagfileData {
- const absl::string_view file_name;
- const absl::Span<const char* const> file_lines;
- };
- // clang-format off
- constexpr const char* const ff1_data[] = {
- "# comment ",
- " # comment ",
- "",
- " ",
- "--int_flag=-1",
- " --string_flag=q2w2 ",
- " ## ",
- " --double_flag=0.1",
- "--bool_flag=Y "
- };
- constexpr const char* const ff2_data[] = {
- "# Setting legacy flag",
- "--legacy_int=1111",
- "--legacy_bool",
- "--nobool_flag",
- "--legacy_str=aqsw",
- "--int_flag=100",
- " ## ============="
- };
- // clang-format on
- // Builds flagfile flag in the flagfile_flag buffer and returns it. This
- // function also creates a temporary flagfile based on FlagfileData input.
- // We create a flagfile in a temporary directory with the name specified in
- // FlagfileData and populate it with lines specifed in FlagfileData. If $0 is
- // referenced in any of the lines in FlagfileData they are replaced with
- // temporary directory location. This way we can test inclusion of one flagfile
- // from another flagfile.
- const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
- std::string& flagfile_flag) {
- flagfile_flag = "--flagfile=";
- absl::string_view separator;
- for (const auto& flagfile_data : ffd) {
- std::string flagfile_name =
- absl::StrCat(GetTestTempDir(), flagfile_data.file_name);
- std::ofstream flagfile_out(flagfile_name);
- for (auto line : flagfile_data.file_lines) {
- flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
- }
- absl::StrAppend(&flagfile_flag, separator, flagfile_name);
- separator = ",";
- }
- return flagfile_flag.c_str();
- }
- } // namespace
- ABSL_FLAG(int, int_flag, 1, "");
- ABSL_FLAG(double, double_flag, 1.1, "");
- ABSL_FLAG(std::string, string_flag, "a", "");
- ABSL_FLAG(bool, bool_flag, false, "");
- ABSL_FLAG(UDT, udt_flag, -1, "");
- ABSL_RETIRED_FLAG(int, legacy_int, 1, "");
- ABSL_RETIRED_FLAG(bool, legacy_bool, false, "");
- ABSL_RETIRED_FLAG(std::string, legacy_str, "l", "");
- namespace {
- namespace flags = absl::flags_internal;
- using testing::ElementsAreArray;
- class ParseTest : public testing::Test {
- public:
- ~ParseTest() override { flags::SetFlagsHelpMode(flags::HelpMode::kNone); }
- private:
- absl::FlagSaver flag_saver_;
- };
- // --------------------------------------------------------------------
- template <int N>
- std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
- return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
- }
- // --------------------------------------------------------------------
- template <int N>
- void TestParse(const char* (&in_argv)[N], int int_flag_value,
- double double_flag_val, absl::string_view string_flag_val,
- bool bool_flag_val, int exp_position_args = 0) {
- auto out_args = InvokeParse(in_argv);
- EXPECT_EQ(out_args.size(), 1 + exp_position_args);
- EXPECT_STREQ(out_args[0], "testbin");
- EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value);
- EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001);
- EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val);
- EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestEmptyArgv) {
- const char* in_argv[] = {"testbin"};
- auto out_args = InvokeParse(in_argv);
- EXPECT_EQ(out_args.size(), 1);
- EXPECT_STREQ(out_args[0], "testbin");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestValidIntArg) {
- const char* in_args1[] = {
- "testbin",
- "--int_flag=10",
- };
- TestParse(in_args1, 10, 1.1, "a", false);
- const char* in_args2[] = {
- "testbin",
- "-int_flag=020",
- };
- TestParse(in_args2, 20, 1.1, "a", false);
- const char* in_args3[] = {
- "testbin",
- "--int_flag",
- "-30",
- };
- TestParse(in_args3, -30, 1.1, "a", false);
- const char* in_args4[] = {
- "testbin",
- "-int_flag",
- "0x21",
- };
- TestParse(in_args4, 33, 1.1, "a", false);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestValidDoubleArg) {
- const char* in_args1[] = {
- "testbin",
- "--double_flag=2.3",
- };
- TestParse(in_args1, 1, 2.3, "a", false);
- const char* in_args2[] = {
- "testbin",
- "--double_flag=0x1.2",
- };
- TestParse(in_args2, 1, 1.125, "a", false);
- const char* in_args3[] = {
- "testbin",
- "--double_flag",
- "99.7",
- };
- TestParse(in_args3, 1, 99.7, "a", false);
- const char* in_args4[] = {
- "testbin",
- "--double_flag",
- "0x20.1",
- };
- TestParse(in_args4, 1, 32.0625, "a", false);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestValidStringArg) {
- const char* in_args1[] = {
- "testbin",
- "--string_flag=aqswde",
- };
- TestParse(in_args1, 1, 1.1, "aqswde", false);
- const char* in_args2[] = {
- "testbin",
- "-string_flag=a=b=c",
- };
- TestParse(in_args2, 1, 1.1, "a=b=c", false);
- const char* in_args3[] = {
- "testbin",
- "--string_flag",
- "zaxscd",
- };
- TestParse(in_args3, 1, 1.1, "zaxscd", false);
- const char* in_args4[] = {
- "testbin",
- "-string_flag",
- "--int_flag",
- };
- TestParse(in_args4, 1, 1.1, "--int_flag", false);
- const char* in_args5[] = {
- "testbin",
- "--string_flag",
- "--no_a_flag=11",
- };
- TestParse(in_args5, 1, 1.1, "--no_a_flag=11", false);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestValidBoolArg) {
- const char* in_args1[] = {
- "testbin",
- "--bool_flag",
- };
- TestParse(in_args1, 1, 1.1, "a", true);
- const char* in_args2[] = {
- "testbin",
- "--nobool_flag",
- };
- TestParse(in_args2, 1, 1.1, "a", false);
- const char* in_args3[] = {
- "testbin",
- "--bool_flag=true",
- };
- TestParse(in_args3, 1, 1.1, "a", true);
- const char* in_args4[] = {
- "testbin",
- "-bool_flag=false",
- };
- TestParse(in_args4, 1, 1.1, "a", false);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestValidUDTArg) {
- const char* in_args1[] = {
- "testbin",
- "--udt_flag=A",
- };
- InvokeParse(in_args1);
- EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1);
- const char* in_args2[] = {"testbin", "--udt_flag", "AAA"};
- InvokeParse(in_args2);
- EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestValidMultipleArg) {
- const char* in_args1[] = {
- "testbin", "--bool_flag", "--int_flag=2",
- "--double_flag=0.1", "--string_flag=asd",
- };
- TestParse(in_args1, 2, 0.1, "asd", true);
- const char* in_args2[] = {
- "testbin", "--string_flag=", "--nobool_flag", "--int_flag",
- "-011", "--double_flag", "-1e-2",
- };
- TestParse(in_args2, -11, -0.01, "", false);
- const char* in_args3[] = {
- "testbin", "--int_flag", "-0", "--string_flag", "\"\"",
- "--bool_flag=true", "--double_flag=1e18",
- };
- TestParse(in_args3, 0, 1e18, "\"\"", true);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestPositionalArgs) {
- const char* in_args1[] = {
- "testbin",
- "p1",
- "p2",
- };
- TestParse(in_args1, 1, 1.1, "a", false, 2);
- auto out_args1 = InvokeParse(in_args1);
- EXPECT_STREQ(out_args1[1], "p1");
- EXPECT_STREQ(out_args1[2], "p2");
- const char* in_args2[] = {
- "testbin",
- "--int_flag=2",
- "p1",
- };
- TestParse(in_args2, 2, 1.1, "a", false, 1);
- auto out_args2 = InvokeParse(in_args2);
- EXPECT_STREQ(out_args2[1], "p1");
- const char* in_args3[] = {"testbin", "p1", "--int_flag=3",
- "p2", "--bool_flag", "true"};
- TestParse(in_args3, 3, 1.1, "a", true, 3);
- auto out_args3 = InvokeParse(in_args3);
- EXPECT_STREQ(out_args3[1], "p1");
- EXPECT_STREQ(out_args3[2], "p2");
- EXPECT_STREQ(out_args3[3], "true");
- const char* in_args4[] = {
- "testbin",
- "--",
- "p1",
- "p2",
- };
- TestParse(in_args4, 3, 1.1, "a", true, 2);
- auto out_args4 = InvokeParse(in_args4);
- EXPECT_STREQ(out_args4[1], "p1");
- EXPECT_STREQ(out_args4[2], "p2");
- const char* in_args5[] = {
- "testbin", "p1", "--int_flag=4", "--", "--bool_flag", "false", "p2",
- };
- TestParse(in_args5, 4, 1.1, "a", true, 4);
- auto out_args5 = InvokeParse(in_args5);
- EXPECT_STREQ(out_args5[1], "p1");
- EXPECT_STREQ(out_args5[2], "--bool_flag");
- EXPECT_STREQ(out_args5[3], "false");
- EXPECT_STREQ(out_args5[4], "p2");
- }
- // --------------------------------------------------------------------
- using ParseDeathTest = ParseTest;
- TEST_F(ParseDeathTest, TestUndefinedArg) {
- const char* in_args1[] = {
- "testbin",
- "--undefined_flag",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
- "Unknown command line flag 'undefined_flag'");
- const char* in_args2[] = {
- "testbin",
- "--noprefixed_flag",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
- "Unknown command line flag 'noprefixed_flag'");
- const char* in_args3[] = {
- "testbin",
- "--Int_flag=1",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
- "Unknown command line flag 'Int_flag'");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {
- const char* in_args1[] = {
- "testbin",
- "--bool_flag=",
- };
- EXPECT_DEATH_IF_SUPPORTED(
- InvokeParse(in_args1),
- "Missing the value after assignment for the boolean flag 'bool_flag'");
- const char* in_args2[] = {
- "testbin",
- "--nobool_flag=true",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
- "Negative form with assignment is not valid for the boolean "
- "flag 'bool_flag'");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) {
- const char* in_args1[] = {
- "testbin",
- "--nostring_flag",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
- "Negative form is not valid for the flag 'string_flag'");
- const char* in_args2[] = {
- "testbin",
- "--int_flag",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
- "Missing the value for the flag 'int_flag'");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {
- const char* in_args1[] = {
- "testbin",
- "--udt_flag=1",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
- "Illegal value '1' specified for flag 'udt_flag'; Use values A, "
- "AAA instead");
- const char* in_args2[] = {
- "testbin",
- "--udt_flag",
- "AA",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
- "Illegal value 'AA' specified for flag 'udt_flag'; Use values "
- "A, AAA instead");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestLegacyFlags) {
- const char* in_args1[] = {
- "testbin",
- "--legacy_int=11",
- };
- TestParse(in_args1, 1, 1.1, "a", false);
- const char* in_args2[] = {
- "testbin",
- "--legacy_bool",
- };
- TestParse(in_args2, 1, 1.1, "a", false);
- const char* in_args3[] = {
- "testbin", "--legacy_int", "22", "--int_flag=2",
- "--legacy_bool", "true", "--legacy_str", "--string_flag=qwe",
- };
- TestParse(in_args3, 2, 1.1, "a", false, 1);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestSimpleValidFlagfile) {
- std::string flagfile_flag;
- const char* in_args1[] = {
- "testbin",
- GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- flagfile_flag),
- };
- TestParse(in_args1, -1, 0.1, "q2w2 ", true);
- const char* in_args2[] = {
- "testbin",
- GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}},
- flagfile_flag),
- };
- TestParse(in_args2, 100, 0.1, "q2w2 ", false);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestValidMultiFlagfile) {
- std::string flagfile_flag;
- const char* in_args1[] = {
- "testbin",
- GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
- {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- flagfile_flag),
- };
- TestParse(in_args1, -1, 0.1, "q2w2 ", true);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
- std::string flagfile_flag;
- const char* in_args1[] = {
- "testbin", "--int_flag=3",
- GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- flagfile_flag),
- "-double_flag=0.2"};
- TestParse(in_args1, -1, 0.2, "q2w2 ", true);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestFlagfileInFlagfile) {
- std::string flagfile_flag;
- constexpr const char* const ff3_data[] = {
- "--flagfile=$0/parse_test.ff1",
- "--flagfile=$0/parse_test.ff2",
- };
- GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
- {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- flagfile_flag);
- const char* in_args1[] = {
- "testbin",
- GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
- flagfile_flag),
- };
- TestParse(in_args1, 100, 0.1, "q2w2 ", false);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
- std::string flagfile_flag;
- constexpr const char* const ff4_data[] = {
- "--unknown_flag=10"
- };
- const char* in_args1[] = {
- "testbin",
- GetFlagfileFlag({{"parse_test.ff4",
- absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
- "Unknown command line flag 'unknown_flag'");
- constexpr const char* const ff5_data[] = {
- "--int_flag 10",
- };
- const char* in_args2[] = {
- "testbin",
- GetFlagfileFlag({{"parse_test.ff5",
- absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
- "Unknown command line flag 'int_flag 10'");
- constexpr const char* const ff6_data[] = {
- "--int_flag=10", "--", "arg1", "arg2", "arg3",
- };
- const char* in_args3[] = {
- "testbin",
- GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
- flagfile_flag),
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
- "Flagfile can't contain position arguments or --");
- const char* in_args4[] = {
- "testbin",
- "--flagfile=invalid_flag_file",
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args4),
- "Can't open flagfile invalid_flag_file");
- constexpr const char* const ff7_data[] = {
- "--int_flag=10",
- "*bin*",
- "--str_flag=aqsw",
- };
- const char* in_args5[] = {
- "testbin",
- GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
- flagfile_flag),
- };
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
- "Unexpected line in the flagfile .*: \\*bin\\*");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) {
- const char* in_args1[] = {"testbin",
- "--fromenv=int_flag,bool_flag,string_flag"};
- ScopedSetEnv set_int_flag("FLAGS_int_flag", "33");
- ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "True");
- ScopedSetEnv set_string_flag("FLAGS_string_flag", "AQ12");
- TestParse(in_args1, 33, 1.1, "AQ12", true);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {
- const char* in_args1[] = {"testbin", "--fromenv=int_flag"};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
- "FLAGS_int_flag not found in environment");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) {
- const char* in_args1[] = {"testbin", "--fromenv=tryfromenv"};
- ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag");
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
- "Infinite recursion on flag tryfromenv");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) {
- const char* in_args1[] = {
- "testbin", "--tryfromenv=int_flag,bool_flag,string_flag,other_flag"};
- ScopedSetEnv set_int_flag("FLAGS_int_flag", "17");
- ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "Y");
- TestParse(in_args1, 17, 1.1, "a", true);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) {
- const char* in_args1[] = {
- "testbin",
- "--bool_flag=T",
- "--tryfromenv=int_flag,bool_flag",
- "--int_flag=-21",
- };
- ScopedSetEnv set_int_flag("FLAGS_int_flag", "-15");
- ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "F");
- TestParse(in_args1, -21, 1.1, "a", false);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestKeepParsedArgs) {
- const char* in_args1[] = {
- "testbin", "arg1", "--bool_flag",
- "--int_flag=211", "arg2", "--double_flag=1.1",
- "--string_flag", "asd", "--",
- "arg3", "arg4",
- };
- auto out_args1 = InvokeParse(in_args1);
- EXPECT_THAT(
- out_args1,
- ElementsAreArray({absl::string_view("testbin"), absl::string_view("arg1"),
- absl::string_view("arg2"), absl::string_view("arg3"),
- absl::string_view("arg4")}));
- auto out_args2 = flags::ParseCommandLineImpl(
- 11, const_cast<char**>(in_args1), flags::ArgvListAction::kKeepParsedArgs,
- flags::UsageFlagsAction::kHandleUsage,
- flags::OnUndefinedFlag::kAbortIfUndefined);
- EXPECT_THAT(
- out_args2,
- ElementsAreArray({absl::string_view("testbin"),
- absl::string_view("--bool_flag"),
- absl::string_view("--int_flag=211"),
- absl::string_view("--double_flag=1.1"),
- absl::string_view("--string_flag"),
- absl::string_view("asd"), absl::string_view("--"),
- absl::string_view("arg1"), absl::string_view("arg2"),
- absl::string_view("arg3"), absl::string_view("arg4")}));
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, TestIgnoreUndefinedFlags) {
- const char* in_args1[] = {
- "testbin",
- "arg1",
- "--undef_flag=aa",
- "--int_flag=21",
- };
- auto out_args1 = flags::ParseCommandLineImpl(
- 4, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
- flags::UsageFlagsAction::kHandleUsage,
- flags::OnUndefinedFlag::kIgnoreUndefined);
- EXPECT_THAT(out_args1, ElementsAreArray({absl::string_view("testbin"),
- absl::string_view("arg1")}));
- EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 21);
- const char* in_args2[] = {
- "testbin",
- "arg1",
- "--undef_flag=aa",
- "--string_flag=AA",
- };
- auto out_args2 = flags::ParseCommandLineImpl(
- 4, const_cast<char**>(in_args2), flags::ArgvListAction::kKeepParsedArgs,
- flags::UsageFlagsAction::kHandleUsage,
- flags::OnUndefinedFlag::kIgnoreUndefined);
- EXPECT_THAT(
- out_args2,
- ElementsAreArray(
- {absl::string_view("testbin"), absl::string_view("--undef_flag=aa"),
- absl::string_view("--string_flag=AA"), absl::string_view("arg1")}));
- EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "AA");
- }
- // --------------------------------------------------------------------
- TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
- const char* in_args1[] = {
- "testbin",
- "--help",
- };
- EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), "");
- const char* in_args2[] = {
- "testbin",
- "--help",
- "--int_flag=3",
- };
- auto out_args2 = flags::ParseCommandLineImpl(
- 3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
- flags::UsageFlagsAction::kIgnoreUsage,
- flags::OnUndefinedFlag::kAbortIfUndefined);
- EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
- EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) {
- const char* in_args1[] = {
- "testbin",
- "--help=abcd",
- };
- auto out_args1 = flags::ParseCommandLineImpl(
- 2, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
- flags::UsageFlagsAction::kIgnoreUsage,
- flags::OnUndefinedFlag::kAbortIfUndefined);
- EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kMatch);
- EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd");
- const char* in_args2[] = {"testbin", "--help", "some_positional_arg"};
- auto out_args2 = flags::ParseCommandLineImpl(
- 3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
- flags::UsageFlagsAction::kIgnoreUsage,
- flags::OnUndefinedFlag::kAbortIfUndefined);
- EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
- }
- // --------------------------------------------------------------------
- TEST_F(ParseTest, WasPresentOnCommandLine) {
- const char* in_args1[] = {
- "testbin", "arg1", "--bool_flag",
- "--int_flag=211", "arg2", "--double_flag=1.1",
- "--string_flag", "asd", "--",
- "--some_flag", "arg4",
- };
- InvokeParse(in_args1);
- EXPECT_TRUE(flags::WasPresentOnCommandLine("bool_flag"));
- EXPECT_TRUE(flags::WasPresentOnCommandLine("int_flag"));
- EXPECT_TRUE(flags::WasPresentOnCommandLine("double_flag"));
- EXPECT_TRUE(flags::WasPresentOnCommandLine("string_flag"));
- EXPECT_FALSE(flags::WasPresentOnCommandLine("some_flag"));
- EXPECT_FALSE(flags::WasPresentOnCommandLine("another_flag"));
- }
- // --------------------------------------------------------------------
- } // namespace
|