diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h index 38fcd7d8..ebd3123b 100644 --- a/include/gtest/gtest.h +++ b/include/gtest/gtest.h @@ -554,13 +554,13 @@ inline Environment* AddGlobalTestEnvironment(Environment* env) { // // No value is returned. Instead, the Google Test flag variables are // updated. +// +// Calling the function for the second time has no user-visible effect. void InitGoogleTest(int* argc, char** argv); // This overloaded version can be used in Windows programs compiled in // UNICODE mode. -#ifdef GTEST_OS_WINDOWS void InitGoogleTest(int* argc, wchar_t** argv); -#endif // GTEST_OS_WINDOWS namespace internal { diff --git a/include/gtest/internal/gtest-internal.h b/include/gtest/internal/gtest-internal.h index 9e353b63..37faaaeb 100644 --- a/include/gtest/internal/gtest-internal.h +++ b/include/gtest/internal/gtest-internal.h @@ -121,6 +121,9 @@ class UnitTestImpl; // Opaque implementation of UnitTest template class List; // A generic list. template class ListNode; // A node in a generic list. +// How many times InitGoogleTest() has been called. +extern int g_init_gtest_count; + // The text used in failure messages to indicate the start of the // stack trace. extern const char kStackTraceMarker[]; diff --git a/include/gtest/internal/gtest-string.h b/include/gtest/internal/gtest-string.h index b37ff4f4..178f14e1 100644 --- a/include/gtest/internal/gtest-string.h +++ b/include/gtest/internal/gtest-string.h @@ -44,6 +44,10 @@ #include #include +#if GTEST_HAS_GLOBAL_STRING || GTEST_HAS_STD_STRING +#include +#endif // GTEST_HAS_GLOBAL_STRING || GTEST_HAS_STD_STRING + namespace testing { namespace internal { @@ -217,6 +221,24 @@ class String { // doesn't need to be virtual. ~String() { delete[] c_str_; } + // Allows a String to be implicitly converted to an ::std::string or + // ::string, and vice versa. Converting a String containing a NULL + // pointer to ::std::string or ::string is undefined behavior. + // Converting a ::std::string or ::string containing an embedded NUL + // character to a String will result in the prefix up to the first + // NUL character. +#if GTEST_HAS_STD_STRING + String(const ::std::string& str) : c_str_(NULL) { *this = str.c_str(); } + + operator ::std::string() const { return ::std::string(c_str_); } +#endif // GTEST_HAS_STD_STRING + +#if GTEST_HAS_GLOBAL_STRING + String(const ::string& str) : c_str_(NULL) { *this = str.c_str(); } + + operator ::string() const { return ::string(c_str_); } +#endif // GTEST_HAS_GLOBAL_STRING + // Returns true iff this is an empty string (i.e. ""). bool empty() const { return (c_str_ != NULL) && (*c_str_ == '\0'); diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h index faf9464d..b8f67c18 100644 --- a/src/gtest-internal-inl.h +++ b/src/gtest-internal-inl.h @@ -1256,6 +1256,11 @@ inline UnitTestImpl* GetUnitTestImpl() { return UnitTest::GetInstance()->impl(); } +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +void ParseGoogleTestFlagsOnly(int* argc, char** argv); +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + } // namespace internal } // namespace testing diff --git a/src/gtest.cc b/src/gtest.cc index 968efb22..b8363912 100644 --- a/src/gtest.cc +++ b/src/gtest.cc @@ -222,13 +222,13 @@ namespace internal { // GTestIsInitialized() returns true iff the user has initialized // Google Test. Useful for catching the user mistake of not initializing // Google Test before calling RUN_ALL_TESTS(). - +// // A user must call testing::InitGoogleTest() to initialize Google -// Test. g_parse_gtest_flags_called is set to true iff +// Test. g_init_gtest_count is set to the number of times // InitGoogleTest() has been called. We don't protect this variable // under a mutex as it is only accessed in the main thread. -static bool g_parse_gtest_flags_called = false; -static bool GTestIsInitialized() { return g_parse_gtest_flags_called; } +int g_init_gtest_count = 0; +static bool GTestIsInitialized() { return g_init_gtest_count != 0; } // Iterates over a list of TestCases, keeping a running sum of the // results of calling a given int-returning method on each. @@ -3844,23 +3844,12 @@ bool ParseStringFlag(const char* str, const char* flag, String* value) { return true; } -// The internal implementation of InitGoogleTest(). -// -// The type parameter CharType can be instantiated to either char or -// wchar_t. +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. The type parameter CharType can be +// instantiated to either char or wchar_t. template -void InitGoogleTestImpl(int* argc, CharType** argv) { - g_parse_gtest_flags_called = true; - if (*argc <= 0) return; - -#ifdef GTEST_HAS_DEATH_TEST - g_argvs.clear(); - for (int i = 0; i != *argc; i++) { - g_argvs.push_back(StreamableToString(argv[i])); - } -#endif // GTEST_HAS_DEATH_TEST - - for (int i = 1; i != *argc; i++) { +void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { + for (int i = 1; i < *argc; i++) { const String arg_string = StreamableToString(argv[i]); const char* const arg = arg_string.c_str(); @@ -3902,6 +3891,40 @@ void InitGoogleTestImpl(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) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} + +// The internal implementation of InitGoogleTest(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleTestImpl(int* argc, CharType** argv) { + g_init_gtest_count++; + + // We don't want to run the initialization code twice. + if (g_init_gtest_count != 1) return; + + if (*argc <= 0) return; + + internal::g_executable_path = internal::StreamableToString(argv[0]); + +#ifdef GTEST_HAS_DEATH_TEST + g_argvs.clear(); + for (int i = 0; i != *argc; i++) { + g_argvs.push_back(StreamableToString(argv[i])); + } +#endif // GTEST_HAS_DEATH_TEST + + ParseGoogleTestFlagsOnly(argc, argv); +} + } // namespace internal // Initializes Google Test. This must be called before calling @@ -3911,20 +3934,16 @@ void InitGoogleTestImpl(int* argc, CharType** argv) { // // No value is returned. Instead, the Google Test flag variables are // updated. +// +// Calling the function for the second time has no user-visible effect. void InitGoogleTest(int* argc, char** argv) { - internal::g_executable_path = argv[0]; internal::InitGoogleTestImpl(argc, argv); } // This overloaded version can be used in Windows programs compiled in // UNICODE mode. -#ifdef GTEST_OS_WINDOWS void InitGoogleTest(int* argc, wchar_t** argv) { - // g_executable_path uses normal characters rather than wide chars, so call - // StreamableToString to convert argv[0] to normal characters (utf8 encoding). - internal::g_executable_path = internal::StreamableToString(argv[0]); internal::InitGoogleTestImpl(argc, argv); } -#endif // GTEST_OS_WINDOWS } // namespace testing diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc index d926a744..1cbb27f6 100644 --- a/test/gtest_unittest.cc +++ b/test/gtest_unittest.cc @@ -510,6 +510,72 @@ TEST(StringTest, Constructors) { EXPECT_STREQ("hel", s4.c_str()); } +#if GTEST_HAS_STD_STRING + +TEST(StringTest, ConvertsFromStdString) { + // An empty std::string. + const std::string src1(""); + const String dest1 = src1; + EXPECT_STREQ("", dest1.c_str()); + + // A normal std::string. + const std::string src2("Hi"); + const String dest2 = src2; + EXPECT_STREQ("Hi", dest2.c_str()); + + // An std::string with an embedded NUL character. + const char src3[] = "Hello\0world."; + const String dest3 = std::string(src3, sizeof(src3)); + EXPECT_STREQ("Hello", dest3.c_str()); +} + +TEST(StringTest, ConvertsToStdString) { + // An empty String. + const String src1(""); + const std::string dest1 = src1; + EXPECT_EQ("", dest1); + + // A normal String. + const String src2("Hi"); + const std::string dest2 = src2; + EXPECT_EQ("Hi", dest2); +} + +#endif // GTEST_HAS_STD_STRING + +#if GTEST_HAS_GLOBAL_STRING + +TEST(StringTest, ConvertsFromGlobalString) { + // An empty ::string. + const ::string src1(""); + const String dest1 = src1; + EXPECT_STREQ("", dest1.c_str()); + + // A normal ::string. + const ::string src2("Hi"); + const String dest2 = src2; + EXPECT_STREQ("Hi", dest2.c_str()); + + // An ::string with an embedded NUL character. + const char src3[] = "Hello\0world."; + const String dest3 = ::string(src3, sizeof(src3)); + EXPECT_STREQ("Hello", dest3.c_str()); +} + +TEST(StringTest, ConvertsToGlobalString) { + // An empty String. + const String src1(""); + const ::string dest1 = src1; + EXPECT_EQ("", dest1); + + // A normal String. + const String src2("Hi"); + const ::string dest2 = src2; + EXPECT_EQ("Hi", dest2); +} + +#endif // GTEST_HAS_GLOBAL_STRING + // Tests String::ShowCString(). TEST(StringTest, ShowCString) { EXPECT_STREQ("(null)", String::ShowCString(NULL)); @@ -4116,7 +4182,7 @@ class InitGoogleTestTest : public Test { int argc2, const CharType** argv2, const Flags& expected) { // Parses the command line. - InitGoogleTest(&argc1, const_cast(argv1)); + internal::ParseGoogleTestFlagsOnly(&argc1, const_cast(argv1)); // Verifies the flag values. CheckFlags(expected);