Fixes a nasty issue in gtest's template instantiation.
This commit is contained in:
parent
b3ed14ac17
commit
6a036a5c8c
@ -48,8 +48,11 @@
|
|||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-string.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
#include "gtest/internal/gtest-internal.h"
|
|
||||||
|
// Ensures that there is at least one operator<< in the global namespace.
|
||||||
|
// See Message& operator<<(...) below for why.
|
||||||
|
void operator<<(const testing::internal::Secret&, int);
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
@ -87,15 +90,7 @@ class GTEST_API_ Message {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructs an empty Message.
|
// Constructs an empty Message.
|
||||||
// We allocate the stringstream separately because otherwise each use of
|
Message();
|
||||||
// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
|
|
||||||
// stack frame leading to huge stack frames in some cases; gcc does not reuse
|
|
||||||
// the stack space.
|
|
||||||
Message() : ss_(new ::std::stringstream) {
|
|
||||||
// By default, we want there to be enough precision when printing
|
|
||||||
// a double to a Message.
|
|
||||||
*ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy constructor.
|
// Copy constructor.
|
||||||
Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
|
Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
|
||||||
@ -118,7 +113,22 @@ class GTEST_API_ Message {
|
|||||||
// Streams a non-pointer value to this object.
|
// Streams a non-pointer value to this object.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Message& operator <<(const T& val) {
|
inline Message& operator <<(const T& val) {
|
||||||
::GTestStreamToHelper(ss_.get(), val);
|
// Some libraries overload << for STL containers. These
|
||||||
|
// overloads are defined in the global namespace instead of ::std.
|
||||||
|
//
|
||||||
|
// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
|
||||||
|
// overloads are visible in either the std namespace or the global
|
||||||
|
// namespace, but not other namespaces, including the testing
|
||||||
|
// namespace which Google Test's Message class is in.
|
||||||
|
//
|
||||||
|
// To allow STL containers (and other types that has a << operator
|
||||||
|
// defined in the global namespace) to be used in Google Test
|
||||||
|
// assertions, testing::Message must access the custom << operator
|
||||||
|
// from the global namespace. With this using declaration,
|
||||||
|
// overloads of << defined in the global namespace and those
|
||||||
|
// visible via Koenig lookup are both exposed in this function.
|
||||||
|
using ::operator <<;
|
||||||
|
*ss_ << val;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +150,7 @@ class GTEST_API_ Message {
|
|||||||
if (pointer == NULL) {
|
if (pointer == NULL) {
|
||||||
*ss_ << "(null)";
|
*ss_ << "(null)";
|
||||||
} else {
|
} else {
|
||||||
::GTestStreamToHelper(ss_.get(), pointer);
|
*ss_ << pointer;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -164,12 +174,8 @@ class GTEST_API_ Message {
|
|||||||
|
|
||||||
// These two overloads allow streaming a wide C string to a Message
|
// These two overloads allow streaming a wide C string to a Message
|
||||||
// using the UTF-8 encoding.
|
// using the UTF-8 encoding.
|
||||||
Message& operator <<(const wchar_t* wide_c_str) {
|
Message& operator <<(const wchar_t* wide_c_str);
|
||||||
return *this << internal::String::ShowWideCString(wide_c_str);
|
Message& operator <<(wchar_t* wide_c_str);
|
||||||
}
|
|
||||||
Message& operator <<(wchar_t* wide_c_str) {
|
|
||||||
return *this << internal::String::ShowWideCString(wide_c_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
// Converts the given wide string to a narrow string using the UTF-8
|
// Converts the given wide string to a narrow string using the UTF-8
|
||||||
@ -187,9 +193,7 @@ class GTEST_API_ Message {
|
|||||||
// Each '\0' character in the buffer is replaced with "\\0".
|
// Each '\0' character in the buffer is replaced with "\\0".
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
std::string GetString() const {
|
std::string GetString() const;
|
||||||
return internal::StringStreamToString(ss_.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -199,16 +203,20 @@ class GTEST_API_ Message {
|
|||||||
// decide between class template specializations for T and T*, so a
|
// decide between class template specializations for T and T*, so a
|
||||||
// tr1::type_traits-like is_pointer works, and we can overload on that.
|
// tr1::type_traits-like is_pointer works, and we can overload on that.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) {
|
inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
|
||||||
if (pointer == NULL) {
|
if (pointer == NULL) {
|
||||||
*ss_ << "(null)";
|
*ss_ << "(null)";
|
||||||
} else {
|
} else {
|
||||||
::GTestStreamToHelper(ss_.get(), pointer);
|
*ss_ << pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
|
inline void StreamHelper(internal::false_type /*is_pointer*/,
|
||||||
::GTestStreamToHelper(ss_.get(), value);
|
const T& value) {
|
||||||
|
// See the comments in Message& operator <<(const T&) above for why
|
||||||
|
// we need this using statement.
|
||||||
|
using ::operator <<;
|
||||||
|
*ss_ << value;
|
||||||
}
|
}
|
||||||
#endif // GTEST_OS_SYMBIAN
|
#endif // GTEST_OS_SYMBIAN
|
||||||
|
|
||||||
@ -225,6 +233,18 @@ inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
|
|||||||
return os << sb.GetString();
|
return os << sb.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Converts a streamable value to an std::string. A NULL pointer is
|
||||||
|
// converted to "(null)". When the input value is a ::string,
|
||||||
|
// ::std::string, ::wstring, or ::std::wstring object, each NUL
|
||||||
|
// character in it is replaced with "\\0".
|
||||||
|
template <typename T>
|
||||||
|
std::string StreamableToString(const T& streamable) {
|
||||||
|
return (Message() << streamable).GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
|
@ -163,18 +163,6 @@ class UnitTestImpl* GetUnitTestImpl();
|
|||||||
void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
|
void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
|
||||||
const std::string& message);
|
const std::string& message);
|
||||||
|
|
||||||
// Converts a streamable value to an std::string. A NULL pointer is
|
|
||||||
// converted to "(null)". When the input value is a ::string,
|
|
||||||
// ::std::string, ::wstring, or ::std::wstring object, each NUL
|
|
||||||
// character in it is replaced with "\\0".
|
|
||||||
// Declared in gtest-internal.h but defined here, so that it has access
|
|
||||||
// to the definition of the Message class, required by the ARM
|
|
||||||
// compiler.
|
|
||||||
template <typename T>
|
|
||||||
std::string StreamableToString(const T& streamable) {
|
|
||||||
return (Message() << streamable).GetString();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// The friend relationship of some of these classes is cyclic.
|
// The friend relationship of some of these classes is cyclic.
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include "gtest/gtest-message.h"
|
||||||
#include "gtest/internal/gtest-string.h"
|
#include "gtest/internal/gtest-string.h"
|
||||||
#include "gtest/internal/gtest-filepath.h"
|
#include "gtest/internal/gtest-filepath.h"
|
||||||
#include "gtest/internal/gtest-type-util.h"
|
#include "gtest/internal/gtest-type-util.h"
|
||||||
@ -71,36 +72,6 @@
|
|||||||
#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
|
#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
|
||||||
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
|
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
|
||||||
|
|
||||||
// Google Test defines the testing::Message class to allow construction of
|
|
||||||
// test messages via the << operator. The idea is that anything
|
|
||||||
// streamable to std::ostream can be streamed to a testing::Message.
|
|
||||||
// This allows a user to use his own types in Google Test assertions by
|
|
||||||
// overloading the << operator.
|
|
||||||
//
|
|
||||||
// util/gtl/stl_logging.h overloads << for STL containers. These
|
|
||||||
// overloads cannot be defined in the std namespace, as that will be
|
|
||||||
// undefined behavior. Therefore, they are defined in the global
|
|
||||||
// namespace instead.
|
|
||||||
//
|
|
||||||
// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
|
|
||||||
// overloads are visible in either the std namespace or the global
|
|
||||||
// namespace, but not other namespaces, including the testing
|
|
||||||
// namespace which Google Test's Message class is in.
|
|
||||||
//
|
|
||||||
// To allow STL containers (and other types that has a << operator
|
|
||||||
// defined in the global namespace) to be used in Google Test assertions,
|
|
||||||
// testing::Message must access the custom << operator from the global
|
|
||||||
// namespace. Hence this helper function.
|
|
||||||
//
|
|
||||||
// Note: Jeffrey Yasskin suggested an alternative fix by "using
|
|
||||||
// ::operator<<;" in the definition of Message's operator<<. That fix
|
|
||||||
// doesn't require a helper function, but unfortunately doesn't
|
|
||||||
// compile with MSVC.
|
|
||||||
template <typename T>
|
|
||||||
inline void GTestStreamToHelper(std::ostream* os, const T& val) {
|
|
||||||
*os << val;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProtocolMessage;
|
class ProtocolMessage;
|
||||||
namespace proto2 { class Message; }
|
namespace proto2 { class Message; }
|
||||||
|
|
||||||
@ -132,11 +103,6 @@ GTEST_API_ extern int g_init_gtest_count;
|
|||||||
// stack trace.
|
// stack trace.
|
||||||
GTEST_API_ extern const char kStackTraceMarker[];
|
GTEST_API_ extern const char kStackTraceMarker[];
|
||||||
|
|
||||||
// A secret type that Google Test users don't know about. It has no
|
|
||||||
// definition on purpose. Therefore it's impossible to create a
|
|
||||||
// Secret object, which is what we want.
|
|
||||||
class Secret;
|
|
||||||
|
|
||||||
// Two overloaded helpers for checking at compile time whether an
|
// Two overloaded helpers for checking at compile time whether an
|
||||||
// expression is a null pointer literal (i.e. NULL or any 0-valued
|
// expression is a null pointer literal (i.e. NULL or any 0-valued
|
||||||
// compile-time integral constant). Their return values have
|
// compile-time integral constant). Their return values have
|
||||||
@ -204,16 +170,6 @@ class GTEST_API_ ScopedTrace {
|
|||||||
// c'tor and d'tor. Therefore it doesn't
|
// c'tor and d'tor. Therefore it doesn't
|
||||||
// need to be used otherwise.
|
// need to be used otherwise.
|
||||||
|
|
||||||
// Converts a streamable value to an std::string. A NULL pointer is
|
|
||||||
// converted to "(null)". When the input value is a ::string,
|
|
||||||
// ::std::string, ::wstring, or ::std::wstring object, each NUL
|
|
||||||
// character in it is replaced with "\\0".
|
|
||||||
// Declared here but defined in gtest.h, so that it has access
|
|
||||||
// to the definition of the Message class, required by the ARM
|
|
||||||
// compiler.
|
|
||||||
template <typename T>
|
|
||||||
std::string StreamableToString(const T& streamable);
|
|
||||||
|
|
||||||
// Constructs and returns the message for an equality assertion
|
// Constructs and returns the message for an equality assertion
|
||||||
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
|
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
|
||||||
//
|
//
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
// Low-level types and utilities for porting Google Test to various
|
// Low-level types and utilities for porting Google Test to various
|
||||||
// platforms. They are subject to change without notice. DO NOT USE
|
// platforms. They are subject to change without notice. DO NOT USE
|
||||||
// THEM IN USER CODE.
|
// THEM IN USER CODE.
|
||||||
|
//
|
||||||
|
// This file is fundamental to Google Test. All other Google Test source
|
||||||
|
// files are expected to #include this. Therefore, it cannot #include
|
||||||
|
// any other Google Test header.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
||||||
@ -784,6 +788,11 @@ class Message;
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
// A secret type that Google Test users don't know about. It has no
|
||||||
|
// definition on purpose. Therefore it's impossible to create a
|
||||||
|
// Secret object, which is what we want.
|
||||||
|
class Secret;
|
||||||
|
|
||||||
// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
|
// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
|
||||||
// expression is true. For example, you could use it to verify the
|
// expression is true. For example, you could use it to verify the
|
||||||
// size of a static array:
|
// size of a static array:
|
||||||
|
@ -161,17 +161,6 @@ class GTEST_API_ String {
|
|||||||
// character in the buffer is replaced with "\\0".
|
// character in the buffer is replaced with "\\0".
|
||||||
GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
|
GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
|
||||||
|
|
||||||
// Converts a streamable value to an std::string. A NULL pointer is
|
|
||||||
// converted to "(null)". When the input value is a ::string,
|
|
||||||
// ::std::string, ::wstring, or ::std::wstring object, each NUL
|
|
||||||
// character in it is replaced with "\\0".
|
|
||||||
|
|
||||||
// Declared here but defined in gtest.h, so that it has access
|
|
||||||
// to the definition of the Message class, required by the ARM
|
|
||||||
// compiler.
|
|
||||||
template <typename T>
|
|
||||||
std::string StreamableToString(const T& streamable);
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@
|
|||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
#include "gtest/internal/gtest-string.h"
|
|
||||||
|
|
||||||
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
||||||
// libstdc++ (which is where cxxabi.h comes from).
|
// libstdc++ (which is where cxxabi.h comes from).
|
||||||
|
@ -43,7 +43,6 @@ $var n = 50 $$ Maximum length of type lists we want to support.
|
|||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
#include "gtest/internal/gtest-string.h"
|
|
||||||
|
|
||||||
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
||||||
// libstdc++ (which is where cxxabi.h comes from).
|
// libstdc++ (which is where cxxabi.h comes from).
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
//
|
//
|
||||||
// Authors: keith.ray@gmail.com (Keith Ray)
|
// Authors: keith.ray@gmail.com (Keith Ray)
|
||||||
|
|
||||||
|
#include "gtest/gtest-message.h"
|
||||||
#include "gtest/internal/gtest-filepath.h"
|
#include "gtest/internal/gtest-filepath.h"
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
|
28
src/gtest.cc
28
src/gtest.cc
@ -44,6 +44,8 @@
|
|||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <limits>
|
||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -886,6 +888,26 @@ static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
|
|||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
// Constructs an empty Message.
|
||||||
|
// We allocate the stringstream separately because otherwise each use of
|
||||||
|
// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
|
||||||
|
// stack frame leading to huge stack frames in some cases; gcc does not reuse
|
||||||
|
// the stack space.
|
||||||
|
Message::Message() : ss_(new ::std::stringstream) {
|
||||||
|
// By default, we want there to be enough precision when printing
|
||||||
|
// a double to a Message.
|
||||||
|
*ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These two overloads allow streaming a wide C string to a Message
|
||||||
|
// using the UTF-8 encoding.
|
||||||
|
Message& Message::operator <<(const wchar_t* wide_c_str) {
|
||||||
|
return *this << internal::String::ShowWideCString(wide_c_str);
|
||||||
|
}
|
||||||
|
Message& Message::operator <<(wchar_t* wide_c_str) {
|
||||||
|
return *this << internal::String::ShowWideCString(wide_c_str);
|
||||||
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
// Converts the given wide string to a narrow string using the UTF-8
|
// Converts the given wide string to a narrow string using the UTF-8
|
||||||
// encoding, and streams the result to this Message object.
|
// encoding, and streams the result to this Message object.
|
||||||
@ -904,6 +926,12 @@ Message& Message::operator <<(const ::wstring& wstr) {
|
|||||||
}
|
}
|
||||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
|
||||||
|
// Gets the text streamed to this object so far as an std::string.
|
||||||
|
// Each '\0' character in the buffer is replaced with "\\0".
|
||||||
|
std::string Message::GetString() const {
|
||||||
|
return internal::StringStreamToString(ss_.get());
|
||||||
|
}
|
||||||
|
|
||||||
// AssertionResult constructors.
|
// AssertionResult constructors.
|
||||||
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||||
AssertionResult::AssertionResult(const AssertionResult& other)
|
AssertionResult::AssertionResult(const AssertionResult& other)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user