summaryrefslogtreecommitdiff
path: root/include/gtest/gtest-printers.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/gtest/gtest-printers.h')
-rw-r--r--include/gtest/gtest-printers.h230
1 files changed, 172 insertions, 58 deletions
diff --git a/include/gtest/gtest-printers.h b/include/gtest/gtest-printers.h
index 8a33164..51865f8 100644
--- a/include/gtest/gtest-printers.h
+++ b/include/gtest/gtest-printers.h
@@ -26,10 +26,9 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: wan@google.com (Zhanyong Wan)
-// Google Test - The Google C++ Testing Framework
+
+// Google Test - The Google C++ Testing and Mocking Framework
//
// This file implements a universal value printer that can print a
// value of any type T:
@@ -46,6 +45,10 @@
// 2. operator<<(ostream&, const T&) defined in either foo or the
// global namespace.
//
+// However if T is an STL-style container then it is printed element-wise
+// unless foo::PrintTo(const T&, ostream*) is defined. Note that
+// operator<<() is ignored for container types.
+//
// If none of the above is defined, it will print the debug string of
// the value if it is a protocol buffer, or print the raw bytes in the
// value otherwise.
@@ -92,6 +95,8 @@
// being defined as many user-defined container types don't have
// value_type.
+// GOOGLETEST_CM0001 DO NOT DELETE
+
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
@@ -107,6 +112,12 @@
# include <tuple>
#endif
+#if GTEST_HAS_ABSL
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "absl/types/variant.h"
+#endif // GTEST_HAS_ABSL
+
namespace testing {
// Definitions in the 'internal' and 'internal2' name spaces are
@@ -125,7 +136,11 @@ enum TypeKind {
kProtobuf, // a protobuf type
kConvertibleToInteger, // a type implicitly convertible to BiggestInt
// (e.g. a named or unnamed enum type)
- kOtherType // anything else
+#if GTEST_HAS_ABSL
+ kConvertibleToStringView, // a type implicitly convertible to
+ // absl::string_view
+#endif
+ kOtherType // anything else
};
// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
@@ -137,7 +152,8 @@ class TypeWithoutFormatter {
public:
// This default version is called when kTypeKind is kOtherType.
static void PrintValue(const T& value, ::std::ostream* os) {
- PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+ PrintBytesInObjectTo(static_cast<const unsigned char*>(
+ reinterpret_cast<const void*>(&value)),
sizeof(value), os);
}
};
@@ -151,10 +167,10 @@ template <typename T>
class TypeWithoutFormatter<T, kProtobuf> {
public:
static void PrintValue(const T& value, ::std::ostream* os) {
- const ::testing::internal::string short_str = value.ShortDebugString();
- const ::testing::internal::string pretty_str =
- short_str.length() <= kProtobufOneLinerMaxLength ?
- short_str : ("\n" + value.DebugString());
+ std::string pretty_str = value.ShortDebugString();
+ if (pretty_str.length() > kProtobufOneLinerMaxLength) {
+ pretty_str = "\n" + value.DebugString();
+ }
*os << ("<" + pretty_str + ">");
}
};
@@ -175,6 +191,19 @@ class TypeWithoutFormatter<T, kConvertibleToInteger> {
}
};
+#if GTEST_HAS_ABSL
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToStringView> {
+ public:
+ // Since T has neither operator<< nor PrintTo() but can be implicitly
+ // converted to absl::string_view, we print it as a absl::string_view.
+ //
+ // Note: the implementation is further below, as it depends on
+ // internal::PrintTo symbol which is defined later in the file.
+ static void PrintValue(const T& value, ::std::ostream* os);
+};
+#endif
+
// Prints the given value to the given ostream. If the value is a
// protocol message, its debug string is printed; if it's an enum or
// of a type implicitly convertible to BiggestInt, it's printed as an
@@ -202,10 +231,19 @@ class TypeWithoutFormatter<T, kConvertibleToInteger> {
template <typename Char, typename CharTraits, typename T>
::std::basic_ostream<Char, CharTraits>& operator<<(
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
- TypeWithoutFormatter<T,
- (internal::IsAProtocolMessage<T>::value ? kProtobuf :
- internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
- kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+ TypeWithoutFormatter<T, (internal::IsAProtocolMessage<T>::value
+ ? kProtobuf
+ : internal::ImplicitlyConvertible<
+ const T&, internal::BiggestInt>::value
+ ? kConvertibleToInteger
+ :
+#if GTEST_HAS_ABSL
+ internal::ImplicitlyConvertible<
+ const T&, absl::string_view>::value
+ ? kConvertibleToStringView
+ :
+#endif
+ kOtherType)>::PrintValue(x, &os);
return os;
}
@@ -364,11 +402,18 @@ class UniversalPrinter;
template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os);
+enum DefaultPrinterType {
+ kPrintContainer,
+ kPrintPointer,
+ kPrintFunctionPointer,
+ kPrintOther,
+};
+template <DefaultPrinterType type> struct WrapPrinterType {};
+
// Used to print an STL-style container when the user doesn't define
// a PrintTo() for it.
template <typename C>
-void DefaultPrintTo(IsContainer /* dummy */,
- false_type /* is not a pointer */,
+void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */,
const C& container, ::std::ostream* os) {
const size_t kMaxCount = 32; // The maximum number of elements to print.
*os << '{';
@@ -401,40 +446,34 @@ void DefaultPrintTo(IsContainer /* dummy */,
// implementation-defined. Therefore they will be printed as raw
// bytes.)
template <typename T>
-void DefaultPrintTo(IsNotContainer /* dummy */,
- true_type /* is a pointer */,
+void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */,
T* p, ::std::ostream* os) {
if (p == NULL) {
*os << "NULL";
} else {
- // C++ doesn't allow casting from a function pointer to any object
- // pointer.
- //
- // IsTrue() silences warnings: "Condition is always true",
- // "unreachable code".
- if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
- // T is not a function type. We just call << to print p,
- // relying on ADL to pick up user-defined << for their pointer
- // types, if any.
- *os << p;
- } else {
- // T is a function type, so '*os << p' doesn't do what we want
- // (it just prints p as bool). We want to print p as a const
- // void*. However, we cannot cast it to const void* directly,
- // even using reinterpret_cast, as earlier versions of gcc
- // (e.g. 3.4.5) cannot compile the cast when p is a function
- // pointer. Casting to UInt64 first solves the problem.
- *os << reinterpret_cast<const void*>(
- reinterpret_cast<internal::UInt64>(p));
- }
+ // T is not a function type. We just call << to print p,
+ // relying on ADL to pick up user-defined << for their pointer
+ // types, if any.
+ *os << p;
+ }
+}
+template <typename T>
+void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */,
+ T* p, ::std::ostream* os) {
+ if (p == NULL) {
+ *os << "NULL";
+ } else {
+ // T is a function type, so '*os << p' doesn't do what we want
+ // (it just prints p as bool). We want to print p as a const
+ // void*.
+ *os << reinterpret_cast<const void*>(p);
}
}
// Used to print a non-container, non-pointer value when the user
// doesn't define PrintTo() for it.
template <typename T>
-void DefaultPrintTo(IsNotContainer /* dummy */,
- false_type /* is not a pointer */,
+void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */,
const T& value, ::std::ostream* os) {
::testing_internal::DefaultPrintNonContainerTo(value, os);
}
@@ -452,11 +491,8 @@ void DefaultPrintTo(IsNotContainer /* dummy */,
// wants).
template <typename T>
void PrintTo(const T& value, ::std::ostream* os) {
- // DefaultPrintTo() is overloaded. The type of its first two
- // arguments determine which version will be picked. If T is an
- // STL-style container, the version for container will be called; if
- // T is a pointer, the pointer version will be called; otherwise the
- // generic version will be called.
+ // DefaultPrintTo() is overloaded. The type of its first argument
+ // determines which version will be picked.
//
// Note that we check for container types here, prior to we check
// for protocol message types in our operator<<. The rationale is:
@@ -468,13 +504,27 @@ void PrintTo(const T& value, ::std::ostream* os) {
// elements; therefore we check for container types here to ensure
// that our format is used.
//
- // The second argument of DefaultPrintTo() is needed to bypass a bug
- // in Symbian's C++ compiler that prevents it from picking the right
- // overload between:
- //
- // PrintTo(const T& x, ...);
- // PrintTo(T* x, ...);
- DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+ // Note that MSVC and clang-cl do allow an implicit conversion from
+ // pointer-to-function to pointer-to-object, but clang-cl warns on it.
+ // So don't use ImplicitlyConvertible if it can be helped since it will
+ // cause this warning, and use a separate overload of DefaultPrintTo for
+ // function pointers so that the `*os << p` in the object pointer overload
+ // doesn't cause that warning either.
+ DefaultPrintTo(
+ WrapPrinterType <
+ (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
+ !IsRecursiveContainer<T>::value
+ ? kPrintContainer
+ : !is_pointer<T>::value
+ ? kPrintOther
+#if GTEST_LANG_CXX11
+ : std::is_function<typename std::remove_pointer<T>::type>::value
+#else
+ : !internal::ImplicitlyConvertible<T, const void*>::value
+#endif
+ ? kPrintFunctionPointer
+ : kPrintPointer > (),
+ value, os);
}
// The following list of PrintTo() overloads tells
@@ -581,6 +631,17 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
}
#endif // GTEST_HAS_STD_WSTRING
+#if GTEST_HAS_ABSL
+// Overload for absl::string_view.
+inline void PrintTo(absl::string_view sp, ::std::ostream* os) {
+ PrintTo(::std::string(sp), os);
+}
+#endif // GTEST_HAS_ABSL
+
+#if GTEST_LANG_CXX11
+inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
+#endif // GTEST_LANG_CXX11
+
#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
// Helper function for printing a tuple. T must be instantiated with
// a tuple type.
@@ -710,6 +771,48 @@ class UniversalPrinter {
GTEST_DISABLE_MSC_WARNINGS_POP_()
};
+#if GTEST_HAS_ABSL
+
+// Printer for absl::optional
+
+template <typename T>
+class UniversalPrinter<::absl::optional<T>> {
+ public:
+ static void Print(const ::absl::optional<T>& value, ::std::ostream* os) {
+ *os << '(';
+ if (!value) {
+ *os << "nullopt";
+ } else {
+ UniversalPrint(*value, os);
+ }
+ *os << ')';
+ }
+};
+
+// Printer for absl::variant
+
+template <typename... T>
+class UniversalPrinter<::absl::variant<T...>> {
+ public:
+ static void Print(const ::absl::variant<T...>& value, ::std::ostream* os) {
+ *os << '(';
+ absl::visit(Visitor{os}, value);
+ *os << ')';
+ }
+
+ private:
+ struct Visitor {
+ template <typename U>
+ void operator()(const U& u) const {
+ *os << "'" << GetTypeName<U>() << "' with value ";
+ UniversalPrint(u, os);
+ }
+ ::std::ostream* os;
+ };
+};
+
+#endif // GTEST_HAS_ABSL
+
// UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'.
template <typename T>
@@ -723,7 +826,7 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
// If the array has more than kThreshold elements, we'll have to
// omit some details by printing only the first and the last
// kChunkSize elements.
- // TODO(wan@google.com): let the user control the threshold using a flag.
+ // FIXME: let the user control the threshold using a flag.
if (len <= kThreshold) {
PrintRawArrayTo(begin, len, os);
} else {
@@ -805,7 +908,7 @@ class UniversalTersePrinter<const char*> {
if (str == NULL) {
*os << "NULL";
} else {
- UniversalPrint(string(str), os);
+ UniversalPrint(std::string(str), os);
}
}
};
@@ -856,7 +959,7 @@ void UniversalPrint(const T& value, ::std::ostream* os) {
UniversalPrinter<T1>::Print(value, os);
}
-typedef ::std::vector<string> Strings;
+typedef ::std::vector< ::std::string> Strings;
// TuplePolicy<TupleT> must provide:
// - tuple_size
@@ -875,12 +978,13 @@ struct TuplePolicy {
static const size_t tuple_size = ::std::tr1::tuple_size<Tuple>::value;
template <size_t I>
- struct tuple_element : ::std::tr1::tuple_element<I, Tuple> {};
+ struct tuple_element : ::std::tr1::tuple_element<static_cast<int>(I), Tuple> {
+ };
template <size_t I>
- static typename AddReference<
- const typename ::std::tr1::tuple_element<I, Tuple>::type>::type get(
- const Tuple& tuple) {
+ static typename AddReference<const typename ::std::tr1::tuple_element<
+ static_cast<int>(I), Tuple>::type>::type
+ get(const Tuple& tuple) {
return ::std::tr1::get<I>(tuple);
}
};
@@ -976,6 +1080,16 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
} // namespace internal
+#if GTEST_HAS_ABSL
+namespace internal2 {
+template <typename T>
+void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue(
+ const T& value, ::std::ostream* os) {
+ internal::PrintTo(absl::string_view(value), os);
+}
+} // namespace internal2
+#endif
+
template <typename T>
::std::string PrintToString(const T& value) {
::std::stringstream ss;