| // | |
| // 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/internal/usage.h" | |
| #include <stdint.h> | |
| #include <sstream> | |
| #include <string> | |
| #include "gmock/gmock.h" | |
| #include "gtest/gtest.h" | |
| #include "absl/flags/config.h" | |
| #include "absl/flags/flag.h" | |
| #include "absl/flags/internal/parse.h" | |
| #include "absl/flags/internal/program_name.h" | |
| #include "absl/flags/reflection.h" | |
| #include "absl/flags/usage.h" | |
| #include "absl/flags/usage_config.h" | |
| #include "absl/strings/match.h" | |
| #include "absl/strings/string_view.h" | |
| ABSL_FLAG(int, usage_reporting_test_flag_01, 101, | |
| "usage_reporting_test_flag_01 help message"); | |
| ABSL_FLAG(bool, usage_reporting_test_flag_02, false, | |
| "usage_reporting_test_flag_02 help message"); | |
| ABSL_FLAG(double, usage_reporting_test_flag_03, 1.03, | |
| "usage_reporting_test_flag_03 help message"); | |
| ABSL_FLAG(int64_t, usage_reporting_test_flag_04, 1000000000000004L, | |
| "usage_reporting_test_flag_04 help message"); | |
| ABSL_FLAG(std::string, usage_reporting_test_flag_07, "\r\n\f\v\a\b\t ", | |
| "usage_reporting_test_flag_07 help \r\n\f\v\a\b\t "); | |
| static const char kTestUsageMessage[] = "Custom usage message"; | |
| struct UDT { | |
| UDT() = default; | |
| UDT(const UDT&) = default; | |
| UDT& operator=(const UDT&) = default; | |
| }; | |
| static bool AbslParseFlag(absl::string_view, UDT*, std::string*) { | |
| return true; | |
| } | |
| static std::string AbslUnparseFlag(const UDT&) { return "UDT{}"; } | |
| ABSL_FLAG(UDT, usage_reporting_test_flag_05, {}, | |
| "usage_reporting_test_flag_05 help message"); | |
| ABSL_FLAG( | |
| std::string, usage_reporting_test_flag_06, {}, | |
| "usage_reporting_test_flag_06 help message.\n" | |
| "\n" | |
| "Some more help.\n" | |
| "Even more long long long long long long long long long long long long " | |
| "help message."); | |
| namespace { | |
| namespace flags = absl::flags_internal; | |
| static std::string NormalizeFileName(absl::string_view fname) { | |
| #ifdef _WIN32 | |
| std::string normalized(fname); | |
| std::replace(normalized.begin(), normalized.end(), '\\', '/'); | |
| fname = normalized; | |
| #endif | |
| auto absl_pos = fname.rfind("absl/"); | |
| if (absl_pos != absl::string_view::npos) { | |
| fname = fname.substr(absl_pos); | |
| } | |
| return std::string(fname); | |
| } | |
| class UsageReportingTest : public testing::Test { | |
| protected: | |
| UsageReportingTest() { | |
| // Install default config for the use on this unit test. | |
| // Binary may install a custom config before tests are run. | |
| absl::FlagsUsageConfig default_config; | |
| default_config.normalize_filename = &NormalizeFileName; | |
| absl::SetFlagsUsageConfig(default_config); | |
| } | |
| ~UsageReportingTest() override { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kNone); | |
| flags::SetFlagsHelpMatchSubstr(""); | |
| flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable); | |
| } | |
| void SetUp() override { | |
| #if ABSL_FLAGS_STRIP_NAMES | |
| GTEST_SKIP() << "This test requires flag names to be present"; | |
| #endif | |
| } | |
| private: | |
| absl::FlagSaver flag_saver_; | |
| }; | |
| // -------------------------------------------------------------------- | |
| using UsageReportingDeathTest = UsageReportingTest; | |
| TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) { | |
| #if !defined(GTEST_HAS_ABSL) || !GTEST_HAS_ABSL | |
| // Check for kTestUsageMessage set in main() below. | |
| EXPECT_EQ(absl::ProgramUsageMessage(), kTestUsageMessage); | |
| #else | |
| // Check for part of the usage message set by GoogleTest. | |
| EXPECT_THAT(absl::ProgramUsageMessage(), | |
| ::testing::HasSubstr( | |
| "This program contains tests written using Google Test")); | |
| #endif | |
| EXPECT_DEATH_IF_SUPPORTED( | |
| absl::SetProgramUsageMessage("custom usage message"), | |
| ::testing::HasSubstr("SetProgramUsageMessage() called twice")); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) { | |
| const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_01"); | |
| std::stringstream test_buf; | |
| flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"( --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | |
| default: 101; | |
| )"); | |
| } | |
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) { | |
| const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02"); | |
| std::stringstream test_buf; | |
| flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"( --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | |
| default: false; | |
| )"); | |
| } | |
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) { | |
| const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03"); | |
| std::stringstream test_buf; | |
| flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"( --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | |
| default: 1.03; | |
| )"); | |
| } | |
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) { | |
| const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04"); | |
| std::stringstream test_buf; | |
| flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"( --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | |
| default: 1000000000000004; | |
| )"); | |
| } | |
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) { | |
| const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05"); | |
| std::stringstream test_buf; | |
| flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"( --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | |
| default: UDT{}; | |
| )"); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestFlagsHelpHRF) { | |
| std::string usage_test_flags_out = | |
| R"(usage_test: Custom usage message | |
| Flags from absl/flags/internal/usage_test.cc: | |
| --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | |
| default: 101; | |
| --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | |
| default: false; | |
| --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | |
| default: 1.03; | |
| --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | |
| default: 1000000000000004; | |
| --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | |
| default: UDT{}; | |
| --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | |
| Some more help. | |
| Even more long long long long long long long long long long long long help | |
| message.); default: "";)" | |
| "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " | |
| "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" | |
| R"( | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"; | |
| std::stringstream test_buf_01; | |
| flags::FlagsHelp(test_buf_01, "usage_test.cc", | |
| flags::HelpFormat::kHumanReadable, kTestUsageMessage); | |
| EXPECT_EQ(test_buf_01.str(), usage_test_flags_out); | |
| std::stringstream test_buf_02; | |
| flags::FlagsHelp(test_buf_02, "flags/internal/usage_test.cc", | |
| flags::HelpFormat::kHumanReadable, kTestUsageMessage); | |
| EXPECT_EQ(test_buf_02.str(), usage_test_flags_out); | |
| std::stringstream test_buf_03; | |
| flags::FlagsHelp(test_buf_03, "usage_test", flags::HelpFormat::kHumanReadable, | |
| kTestUsageMessage); | |
| EXPECT_EQ(test_buf_03.str(), usage_test_flags_out); | |
| std::stringstream test_buf_04; | |
| flags::FlagsHelp(test_buf_04, "flags/invalid_file_name.cc", | |
| flags::HelpFormat::kHumanReadable, kTestUsageMessage); | |
| EXPECT_EQ(test_buf_04.str(), | |
| R"(usage_test: Custom usage message | |
| No flags matched. | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"); | |
| std::stringstream test_buf_05; | |
| flags::FlagsHelp(test_buf_05, "", flags::HelpFormat::kHumanReadable, | |
| kTestUsageMessage); | |
| std::string test_out = test_buf_05.str(); | |
| absl::string_view test_out_str(test_out); | |
| EXPECT_TRUE( | |
| absl::StartsWith(test_out_str, "usage_test: Custom usage message")); | |
| EXPECT_TRUE(absl::StrContains( | |
| test_out_str, "Flags from absl/flags/internal/usage_test.cc:")); | |
| EXPECT_TRUE( | |
| absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 ")); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestNoUsageFlags) { | |
| std::stringstream test_buf; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), | |
| flags::HelpMode::kNone); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestUsageFlag_helpshort) { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kShort); | |
| std::stringstream test_buf; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), | |
| flags::HelpMode::kShort); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"(usage_test: Custom usage message | |
| Flags from absl/flags/internal/usage_test.cc: | |
| --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | |
| default: 101; | |
| --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | |
| default: false; | |
| --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | |
| default: 1.03; | |
| --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | |
| default: 1000000000000004; | |
| --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | |
| default: UDT{}; | |
| --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | |
| Some more help. | |
| Even more long long long long long long long long long long long long help | |
| message.); default: "";)" | |
| "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " | |
| "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" | |
| R"( | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestUsageFlag_help_simple) { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kImportant); | |
| std::stringstream test_buf; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), | |
| flags::HelpMode::kImportant); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"(usage_test: Custom usage message | |
| Flags from absl/flags/internal/usage_test.cc: | |
| --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | |
| default: 101; | |
| --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | |
| default: false; | |
| --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | |
| default: 1.03; | |
| --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | |
| default: 1000000000000004; | |
| --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | |
| default: UDT{}; | |
| --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | |
| Some more help. | |
| Even more long long long long long long long long long long long long help | |
| message.); default: "";)" | |
| "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " | |
| "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" | |
| R"( | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kMatch); | |
| flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06"); | |
| std::stringstream test_buf; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), | |
| flags::HelpMode::kMatch); | |
| EXPECT_EQ(test_buf.str(), | |
| R"(usage_test: Custom usage message | |
| Flags from absl/flags/internal/usage_test.cc: | |
| --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | |
| Some more help. | |
| Even more long long long long long long long long long long long long help | |
| message.); default: ""; | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kMatch); | |
| flags::SetFlagsHelpMatchSubstr("test_flag"); | |
| std::stringstream test_buf; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), | |
| flags::HelpMode::kMatch); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"(usage_test: Custom usage message | |
| Flags from absl/flags/internal/usage_test.cc: | |
| --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | |
| default: 101; | |
| --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | |
| default: false; | |
| --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | |
| default: 1.03; | |
| --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | |
| default: 1000000000000004; | |
| --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | |
| default: UDT{}; | |
| --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | |
| Some more help. | |
| Even more long long long long long long long long long long long long help | |
| message.); default: "";)" | |
| "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " | |
| "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" | |
| R"( | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestUsageFlag_helppackage) { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kPackage); | |
| std::stringstream test_buf; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), | |
| flags::HelpMode::kPackage); | |
| EXPECT_EQ( | |
| test_buf.str(), | |
| R"(usage_test: Custom usage message | |
| Flags from absl/flags/internal/usage_test.cc: | |
| --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | |
| default: 101; | |
| --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | |
| default: false; | |
| --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | |
| default: 1.03; | |
| --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | |
| default: 1000000000000004; | |
| --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | |
| default: UDT{}; | |
| --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | |
| Some more help. | |
| Even more long long long long long long long long long long long long help | |
| message.); default: "";)" | |
| "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " | |
| "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" | |
| R"( | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestUsageFlag_version) { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kVersion); | |
| std::stringstream test_buf; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), | |
| flags::HelpMode::kVersion); | |
| #ifndef NDEBUG | |
| EXPECT_EQ(test_buf.str(), "usage_test\nDebug build (NDEBUG not #defined)\n"); | |
| #else | |
| EXPECT_EQ(test_buf.str(), "usage_test\n"); | |
| #endif | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs); | |
| std::stringstream test_buf; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), | |
| flags::HelpMode::kOnlyCheckArgs); | |
| EXPECT_EQ(test_buf.str(), ""); | |
| } | |
| // -------------------------------------------------------------------- | |
| TEST_F(UsageReportingTest, TestUsageFlag_helpon) { | |
| flags::SetFlagsHelpMode(flags::HelpMode::kMatch); | |
| flags::SetFlagsHelpMatchSubstr("/bla-bla."); | |
| std::stringstream test_buf_01; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), | |
| flags::HelpMode::kMatch); | |
| EXPECT_EQ(test_buf_01.str(), | |
| R"(usage_test: Custom usage message | |
| No flags matched. | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"); | |
| flags::SetFlagsHelpMatchSubstr("/usage_test."); | |
| std::stringstream test_buf_02; | |
| EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), | |
| flags::HelpMode::kMatch); | |
| EXPECT_EQ( | |
| test_buf_02.str(), | |
| R"(usage_test: Custom usage message | |
| Flags from absl/flags/internal/usage_test.cc: | |
| --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | |
| default: 101; | |
| --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | |
| default: false; | |
| --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | |
| default: 1.03; | |
| --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | |
| default: 1000000000000004; | |
| --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | |
| default: UDT{}; | |
| --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | |
| Some more help. | |
| Even more long long long long long long long long long long long long help | |
| message.); default: "";)" | |
| "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " | |
| "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" | |
| R"( | |
| Try --helpfull to get a list of all flags or --help=substring shows help for | |
| flags which include specified substring in either in the name, or description or | |
| path. | |
| )"); | |
| } | |
| // -------------------------------------------------------------------- | |
| } // namespace | |
| int main(int argc, char* argv[]) { | |
| (void)absl::GetFlag(FLAGS_undefok); // Force linking of parse.cc | |
| flags::SetProgramInvocationName("usage_test"); | |
| #if !defined(GTEST_HAS_ABSL) || !GTEST_HAS_ABSL | |
| // GoogleTest calls absl::SetProgramUsageMessage() already. | |
| absl::SetProgramUsageMessage(kTestUsageMessage); | |
| #endif | |
| ::testing::InitGoogleTest(&argc, argv); | |
| return RUN_ALL_TESTS(); | |
| } |