Moves the universal printer from gmock to gtest and refactors the cmake script for reusing in gmock (by Vlad Losev).

This commit is contained in:
zhanyong.wan 2010-05-10 17:11:58 +00:00
parent cdc0aae155
commit 2ccea88c99
12 changed files with 3293 additions and 206 deletions

View File

@ -39,29 +39,9 @@ if (COMMAND set_up_hermetic_build)
set_up_hermetic_build()
endif()
if (MSVC)
# For MSVC, CMake sets certain flags to defaults we want to override.
# This replacement code is taken from sample in the CMake Wiki at
# http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace.
foreach (flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if (NOT BUILD_SHARED_LIBS)
# When Google Test is built as a shared library, it should also use
# shared runtime libraries. Otherwise, it may end up with multiple
# copies of runtime library data in different modules, resulting in
# hard-to-find crashes. When it is built as a static library, it is
# preferable to use CRT as static libraries, as we don't have to rely
# on CRT DLLs being available. CMake always defaults to using shared
# CRT libraries, so we override that default here.
string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
endif()
include(cmake/internal_utils.cmake)
# We prefer more strict warning checking for building Google Test.
# Replaces /W3 with /W4 in defaults.
string(REPLACE "/W3" "-W4" ${flag_var} "${${flag_var}}")
endforeach()
endif()
fix_default_settings() # Defined in internal_utils.cmake.
# Where gtest's .h files can be found.
include_directories(
@ -72,91 +52,10 @@ include_directories(
link_directories(
${gtest_BINARY_DIR}/src)
# Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
find_package(Threads)
# Defines the compiler/linker flags used to build gtest. You can
# tweak these definitions to suit your need. A variable's value is
# empty before it's explicitly assigned to.
if (MSVC)
# Newlines inside flags variables break CMake's NMake generator.
# TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J -Zi")
set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-GR-")
elseif (CMAKE_COMPILER_IS_GNUCXX)
set(cxx_base_flags "-Wall -Wshadow")
set(cxx_exception_flags "-fexceptions")
set(cxx_no_exception_flags "-fno-exceptions")
# Until version 4.3.2, GCC doesn't define a macro to indicate
# whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
# explicitly.
set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
set(cxx_strict_flags "-Wextra")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
set(cxx_exception_flags "-features=except")
# Sun Pro doesn't provide macros to indicate whether exceptions and
# RTTI are enabled, so we define GTEST_HAS_* explicitly.
set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
CMAKE_CXX_COMPILER_ID STREQUAL "XL")
# CMake 2.8 changes Visual Age's compiler ID to "XL".
set(cxx_exception_flags "-qeh")
set(cxx_no_exception_flags "-qnoeh")
# Until version 9.0, Visual Age doesn't define a macro to indicate
# whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
# explicitly.
set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
endif()
if (CMAKE_USE_PTHREADS_INIT) # The pthreads library is available.
set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=1")
endif()
# For building gtest's own tests and samples.
set(cxx_exception "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_exception_flags}")
set(cxx_no_exception
"${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
set(cxx_default "${cxx_exception}")
set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1")
# For building the gtest libraries.
set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
########################################################################
#
# Defines the gtest & gtest_main libraries. User tests should link
# with one of them.
function(cxx_library_with_type name type cxx_flags)
# type can be either STATIC or SHARED to denote a static or shared library.
# ARGN refers to additional arguments after 'cxx_flags'.
add_library(${name} ${type} ${ARGN})
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "${cxx_flags}")
if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
set_target_properties(${name}
PROPERTIES
COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
endif()
if (CMAKE_USE_PTHREADS_INIT)
target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
endif()
endfunction()
function(cxx_shared_library name cxx_flags)
cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
endfunction()
function(cxx_library name cxx_flags)
cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
endfunction()
# Google Test libraries. We build them using more strict warnings than what
# are used for other targets, to ensure that gtest can be compiled by a user
@ -173,39 +72,6 @@ target_link_libraries(gtest_main gtest)
# build_gtest_samples option to ON. You can do it by running ccmake
# or specifying the -Dbuild_gtest_samples=ON flag when running cmake.
# cxx_executable_with_flags(name cxx_flags libs srcs...)
#
# creates a named C++ executable that depends on the given libraries and
# is built from the given source files with the given compiler flags.
function(cxx_executable_with_flags name cxx_flags libs)
add_executable(${name} ${ARGN})
if (cxx_flags)
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "${cxx_flags}")
endif()
if (BUILD_SHARED_LIBS)
set_target_properties(${name}
PROPERTIES
COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
endif()
# To support mixing linking in static and dynamic libraries, link each
# library in with an extra call to target_link_libraries.
foreach (lib "${libs}")
target_link_libraries(${name} ${lib})
endforeach()
endfunction()
# cxx_executable(name dir lib srcs...)
#
# creates a named target that depends on the given libs and is built
# from the given source files. dir/name.cc is implicitly included in
# the source file list.
function(cxx_executable name dir libs)
cxx_executable_with_flags(
${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
endfunction()
if (build_gtest_samples)
cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
@ -230,38 +96,14 @@ endif()
# build_all_gtest_tests option to ON. You can do it by running ccmake
# or specifying the -Dbuild_all_gtest_tests=ON flag when running cmake.
# This must be set in the root directory for the tests to be run by
# 'make test' or ctest.
enable_testing()
# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
find_package(PythonInterp)
############################################################
# C++ tests built with standard compiler flags.
# cxx_test_with_flags(name cxx_flags libs srcs...)
#
# creates a named C++ test that depends on the given libs and is built
# from the given source files with the given compiler flags.
function(cxx_test_with_flags name cxx_flags libs)
cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
add_test(${name} ${name})
endfunction()
# cxx_test(name libs srcs...)
#
# creates a named test target that depends on the given libs and is
# built from the given source files. Unlike cxx_test_with_flags,
# test/name.cc is already implicitly included in the source file list.
function(cxx_test name libs)
cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
"test/${name}.cc" ${ARGN})
endfunction()
cxx_test(gtest_unittest gtest_main)
if (build_all_gtest_tests)
# This must be set in the root directory for the tests to be run by
# 'make test' or ctest.
enable_testing()
############################################################
# C++ tests built with standard compiler flags.
cxx_test(gtest-death-test_test gtest_main)
cxx_test(gtest_environment_test gtest)
cxx_test(gtest-filepath_test gtest_main)
@ -275,6 +117,7 @@ if (build_all_gtest_tests)
test/gtest-param-test2_test.cc)
cxx_test(gtest-port_test gtest_main)
cxx_test(gtest_pred_impl_unittest gtest_main)
cxx_test(gtest-printers_test gtest_main)
cxx_test(gtest_prod_test gtest_main
test/production.cc)
cxx_test(gtest_repeat_test gtest)
@ -284,13 +127,12 @@ if (build_all_gtest_tests)
cxx_test(gtest_throw_on_failure_ex_test gtest)
cxx_test(gtest-typed-test_test gtest_main
test/gtest-typed-test2_test.cc)
cxx_test(gtest_unittest gtest_main)
cxx_test(gtest-unittest-api_test gtest)
endif()
############################################################
# C++ tests built with non-standard compiler flags.
############################################################
# C++ tests built with non-standard compiler flags.
if (build_all_gtest_tests)
cxx_library(gtest_no_exception "${cxx_no_exception}"
src/gtest-all.cc)
cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
@ -325,28 +167,9 @@ if (build_all_gtest_tests)
test/gtest-param-test_test.cc test/gtest-param-test2_test.cc)
endif()
endif()
############################################################
# Python tests.
############################################################
# Python tests.
# py_test(name)
#
# creates a Python test with the given name whose main module is in
# test/name.py. It does nothing if Python is not installed.
function(py_test name)
if (PYTHONINTERP_FOUND)
# ${gtest_BINARY_DIR} is known at configuration time, so we can
# directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
# only at ctest runtime (by calling ctest -c <Configuration>), so
# we have to escape $ to delay variable substitution here.
add_test(${name}
${PYTHON_EXECUTABLE} ${gtest_SOURCE_DIR}/test/${name}.py
--gtest_build_dir=${gtest_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE})
endif()
endfunction()
if (build_all_gtest_tests)
cxx_executable(gtest_break_on_failure_unittest_ test gtest)
py_test(gtest_break_on_failure_unittest)

View File

@ -22,6 +22,7 @@ GTEST_SRC = \
src/gtest-filepath.cc \
src/gtest-internal-inl.h \
src/gtest-port.cc \
src/gtest-printers.cc \
src/gtest-test-part.cc \
src/gtest-typed-test.cc
@ -52,6 +53,7 @@ EXTRA_DIST += \
test/gtest-param-test2_test.cc \
test/gtest-param-test_test.h \
test/gtest-port_test.cc \
test/gtest-printers_test.cc \
test/gtest_pred_impl_unittest.cc \
test/gtest_prod_test.cc \
test/production.cc \
@ -186,6 +188,7 @@ pkginclude_HEADERS = include/gtest/gtest.h \
include/gtest/gtest-message.h \
include/gtest/gtest-param-test.h \
include/gtest/gtest_pred_impl.h \
include/gtest/gtest-printers.h \
include/gtest/gtest_prod.h \
include/gtest/gtest-spi.h \
include/gtest/gtest-test-part.h \

186
cmake/internal_utils.cmake Normal file
View File

@ -0,0 +1,186 @@
# Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
find_package(Threads)
# macro is required here, as inside a function string() will update
# variables only at the function scope.
macro(fix_default_settings)
if (MSVC)
# For MSVC, CMake sets certain flags to defaults we want to override.
# This replacement code is taken from sample in the CMake Wiki at
# http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace.
foreach (flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if (NOT BUILD_SHARED_LIBS)
# When Google Test is built as a shared library, it should also use
# shared runtime libraries. Otherwise, it may end up with multiple
# copies of runtime library data in different modules, resulting in
# hard-to-find crashes. When it is built as a static library, it is
# preferable to use CRT as static libraries, as we don't have to rely
# on CRT DLLs being available. CMake always defaults to using shared
# CRT libraries, so we override that default here.
string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
endif()
# We prefer more strict warning checking for building Google Test.
# Replaces /W3 with /W4 in defaults.
string(REPLACE "/W3" "-W4" ${flag_var} "${${flag_var}}")
endforeach()
endif()
endmacro()
# Defines the compiler/linker flags used to build gtest. You can
# tweak these definitions to suit your need. A variable's value is
# empty before it's explicitly assigned to.
if (MSVC)
# Newlines inside flags variables break CMake's NMake generator.
# TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
set(cxx_base_flags "-GS -W4 -WX -wd4127 -wd4251 -wd4275 -nologo -J -Zi")
set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-GR-")
elseif (CMAKE_COMPILER_IS_GNUCXX)
set(cxx_base_flags "-Wall -Wshadow")
set(cxx_exception_flags "-fexceptions")
set(cxx_no_exception_flags "-fno-exceptions")
# Until version 4.3.2, GCC doesn't define a macro to indicate
# whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
# explicitly.
set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
set(cxx_strict_flags "-Wextra")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
set(cxx_exception_flags "-features=except")
# Sun Pro doesn't provide macros to indicate whether exceptions and
# RTTI are enabled, so we define GTEST_HAS_* explicitly.
set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
CMAKE_CXX_COMPILER_ID STREQUAL "XL")
# CMake 2.8 changes Visual Age's compiler ID to "XL".
set(cxx_exception_flags "-qeh")
set(cxx_no_exception_flags "-qnoeh")
# Until version 9.0, Visual Age doesn't define a macro to indicate
# whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
# explicitly.
set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
endif()
if (CMAKE_USE_PTHREADS_INIT) # The pthreads library is available.
set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=1")
endif()
# For building gtest's own tests and samples.
set(cxx_exception "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_exception_flags}")
set(cxx_no_exception
"${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
set(cxx_default "${cxx_exception}")
set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1")
# For building the gtest libraries.
set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
########################################################################
#
# Defines the gtest & gtest_main libraries. User tests should link
# with one of them.
function(cxx_library_with_type name type cxx_flags)
# type can be either STATIC or SHARED to denote a static or shared library.
# ARGN refers to additional arguments after 'cxx_flags'.
add_library(${name} ${type} ${ARGN})
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "${cxx_flags}")
if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
set_target_properties(${name}
PROPERTIES
COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
endif()
if (CMAKE_USE_PTHREADS_INIT)
target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
endif()
endfunction()
function(cxx_shared_library name cxx_flags)
cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
endfunction()
function(cxx_library name cxx_flags)
cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
endfunction()
# cxx_executable_with_flags(name cxx_flags libs srcs...)
#
# creates a named C++ executable that depends on the given libraries and
# is built from the given source files with the given compiler flags.
function(cxx_executable_with_flags name cxx_flags libs)
add_executable(${name} ${ARGN})
if (cxx_flags)
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "${cxx_flags}")
endif()
if (BUILD_SHARED_LIBS)
set_target_properties(${name}
PROPERTIES
COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
endif()
# To support mixing linking in static and dynamic libraries, link each
# library in with an extra call to target_link_libraries.
foreach (lib "${libs}")
target_link_libraries(${name} ${lib})
endforeach()
endfunction()
# cxx_executable(name dir lib srcs...)
#
# creates a named target that depends on the given libs and is built
# from the given source files. dir/name.cc is implicitly included in
# the source file list.
function(cxx_executable name dir libs)
cxx_executable_with_flags(
${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
endfunction()
# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
find_package(PythonInterp)
# cxx_test_with_flags(name cxx_flags libs srcs...)
#
# creates a named C++ test that depends on the given libs and is built
# from the given source files with the given compiler flags.
function(cxx_test_with_flags name cxx_flags libs)
cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
add_test(${name} ${name})
endfunction()
# cxx_test(name libs srcs...)
#
# creates a named test target that depends on the given libs and is
# built from the given source files. Unlike cxx_test_with_flags,
# test/name.cc is already implicitly included in the source file list.
function(cxx_test name libs)
cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
"test/${name}.cc" ${ARGN})
endfunction()
# py_test(name)
#
# creates a Python test with the given name whose main module is in
# test/name.py. It does nothing if Python is not installed.
function(py_test name)
# We are not supporting Python tests on Linux yet as they consider
# all Linux environments to be google3 and try to use google3 features.
if (PYTHONINTERP_FOUND AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# ${gtest_BINARY_DIR} is known at configuration time, so we can
# directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
# only at ctest runtime (by calling ctest -c <Configuration>), so
# we have to escape $ to delay variable substitution here.
add_test(${name}
${PYTHON_EXECUTABLE} ${gtest_SOURCE_DIR}/test/${name}.py
--gtest_build_dir=${gtest_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE})
endif()
endfunction()

View File

@ -0,0 +1,730 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// 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
//
// This file implements a universal value printer that can print a
// value of any type T:
//
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
//
// A user can teach this function how to print a class type T by
// defining either operator<<() or PrintTo() in the namespace that
// defines T. More specifically, the FIRST defined function in the
// following list will be used (assuming T is defined in namespace
// foo):
//
// 1. foo::PrintTo(const T&, ostream*)
// 2. operator<<(ostream&, const T&) defined in either foo or the
// global namespace.
//
// 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.
//
// To aid debugging: when T is a reference type, the address of the
// value is also printed; when T is a (const) char pointer, both the
// pointer value and the NUL-terminated string it points to are
// printed.
//
// We also provide some convenient wrappers:
//
// // Prints a value to a string. For a (const or not) char
// // pointer, the NUL-terminated string (but not the pointer) is
// // printed.
// std::string ::testing::PrintToString(const T& value);
//
// // Prints a value tersely: for a reference type, the referenced
// // value (but not the address) is printed; for a (const or not) char
// // pointer, the NUL-terminated string (but not the pointer) is
// // printed.
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
//
// // Prints value using the type inferred by the compiler. The difference
// // from UniversalTersePrint() is that this function prints both the
// // pointer and the NUL-terminated string for a (const or not) char pointer.
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
//
// // Prints the fields of a tuple tersely to a string vector, one
// // element for each field. Tuple support must be enabled in
// // gtest-port.h.
// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
// const Tuple& value);
//
// Known limitation:
//
// The print primitives print the elements of an STL-style container
// using the compiler-inferred type of *iter where iter is a
// const_iterator of the container. When const_iterator is an input
// iterator but not a forward iterator, this inferred type may not
// match value_type, and the print output may be incorrect. In
// practice, this is rarely a problem as for most containers
// const_iterator is a forward iterator. We'll fix this if there's an
// actual need for it. Note that this fix cannot rely on value_type
// being defined as many user-defined container types don't have
// value_type.
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
#include <ostream> // NOLINT
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <gtest/internal/gtest-port.h>
#include <gtest/internal/gtest-internal.h>
namespace testing {
// Definitions in the 'internal' and 'internal2' name spaces are
// subject to change without notice. DO NOT USE THEM IN USER CODE!
namespace internal2 {
// Prints the given number of bytes in the given object to the given
// ostream.
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
size_t count,
::std::ostream* os);
// TypeWithoutFormatter<T, kIsProto>::PrintValue(value, os) is called
// by the universal printer to print a value of type T when neither
// operator<< nor PrintTo() is defined for type T. When T is
// ProtocolMessage, proto2::Message, or a subclass of those, kIsProto
// will be true and the short debug string of the protocol message
// value will be printed; otherwise kIsProto will be false and the
// bytes in the value will be printed.
template <typename T, bool kIsProto>
class TypeWithoutFormatter {
public:
static void PrintValue(const T& value, ::std::ostream* os) {
PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
sizeof(value), os);
}
};
// We print a protobuf using its ShortDebugString() when the string
// doesn't exceed this many characters; otherwise we print it using
// DebugString() for better readability.
const size_t kProtobufOneLinerMaxLength = 50;
template <typename T>
class TypeWithoutFormatter<T, true> {
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::operator<<(*os, "<" + pretty_str + ">");
}
};
// Prints the given value to the given ostream. If the value is a
// protocol message, its short debug string is printed; otherwise the
// bytes in the value are printed. This is what
// UniversalPrinter<T>::Print() does when it knows nothing about type
// T and T has no << operator.
//
// A user can override this behavior for a class type Foo by defining
// a << operator in the namespace where Foo is defined.
//
// We put this operator in namespace 'internal2' instead of 'internal'
// to simplify the implementation, as much code in 'internal' needs to
// use << in STL, which would conflict with our own << were it defined
// in 'internal'.
//
// Note that this operator<< takes a generic std::basic_ostream<Char,
// CharTraits> type instead of the more restricted std::ostream. If
// we define it to take an std::ostream instead, we'll get an
// "ambiguous overloads" compiler error when trying to print a type
// Foo that supports streaming to std::basic_ostream<Char,
// CharTraits>, as the compiler cannot tell whether
// operator<<(std::ostream&, const T&) or
// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
// specific.
template <typename Char, typename CharTraits, typename T>
::std::basic_ostream<Char, CharTraits>& operator<<(
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
TypeWithoutFormatter<T, ::testing::internal::IsAProtocolMessage<T>::value>::
PrintValue(x, &os);
return os;
}
} // namespace internal2
} // namespace testing
// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
// magic needed for implementing UniversalPrinter won't work.
namespace testing_internal {
// Used to print a value that is not an STL-style container when the
// user doesn't define PrintTo() for it.
template <typename T>
void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
// With the following statement, during unqualified name lookup,
// testing::internal2::operator<< appears as if it was declared in
// the nearest enclosing namespace that contains both
// ::testing_internal and ::testing::internal2, i.e. the global
// namespace. For more details, refer to the C++ Standard section
// 7.3.4-1 [namespace.udir]. This allows us to fall back onto
// testing::internal2::operator<< in case T doesn't come with a <<
// operator.
//
// We cannot write 'using ::testing::internal2::operator<<;', which
// gcc 3.3 fails to compile due to a compiler bug.
using namespace ::testing::internal2; // NOLINT
// Assuming T is defined in namespace foo, in the next statement,
// the compiler will consider all of:
//
// 1. foo::operator<< (thanks to Koenig look-up),
// 2. ::operator<< (as the current namespace is enclosed in ::),
// 3. testing::internal2::operator<< (thanks to the using statement above).
//
// The operator<< whose type matches T best will be picked.
//
// We deliberately allow #2 to be a candidate, as sometimes it's
// impossible to define #1 (e.g. when foo is ::std, defining
// anything in it is undefined behavior unless you are a compiler
// vendor.).
*os << value;
}
} // namespace testing_internal
namespace testing {
namespace internal {
// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
// value to the given ostream. The caller must ensure that
// 'ostream_ptr' is not NULL, or the behavior is undefined.
//
// We define UniversalPrinter as a class template (as opposed to a
// function template), as we need to partially specialize it for
// reference types, which cannot be done with function templates.
template <typename T>
class UniversalPrinter;
template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os);
// 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 */,
const C& container, ::std::ostream* os) {
const size_t kMaxCount = 32; // The maximum number of elements to print.
*os << '{';
size_t count = 0;
for (typename C::const_iterator it = container.begin();
it != container.end(); ++it, ++count) {
if (count > 0) {
*os << ',';
if (count == kMaxCount) { // Enough has been printed.
*os << " ...";
break;
}
}
*os << ' ';
// We cannot call PrintTo(*it, os) here as PrintTo() doesn't
// handle *it being a native array.
internal::UniversalPrint(*it, os);
}
if (count > 0) {
*os << ' ';
}
*os << '}';
}
// Used to print a pointer that is neither a char pointer nor a member
// pointer, when the user doesn't define PrintTo() for it. (A member
// variable pointer or member function pointer doesn't really point to
// a location in the address space. Their representation is
// implementation-defined. Therefore they will be printed as raw
// bytes.)
template <typename T>
void DefaultPrintTo(IsNotContainer /* dummy */,
true_type /* is a pointer */,
T* p, ::std::ostream* os) {
if (p == NULL) {
*os << "NULL";
} else {
// 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));
}
}
// 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 */,
const T& value, ::std::ostream* os) {
::testing_internal::DefaultPrintNonContainerTo(value, os);
}
// Prints the given value using the << operator if it has one;
// otherwise prints the bytes in it. This is what
// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
// or overloaded for type T.
//
// A user can override this behavior for a class type Foo by defining
// an overload of PrintTo() in the namespace where Foo is defined. We
// give the user this option as sometimes defining a << operator for
// Foo is not desirable (e.g. the coding style may prevent doing it,
// or there is already a << operator but it doesn't do what the user
// 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.
//
// Note that we check for container types here, prior to we check
// for protocol message types in our operator<<. The rationale is:
//
// For protocol messages, we want to give people a chance to
// override Google Mock's format by defining a PrintTo() or
// operator<<. For STL containers, other formats can be
// incompatible with Google Mock's format for the container
// 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);
}
// The following list of PrintTo() overloads tells
// UniversalPrinter<T>::Print() how to print standard types (built-in
// types, strings, plain arrays, and pointers).
// Overloads for various char types.
GTEST_API_ void PrintCharTo(char c, int char_code, ::std::ostream* os);
inline void PrintTo(unsigned char c, ::std::ostream* os) {
PrintCharTo(c, c, os);
}
inline void PrintTo(signed char c, ::std::ostream* os) {
PrintCharTo(c, c, os);
}
inline void PrintTo(char c, ::std::ostream* os) {
// When printing a plain char, we always treat it as unsigned. This
// way, the output won't be affected by whether the compiler thinks
// char is signed or not.
PrintTo(static_cast<unsigned char>(c), os);
}
// Overloads for other simple built-in types.
inline void PrintTo(bool x, ::std::ostream* os) {
*os << (x ? "true" : "false");
}
// Overload for wchar_t type.
// Prints a wchar_t as a symbol if it is printable or as its internal
// code otherwise and also as its decimal code (except for L'\0').
// The L'\0' char is printed as "L'\\0'". The decimal code is printed
// as signed integer when wchar_t is implemented by the compiler
// as a signed type and is printed as an unsigned integer when wchar_t
// is implemented as an unsigned type.
GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
// Overloads for C strings.
GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
inline void PrintTo(char* s, ::std::ostream* os) {
PrintTo(implicit_cast<const char*>(s), os);
}
// MSVC can be configured to define wchar_t as a typedef of unsigned
// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
// type. When wchar_t is a typedef, defining an overload for const
// wchar_t* would cause unsigned short* be printed as a wide string,
// possibly causing invalid memory accesses.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Overloads for wide C strings
GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
inline void PrintTo(wchar_t* s, ::std::ostream* os) {
PrintTo(implicit_cast<const wchar_t*>(s), os);
}
#endif
// Overload for C arrays. Multi-dimensional arrays are printed
// properly.
// Prints the given number of elements in an array, without printing
// the curly braces.
template <typename T>
void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
UniversalPrinter<T>::Print(a[0], os);
for (size_t i = 1; i != count; i++) {
*os << ", ";
UniversalPrinter<T>::Print(a[i], os);
}
}
// Overloads for ::string and ::std::string.
#if GTEST_HAS_GLOBAL_STRING
GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
inline void PrintTo(const ::string& s, ::std::ostream* os) {
PrintStringTo(s, os);
}
#endif // GTEST_HAS_GLOBAL_STRING
GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
PrintStringTo(s, os);
}
// Overloads for ::wstring and ::std::wstring.
#if GTEST_HAS_GLOBAL_WSTRING
GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
PrintWideStringTo(s, os);
}
#endif // GTEST_HAS_GLOBAL_WSTRING
#if GTEST_HAS_STD_WSTRING
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
PrintWideStringTo(s, os);
}
#endif // GTEST_HAS_STD_WSTRING
#if GTEST_HAS_TR1_TUPLE
// Overload for ::std::tr1::tuple. Needed for printing function arguments,
// which are packed as tuples.
// Helper function for printing a tuple. T must be instantiated with
// a tuple type.
template <typename T>
void PrintTupleTo(const T& t, ::std::ostream* os);
// Overloaded PrintTo() for tuples of various arities. We support
// tuples of up-to 10 fields. The following implementation works
// regardless of whether tr1::tuple is implemented using the
// non-standard variadic template feature or not.
inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1>
void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2>
void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10>
void PrintTo(
const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
#endif // GTEST_HAS_TR1_TUPLE
// Overload for std::pair.
template <typename T1, typename T2>
void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
*os << '(';
UniversalPrinter<T1>::Print(value.first, os);
*os << ", ";
UniversalPrinter<T2>::Print(value.second, os);
*os << ')';
}
// Implements printing a non-reference type T by letting the compiler
// pick the right overload of PrintTo() for T.
template <typename T>
class UniversalPrinter {
public:
// MSVC warns about adding const to a function type, so we want to
// disable the warning.
#ifdef _MSC_VER
#pragma warning(push) // Saves the current warning state.
#pragma warning(disable:4180) // Temporarily disables warning 4180.
#endif // _MSC_VER
// Note: we deliberately don't call this PrintTo(), as that name
// conflicts with ::testing::internal::PrintTo in the body of the
// function.
static void Print(const T& value, ::std::ostream* os) {
// By default, ::testing::internal::PrintTo() is used for printing
// the value.
//
// Thanks to Koenig look-up, if T is a class and has its own
// PrintTo() function defined in its namespace, that function will
// be visible here. Since it is more specific than the generic ones
// in ::testing::internal, it will be picked by the compiler in the
// following statement - exactly what we want.
PrintTo(value, os);
}
#ifdef _MSC_VER
#pragma warning(pop) // Restores the warning state.
#endif // _MSC_VER
};
// UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'.
template <typename T>
void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
if (len == 0) {
*os << "{}";
} else {
*os << "{ ";
const size_t kThreshold = 18;
const size_t kChunkSize = 8;
// 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.
if (len <= kThreshold) {
PrintRawArrayTo(begin, len, os);
} else {
PrintRawArrayTo(begin, kChunkSize, os);
*os << ", ..., ";
PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
}
*os << " }";
}
}
// This overload prints a (const) char array compactly.
GTEST_API_ void UniversalPrintArray(const char* begin,
size_t len,
::std::ostream* os);
// Implements printing an array type T[N].
template <typename T, size_t N>
class UniversalPrinter<T[N]> {
public:
// Prints the given array, omitting some elements when there are too
// many.
static void Print(const T (&a)[N], ::std::ostream* os) {
UniversalPrintArray(a, N, os);
}
};
// Implements printing a reference type T&.
template <typename T>
class UniversalPrinter<T&> {
public:
// MSVC warns about adding const to a function type, so we want to
// disable the warning.
#ifdef _MSC_VER
#pragma warning(push) // Saves the current warning state.
#pragma warning(disable:4180) // Temporarily disables warning 4180.
#endif // _MSC_VER
static void Print(const T& value, ::std::ostream* os) {
// Prints the address of the value. We use reinterpret_cast here
// as static_cast doesn't compile when T is a function type.
*os << "@" << reinterpret_cast<const void*>(&value) << " ";
// Then prints the value itself.
UniversalPrinter<T>::Print(value, os);
}
#ifdef _MSC_VER
#pragma warning(pop) // Restores the warning state.
#endif // _MSC_VER
};
// Prints a value tersely: for a reference type, the referenced value
// (but not the address) is printed; for a (const) char pointer, the
// NUL-terminated string (but not the pointer) is printed.
template <typename T>
void UniversalTersePrint(const T& value, ::std::ostream* os) {
UniversalPrinter<T>::Print(value, os);
}
inline void UniversalTersePrint(const char* str, ::std::ostream* os) {
if (str == NULL) {
*os << "NULL";
} else {
UniversalPrinter<string>::Print(string(str), os);
}
}
inline void UniversalTersePrint(char* str, ::std::ostream* os) {
UniversalTersePrint(static_cast<const char*>(str), os);
}
// Prints a value using the type inferred by the compiler. The
// difference between this and UniversalTersePrint() is that for a
// (const) char pointer, this prints both the pointer and the
// NUL-terminated string.
template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os) {
UniversalPrinter<T>::Print(value, os);
}
#if GTEST_HAS_TR1_TUPLE
typedef ::std::vector<string> Strings;
// This helper template allows PrintTo() for tuples and
// UniversalTersePrintTupleFieldsToStrings() to be defined by
// induction on the number of tuple fields. The idea is that
// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
// fields in tuple t, and can be defined in terms of
// TuplePrefixPrinter<N - 1>.
// The inductive case.
template <size_t N>
struct TuplePrefixPrinter {
// Prints the first N fields of a tuple.
template <typename Tuple>
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
*os << ", ";
UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
::Print(::std::tr1::get<N - 1>(t), os);
}
// Tersely prints the first N fields of a tuple to a string vector,
// one element for each field.
template <typename Tuple>
static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
::std::stringstream ss;
UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
strings->push_back(ss.str());
}
};
// Base cases.
template <>
struct TuplePrefixPrinter<0> {
template <typename Tuple>
static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
template <typename Tuple>
static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
};
template <>
template <typename Tuple>
void TuplePrefixPrinter<1>::PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
Print(::std::tr1::get<0>(t), os);
}
// Helper function for printing a tuple. T must be instantiated with
// a tuple type.
template <typename T>
void PrintTupleTo(const T& t, ::std::ostream* os) {
*os << "(";
TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
PrintPrefixTo(t, os);
*os << ")";
}
// Prints the fields of a tuple tersely to a string vector, one
// element for each field. See the comment before
// UniversalTersePrint() for how we define "tersely".
template <typename Tuple>
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
Strings result;
TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
TersePrintPrefixToStrings(value, &result);
return result;
}
#endif // GTEST_HAS_TR1_TUPLE
} // namespace internal
template <typename T>
::std::string PrintToString(const T& value) {
::std::stringstream ss;
internal::UniversalTersePrint(value, &ss);
return ss.str();
}
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_

