diff options
Diffstat (limited to 'googletest')
-rw-r--r-- | googletest/include/gtest/internal/custom/README.md | 14 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-port.h | 80 | ||||
-rw-r--r-- | googletest/src/gtest.cc | 33 | ||||
-rw-r--r-- | googletest/test/BUILD.bazel | 4 | ||||
-rwxr-xr-x | googletest/test/gtest_help_test.py | 67 | ||||
-rw-r--r-- | googletest/test/gtest_unittest.cc | 70 |
6 files changed, 180 insertions, 88 deletions
diff --git a/googletest/include/gtest/internal/custom/README.md b/googletest/include/gtest/internal/custom/README.md index 0af3539..cb49e2c 100644 --- a/googletest/include/gtest/internal/custom/README.md +++ b/googletest/include/gtest/internal/custom/README.md @@ -15,20 +15,6 @@ The custom directory is an injection point for custom user configurations. The following macros can be defined: -### Flag related macros: - -* `GTEST_FLAG(flag_name)` -* `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its - own flagfile flag parsing. -* `GTEST_DECLARE_bool_(name)` -* `GTEST_DECLARE_int32_(name)` -* `GTEST_DECLARE_string_(name)` -* `GTEST_DEFINE_bool_(name, default_val, doc)` -* `GTEST_DEFINE_int32_(name, default_val, doc)` -* `GTEST_DEFINE_string_(name, default_val, doc)` -* `GTEST_FLAG_GET(flag_name)` -* `GTEST_FLAG_SET(flag_name, value)` - ### Logging: * `GTEST_LOG_(severity)` diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h index e178782..574af24 100644 --- a/googletest/include/gtest/internal/gtest-port.h +++ b/googletest/include/gtest/internal/gtest-port.h @@ -240,8 +240,6 @@ // BiggestInt - the biggest signed integer type. // // Command-line utilities: -// GTEST_DECLARE_*() - declares a flag. -// GTEST_DEFINE_*() - defines a flag. // GetInjectableArgvs() - returns the command line as a vector of strings. // // Environment variable utilities: @@ -287,6 +285,12 @@ #include "gtest/internal/custom/gtest-port.h" #include "gtest/internal/gtest-port-arch.h" +#if GTEST_HAS_ABSL +#include "absl/flags/declare.h" +#include "absl/flags/flag.h" +#include "absl/flags/reflection.h" +#endif + #if !defined(GTEST_DEV_EMAIL_) #define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" #define GTEST_FLAG_PREFIX_ "gtest_" @@ -2157,32 +2161,37 @@ using TimeInMillis = int64_t; // Represents time in milliseconds. // Macro for referencing flags. #if !defined(GTEST_FLAG) +#define GTEST_FLAG_NAME_(name) gtest_##name #define GTEST_FLAG(name) FLAGS_gtest_##name #endif // !defined(GTEST_FLAG) -#if !defined(GTEST_USE_OWN_FLAGFILE_FLAG_) -#define GTEST_USE_OWN_FLAGFILE_FLAG_ 1 -#endif // !defined(GTEST_USE_OWN_FLAGFILE_FLAG_) +// Pick a command line flags implementation. +#if GTEST_HAS_ABSL -#if !defined(GTEST_DECLARE_bool_) -#define GTEST_FLAG_SAVER_ ::testing::internal::GTestFlagSaver +// Macros for defining flags. +#define GTEST_DEFINE_bool_(name, default_val, doc) \ + ABSL_FLAG(bool, GTEST_FLAG_NAME_(name), default_val, doc) +#define GTEST_DEFINE_int32_(name, default_val, doc) \ + ABSL_FLAG(int32_t, GTEST_FLAG_NAME_(name), default_val, doc) +#define GTEST_DEFINE_string_(name, default_val, doc) \ + ABSL_FLAG(std::string, GTEST_FLAG_NAME_(name), default_val, doc) // Macros for declaring flags. -#define GTEST_DECLARE_bool_(name) \ - namespace testing { \ - GTEST_API_ extern bool GTEST_FLAG(name); \ - } \ - static_assert(true, "no-op to require trailing semicolon") -#define GTEST_DECLARE_int32_(name) \ - namespace testing { \ - GTEST_API_ extern std::int32_t GTEST_FLAG(name); \ - } \ - static_assert(true, "no-op to require trailing semicolon") -#define GTEST_DECLARE_string_(name) \ - namespace testing { \ - GTEST_API_ extern ::std::string GTEST_FLAG(name); \ - } \ - static_assert(true, "no-op to require trailing semicolon") +#define GTEST_DECLARE_bool_(name) \ + ABSL_DECLARE_FLAG(bool, GTEST_FLAG_NAME_(name)) +#define GTEST_DECLARE_int32_(name) \ + ABSL_DECLARE_FLAG(int32_t, GTEST_FLAG_NAME_(name)) +#define GTEST_DECLARE_string_(name) \ + ABSL_DECLARE_FLAG(std::string, GTEST_FLAG_NAME_(name)) + +#define GTEST_FLAG_SAVER_ ::absl::FlagSaver + +#define GTEST_FLAG_GET(name) ::absl::GetFlag(GTEST_FLAG(name)) +#define GTEST_FLAG_SET(name, value) \ + (void)(::absl::SetFlag(>EST_FLAG(name), value)) +#define GTEST_USE_OWN_FLAGFILE_FLAG_ 0 + +#else // GTEST_HAS_ABSL // Macros for defining flags. #define GTEST_DEFINE_bool_(name, default_val, doc) \ @@ -2201,12 +2210,30 @@ using TimeInMillis = int64_t; // Represents time in milliseconds. } \ static_assert(true, "no-op to require trailing semicolon") -#endif // !defined(GTEST_DECLARE_bool_) +// Macros for declaring flags. +#define GTEST_DECLARE_bool_(name) \ + namespace testing { \ + GTEST_API_ extern bool GTEST_FLAG(name); \ + } \ + static_assert(true, "no-op to require trailing semicolon") +#define GTEST_DECLARE_int32_(name) \ + namespace testing { \ + GTEST_API_ extern std::int32_t GTEST_FLAG(name); \ + } \ + static_assert(true, "no-op to require trailing semicolon") +#define GTEST_DECLARE_string_(name) \ + namespace testing { \ + GTEST_API_ extern ::std::string GTEST_FLAG(name); \ + } \ + static_assert(true, "no-op to require trailing semicolon") + +#define GTEST_FLAG_SAVER_ ::testing::internal::GTestFlagSaver -#if !defined(GTEST_FLAG_GET) #define GTEST_FLAG_GET(name) ::testing::GTEST_FLAG(name) #define GTEST_FLAG_SET(name, value) (void)(::testing::GTEST_FLAG(name) = value) -#endif // !defined(GTEST_FLAG_GET) +#define GTEST_USE_OWN_FLAGFILE_FLAG_ 1 + +#endif // GTEST_HAS_ABSL // Thread annotations #if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_) @@ -2362,8 +2389,7 @@ template <typename... T> using Variant = ::std::variant<T...>; } // namespace internal } // namespace testing - // The case where absl is configured NOT to alias std::variant is not - // supported. +// The case where absl is configured NOT to alias std::variant is not supported. #endif // __has_include(<variant>) && __cplusplus >= 201703L #endif // __has_include #endif // GTEST_HAS_ABSL diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index 10cff8e..acfb941 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -136,7 +136,10 @@ #include "absl/debugging/failure_signal_handler.h" #include "absl/debugging/stacktrace.h" #include "absl/debugging/symbolize.h" +#include "absl/flags/parse.h" +#include "absl/flags/usage.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_replace.h" #endif // GTEST_HAS_ABSL namespace testing { @@ -6590,9 +6593,7 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { LoadFlagsFromFile(flagfile_value); remove_flag = true; #endif // GTEST_USE_OWN_FLAGFILE_FLAG_ - } else if (arg_string == "--help" || arg_string == "-h" || - arg_string == "-?" || arg_string == "/?" || - HasGoogleTestFlagPrefix(arg)) { + } else if (arg_string == "--help" || HasGoogleTestFlagPrefix(arg)) { // Both help flag and unrecognized Google Test flags (excluding // internal ones) trigger help display. g_help_flag = true; @@ -6627,7 +6628,27 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { // Parses the command line for Google Test flags, without initializing // other parts of Google Test. void ParseGoogleTestFlagsOnly(int* argc, char** argv) { +#if GTEST_HAS_ABSL + if (*argc > 0) { + // absl::ParseCommandLine() requires *argc > 0. + auto positional_args = absl::flags_internal::ParseCommandLineImpl( + *argc, argv, absl::flags_internal::ArgvListAction::kRemoveParsedArgs, + absl::flags_internal::UsageFlagsAction::kHandleUsage, + absl::flags_internal::OnUndefinedFlag::kReportUndefined); + // Any command-line positional arguments not part of any command-line flag + // (or arguments to a flag) are copied back out to argv, with the program + // invocation name at position 0, and argc is resized. This includes + // positional arguments after the flag-terminating delimiter '--'. + // See https://abseil.io/docs/cpp/guides/flags. + std::copy(positional_args.begin(), positional_args.end(), argv); + if (static_cast<int>(positional_args.size()) < *argc) { + argv[positional_args.size()] = nullptr; + *argc = static_cast<int>(positional_args.size()); + } + } +#else ParseGoogleTestFlagsOnlyImpl(argc, argv); +#endif // Fix the value of *_NSGetArgc() on macOS, but if and only if // *_NSGetArgv() == argv @@ -6662,6 +6683,12 @@ void InitGoogleTestImpl(int* argc, CharType** argv) { #if GTEST_HAS_ABSL absl::InitializeSymbolizer(g_argvs[0].c_str()); + + // When using the Abseil Flags library, set the program usage message to the + // help message, but remove the color-encoding from the message first. + absl::SetProgramUsageMessage(absl::StrReplaceAll( + kColorEncodedHelpMessage, + {{"@D", ""}, {"@R", ""}, {"@G", ""}, {"@Y", ""}, {"@@", "@"}})); #endif // GTEST_HAS_ABSL ParseGoogleTestFlagsOnly(argc, argv); diff --git a/googletest/test/BUILD.bazel b/googletest/test/BUILD.bazel index 8fd595c..7754c13 100644 --- a/googletest/test/BUILD.bazel +++ b/googletest/test/BUILD.bazel @@ -174,6 +174,10 @@ py_test( name = "gtest_help_test", size = "small", srcs = ["gtest_help_test.py"], + args = select({ + "//:has_absl": ["--has_absl_flags"], + "//conditions:default": [], + }), data = [":gtest_help_test_"], deps = [":gtest_test_utils"], ) diff --git a/googletest/test/gtest_help_test.py b/googletest/test/gtest_help_test.py index 6d2dde0..642ab86 100755 --- a/googletest/test/gtest_help_test.py +++ b/googletest/test/gtest_help_test.py @@ -39,6 +39,7 @@ SYNOPSIS import os import re +import sys from googletest.test import gtest_test_utils @@ -52,16 +53,15 @@ PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_help_test_') FLAG_PREFIX = '--gtest_' DEATH_TEST_STYLE_FLAG = FLAG_PREFIX + 'death_test_style' STREAM_RESULT_TO_FLAG = FLAG_PREFIX + 'stream_result_to' -UNKNOWN_FLAG = FLAG_PREFIX + 'unknown_flag_for_testing' +UNKNOWN_GTEST_PREFIXED_FLAG = FLAG_PREFIX + 'unknown_flag_for_testing' LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests' -INCORRECT_FLAG_VARIANTS = [re.sub('^--', '-', LIST_TESTS_FLAG), - re.sub('^--', '/', LIST_TESTS_FLAG), - re.sub('_', '-', LIST_TESTS_FLAG)] INTERNAL_FLAG_FOR_TESTING = FLAG_PREFIX + 'internal_flag_for_testing' SUPPORTS_DEATH_TESTS = "DeathTest" in gtest_test_utils.Subprocess( [PROGRAM_PATH, LIST_TESTS_FLAG]).output +HAS_ABSL_FLAGS = '--has_absl_flags' in sys.argv + # The help message must match this regex. HELP_REGEX = re.compile( FLAG_PREFIX + r'list_tests.*' + @@ -111,18 +111,37 @@ class GTestHelpTest(gtest_test_utils.TestCase): """ exit_code, output = RunWithFlag(flag) - self.assertEquals(0, exit_code) - self.assert_(HELP_REGEX.search(output), output) + if HAS_ABSL_FLAGS: + # The Abseil flags library prints the ProgramUsageMessage() with + # --help and returns 1. + self.assertEqual(1, exit_code) + else: + self.assertEqual(0, exit_code) + + self.assertTrue(HELP_REGEX.search(output), output) if IS_LINUX or IS_GNUHURD or IS_GNUKFREEBSD or IS_OPENBSD: - self.assert_(STREAM_RESULT_TO_FLAG in output, output) + self.assertIn(STREAM_RESULT_TO_FLAG, output) else: - self.assert_(STREAM_RESULT_TO_FLAG not in output, output) + self.assertNotIn(STREAM_RESULT_TO_FLAG, output) if SUPPORTS_DEATH_TESTS and not IS_WINDOWS: - self.assert_(DEATH_TEST_STYLE_FLAG in output, output) + self.assertIn(DEATH_TEST_STYLE_FLAG, output) else: - self.assert_(DEATH_TEST_STYLE_FLAG not in output, output) + self.assertNotIn(DEATH_TEST_STYLE_FLAG, output) + + def TestUnknownFlagWithAbseil(self, flag): + """Verifies correct behavior when an unknown flag is specified. + + The right message must be printed and the tests must + skipped when the given flag is specified. + + Args: + flag: A flag to pass to the binary or None. + """ + exit_code, output = RunWithFlag(flag) + self.assertEqual(1, exit_code) + self.assertIn('ERROR: Unknown command line flag', output) def TestNonHelpFlag(self, flag): """Verifies correct behavior when no help flag is specified. @@ -135,27 +154,21 @@ class GTestHelpTest(gtest_test_utils.TestCase): """ exit_code, output = RunWithFlag(flag) - self.assert_(exit_code != 0) - self.assert_(not HELP_REGEX.search(output), output) + self.assertNotEqual(exit_code, 0) + self.assertFalse(HELP_REGEX.search(output), output) def testPrintsHelpWithFullFlag(self): self.TestHelpFlag('--help') - def testPrintsHelpWithShortFlag(self): - self.TestHelpFlag('-h') - - def testPrintsHelpWithQuestionFlag(self): - self.TestHelpFlag('-?') - - def testPrintsHelpWithWindowsStyleQuestionFlag(self): - self.TestHelpFlag('/?') - def testPrintsHelpWithUnrecognizedGoogleTestFlag(self): - self.TestHelpFlag(UNKNOWN_FLAG) - - def testPrintsHelpWithIncorrectFlagStyle(self): - for incorrect_flag in INCORRECT_FLAG_VARIANTS: - self.TestHelpFlag(incorrect_flag) + # The behavior is slightly different when Abseil flags is + # used. Abseil flags rejects all unknown flags, while the builtin + # GTest flags implementation interprets an unknown flag with a + # '--gtest_' prefix as a request for help. + if HAS_ABSL_FLAGS: + self.TestUnknownFlagWithAbseil(UNKNOWN_GTEST_PREFIXED_FLAG) + else: + self.TestHelpFlag(UNKNOWN_GTEST_PREFIXED_FLAG) def testRunsTestsWithoutHelpFlag(self): """Verifies that when no help flag is specified, the tests are run @@ -171,4 +184,6 @@ class GTestHelpTest(gtest_test_utils.TestCase): if __name__ == '__main__': + if '--has_absl_flags' in sys.argv: + sys.argv.remove('--has_absl_flags') gtest_test_utils.Main() diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 9b26899..8ed0921 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -5770,15 +5770,6 @@ TEST_F(ParseFlagsTest, FailFast) { GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::FailFast(true), false); } -// Tests parsing a bad --gtest_filter flag. -TEST_F(ParseFlagsTest, FilterBad) { - const char* argv[] = {"foo.exe", "--gtest_filter", nullptr}; - - const char* argv2[] = {"foo.exe", "--gtest_filter", nullptr}; - - GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), true); -} - // Tests parsing an empty --gtest_filter flag. TEST_F(ParseFlagsTest, FilterEmpty) { const char* argv[] = {"foo.exe", "--gtest_filter=", nullptr}; @@ -5931,15 +5922,6 @@ TEST_F(ParseFlagsTest, ListTestsFalse_F) { GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false); } -// Tests parsing --gtest_output (invalid). -TEST_F(ParseFlagsTest, OutputEmpty) { - const char* argv[] = {"foo.exe", "--gtest_output", nullptr}; - - const char* argv2[] = {"foo.exe", "--gtest_output", nullptr}; - - GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), true); -} - // Tests parsing --gtest_output=xml TEST_F(ParseFlagsTest, OutputXml) { const char* argv[] = {"foo.exe", "--gtest_output=xml", nullptr}; @@ -6179,6 +6161,58 @@ TEST_F(ParseFlagsTest, ThrowOnFailureTrue) { GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false); } +// Tests parsing a bad --gtest_filter flag. +TEST_F(ParseFlagsTest, FilterBad) { + const char* argv[] = {"foo.exe", "--gtest_filter", nullptr}; + + const char* argv2[] = {"foo.exe", "--gtest_filter", nullptr}; + +#if GTEST_HAS_ABSL && GTEST_HAS_DEATH_TEST + // Invalid flag arguments are a fatal error when using the Abseil Flags. + EXPECT_EXIT(GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), true), + testing::ExitedWithCode(1), + "ERROR: Missing the value for the flag 'gtest_filter'"); +#elif !GTEST_HAS_ABSL + GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), true); +#else + static_cast<void>(argv); + static_cast<void>(argv2); +#endif +} + +// Tests parsing --gtest_output (invalid). +TEST_F(ParseFlagsTest, OutputEmpty) { + const char* argv[] = {"foo.exe", "--gtest_output", nullptr}; + + const char* argv2[] = {"foo.exe", "--gtest_output", nullptr}; + +#if GTEST_HAS_ABSL && GTEST_HAS_DEATH_TEST + // Invalid flag arguments are a fatal error when using the Abseil Flags. + EXPECT_EXIT(GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), true), + testing::ExitedWithCode(1), + "ERROR: Missing the value for the flag 'gtest_output'"); +#elif !GTEST_HAS_ABSL + GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), true); +#else + static_cast<void>(argv); + static_cast<void>(argv2); +#endif +} + +#if GTEST_HAS_ABSL +TEST_F(ParseFlagsTest, AbseilPositionalFlags) { + const char* argv[] = {"foo.exe", "--gtest_throw_on_failure=1", "--", + "--other_flag", nullptr}; + + // When using Abseil flags, it should be possible to pass flags not recognized + // using "--" to delimit positional arguments. These flags should be returned + // though argv. + const char* argv2[] = {"foo.exe", "--other_flag", nullptr}; + + GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false); +} +#endif + #if GTEST_OS_WINDOWS // Tests parsing wide strings. TEST_F(ParseFlagsTest, WideStrings) { |