View File

@ -59,6 +59,7 @@
#include <gtest/gtest-death-test.h>
#include <gtest/gtest-message.h>
#include <gtest/gtest-param-test.h>
#include <gtest/gtest-printers.h>
#include <gtest/gtest_prod.h>
#include <gtest/gtest-test-part.h>
#include <gtest/gtest-typed-test.h>
@ -1926,17 +1927,6 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
__FILE__, __LINE__, ::testing::Message() << (message))
namespace internal {
// This template is declared, but intentionally undefined.
template <typename T1, typename T2>
struct StaticAssertTypeEqHelper;
template <typename T>
struct StaticAssertTypeEqHelper<T, T> {};
} // namespace internal
// Compile-time assertion for type equality.
// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
// the same type. The value it returns is not interesting.
@ -1969,7 +1959,7 @@ struct StaticAssertTypeEqHelper<T, T> {};
// to cause a compiler error.
template <typename T1, typename T2>
bool StaticAssertTypeEq() {
(void)internal::StaticAssertTypeEqHelper<T1, T2>();
internal::StaticAssertTypeEqHelper<T1, T2>();
return true;
}

View File

@ -97,6 +97,9 @@ inline void GTestStreamToHelper(std::ostream* os, const T& val) {
*os << val;
}
class ProtocolMessage;
namespace proto2 { class Message; }
namespace testing {
// Forward declaration of classes.
@ -784,6 +787,292 @@ class GTEST_API_ Random {
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
};
// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
// compiler error iff T1 and T2 are different types.
template <typename T1, typename T2>
struct CompileAssertTypesEqual;
template <typename T>
struct CompileAssertTypesEqual<T, T> {
};
// Removes the reference from a type if it is a reference type,
// otherwise leaves it unchanged. This is the same as
// tr1::remove_reference, which is not widely available yet.
template <typename T>
struct RemoveReference { typedef T type; }; // NOLINT
template <typename T>
struct RemoveReference<T&> { typedef T type; }; // NOLINT
// A handy wrapper around RemoveReference that works when the argument
// T depends on template parameters.
#define GTEST_REMOVE_REFERENCE_(T) \
typename ::testing::internal::RemoveReference<T>::type
// Removes const from a type if it is a const type, otherwise leaves
// it unchanged. This is the same as tr1::remove_const, which is not
// widely available yet.
template <typename T>
struct RemoveConst { typedef T type; }; // NOLINT
template <typename T>
struct RemoveConst<const T> { typedef T type; }; // NOLINT
// MSVC 8.0 has a bug which causes the above definition to fail to
// remove the const in 'const int[3]'. The following specialization
// works around the bug. However, it causes trouble with gcc and thus
// needs to be conditionally compiled.
#ifdef _MSC_VER
template <typename T, size_t N>
struct RemoveConst<T[N]> {
typedef typename RemoveConst<T>::type type[N];
};
#endif // _MSC_VER
// A handy wrapper around RemoveConst that works when the argument
// T depends on template parameters.
#define GTEST_REMOVE_CONST_(T) \
typename ::testing::internal::RemoveConst<T>::type
// Adds reference to a type if it is not a reference type,
// otherwise leaves it unchanged. This is the same as
// tr1::add_reference, which is not widely available yet.
template <typename T>
struct AddReference { typedef T& type; }; // NOLINT
template <typename T>
struct AddReference<T&> { typedef T& type; }; // NOLINT
// A handy wrapper around AddReference that works when the argument T
// depends on template parameters.
#define GTEST_ADD_REFERENCE_(T) \
typename ::testing::internal::AddReference<T>::type
// Adds a reference to const on top of T as necessary. For example,
// it transforms
//
// char ==> const char&
// const char ==> const char&
// char& ==> const char&
// const char& ==> const char&
//
// The argument T must depend on some template parameters.
#define GTEST_REFERENCE_TO_CONST_(T) \
GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
// ImplicitlyConvertible<From, To>::value is a compile-time bool
// constant that's true iff type From can be implicitly converted to
// type To.
template <typename From, typename To>
class ImplicitlyConvertible {
private:
// We need the following helper functions only for their types.
// They have no implementations.
// MakeFrom() is an expression whose type is From. We cannot simply
// use From(), as the type From may not have a public default
// constructor.
static From MakeFrom();
// These two functions are overloaded. Given an expression
// Helper(x), the compiler will pick the first version if x can be
// implicitly converted to type To; otherwise it will pick the
// second version.
//
// The first version returns a value of size 1, and the second
// version returns a value of size 2. Therefore, by checking the
// size of Helper(x), which can be done at compile time, we can tell
// which version of Helper() is used, and hence whether x can be
// implicitly converted to type To.
static char Helper(To);
static char (&Helper(...))[2]; // NOLINT
// We have to put the 'public' section after the 'private' section,
// or MSVC refuses to compile the code.
public:
// MSVC warns about implicitly converting from double to int for
// possible loss of data, so we need to temporarily disable the
// warning.
#ifdef _MSC_VER
#pragma warning(push) // Saves the current warning state.
#pragma warning(disable:4244) // Temporarily disables warning 4244.
static const bool value =
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
#pragma warning(pop) // Restores the warning state.
#else
static const bool value =
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
#endif // _MSV_VER
};
template <typename From, typename To>
const bool ImplicitlyConvertible<From, To>::value;
// IsAProtocolMessage<T>::value is a compile-time bool constant that's
// true iff T is type ProtocolMessage, proto2::Message, or a subclass
// of those.
template <typename T>
struct IsAProtocolMessage
: public bool_constant<
ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
};
// When the compiler sees expression IsContainerTest<C>(0), the first
// overload of IsContainerTest will be picked if C is an STL-style
// container class (since C::const_iterator* is a valid type and 0 can
// be converted to it), while the second overload will be picked
// otherwise (since C::const_iterator will be an invalid type in this
// case). Therefore, we can determine whether C is a container class
// by checking the type of IsContainerTest<C>(0). The value of the
// expression is insignificant.
typedef int IsContainer;
template <class C>
IsContainer IsContainerTest(typename C::const_iterator*) { return 0; }
typedef char IsNotContainer;
template <class C>
IsNotContainer IsContainerTest(...) { return '\0'; }
// Utilities for native arrays.
// ArrayEq() compares two k-dimensional native arrays using the
// elements' operator==, where k can be any integer >= 0. When k is
// 0, ArrayEq() degenerates into comparing a single pair of values.
template <typename T, typename U>
bool ArrayEq(const T* lhs, size_t size, const U* rhs);
// This generic version is used when k is 0.
template <typename T, typename U>
inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
// This overload is used when k >= 1.
template <typename T, typename U, size_t N>
inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
return internal::ArrayEq(lhs, N, rhs);
}
// This helper reduces code bloat. If we instead put its logic inside
// the previous ArrayEq() function, arrays with different sizes would
// lead to different copies of the template code.
template <typename T, typename U>
bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
for (size_t i = 0; i != size; i++) {
if (!internal::ArrayEq(lhs[i], rhs[i]))
return false;
}
return true;
}
// Finds the first element in the iterator range [begin, end) that
// equals elem. Element may be a native array type itself.
template <typename Iter, typename Element>
Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
for (Iter it = begin; it != end; ++it) {
if (internal::ArrayEq(*it, elem))
return it;
}
return end;
}
// CopyArray() copies a k-dimensional native array using the elements'
// operator=, where k can be any integer >= 0. When k is 0,
// CopyArray() degenerates into copying a single value.
template <typename T, typename U>
void CopyArray(const T* from, size_t size, U* to);
// This generic version is used when k is 0.
template <typename T, typename U>
inline void CopyArray(const T& from, U* to) { *to = from; }
// This overload is used when k >= 1.
template <typename T, typename U, size_t N>
inline void CopyArray(const T(&from)[N], U(*to)[N]) {
internal::CopyArray(from, N, *to);
}
// This helper reduces code bloat. If we instead put its logic inside
// the previous CopyArray() function, arrays with different sizes
// would lead to different copies of the template code.
template <typename T, typename U>
void CopyArray(const T* from, size_t size, U* to) {
for (size_t i = 0; i != size; i++) {
internal::CopyArray(from[i], to + i);
}
}
// The relation between an NativeArray object (see below) and the
// native array it represents.
enum RelationToSource {
kReference, // The NativeArray references the native array.
kCopy // The NativeArray makes a copy of the native array and
// owns the copy.
};
// Adapts a native array to a read-only STL-style container. Instead
// of the complete STL container concept, this adaptor only implements
// members useful for Google Mock's container matchers. New members
// should be added as needed. To simplify the implementation, we only
// support Element being a raw type (i.e. having no top-level const or
// reference modifier). It's the client's responsibility to satisfy
// this requirement. Element can be an array type itself (hence
// multi-dimensional arrays are supported).
template <typename Element>
class NativeArray {
public:
// STL-style container typedefs.
typedef Element value_type;
typedef const Element* const_iterator;
// Constructs from a native array.
NativeArray(const Element* array, size_t count, RelationToSource relation) {
Init(array, count, relation);
}
// Copy constructor.
NativeArray(const NativeArray& rhs) {
Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
}
~NativeArray() {
// Ensures that the user doesn't instantiate NativeArray with a
// const or reference type.
static_cast<void>(StaticAssertTypeEqHelper<Element,
GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Element))>());
if (relation_to_source_ == kCopy)
delete[] array_;
}
// STL-style container methods.
size_t size() const { return size_; }
const_iterator begin() const { return array_; }
const_iterator end() const { return array_ + size_; }
bool operator==(const NativeArray& rhs) const {
return size() == rhs.size() &&
ArrayEq(begin(), size(), rhs.begin());
}
private:
// Initializes this object; makes a copy of the input array if
// 'relation' is kCopy.
void Init(const Element* array, size_t a_size, RelationToSource relation) {
if (relation == kReference) {
array_ = array;
} else {
Element* const copy = new Element[a_size];
CopyArray(array, a_size, copy);
array_ = copy;
}
size_ = a_size;
relation_to_source_ = relation;
}
const Element* array_;
size_t size_;
RelationToSource relation_to_source_;
GTEST_DISALLOW_ASSIGN_(NativeArray);
};
} // namespace internal
} // namespace testing

View File

@ -609,6 +609,91 @@ namespace internal {
class String;
// 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
// size of a static array:
//
// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
// content_type_names_incorrect_size);
//
// or to make sure a struct is smaller than a certain size:
//
// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
//
// The second argument to the macro is the name of the variable. If
// the expression is false, most compilers will issue a warning/error
// containing the name of the variable.
template <bool>
struct CompileAssert {
};
#define GTEST_COMPILE_ASSERT_(expr, msg) \
typedef ::testing::internal::CompileAssert<(bool(expr))> \
msg[bool(expr) ? 1 : -1]
// Implementation details of GTEST_COMPILE_ASSERT_:
//
// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
// elements (and thus is invalid) when the expression is false.
//
// - The simpler definition
//
// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
//
// does not work, as gcc supports variable-length arrays whose sizes
// are determined at run-time (this is gcc's extension and not part
// of the C++ standard). As a result, gcc fails to reject the
// following code with the simple definition:
//
// int foo;
// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
// // not a compile-time constant.
//
// - By using the type CompileAssert<(bool(expr))>, we ensures that
// expr is a compile-time constant. (Template arguments must be
// determined at compile-time.)
//
// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
//
// CompileAssert<bool(expr)>
//
// instead, these compilers will refuse to compile
//
// GTEST_COMPILE_ASSERT_(5 > 0, some_message);
//
// (They seem to think the ">" in "5 > 0" marks the end of the
// template argument list.)
//
// - The array size is (bool(expr) ? 1 : -1), instead of simply
//
// ((expr) ? 1 : -1).
//
// This is to avoid running into a bug in MS VC 7.1, which
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
//
// This template is declared, but intentionally undefined.
template <typename T1, typename T2>
struct StaticAssertTypeEqHelper;
template <typename T>
struct StaticAssertTypeEqHelper<T, T> {};
#if GTEST_HAS_GLOBAL_STRING
typedef ::string string;
#else
typedef ::std::string string;
#endif // GTEST_HAS_GLOBAL_STRING
#if GTEST_HAS_GLOBAL_WSTRING
typedef ::wstring wstring;
#elif GTEST_HAS_STD_WSTRING
typedef ::std::wstring wstring;
#endif // GTEST_HAS_GLOBAL_WSTRING
typedef ::std::stringstream StrStream;
// A helper for suppressing warnings on constant condition. It just
@ -790,6 +875,58 @@ inline void FlushInfoLog() { fflush(NULL); }
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Use implicit_cast as a safe version of static_cast for upcasting in
// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
// const Foo*). When you use implicit_cast, the compiler checks that
// the cast is safe. Such explicit implicit_casts are necessary in
// surprisingly many situations where C++ demands an exact type match
// instead of an argument type convertable to a target type.
//
// The syntax for using implicit_cast is the same as for static_cast:
//
// implicit_cast<ToType>(expr)
//
// implicit_cast would have been part of the C++ standard library,
// but the proposal was submitted too late. It will probably make
// its way into the language in the future.
template<typename To>
inline To implicit_cast(To x) { return x; }
// When you upcast (that is, cast a pointer from type Foo to type
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
// always succeed. When you downcast (that is, cast a pointer from
// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
// how do you know the pointer is really of type SubclassOfFoo? It
// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
// when you downcast, you should use this macro. In debug mode, we
// use dynamic_cast<> to double-check the downcast is legal (we die
// if it's not). In normal mode, we do the efficient static_cast<>
// instead. Thus, it's important to test in debug mode to make sure
// the cast is legal!
// This is the only place in the code we should use dynamic_cast<>.
// In particular, you SHOULDN'T be using dynamic_cast<> in order to
// do RTTI (eg code like this:
// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
// You should design the code some other way not to need this.
template<typename To, typename From> // use like this: down_cast<T*>(foo);
inline To down_cast(From* f) { // so we only accept pointers
// Ensures that To is a sub-type of From *. This test is here only
// for compile-time type checking, and has no overhead in an
// optimized build at run-time, as it will be optimized away
// completely.
if (false) {
const To to = NULL;
::testing::internal::implicit_cast<From*>(to);
}
#if GTEST_HAS_RTTI
// RTTI: debug mode only!
GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
#endif
return static_cast<To>(f);
}
// Downcasts the pointer of type Base to Derived.
// Derived must be a subclass of Base. The parameter MUST
// point to a class of type Derived, not any subclass of it.

View File

@ -43,5 +43,6 @@
#include "src/gtest-death-test.cc"
#include "src/gtest-filepath.cc"
#include "src/gtest-port.cc"
#include "src/gtest-printers.cc"
#include "src/gtest-test-part.cc"
#include "src/gtest-typed-test.cc"

318
src/gtest-printers.cc Normal file
View File

@ -0,0 +1,318 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// 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
//
// This file implements a universal value printer that can print a
// value of any type T:
//
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
//
// It uses the << operator when possible, and prints the bytes in the
// object otherwise. A user can override its behavior for a class
// type Foo by defining either operator<<(::std::ostream&, const Foo&)
// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
// defines Foo.
#include <gtest/gtest-printers.h>
#include <ctype.h>
#include <stdio.h>
#include <ostream> // NOLINT
#include <string>
#include <gtest/internal/gtest-port.h>
namespace testing {
namespace {
using ::std::ostream;
#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s.
#define snprintf _snprintf
#elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf.
#define snprintf _snprintf_s
#elif _MSC_VER
#define snprintf _snprintf
#endif // GTEST_OS_WINDOWS_MOBILE
// Prints a segment of bytes in the given object.
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
size_t count, ostream* os) {
char text[5] = "";
for (size_t i = 0; i != count; i++) {
const size_t j = start + i;
if (i != 0) {
// Organizes the bytes into groups of 2 for easy parsing by
// human.
if ((j % 2) == 0) {
*os << " ";
}
}
snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
*os << text;
}
}
// Prints the bytes in the given value to the given ostream.
void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
ostream* os) {
// Tells the user how big the object is.
*os << count << "-byte object <";
const size_t kThreshold = 132;
const size_t kChunkSize = 64;
// If the object size is bigger than kThreshold, we'll have to omit
// some details by printing only the first and the last kChunkSize
// bytes.
// TODO(wan): let the user control the threshold using a flag.
if (count < kThreshold) {
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
} else {
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
*os << " ... ";
// Rounds up to 2-byte boundary.
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
}
*os << ">";
}
} // namespace
namespace internal2 {
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
// given object. The delegation simplifies the implementation, which
// uses the << operator and thus is easier done outside of the
// ::testing::internal namespace, which contains a << operator that
// sometimes conflicts with the one in STL.
void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
ostream* os) {
PrintBytesInObjectToImpl(obj_bytes, count, os);
}
} // namespace internal2
namespace internal {
// Prints a wide char as a char literal without the quotes, escaping it
// when necessary.
static void PrintAsWideCharLiteralTo(wchar_t c, ostream* os) {
switch (c) {
case L'\0':
*os << "\\0";
break;
case L'\'':
*os << "\\'";
break;
case L'\?':
*os << "\\?";
break;
case L'\\':
*os << "\\\\";
break;
case L'\a':
*os << "\\a";
break;
case L'\b':
*os << "\\b";
break;
case L'\f':
*os << "\\f";
break;
case L'\n':
*os << "\\n";
break;
case L'\r':
*os << "\\r";
break;
case L'\t':
*os << "\\t";
break;
case L'\v':
*os << "\\v";
break;
default:
// Checks whether c is printable or not. Printable characters are in
// the range [0x20,0x7E].
// We test the value of c directly instead of calling isprint(), as
// isprint() is buggy on Windows mobile.
if (0x20 <= c && c <= 0x7E) {
*os << static_cast<char>(c);
} else {
// Buffer size enough for the maximum number of digits and \0.
char text[2 * sizeof(unsigned long) + 1] = "";
snprintf(text, sizeof(text), "%lX", static_cast<unsigned long>(c));
*os << "\\x" << text;
}
}
}
// Prints a char as if it's part of a string literal, escaping it when
// necessary.
static void PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
switch (c) {
case L'\'':
*os << "'";
break;
case L'"':
*os << "\\\"";
break;
default:
PrintAsWideCharLiteralTo(c, os);
}
}
// Prints a char as a char literal without the quotes, escaping it
// when necessary.
static void PrintAsCharLiteralTo(char c, ostream* os) {
PrintAsWideCharLiteralTo(static_cast<unsigned char>(c), os);
}
// Prints a char as if it's part of a string literal, escaping it when
// necessary.
static void PrintAsStringLiteralTo(char c, ostream* os) {
PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
}
// Prints a char and its code. The '\0' char is printed as "'\\0'",
// other unprintable characters are also properly escaped using the
// standard C++ escape sequence.
void PrintCharTo(char c, int char_code, ostream* os) {
*os << "'";
PrintAsCharLiteralTo(c, os);
*os << "'";
if (c != '\0')
*os << " (" << char_code << ")";
}
// Prints a wchar_t as a symbol if it is printable or as its internal
// code otherwise and also as its decimal code (except for L'\0').
// The L'\0' char is printed as "L'\\0'". The decimal code is printed
// as signed integer when wchar_t is implemented by the compiler
// as a signed type and is printed as an unsigned integer when wchar_t
// is implemented as an unsigned type.
void PrintTo(wchar_t wc, ostream* os) {
*os << "L'";
PrintAsWideCharLiteralTo(wc, os);
*os << "'";
if (wc != L'\0') {
// Type Int64 is used because it provides more storage than wchar_t thus
// when the compiler converts signed or unsigned implementation of wchar_t
// to Int64 it fills higher bits with either zeros or the sign bit
// passing it to operator <<() as either signed or unsigned integer.
*os << " (" << static_cast<Int64>(wc) << ")";
}
}
// Prints the given array of characters to the ostream.
// The array starts at *begin, the length is len, it may include '\0' characters
// and may not be null-terminated.
static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
*os << "\"";
for (size_t index = 0; index < len; ++index) {
PrintAsStringLiteralTo(begin[index], os);
}
*os << "\"";
}
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
PrintCharsAsStringTo(begin, len, os);
}
// Prints the given array of wide characters to the ostream.
// The array starts at *begin, the length is len, it may include L'\0'
// characters and may not be null-terminated.
static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
ostream* os) {
*os << "L\"";
for (size_t index = 0; index < len; ++index) {
PrintAsWideStringLiteralTo(begin[index], os);
}
*os << "\"";
}
// Prints the given C string to the ostream.
void PrintTo(const char* s, ostream* os) {
if (s == NULL) {
*os << "NULL";
} else {
*os << implicit_cast<const void*>(s) << " pointing to ";
PrintCharsAsStringTo(s, strlen(s), os);
}
}
// MSVC compiler can be configured to define whar_t as a typedef
// of unsigned short. Defining an overload for const wchar_t* in that case
// would cause pointers to unsigned shorts be printed as wide strings,
// possibly accessing more memory than intended and causing invalid
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
// wchar_t is implemented as a native type.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Prints the given wide C string to the ostream.
void PrintTo(const wchar_t* s, ostream* os) {
if (s == NULL) {
*os << "NULL";
} else {
*os << implicit_cast<const void*>(s) << " pointing to ";
PrintWideCharsAsStringTo(s, wcslen(s), os);
}
}
#endif // wchar_t is native
// Prints a ::string object.
#if GTEST_HAS_GLOBAL_STRING
void PrintStringTo(const ::string& s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
}
#endif // GTEST_HAS_GLOBAL_STRING
void PrintStringTo(const ::std::string& s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
}
// Prints a ::wstring object.
#if GTEST_HAS_GLOBAL_WSTRING
void PrintWideStringTo(const ::wstring& s, ostream* os) {
PrintWideCharsAsStringTo(s.data(), s.size(), os);
}
#endif // GTEST_HAS_GLOBAL_WSTRING
#if GTEST_HAS_STD_WSTRING
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
PrintWideCharsAsStringTo(s.data(), s.size(), os);
}
#endif // GTEST_HAS_STD_WSTRING
} // namespace internal
} // namespace testing

View File

@ -59,6 +59,118 @@ using std::pair;
namespace testing {
namespace internal {
class Base {
public:
// Copy constructor and assignment operator do exactly what we need, so we
// use them.
Base() : member_(0) {}
explicit Base(int n) : member_(n) {}
virtual ~Base() {}
int member() { return member_; }
private:
int member_;
};
class Derived : public Base {
public:
explicit Derived(int n) : Base(n) {}
};
TEST(ImplicitCastTest, ConvertsPointers) {
Derived derived(0);
EXPECT_TRUE(&derived == ::testing::internal::implicit_cast<Base*>(&derived));
}
TEST(ImplicitCastTest, CanUseInheritance) {
Derived derived(1);
Base base = ::testing::internal::implicit_cast<Base>(derived);
EXPECT_EQ(derived.member(), base.member());
}
class Castable {
public:
Castable(bool* converted) : converted_(converted) {}
operator Base() {
*converted_ = true;
return Base();
}
private:
bool* converted_;
};
TEST(ImplicitCastTest, CanUseNonConstCastOperator) {
bool converted = false;
Castable castable(&converted);
Base base = ::testing::internal::implicit_cast<Base>(castable);
EXPECT_TRUE(converted);
}
class ConstCastable {
public:
ConstCastable(bool* converted) : converted_(converted) {}
operator Base() const {
*converted_ = true;
return Base();
}
private:
bool* converted_;
};
TEST(ImplicitCastTest, CanUseConstCastOperatorOnConstValues) {
bool converted = false;
const ConstCastable const_castable(&converted);
Base base = ::testing::internal::implicit_cast<Base>(const_castable);
EXPECT_TRUE(converted);
}
class ConstAndNonConstCastable {
public:
ConstAndNonConstCastable(bool* converted, bool* const_converted)
: converted_(converted), const_converted_(const_converted) {}
operator Base() {
*converted_ = true;
return Base();
}
operator Base() const {
*const_converted_ = true;
return Base();
}
private:
bool* converted_;
bool* const_converted_;
};
TEST(ImplicitCastTest, CanSelectBetweenConstAndNonConstCasrAppropriately) {
bool converted = false;
bool const_converted = false;
ConstAndNonConstCastable castable(&converted, &const_converted);
Base base = ::testing::internal::implicit_cast<Base>(castable);
EXPECT_TRUE(converted);
EXPECT_FALSE(const_converted);
converted = false;
const_converted = false;
const ConstAndNonConstCastable const_castable(&converted, &const_converted);
base = ::testing::internal::implicit_cast<Base>(const_castable);
EXPECT_FALSE(converted);
EXPECT_TRUE(const_converted);
}
class To {
public:
To(bool* converted) { *converted = true; } // NOLINT
};
TEST(ImplicitCastTest, CanUseImplicitConstructor) {
bool converted = false;
To to = ::testing::internal::implicit_cast<To>(&converted);
EXPECT_TRUE(converted);
}
// Tests that the element_type typedef is available in scoped_ptr and refers
// to the parameter type.
TEST(ScopedPtrTest, DefinesElementType) {

1163
test/gtest-printers_test.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -132,23 +132,28 @@ using testing::Message;
using testing::ScopedFakeTestPartResultReporter;
using testing::StaticAssertTypeEq;
using testing::Test;
using testing::TestEventListeners;
using testing::TestCase;
using testing::TestEventListeners;
using testing::TestPartResult;
using testing::TestPartResultArray;
using testing::TestProperty;
using testing::TestResult;
using testing::UnitTest;
using testing::kMaxStackTraceDepth;
using testing::internal::AddReference;
using testing::internal::AlwaysFalse;
using testing::internal::AlwaysTrue;
using testing::internal::AppendUserMessage;
using testing::internal::ArrayAwareFind;
using testing::internal::ArrayEq;
using testing::internal::CodePointToUtf8;
using testing::internal::CompileAssertTypesEqual;
using testing::internal::CopyArray;
using testing::internal::CountIf;
using testing::internal::EqFailure;
using testing::internal::FloatingPoint;
using testing::internal::FormatTimeInMillisAsSeconds;
using testing::internal::ForEach;
using testing::internal::FormatTimeInMillisAsSeconds;
using testing::internal::GTestFlagSaver;
using testing::internal::GetCurrentOsStackTraceExceptTop;
using testing::internal::GetElementOr;
@ -157,9 +162,17 @@ using testing::internal::GetRandomSeedFromFlag;
using testing::internal::GetTestTypeId;
using testing::internal::GetTypeId;
using testing::internal::GetUnitTestImpl;
using testing::internal::ImplicitlyConvertible;
using testing::internal::Int32;
using testing::internal::Int32FromEnvOrDie;
using testing::internal::IsAProtocolMessage;
using testing::internal::IsContainer;
using testing::internal::IsContainerTest;
using testing::internal::IsNotContainer;
using testing::internal::NativeArray;
using testing::internal::ParseInt32Flag;
using testing::internal::RemoveConst;
using testing::internal::RemoveReference;
using testing::internal::ShouldRunTestOnShard;
using testing::internal::ShouldShard;
using testing::internal::ShouldUseColor;
@ -171,7 +184,9 @@ using testing::internal::TestEventListenersAccessor;
using testing::internal::TestResultAccessor;
using testing::internal::UInt32;
using testing::internal::WideStringToUtf8;
using testing::internal::kCopy;
using testing::internal::kMaxRandomSeed;
using testing::internal::kReference;
using testing::internal::kTestTypeIdInGoogleTest;
using testing::internal::scoped_ptr;
@ -184,6 +199,10 @@ using testing::internal::GetCapturedStdout;
using testing::internal::ThreadWithParam;
#endif
#if GTEST_HAS_PROTOBUF_
using ::testing::internal::TestMessage;
#endif // GTEST_HAS_PROTOBUF_
class TestingVector : public std::vector<int> {
};
@ -6725,3 +6744,319 @@ GTEST_TEST(AlternativeNameTest, Works) { // GTEST_TEST is the same as TEST.
EXPECT_FATAL_FAILURE(GTEST_FAIL() << "An expected failure",
"An expected failure");
}
// Tests for internal utilities necessary for implementation of the universal
// printing.
// TODO(vladl@google.com): Find a better home for them.
class ConversionHelperBase {};
class ConversionHelperDerived : public ConversionHelperBase {};
// Tests that IsAProtocolMessage<T>::value is a compile-time constant.
TEST(IsAProtocolMessageTest, ValueIsCompileTimeConstant) {
GTEST_COMPILE_ASSERT_(IsAProtocolMessage<ProtocolMessage>::value,
const_true);
GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<int>::value, const_false);
}
// Tests that IsAProtocolMessage<T>::value is true when T is
// ProtocolMessage or a sub-class of it.
TEST(IsAProtocolMessageTest, ValueIsTrueWhenTypeIsAProtocolMessage) {
EXPECT_TRUE(IsAProtocolMessage< ::proto2::Message>::value);
EXPECT_TRUE(IsAProtocolMessage<ProtocolMessage>::value);
#if GTEST_HAS_PROTOBUF_
EXPECT_TRUE(IsAProtocolMessage<const TestMessage>::value);
#endif // GTEST_HAS_PROTOBUF_
}
// Tests that IsAProtocolMessage<T>::value is false when T is neither
// ProtocolMessage nor a sub-class of it.
TEST(IsAProtocolMessageTest, ValueIsFalseWhenTypeIsNotAProtocolMessage) {
EXPECT_FALSE(IsAProtocolMessage<int>::value);
EXPECT_FALSE(IsAProtocolMessage<const ConversionHelperBase>::value);
}
// Tests that CompileAssertTypesEqual compiles when the type arguments are
// equal.
TEST(CompileAssertTypesEqual, CompilesWhenTypesAreEqual) {
CompileAssertTypesEqual<void, void>();
CompileAssertTypesEqual<int*, int*>();
}
// Tests that RemoveReference does not affect non-reference types.
TEST(RemoveReferenceTest, DoesNotAffectNonReferenceType) {
CompileAssertTypesEqual<int, RemoveReference<int>::type>();
CompileAssertTypesEqual<const char, RemoveReference<const char>::type>();
}
// Tests that RemoveReference removes reference from reference types.
TEST(RemoveReferenceTest, RemovesReference) {
CompileAssertTypesEqual<int, RemoveReference<int&>::type>();
CompileAssertTypesEqual<const char, RemoveReference<const char&>::type>();
}
// Tests GTEST_REMOVE_REFERENCE_.
template <typename T1, typename T2>
void TestGTestRemoveReference() {
CompileAssertTypesEqual<T1, GTEST_REMOVE_REFERENCE_(T2)>();
}
TEST(RemoveReferenceTest, MacroVersion) {
TestGTestRemoveReference<int, int>();
TestGTestRemoveReference<const char, const char&>();
}
// Tests that RemoveConst does not affect non-const types.
TEST(RemoveConstTest, DoesNotAffectNonConstType) {
CompileAssertTypesEqual<int, RemoveConst<int>::type>();
CompileAssertTypesEqual<char&, RemoveConst<char&>::type>();
}
// Tests that RemoveConst removes const from const types.
TEST(RemoveConstTest, RemovesConst) {
CompileAssertTypesEqual<int, RemoveConst<const int>::type>();
CompileAssertTypesEqual<char[2], RemoveConst<const char[2]>::type>();
CompileAssertTypesEqual<char[2][3], RemoveConst<const char[2][3]>::type>();
}
// Tests GTEST_REMOVE_CONST_.
template <typename T1, typename T2>
void TestGTestRemoveConst() {
CompileAssertTypesEqual<T1, GTEST_REMOVE_CONST_(T2)>();
}
TEST(RemoveConstTest, MacroVersion) {
TestGTestRemoveConst<int, int>();
TestGTestRemoveConst<double&, double&>();
TestGTestRemoveConst<char, const char>();
}
// Tests that AddReference does not affect reference types.
TEST(AddReferenceTest, DoesNotAffectReferenceType) {
CompileAssertTypesEqual<int&, AddReference<int&>::type>();
CompileAssertTypesEqual<const char&, AddReference<const char&>::type>();
}
// Tests that AddReference adds reference to non-reference types.
TEST(AddReferenceTest, AddsReference) {
CompileAssertTypesEqual<int&, AddReference<int>::type>();
CompileAssertTypesEqual<const char&, AddReference<const char>::type>();
}
// Tests GTEST_ADD_REFERENCE_.
template <typename T1, typename T2>
void TestGTestAddReference() {
CompileAssertTypesEqual<T1, GTEST_ADD_REFERENCE_(T2)>();
}
TEST(AddReferenceTest, MacroVersion) {
TestGTestAddReference<int&, int>();
TestGTestAddReference<const char&, const char&>();
}
// Tests GTEST_REFERENCE_TO_CONST_.
template <typename T1, typename T2>
void TestGTestReferenceToConst() {
CompileAssertTypesEqual<T1, GTEST_REFERENCE_TO_CONST_(T2)>();
}
TEST(GTestReferenceToConstTest, Works) {
TestGTestReferenceToConst<const char&, char>();
TestGTestReferenceToConst<const int&, const int>();
TestGTestReferenceToConst<const double&, double>();
TestGTestReferenceToConst<const String&, const String&>();
}
// Tests that ImplicitlyConvertible<T1, T2>::value is a compile-time constant.
TEST(ImplicitlyConvertibleTest, ValueIsCompileTimeConstant) {
GTEST_COMPILE_ASSERT_((ImplicitlyConvertible<int, int>::value), const_true);
GTEST_COMPILE_ASSERT_((!ImplicitlyConvertible<void*, int*>::value),
const_false);
}
// Tests that ImplicitlyConvertible<T1, T2>::value is true when T1 can
// be implicitly converted to T2.
TEST(ImplicitlyConvertibleTest, ValueIsTrueWhenConvertible) {
EXPECT_TRUE((ImplicitlyConvertible<int, double>::value));
EXPECT_TRUE((ImplicitlyConvertible<double, int>::value));
EXPECT_TRUE((ImplicitlyConvertible<int*, void*>::value));
EXPECT_TRUE((ImplicitlyConvertible<int*, const int*>::value));
EXPECT_TRUE((ImplicitlyConvertible<ConversionHelperDerived&,
const ConversionHelperBase&>::value));
EXPECT_TRUE((ImplicitlyConvertible<const ConversionHelperBase,
ConversionHelperBase>::value));
}
// Tests that ImplicitlyConvertible<T1, T2>::value is false when T1
// cannot be implicitly converted to T2.
TEST(ImplicitlyConvertibleTest, ValueIsFalseWhenNotConvertible) {
EXPECT_FALSE((ImplicitlyConvertible<double, int*>::value));
EXPECT_FALSE((ImplicitlyConvertible<void*, int*>::value));
EXPECT_FALSE((ImplicitlyConvertible<const int*, int*>::value));
EXPECT_FALSE((ImplicitlyConvertible<ConversionHelperBase&,
ConversionHelperDerived&>::value));
}
// Tests IsContainerTest.
class NonContainer {};
TEST(IsContainerTestTest, WorksForNonContainer) {
EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<int>(0)));
EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<char[5]>(0)));
EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<NonContainer>(0)));
}
TEST(IsContainerTestTest, WorksForContainer) {
EXPECT_EQ(sizeof(IsContainer),
sizeof(IsContainerTest<std::vector<bool> >(0)));
EXPECT_EQ(sizeof(IsContainer),
sizeof(IsContainerTest<std::map<int, double> >(0)));
}
// Tests ArrayEq().
TEST(ArrayEqTest, WorksForDegeneratedArrays) {
EXPECT_TRUE(ArrayEq(5, 5L));
EXPECT_FALSE(ArrayEq('a', 0));
}
TEST(ArrayEqTest, WorksForOneDimensionalArrays) {
const int a[] = { 0, 1 };
long b[] = { 0, 1 };
EXPECT_TRUE(ArrayEq(a, b));
EXPECT_TRUE(ArrayEq(a, 2, b));
b[0] = 2;
EXPECT_FALSE(ArrayEq(a, b));
EXPECT_FALSE(ArrayEq(a, 1, b));
}
TEST(ArrayEqTest, WorksForTwoDimensionalArrays) {
const char a[][3] = { "hi", "lo" };
const char b[][3] = { "hi", "lo" };
const char c[][3] = { "hi", "li" };
EXPECT_TRUE(ArrayEq(a, b));
EXPECT_TRUE(ArrayEq(a, 2, b));
EXPECT_FALSE(ArrayEq(a, c));
EXPECT_FALSE(ArrayEq(a, 2, c));
}
// Tests ArrayAwareFind().
TEST(ArrayAwareFindTest, WorksForOneDimensionalArray) {
const char a[] = "hello";
EXPECT_EQ(a + 4, ArrayAwareFind(a, a + 5, 'o'));
EXPECT_EQ(a + 5, ArrayAwareFind(a, a + 5, 'x'));
}
TEST(ArrayAwareFindTest, WorksForTwoDimensionalArray) {
int a[][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
const int b[2] = { 2, 3 };
EXPECT_EQ(a + 1, ArrayAwareFind(a, a + 3, b));
const int c[2] = { 6, 7 };
EXPECT_EQ(a + 3, ArrayAwareFind(a, a + 3, c));
}
// Tests CopyArray().
TEST(CopyArrayTest, WorksForDegeneratedArrays) {
int n = 0;
CopyArray('a', &n);
EXPECT_EQ('a', n);
}
TEST(CopyArrayTest, WorksForOneDimensionalArrays) {
const char a[3] = "hi";
int b[3];
CopyArray(a, &b);
EXPECT_TRUE(ArrayEq(a, b));
int c[3];
CopyArray(a, 3, c);
EXPECT_TRUE(ArrayEq(a, c));
}
TEST(CopyArrayTest, WorksForTwoDimensionalArrays) {
const int a[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };
int b[2][3];
CopyArray(a, &b);
EXPECT_TRUE(ArrayEq(a, b));
int c[2][3];
CopyArray(a, 2, c);
EXPECT_TRUE(ArrayEq(a, c));
}
// Tests NativeArray.
TEST(NativeArrayTest, ConstructorFromArrayWorks) {
const int a[3] = { 0, 1, 2 };
NativeArray<int> na(a, 3, kReference);
EXPECT_EQ(3U, na.size());
EXPECT_EQ(a, na.begin());
}
TEST(NativeArrayTest, CreatesAndDeletesCopyOfArrayWhenAskedTo) {
typedef int Array[2];
Array* a = new Array[1];
(*a)[0] = 0;
(*a)[1] = 1;
NativeArray<int> na(*a, 2, kCopy);
EXPECT_NE(*a, na.begin());
delete[] a;
EXPECT_EQ(0, na.begin()[0]);
EXPECT_EQ(1, na.begin()[1]);
// We rely on the heap checker to verify that na deletes the copy of
// array.
}
TEST(NativeArrayTest, TypeMembersAreCorrect) {
StaticAssertTypeEq<char, NativeArray<char>::value_type>();
StaticAssertTypeEq<int[2], NativeArray<int[2]>::value_type>();
StaticAssertTypeEq<const char*, NativeArray<char>::const_iterator>();
StaticAssertTypeEq<const bool(*)[2], NativeArray<bool[2]>::const_iterator>();
}
TEST(NativeArrayTest, MethodsWork) {
const int a[3] = { 0, 1, 2 };
NativeArray<int> na(a, 3, kCopy);
ASSERT_EQ(3U, na.size());
EXPECT_EQ(3, na.end() - na.begin());
NativeArray<int>::const_iterator it = na.begin();
EXPECT_EQ(0, *it);
++it;
EXPECT_EQ(1, *it);
it++;
EXPECT_EQ(2, *it);
++it;
EXPECT_EQ(na.end(), it);
EXPECT_TRUE(na == na);
NativeArray<int> na2(a, 3, kReference);
EXPECT_TRUE(na == na2);
const int b1[3] = { 0, 1, 1 };
const int b2[4] = { 0, 1, 2, 3 };
EXPECT_FALSE(na == NativeArray<int>(b1, 3, kReference));
EXPECT_FALSE(na == NativeArray<int>(b2, 4, kCopy));
}
TEST(NativeArrayTest, WorksForTwoDimensionalArray) {
const char a[2][3] = { "hi", "lo" };
NativeArray<char[3]> na(a, 2, kReference);
ASSERT_EQ(2U, na.size());
EXPECT_EQ(a, na.begin());
}