Commit 2ccea88c authored by zhanyong.wan's avatar zhanyong.wan
Browse files

Moves the universal printer from gmock to gtest and refactors the cmake script...

Moves the universal printer from gmock to gtest and refactors the cmake script for reusing in gmock (by Vlad Losev).
parent cdc0aae1
...@@ -39,29 +39,9 @@ if (COMMAND set_up_hermetic_build) ...@@ -39,29 +39,9 @@ if (COMMAND set_up_hermetic_build)
set_up_hermetic_build() set_up_hermetic_build()
endif() endif()
if (MSVC) include(cmake/internal_utils.cmake)
# For MSVC, CMake sets certain flags to defaults we want to override.
# This replacement code is taken from sample in the CMake Wiki at fix_default_settings() # Defined in internal_utils.cmake.
# 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()
# Where gtest's .h files can be found. # Where gtest's .h files can be found.
include_directories( include_directories(
...@@ -72,91 +52,10 @@ include_directories( ...@@ -72,91 +52,10 @@ include_directories(
link_directories( link_directories(
${gtest_BINARY_DIR}/src) ${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 # Defines the gtest & gtest_main libraries. User tests should link
# with one of them. # 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 # 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 # 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) ...@@ -173,39 +72,6 @@ target_link_libraries(gtest_main gtest)
# build_gtest_samples option to ON. You can do it by running ccmake # build_gtest_samples option to ON. You can do it by running ccmake
# or specifying the -Dbuild_gtest_samples=ON flag when running cmake. # 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) if (build_gtest_samples)
cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc) cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc) cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
...@@ -230,38 +96,14 @@ endif() ...@@ -230,38 +96,14 @@ endif()
# build_all_gtest_tests option to ON. You can do it by running ccmake # 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. # 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 if (build_all_gtest_tests)
# 'make test' or ctest. # This must be set in the root directory for the tests to be run by
enable_testing() # '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) ############################################################
# C++ tests built with standard compiler flags.
if (build_all_gtest_tests)
cxx_test(gtest-death-test_test gtest_main) cxx_test(gtest-death-test_test gtest_main)
cxx_test(gtest_environment_test gtest) cxx_test(gtest_environment_test gtest)
cxx_test(gtest-filepath_test gtest_main) cxx_test(gtest-filepath_test gtest_main)
...@@ -275,6 +117,7 @@ if (build_all_gtest_tests) ...@@ -275,6 +117,7 @@ if (build_all_gtest_tests)
test/gtest-param-test2_test.cc) test/gtest-param-test2_test.cc)
cxx_test(gtest-port_test gtest_main) cxx_test(gtest-port_test gtest_main)
cxx_test(gtest_pred_impl_unittest gtest_main) cxx_test(gtest_pred_impl_unittest gtest_main)
cxx_test(gtest-printers_test gtest_main)
cxx_test(gtest_prod_test gtest_main cxx_test(gtest_prod_test gtest_main
test/production.cc) test/production.cc)
cxx_test(gtest_repeat_test gtest) cxx_test(gtest_repeat_test gtest)
...@@ -284,13 +127,12 @@ if (build_all_gtest_tests) ...@@ -284,13 +127,12 @@ if (build_all_gtest_tests)
cxx_test(gtest_throw_on_failure_ex_test gtest) cxx_test(gtest_throw_on_failure_ex_test gtest)
cxx_test(gtest-typed-test_test gtest_main cxx_test(gtest-typed-test_test gtest_main
test/gtest-typed-test2_test.cc) test/gtest-typed-test2_test.cc)
cxx_test(gtest_unittest gtest_main)
cxx_test(gtest-unittest-api_test gtest) 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}" cxx_library(gtest_no_exception "${cxx_no_exception}"
src/gtest-all.cc) src/gtest-all.cc)
cxx_library(gtest_main_no_rtti "${cxx_no_rtti}" cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
...@@ -325,28 +167,9 @@ if (build_all_gtest_tests) ...@@ -325,28 +167,9 @@ if (build_all_gtest_tests)
test/gtest-param-test_test.cc test/gtest-param-test2_test.cc) test/gtest-param-test_test.cc test/gtest-param-test2_test.cc)
endif() 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) cxx_executable(gtest_break_on_failure_unittest_ test gtest)
py_test(gtest_break_on_failure_unittest) py_test(gtest_break_on_failure_unittest)
......
...@@ -22,6 +22,7 @@ GTEST_SRC = \ ...@@ -22,6 +22,7 @@ GTEST_SRC = \
src/gtest-filepath.cc \ src/gtest-filepath.cc \
src/gtest-internal-inl.h \ src/gtest-internal-inl.h \
src/gtest-port.cc \ src/gtest-port.cc \
src/gtest-printers.cc \
src/gtest-test-part.cc \ src/gtest-test-part.cc \
src/gtest-typed-test.cc src/gtest-typed-test.cc
...@@ -52,6 +53,7 @@ EXTRA_DIST += \ ...@@ -52,6 +53,7 @@ EXTRA_DIST += \
test/gtest-param-test2_test.cc \ test/gtest-param-test2_test.cc \
test/gtest-param-test_test.h \ test/gtest-param-test_test.h \
test/gtest-port_test.cc \ test/gtest-port_test.cc \
test/gtest-printers_test.cc \
test/gtest_pred_impl_unittest.cc \ test/gtest_pred_impl_unittest.cc \
test/gtest_prod_test.cc \ test/gtest_prod_test.cc \
test/production.cc \ test/production.cc \
...@@ -186,6 +188,7 @@ pkginclude_HEADERS = include/gtest/gtest.h \ ...@@ -186,6 +188,7 @@ pkginclude_HEADERS = include/gtest/gtest.h \
include/gtest/gtest-message.h \ include/gtest/gtest-message.h \
include/gtest/gtest-param-test.h \ include/gtest/gtest-param-test.h \
include/gtest/gtest_pred_impl.h \ include/gtest/gtest_pred_impl.h \
include/gtest/gtest-printers.h \
include/gtest/gtest_prod.h \ include/gtest/gtest_prod.h \
include/gtest/gtest-spi.h \ include/gtest/gtest-spi.h \
include/gtest/gtest-test-part.h \ include/gtest/gtest-test-part.h \
......
# 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()
// 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_
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#include <gtest/gtest-death-test.h> #include <gtest/gtest-death-test.h>
#include <gtest/gtest-message.h> #include <gtest/gtest-message.h>
#include <gtest/gtest-param-test.h> #include <gtest/gtest-param-test.h>
#include <gtest/gtest-printers.h>
#include <gtest/gtest_prod.h> #include <gtest/gtest_prod.h>
#include <gtest/gtest-test-part.h> #include <gtest/gtest-test-part.h>
#include <gtest/gtest-typed-test.h> #include <gtest/gtest-typed-test.h>
...@@ -1926,17 +1927,6 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, ...@@ -1926,17 +1927,6 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
__FILE__, __LINE__, ::testing::Message() << (message)) __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. // Compile-time assertion for type equality.
// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are // StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
// the same type. The value it returns is not interesting. // the same type. The value it returns is not interesting.
...@@ -1969,7 +1959,7 @@ struct StaticAssertTypeEqHelper<T, T> {}; ...@@ -1969,7 +1959,7 @@ struct StaticAssertTypeEqHelper<T, T> {};
// to cause a compiler error. // to cause a compiler error.
template <typename T1, typename T2> template <typename T1, typename T2>
bool StaticAssertTypeEq() { bool StaticAssertTypeEq() {
(void)internal::StaticAssertTypeEqHelper<T1, T2>(); internal::StaticAssertTypeEqHelper<T1, T2>();
return true; return true;
} }
......
...@@ -97,6 +97,9 @@ inline void GTestStreamToHelper(std::ostream* os, const T& val) { ...@@ -97,6 +97,9 @@ inline void GTestStreamToHelper(std::ostream* os, const T& val) {
*os << val; *os << val;
} }
class ProtocolMessage;
namespace proto2 { class Message; }
namespace testing { namespace testing {
// Forward declaration of classes. // Forward declaration of classes.
...@@ -784,6 +787,292 @@ class GTEST_API_ Random { ...@@ -784,6 +787,292 @@ class GTEST_API_ Random {
GTEST_DISALLOW_COPY_AND_ASSIGN_(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 internal
} // namespace testing } // namespace testing
......
...@@ -609,6 +609,91 @@ namespace internal { ...@@ -609,6 +609,91 @@ namespace internal {
class String; 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; typedef ::std::stringstream StrStream;
// A helper for suppressing warnings on constant condition. It just // A helper for suppressing warnings on constant condition. It just
...@@ -790,6 +875,58 @@ inline void FlushInfoLog() { fflush(NULL); } ...@@ -790,6 +875,58 @@ inline void FlushInfoLog() { fflush(NULL); }
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // 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. // Downcasts the pointer of type Base to Derived.
// Derived must be a subclass of Base. The parameter MUST // Derived must be a subclass of Base. The parameter MUST
// point to a class of type Derived, not any subclass of it. // point to a class of type Derived, not any subclass of it.
......
...@@ -43,5 +43,6 @@ ...@@ -43,5 +43,6 @@
#include "src/gtest-death-test.cc" #include "src/gtest-death-test.cc"
#include "src/gtest-filepath.cc" #include "src/gtest-filepath.cc"
#include "src/gtest-port.cc" #include "src/gtest-port.cc"
#include "src/gtest-printers.cc"
#include "src/gtest-test-part.cc" #include "src/gtest-test-part.cc"
#include "src/gtest-typed-test.cc" #include "src/gtest-typed-test.cc"
// 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
...@@ -59,6 +59,118 @@ using std::pair; ...@@ -59,6 +59,118 @@ using std::pair;
namespace testing { namespace testing {
namespace internal { 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 // Tests that the element_type typedef is available in scoped_ptr and refers
// to the parameter type. // to the parameter type.
TEST(ScopedPtrTest, DefinesElementType) { TEST(ScopedPtrTest, DefinesElementType) {
......
// 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 tests the universal value printer.
#include <gtest/gtest-printers.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <algorithm>
#include <deque>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
// hash_map and hash_set are available on Windows.
#if GTEST_OS_WINDOWS
#define GTEST_HAS_HASH_MAP_ 1 // Indicates that hash_map is available.
#include <hash_map> // NOLINT
#define GTEST_HAS_HASH_SET_ 1 // Indicates that hash_set is available.
#include <hash_set> // NOLINT
#endif // GTEST_OS_WINDOWS
// Some user-defined types for testing the universal value printer.
// A user-defined unprintable class template in the global namespace.
template <typename T>
class UnprintableTemplateInGlobal {
public:
UnprintableTemplateInGlobal() : value_() {}
private:
T value_;
};
// A user-defined streamable type in the global namespace.
class StreamableInGlobal {
public:
virtual ~StreamableInGlobal() {}
};
inline void operator<<(::std::ostream& os, const StreamableInGlobal& /* x */) {
os << "StreamableInGlobal";
}
namespace foo {
// A user-defined unprintable type in a user namespace.
class UnprintableInFoo {
public:
UnprintableInFoo() : x_(0x12EF), y_(0xAB34), z_(0) {}
private:
testing::internal::Int32 x_;
testing::internal::Int32 y_;
double z_;
};
// A user-defined printable type in a user-chosen namespace.
struct PrintableViaPrintTo {
PrintableViaPrintTo() : value() {}
int value;
};
void PrintTo(const PrintableViaPrintTo& x, ::std::ostream* os) {
*os << "PrintableViaPrintTo: " << x.value;
}
// A user-defined printable class template in a user-chosen namespace.
template <typename T>
class PrintableViaPrintToTemplate {
public:
explicit PrintableViaPrintToTemplate(const T& a_value) : value_(a_value) {}
const T& value() const { return value_; }
private:
T value_;
};
template <typename T>
void PrintTo(const PrintableViaPrintToTemplate<T>& x, ::std::ostream* os) {
*os << "PrintableViaPrintToTemplate: " << x.value();
}
// A user-defined streamable class template in a user namespace.
template <typename T>
class StreamableTemplateInFoo {
public:
StreamableTemplateInFoo() : value_() {}
const T& value() const { return value_; }
private:
T value_;
};
template <typename T>
inline ::std::ostream& operator<<(::std::ostream& os,
const StreamableTemplateInFoo<T>& x) {
return os << "StreamableTemplateInFoo: " << x.value();
}
} // namespace foo
namespace testing {
namespace gtest_printers_test {
using ::std::deque;
using ::std::list;
using ::std::make_pair;
using ::std::map;
using ::std::multimap;
using ::std::multiset;
using ::std::pair;
using ::std::set;
using ::std::vector;
using ::testing::PrintToString;
using ::testing::internal::NativeArray;
using ::testing::internal::RE;
using ::testing::internal::Strings;
using ::testing::internal::UniversalTersePrint;
using ::testing::internal::UniversalPrint;
using ::testing::internal::UniversalTersePrintTupleFieldsToStrings;
using ::testing::internal::UniversalPrinter;
using ::testing::internal::kReference;
using ::testing::internal::string;
#if GTEST_HAS_TR1_TUPLE
using ::std::tr1::make_tuple;
using ::std::tr1::tuple;
#endif
#if GTEST_OS_WINDOWS
// MSVC defines the following classes in the ::stdext namespace while
// gcc defines them in the :: namespace. Note that they are not part
// of the C++ standard.
using ::stdext::hash_map;
using ::stdext::hash_set;
using ::stdext::hash_multimap;
using ::stdext::hash_multiset;
#endif // GTEST_OS_WINDOWS
// Prints a value to a string using the universal value printer. This
// is a helper for testing UniversalPrinter<T>::Print() for various types.
template <typename T>
string Print(const T& value) {
::std::stringstream ss;
UniversalPrinter<T>::Print(value, &ss);
return ss.str();
}
// Prints a value passed by reference to a string, using the universal
// value printer. This is a helper for testing
// UniversalPrinter<T&>::Print() for various types.
template <typename T>
string PrintByRef(const T& value) {
::std::stringstream ss;
UniversalPrinter<T&>::Print(value, &ss);
return ss.str();
}
// Tests printing various char types.
// char.
TEST(PrintCharTest, PlainChar) {
EXPECT_EQ("'\\0'", Print('\0'));
EXPECT_EQ("'\\'' (39)", Print('\''));
EXPECT_EQ("'\"' (34)", Print('"'));
EXPECT_EQ("'\\?' (63)", Print('\?'));
EXPECT_EQ("'\\\\' (92)", Print('\\'));
EXPECT_EQ("'\\a' (7)", Print('\a'));
EXPECT_EQ("'\\b' (8)", Print('\b'));
EXPECT_EQ("'\\f' (12)", Print('\f'));
EXPECT_EQ("'\\n' (10)", Print('\n'));
EXPECT_EQ("'\\r' (13)", Print('\r'));
EXPECT_EQ("'\\t' (9)", Print('\t'));
EXPECT_EQ("'\\v' (11)", Print('\v'));
EXPECT_EQ("'\\x7F' (127)", Print('\x7F'));
EXPECT_EQ("'\\xFF' (255)", Print('\xFF'));
EXPECT_EQ("' ' (32)", Print(' '));
EXPECT_EQ("'a' (97)", Print('a'));
}
// signed char.
TEST(PrintCharTest, SignedChar) {
EXPECT_EQ("'\\0'", Print(static_cast<signed char>('\0')));
EXPECT_EQ("'\\xCE' (-50)",
Print(static_cast<signed char>(-50)));
}
// unsigned char.
TEST(PrintCharTest, UnsignedChar) {
EXPECT_EQ("'\\0'", Print(static_cast<unsigned char>('\0')));
EXPECT_EQ("'b' (98)",
Print(static_cast<unsigned char>('b')));
}
// Tests printing other simple, built-in types.
// bool.
TEST(PrintBuiltInTypeTest, Bool) {
EXPECT_EQ("false", Print(false));
EXPECT_EQ("true", Print(true));
}
// wchar_t.
TEST(PrintBuiltInTypeTest, Wchar_t) {
EXPECT_EQ("L'\\0'", Print(L'\0'));
EXPECT_EQ("L'\\'' (39)", Print(L'\''));
EXPECT_EQ("L'\"' (34)", Print(L'"'));
EXPECT_EQ("L'\\?' (63)", Print(L'\?'));
EXPECT_EQ("L'\\\\' (92)", Print(L'\\'));
EXPECT_EQ("L'\\a' (7)", Print(L'\a'));
EXPECT_EQ("L'\\b' (8)", Print(L'\b'));
EXPECT_EQ("L'\\f' (12)", Print(L'\f'));
EXPECT_EQ("L'\\n' (10)", Print(L'\n'));
EXPECT_EQ("L'\\r' (13)", Print(L'\r'));
EXPECT_EQ("L'\\t' (9)", Print(L'\t'));
EXPECT_EQ("L'\\v' (11)", Print(L'\v'));
EXPECT_EQ("L'\\x7F' (127)", Print(L'\x7F'));
EXPECT_EQ("L'\\xFF' (255)", Print(L'\xFF'));
EXPECT_EQ("L' ' (32)", Print(L' '));
EXPECT_EQ("L'a' (97)", Print(L'a'));
EXPECT_EQ("L'\\x576' (1398)", Print(L'\x576'));
EXPECT_EQ("L'\\xC74D' (51021)", Print(L'\xC74D'));
}
// Test that Int64 provides more storage than wchar_t.
TEST(PrintTypeSizeTest, Wchar_t) {
EXPECT_LT(sizeof(wchar_t), sizeof(testing::internal::Int64));
}
// Various integer types.
TEST(PrintBuiltInTypeTest, Integer) {
EXPECT_EQ("'\\xFF' (255)", Print(static_cast<unsigned char>(255))); // uint8
EXPECT_EQ("'\\x80' (-128)", Print(static_cast<signed char>(-128))); // int8
EXPECT_EQ("65535", Print(USHRT_MAX)); // uint16
EXPECT_EQ("-32768", Print(SHRT_MIN)); // int16
EXPECT_EQ("4294967295", Print(UINT_MAX)); // uint32
EXPECT_EQ("-2147483648", Print(INT_MIN)); // int32
EXPECT_EQ("18446744073709551615",
Print(static_cast<testing::internal::UInt64>(-1))); // uint64
EXPECT_EQ("-9223372036854775808",
Print(static_cast<testing::internal::Int64>(1) << 63)); // int64
}
// Size types.
TEST(PrintBuiltInTypeTest, Size_t) {
EXPECT_EQ("1", Print(sizeof('a'))); // size_t.
#if !GTEST_OS_WINDOWS
// Windows has no ssize_t type.
EXPECT_EQ("-2", Print(static_cast<ssize_t>(-2))); // ssize_t.
#endif // !GTEST_OS_WINDOWS
}
// Floating-points.
TEST(PrintBuiltInTypeTest, FloatingPoints) {
EXPECT_EQ("1.5", Print(1.5f)); // float
EXPECT_EQ("-2.5", Print(-2.5)); // double
}
// Since ::std::stringstream::operator<<(const void *) formats the pointer
// output differently with different compilers, we have to create the expected
// output first and use it as our expectation.
static string PrintPointer(const void *p) {
::std::stringstream expected_result_stream;
expected_result_stream << p;
return expected_result_stream.str();
}
// Tests printing C strings.
// const char*.
TEST(PrintCStringTest, Const) {
const char* p = "World";
EXPECT_EQ(PrintPointer(p) + " pointing to \"World\"", Print(p));
}
// char*.
TEST(PrintCStringTest, NonConst) {
char p[] = "Hi";
EXPECT_EQ(PrintPointer(p) + " pointing to \"Hi\"",
Print(static_cast<char*>(p)));
}
// NULL C string.
TEST(PrintCStringTest, Null) {
const char* p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// Tests that C strings are escaped properly.
TEST(PrintCStringTest, EscapesProperly) {
const char* p = "'\"\?\\\a\b\f\n\r\t\v\x7F\xFF a";
EXPECT_EQ(PrintPointer(p) + " pointing to \"'\\\"\\?\\\\\\a\\b\\f"
"\\n\\r\\t\\v\\x7F\\xFF a\"",
Print(p));
}
// 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)
// const wchar_t*.
TEST(PrintWideCStringTest, Const) {
const wchar_t* p = L"World";
EXPECT_EQ(PrintPointer(p) + " pointing to L\"World\"", Print(p));
}
// wchar_t*.
TEST(PrintWideCStringTest, NonConst) {
wchar_t p[] = L"Hi";
EXPECT_EQ(PrintPointer(p) + " pointing to L\"Hi\"",
Print(static_cast<wchar_t*>(p)));
}
// NULL wide C string.
TEST(PrintWideCStringTest, Null) {
const wchar_t* p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// Tests that wide C strings are escaped properly.
TEST(PrintWideCStringTest, EscapesProperly) {
const wchar_t* p = L"'\"\?\\\a\b\f\n\r\t\v\xD3\x576\x8D3\xC74D a";
EXPECT_EQ(PrintPointer(p) + " pointing to L\"'\\\"\\?\\\\\\a\\b\\f"
"\\n\\r\\t\\v\\xD3\\x576\\x8D3\\xC74D a\"",
Print(p));
}
#endif // native wchar_t
// Tests printing pointers to other char types.
// signed char*.
TEST(PrintCharPointerTest, SignedChar) {
signed char* p = reinterpret_cast<signed char*>(0x1234);
EXPECT_EQ(PrintPointer(p), Print(p));
p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// const signed char*.
TEST(PrintCharPointerTest, ConstSignedChar) {
signed char* p = reinterpret_cast<signed char*>(0x1234);
EXPECT_EQ(PrintPointer(p), Print(p));
p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// unsigned char*.
TEST(PrintCharPointerTest, UnsignedChar) {
unsigned char* p = reinterpret_cast<unsigned char*>(0x1234);
EXPECT_EQ(PrintPointer(p), Print(p));
p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// const unsigned char*.
TEST(PrintCharPointerTest, ConstUnsignedChar) {
const unsigned char* p = reinterpret_cast<const unsigned char*>(0x1234);
EXPECT_EQ(PrintPointer(p), Print(p));
p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// Tests printing pointers to simple, built-in types.
// bool*.
TEST(PrintPointerToBuiltInTypeTest, Bool) {
bool* p = reinterpret_cast<bool*>(0xABCD);
EXPECT_EQ(PrintPointer(p), Print(p));
p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// void*.
TEST(PrintPointerToBuiltInTypeTest, Void) {
void* p = reinterpret_cast<void*>(0xABCD);
EXPECT_EQ(PrintPointer(p), Print(p));
p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// const void*.
TEST(PrintPointerToBuiltInTypeTest, ConstVoid) {
const void* p = reinterpret_cast<const void*>(0xABCD);
EXPECT_EQ(PrintPointer(p), Print(p));
p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// Tests printing pointers to pointers.
TEST(PrintPointerToPointerTest, IntPointerPointer) {
int** p = reinterpret_cast<int**>(0xABCD);
EXPECT_EQ(PrintPointer(p), Print(p));
p = NULL;
EXPECT_EQ("NULL", Print(p));
}
// Tests printing (non-member) function pointers.
void MyFunction(int /* n */) {}
TEST(PrintPointerTest, NonMemberFunctionPointer) {
// We cannot directly cast &MyFunction to const void* because the
// standard disallows casting between pointers to functions and
// pointers to objects, and some compilers (e.g. GCC 3.4) enforce
// this limitation.
EXPECT_EQ(
PrintPointer(reinterpret_cast<const void*>(
reinterpret_cast<internal::BiggestInt>(&MyFunction))),
Print(&MyFunction));
int (*p)(bool) = NULL; // NOLINT
EXPECT_EQ("NULL", Print(p));
}
// An assertion predicate determining whether a one string is a prefix for
// another.
template <typename StringType>
AssertionResult HasPrefix(const StringType& str, const StringType& prefix) {
if (str.find(prefix, 0) == 0)
return AssertionSuccess();
const bool is_wide_string = sizeof(prefix[0]) > 1;
const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
return AssertionFailure()
<< begin_string_quote << prefix << "\" is not a prefix of "
<< begin_string_quote << str << "\"\n";
}
// Tests printing member variable pointers. Although they are called
// pointers, they don't point to a location in the address space.
// Their representation is implementation-defined. Thus they will be
// printed as raw bytes.
struct Foo {
public:
virtual ~Foo() {}
int MyMethod(char x) { return x + 1; }
virtual char MyVirtualMethod(int /* n */) { return 'a'; }
int value;
};
TEST(PrintPointerTest, MemberVariablePointer) {
EXPECT_TRUE(HasPrefix(Print(&Foo::value),
Print(sizeof(&Foo::value)) + "-byte object "));
int (Foo::*p) = NULL; // NOLINT
EXPECT_TRUE(HasPrefix(Print(p),
Print(sizeof(p)) + "-byte object "));
}
// Tests printing member function pointers. Although they are called
// pointers, they don't point to a location in the address space.
// Their representation is implementation-defined. Thus they will be
// printed as raw bytes.
TEST(PrintPointerTest, MemberFunctionPointer) {
EXPECT_TRUE(HasPrefix(Print(&Foo::MyMethod),
Print(sizeof(&Foo::MyMethod)) + "-byte object "));
EXPECT_TRUE(
HasPrefix(Print(&Foo::MyVirtualMethod),
Print(sizeof((&Foo::MyVirtualMethod))) + "-byte object "));
int (Foo::*p)(char) = NULL; // NOLINT
EXPECT_TRUE(HasPrefix(Print(p),
Print(sizeof(p)) + "-byte object "));
}
// Tests printing C arrays.
// The difference between this and Print() is that it ensures that the
// argument is a reference to an array.
template <typename T, size_t N>
string PrintArrayHelper(T (&a)[N]) {
return Print(a);
}
// One-dimensional array.
TEST(PrintArrayTest, OneDimensionalArray) {
int a[5] = { 1, 2, 3, 4, 5 };
EXPECT_EQ("{ 1, 2, 3, 4, 5 }", PrintArrayHelper(a));
}
// Two-dimensional array.
TEST(PrintArrayTest, TwoDimensionalArray) {
int a[2][5] = {
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 0 }
};
EXPECT_EQ("{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }", PrintArrayHelper(a));
}
// Array of const elements.
TEST(PrintArrayTest, ConstArray) {
const bool a[1] = { false };
EXPECT_EQ("{ false }", PrintArrayHelper(a));
}
// Char array.
TEST(PrintArrayTest, CharArray) {
// Array a contains '\0' in the middle and doesn't end with '\0'.
char a[3] = { 'H', '\0', 'i' };
EXPECT_EQ("\"H\\0i\"", PrintArrayHelper(a));
}
// Const char array.
TEST(PrintArrayTest, ConstCharArray) {
const char a[4] = "\0Hi";
EXPECT_EQ("\"\\0Hi\\0\"", PrintArrayHelper(a));
}
// Array of objects.
TEST(PrintArrayTest, ObjectArray) {
string a[3] = { "Hi", "Hello", "Ni hao" };
EXPECT_EQ("{ \"Hi\", \"Hello\", \"Ni hao\" }", PrintArrayHelper(a));
}
// Array with many elements.
TEST(PrintArrayTest, BigArray) {
int a[100] = { 1, 2, 3 };
EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0, 0, 0 }",
PrintArrayHelper(a));
}
// Tests printing ::string and ::std::string.
#if GTEST_HAS_GLOBAL_STRING
// ::string.
TEST(PrintStringTest, StringInGlobalNamespace) {
const char s[] = "'\"\?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
const ::string str(s, sizeof(s));
EXPECT_EQ("\"'\\\"\\?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
Print(str));
}
#endif // GTEST_HAS_GLOBAL_STRING
// ::std::string.
TEST(PrintStringTest, StringInStdNamespace) {
const char s[] = "'\"\?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
const ::std::string str(s, sizeof(s));
EXPECT_EQ("\"'\\\"\\?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
Print(str));
}
// Tests printing ::wstring and ::std::wstring.
#if GTEST_HAS_GLOBAL_WSTRING
// ::wstring.
TEST(PrintWideStringTest, StringInGlobalNamespace) {
const wchar_t s[] = L"'\"\?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
const ::wstring str(s, sizeof(s)/sizeof(wchar_t));
EXPECT_EQ("L\"'\\\"\\?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
"\\xD3\\x576\\x8D3\\xC74D a\\0\"",
Print(str));
}
#endif // GTEST_HAS_GLOBAL_WSTRING
#if GTEST_HAS_STD_WSTRING
// ::std::wstring.
TEST(PrintWideStringTest, StringInStdNamespace) {
const wchar_t s[] = L"'\"\?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
const ::std::wstring str(s, sizeof(s)/sizeof(wchar_t));
EXPECT_EQ("L\"'\\\"\\?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
"\\xD3\\x576\\x8D3\\xC74D a\\0\"",
Print(str));
}
#endif // GTEST_HAS_STD_WSTRING
// Tests printing types that support generic streaming (i.e. streaming
// to std::basic_ostream<Char, CharTraits> for any valid Char and
// CharTraits types).
// Tests printing a non-template type that supports generic streaming.
class AllowsGenericStreaming {};
template <typename Char, typename CharTraits>
std::basic_ostream<Char, CharTraits>& operator<<(
std::basic_ostream<Char, CharTraits>& os,
const AllowsGenericStreaming& /* a */) {
return os << "AllowsGenericStreaming";
}
TEST(PrintTypeWithGenericStreamingTest, NonTemplateType) {
AllowsGenericStreaming a;
EXPECT_EQ("AllowsGenericStreaming", Print(a));
}
// Tests printing a template type that supports generic streaming.
template <typename T>
class AllowsGenericStreamingTemplate {};
template <typename Char, typename CharTraits, typename T>
std::basic_ostream<Char, CharTraits>& operator<<(
std::basic_ostream<Char, CharTraits>& os,
const AllowsGenericStreamingTemplate<T>& /* a */) {
return os << "AllowsGenericStreamingTemplate";
}
TEST(PrintTypeWithGenericStreamingTest, TemplateType) {
AllowsGenericStreamingTemplate<int> a;
EXPECT_EQ("AllowsGenericStreamingTemplate", Print(a));
}
// Tests printing a type that supports generic streaming and can be
// implicitly converted to another printable type.
template <typename T>
class AllowsGenericStreamingAndImplicitConversionTemplate {
public:
operator bool() const { return false; }
};
template <typename Char, typename CharTraits, typename T>
std::basic_ostream<Char, CharTraits>& operator<<(
std::basic_ostream<Char, CharTraits>& os,
const AllowsGenericStreamingAndImplicitConversionTemplate<T>& /* a */) {
return os << "AllowsGenericStreamingAndImplicitConversionTemplate";
}
TEST(PrintTypeWithGenericStreamingTest, TypeImplicitlyConvertible) {
AllowsGenericStreamingAndImplicitConversionTemplate<int> a;
EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a));
}
#if GTEST_HAS_STRING_PIECE_
// Tests printing StringPiece.
TEST(PrintStringPieceTest, SimpleStringPiece) {
const StringPiece sp = "Hello";
EXPECT_EQ("\"Hello\"", Print(sp));
}
TEST(PrintStringPieceTest, UnprintableCharacters) {
const char str[] = "NUL (\0) and \r\t";
const StringPiece sp(str, sizeof(str) - 1);
EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp));
}
#endif // GTEST_HAS_STRING_PIECE_
// Tests printing STL containers.
TEST(PrintStlContainerTest, EmptyDeque) {
deque<char> empty;
EXPECT_EQ("{}", Print(empty));
}
TEST(PrintStlContainerTest, NonEmptyDeque) {
deque<int> non_empty;
non_empty.push_back(1);
non_empty.push_back(3);
EXPECT_EQ("{ 1, 3 }", Print(non_empty));
}
#if GTEST_HAS_HASH_MAP_
TEST(PrintStlContainerTest, OneElementHashMap) {
hash_map<int, char> map1;
map1[1] = 'a';
EXPECT_EQ("{ (1, 'a' (97)) }", Print(map1));
}
TEST(PrintStlContainerTest, HashMultiMap) {
hash_multimap<int, bool> map1;
map1.insert(make_pair(5, true));
map1.insert(make_pair(5, false));
// Elements of hash_multimap can be printed in any order.
const string result = Print(map1);
EXPECT_TRUE(result == "{ (5, true), (5, false) }" ||
result == "{ (5, false), (5, true) }")
<< " where Print(map1) returns \"" << result << "\".";
}
#endif // GTEST_HAS_HASH_MAP_
#if GTEST_HAS_HASH_SET_
TEST(PrintStlContainerTest, HashSet) {
hash_set<string> set1;
set1.insert("hello");
EXPECT_EQ("{ \"hello\" }", Print(set1));
}
TEST(PrintStlContainerTest, HashMultiSet) {
const int kSize = 5;
int a[kSize] = { 1, 1, 2, 5, 1 };
hash_multiset<int> set1(a, a + kSize);
// Elements of hash_multiset can be printed in any order.
const string result = Print(set1);
const string expected_pattern = "{ d, d, d, d, d }"; // d means a digit.
// Verifies the result matches the expected pattern; also extracts
// the numbers in the result.
ASSERT_EQ(expected_pattern.length(), result.length());
std::vector<int> numbers;
for (size_t i = 0; i != result.length(); i++) {
if (expected_pattern[i] == 'd') {
ASSERT_TRUE(isdigit(result[i]) != 0);
numbers.push_back(result[i] - '0');
} else {
EXPECT_EQ(expected_pattern[i], result[i]) << " where result is "
<< result;
}
}
// Makes sure the result contains the right numbers.
std::sort(numbers.begin(), numbers.end());
std::sort(a, a + kSize);
EXPECT_TRUE(std::equal(a, a + kSize, numbers.begin()));
}
#endif // GTEST_HAS_HASH_SET_
TEST(PrintStlContainerTest, List) {
const char* a[] = {
"hello",
"world"
};
const list<string> strings(a, a + 2);
EXPECT_EQ("{ \"hello\", \"world\" }", Print(strings));
}
TEST(PrintStlContainerTest, Map) {
map<int, bool> map1;
map1[1] = true;
map1[5] = false;
map1[3] = true;
EXPECT_EQ("{ (1, true), (3, true), (5, false) }", Print(map1));
}
TEST(PrintStlContainerTest, MultiMap) {
multimap<bool, int> map1;
map1.insert(make_pair(true, 0));
map1.insert(make_pair(true, 1));
map1.insert(make_pair(false, 2));
EXPECT_EQ("{ (false, 2), (true, 0), (true, 1) }", Print(map1));
}
TEST(PrintStlContainerTest, Set) {
const unsigned int a[] = { 3, 0, 5 };
set<unsigned int> set1(a, a + 3);
EXPECT_EQ("{ 0, 3, 5 }", Print(set1));
}
TEST(PrintStlContainerTest, MultiSet) {
const int a[] = { 1, 1, 2, 5, 1 };
multiset<int> set1(a, a + 5);
EXPECT_EQ("{ 1, 1, 1, 2, 5 }", Print(set1));
}
TEST(PrintStlContainerTest, Pair) {
pair<const bool, int> p(true, 5);
EXPECT_EQ("(true, 5)", Print(p));
}
TEST(PrintStlContainerTest, Vector) {
vector<int> v;
v.push_back(1);
v.push_back(2);
EXPECT_EQ("{ 1, 2 }", Print(v));
}
TEST(PrintStlContainerTest, LongSequence) {
const int a[100] = { 1, 2, 3 };
const vector<int> v(a, a + 100);
EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "
"0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... }", Print(v));
}
TEST(PrintStlContainerTest, NestedContainer) {
const int a1[] = { 1, 2 };
const int a2[] = { 3, 4, 5 };
const list<int> l1(a1, a1 + 2);
const list<int> l2(a2, a2 + 3);
vector<list<int> > v;
v.push_back(l1);
v.push_back(l2);
EXPECT_EQ("{ { 1, 2 }, { 3, 4, 5 } }", Print(v));
}
TEST(PrintStlContainerTest, OneDimensionalNativeArray) {
const int a[3] = { 1, 2, 3 };
NativeArray<int> b(a, 3, kReference);
EXPECT_EQ("{ 1, 2, 3 }", Print(b));
}
TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
const int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
NativeArray<int[3]> b(a, 2, kReference);
EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
}
#if GTEST_HAS_TR1_TUPLE
// Tests printing tuples.
// Tuples of various arities.
TEST(PrintTupleTest, VariousSizes) {
tuple<> t0;
EXPECT_EQ("()", Print(t0));
tuple<int> t1(5);
EXPECT_EQ("(5)", Print(t1));
tuple<char, bool> t2('a', true);
EXPECT_EQ("('a' (97), true)", Print(t2));
tuple<bool, int, int> t3(false, 2, 3);
EXPECT_EQ("(false, 2, 3)", Print(t3));
tuple<bool, int, int, int> t4(false, 2, 3, 4);
EXPECT_EQ("(false, 2, 3, 4)", Print(t4));
tuple<bool, int, int, int, bool> t5(false, 2, 3, 4, true);
EXPECT_EQ("(false, 2, 3, 4, true)", Print(t5));
tuple<bool, int, int, int, bool, int> t6(false, 2, 3, 4, true, 6);
EXPECT_EQ("(false, 2, 3, 4, true, 6)", Print(t6));
tuple<bool, int, int, int, bool, int, int> t7(false, 2, 3, 4, true, 6, 7);
EXPECT_EQ("(false, 2, 3, 4, true, 6, 7)", Print(t7));
tuple<bool, int, int, int, bool, int, int, bool> t8(
false, 2, 3, 4, true, 6, 7, true);
EXPECT_EQ("(false, 2, 3, 4, true, 6, 7, true)", Print(t8));
tuple<bool, int, int, int, bool, int, int, bool, int> t9(
false, 2, 3, 4, true, 6, 7, true, 9);
EXPECT_EQ("(false, 2, 3, 4, true, 6, 7, true, 9)", Print(t9));
const char* const str = "8";
tuple<bool, char, short, testing::internal::Int32, // NOLINT
testing::internal::Int64, float, double, const char*, void*, string>
t10(false, 'a', 3, 4, 5, 1.5F, -2.5, str, NULL, "10");
EXPECT_EQ("(false, 'a' (97), 3, 4, 5, 1.5, -2.5, " + PrintPointer(str) +
" pointing to \"8\", NULL, \"10\")",
Print(t10));
}
// Nested tuples.
TEST(PrintTupleTest, NestedTuple) {
tuple<tuple<int, bool>, char> nested(make_tuple(5, true), 'a');
EXPECT_EQ("((5, true), 'a' (97))", Print(nested));
}
#endif // GTEST_HAS_TR1_TUPLE
// Tests printing user-defined unprintable types.
// Unprintable types in the global namespace.
TEST(PrintUnprintableTypeTest, InGlobalNamespace) {
EXPECT_EQ("1-byte object <00>",
Print(UnprintableTemplateInGlobal<bool>()));
}
// Unprintable types in a user namespace.
TEST(PrintUnprintableTypeTest, InUserNamespace) {
EXPECT_EQ("16-byte object <EF12 0000 34AB 0000 0000 0000 0000 0000>",
Print(::foo::UnprintableInFoo()));
}
// Unprintable types are that too big to be printed completely.
struct Big {
Big() { memset(array, 0, sizeof(array)); }
char array[257];
};
TEST(PrintUnpritableTypeTest, BigObject) {
EXPECT_EQ("257-byte object <0000 0000 0000 0000 0000 0000 "
"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 "
"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 "
"0000 0000 0000 0000 0000 0000 ... 0000 0000 0000 "
"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 "
"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 "
"0000 0000 0000 0000 0000 0000 0000 0000 00>",
Print(Big()));
}
// Tests printing user-defined streamable types.
// Streamable types in the global namespace.
TEST(PrintStreamableTypeTest, InGlobalNamespace) {
EXPECT_EQ("StreamableInGlobal",
Print(StreamableInGlobal()));
}
// Printable template types in a user namespace.
TEST(PrintStreamableTypeTest, TemplateTypeInUserNamespace) {
EXPECT_EQ("StreamableTemplateInFoo: 0",
Print(::foo::StreamableTemplateInFoo<int>()));
}
// Tests printing user-defined types that have a PrintTo() function.
TEST(PrintPrintableTypeTest, InUserNamespace) {
EXPECT_EQ("PrintableViaPrintTo: 0",
Print(::foo::PrintableViaPrintTo()));
}
// Tests printing user-defined class template that have a PrintTo() function.
TEST(PrintPrintableTypeTest, TemplateInUserNamespace) {
EXPECT_EQ("PrintableViaPrintToTemplate: 5",
Print(::foo::PrintableViaPrintToTemplate<int>(5)));
}
#if GTEST_HAS_PROTOBUF_
// Tests printing a protocol message.
TEST(PrintProtocolMessageTest, PrintsShortDebugString) {
testing::internal::TestMessage msg;
msg.set_member("yes");
EXPECT_EQ("<member:\"yes\">", Print(msg));
}
// Tests printing a short proto2 message.
TEST(PrintProto2MessageTest, PrintsShortDebugStringWhenItIsShort) {
testing::internal::FooMessage msg;
msg.set_int_field(2);
msg.set_string_field("hello");
EXPECT_PRED2(RE::FullMatch, Print(msg),
"<int_field:\\s*2\\s+string_field:\\s*\"hello\">");
}
// Tests printing a long proto2 message.
TEST(PrintProto2MessageTest, PrintsDebugStringWhenItIsLong) {
testing::internal::FooMessage msg;
msg.set_int_field(2);
msg.set_string_field("hello");
msg.add_names("peter");
msg.add_names("paul");
msg.add_names("mary");
EXPECT_PRED2(RE::FullMatch, Print(msg),
"<\n"
"int_field:\\s*2\n"
"string_field:\\s*\"hello\"\n"
"names:\\s*\"peter\"\n"
"names:\\s*\"paul\"\n"
"names:\\s*\"mary\"\n"
">");
}
#endif // GTEST_HAS_PROTOBUF_
// Tests that the universal printer prints both the address and the
// value of a reference.
TEST(PrintReferenceTest, PrintsAddressAndValue) {
int n = 5;
EXPECT_EQ("@" + PrintPointer(&n) + " 5", PrintByRef(n));
int a[2][3] = {
{ 0, 1, 2 },
{ 3, 4, 5 }
};
EXPECT_EQ("@" + PrintPointer(a) + " { { 0, 1, 2 }, { 3, 4, 5 } }",
PrintByRef(a));
const ::foo::UnprintableInFoo x;
EXPECT_EQ("@" + PrintPointer(&x) + " 16-byte object "
"<EF12 0000 34AB 0000 0000 0000 0000 0000>",
PrintByRef(x));
}
// Tests that the universal printer prints a function pointer passed by
// reference.
TEST(PrintReferenceTest, HandlesFunctionPointer) {
void (*fp)(int n) = &MyFunction;
const string fp_pointer_string =
PrintPointer(reinterpret_cast<const void*>(&fp));
// We cannot directly cast &MyFunction to const void* because the
// standard disallows casting between pointers to functions and
// pointers to objects, and some compilers (e.g. GCC 3.4) enforce
// this limitation.
const string fp_string = PrintPointer(reinterpret_cast<const void*>(
reinterpret_cast<internal::BiggestInt>(fp)));
EXPECT_EQ("@" + fp_pointer_string + " " + fp_string,
PrintByRef(fp));
}
// Tests that the universal printer prints a member function pointer
// passed by reference.
TEST(PrintReferenceTest, HandlesMemberFunctionPointer) {
int (Foo::*p)(char ch) = &Foo::MyMethod;
EXPECT_TRUE(HasPrefix(
PrintByRef(p),
"@" + PrintPointer(reinterpret_cast<const void*>(&p)) + " " +
Print(sizeof(p)) + "-byte object "));
char (Foo::*p2)(int n) = &Foo::MyVirtualMethod;
EXPECT_TRUE(HasPrefix(
PrintByRef(p2),
"@" + PrintPointer(reinterpret_cast<const void*>(&p2)) + " " +
Print(sizeof(p2)) + "-byte object "));
}
// Tests that the universal printer prints a member variable pointer
// passed by reference.
TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
int (Foo::*p) = &Foo::value; // NOLINT
EXPECT_TRUE(HasPrefix(
PrintByRef(p),
"@" + PrintPointer(&p) + " " + Print(sizeof(p)) + "-byte object "));
}
TEST(PrintToStringTest, WorksForScalar) {
EXPECT_EQ("123", PrintToString(123));
}
TEST(PrintToStringTest, WorksForPointerToConstChar) {
const char* p = "hello";
EXPECT_EQ("\"hello\"", PrintToString(p));
}
TEST(PrintToStringTest, WorksForPointerToNonConstChar) {
char s[] = "hello";
char* p = s;
EXPECT_EQ("\"hello\"", PrintToString(p));
}
TEST(PrintToStringTest, WorksForArray) {
int n[3] = { 1, 2, 3 };
EXPECT_EQ("{ 1, 2, 3 }", PrintToString(n));
}
TEST(UniversalTersePrintTest, WorksForNonReference) {
::std::stringstream ss;
UniversalTersePrint(123, &ss);
EXPECT_EQ("123", ss.str());
}
TEST(UniversalTersePrintTest, WorksForReference) {
const int& n = 123;
::std::stringstream ss;
UniversalTersePrint(n, &ss);
EXPECT_EQ("123", ss.str());
}
TEST(UniversalTersePrintTest, WorksForCString) {
const char* s1 = "abc";
::std::stringstream ss1;
UniversalTersePrint(s1, &ss1);
EXPECT_EQ("\"abc\"", ss1.str());
char* s2 = const_cast<char*>(s1);
::std::stringstream ss2;
UniversalTersePrint(s2, &ss2);
EXPECT_EQ("\"abc\"", ss2.str());
const char* s3 = NULL;
::std::stringstream ss3;
UniversalTersePrint(s3, &ss3);
EXPECT_EQ("NULL", ss3.str());
}
TEST(UniversalPrintTest, WorksForNonReference) {
::std::stringstream ss;
UniversalPrint(123, &ss);
EXPECT_EQ("123", ss.str());
}
TEST(UniversalPrintTest, WorksForReference) {
const int& n = 123;
::std::stringstream ss;
UniversalPrint(n, &ss);
EXPECT_EQ("123", ss.str());
}
TEST(UniversalPrintTest, WorksForCString) {
const char* s1 = "abc";
::std::stringstream ss1;
UniversalPrint(s1, &ss1);
EXPECT_EQ(PrintPointer(s1) + " pointing to \"abc\"", string(ss1.str()));
char* s2 = const_cast<char*>(s1);
::std::stringstream ss2;
UniversalPrint(s2, &ss2);
EXPECT_EQ(PrintPointer(s2) + " pointing to \"abc\"", string(ss2.str()));
const char* s3 = NULL;
::std::stringstream ss3;
UniversalPrint(s3, &ss3);
EXPECT_EQ("NULL", ss3.str());
}
#if GTEST_HAS_TR1_TUPLE
TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsEmptyTuple) {
Strings result = UniversalTersePrintTupleFieldsToStrings(make_tuple());
EXPECT_EQ(0u, result.size());
}
TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsOneTuple) {
Strings result = UniversalTersePrintTupleFieldsToStrings(make_tuple(1));
ASSERT_EQ(1u, result.size());
EXPECT_EQ("1", result[0]);
}
TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsTwoTuple) {
Strings result = UniversalTersePrintTupleFieldsToStrings(make_tuple(1, 'a'));
ASSERT_EQ(2u, result.size());
EXPECT_EQ("1", result[0]);
EXPECT_EQ("'a' (97)", result[1]);
}
TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsTersely) {
const int n = 1;
Strings result = UniversalTersePrintTupleFieldsToStrings(
tuple<const int&, const char*>(n, "a"));
ASSERT_EQ(2u, result.size());
EXPECT_EQ("1", result[0]);
EXPECT_EQ("\"a\"", result[1]);
}
#endif // GTEST_HAS_TR1_TUPLE
} // namespace gtest_printers_test
} // namespace testing
...@@ -132,23 +132,28 @@ using testing::Message; ...@@ -132,23 +132,28 @@ using testing::Message;
using testing::ScopedFakeTestPartResultReporter; using testing::ScopedFakeTestPartResultReporter;
using testing::StaticAssertTypeEq; using testing::StaticAssertTypeEq;
using testing::Test; using testing::Test;
using testing::TestEventListeners;
using testing::TestCase; using testing::TestCase;
using testing::TestEventListeners;
using testing::TestPartResult; using testing::TestPartResult;
using testing::TestPartResultArray; using testing::TestPartResultArray;
using testing::TestProperty; using testing::TestProperty;
using testing::TestResult; using testing::TestResult;
using testing::UnitTest; using testing::UnitTest;
using testing::kMaxStackTraceDepth; using testing::kMaxStackTraceDepth;
using testing::internal::AddReference;
using testing::internal::AlwaysFalse; using testing::internal::AlwaysFalse;
using testing::internal::AlwaysTrue; using testing::internal::AlwaysTrue;
using testing::internal::AppendUserMessage; using testing::internal::AppendUserMessage;
using testing::internal::ArrayAwareFind;
using testing::internal::ArrayEq;
using testing::internal::CodePointToUtf8; using testing::internal::CodePointToUtf8;
using testing::internal::CompileAssertTypesEqual;
using testing::internal::CopyArray;
using testing::internal::CountIf; using testing::internal::CountIf;
using testing::internal::EqFailure; using testing::internal::EqFailure;
using testing::internal::FloatingPoint; using testing::internal::FloatingPoint;
using testing::internal::FormatTimeInMillisAsSeconds;
using testing::internal::ForEach; using testing::internal::ForEach;
using testing::internal::FormatTimeInMillisAsSeconds;
using testing::internal::GTestFlagSaver; using testing::internal::GTestFlagSaver;
using testing::internal::GetCurrentOsStackTraceExceptTop; using testing::internal::GetCurrentOsStackTraceExceptTop;
using testing::internal::GetElementOr; using testing::internal::GetElementOr;
...@@ -157,9 +162,17 @@ using testing::internal::GetRandomSeedFromFlag; ...@@ -157,9 +162,17 @@ using testing::internal::GetRandomSeedFromFlag;
using testing::internal::GetTestTypeId; using testing::internal::GetTestTypeId;
using testing::internal::GetTypeId; using testing::internal::GetTypeId;
using testing::internal::GetUnitTestImpl; using testing::internal::GetUnitTestImpl;
using testing::internal::ImplicitlyConvertible;
using testing::internal::Int32; using testing::internal::Int32;
using testing::internal::Int32FromEnvOrDie; 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::ParseInt32Flag;
using testing::internal::RemoveConst;
using testing::internal::RemoveReference;
using testing::internal::ShouldRunTestOnShard; using testing::internal::ShouldRunTestOnShard;
using testing::internal::ShouldShard; using testing::internal::ShouldShard;
using testing::internal::ShouldUseColor; using testing::internal::ShouldUseColor;
...@@ -171,7 +184,9 @@ using testing::internal::TestEventListenersAccessor; ...@@ -171,7 +184,9 @@ using testing::internal::TestEventListenersAccessor;
using testing::internal::TestResultAccessor; using testing::internal::TestResultAccessor;
using testing::internal::UInt32; using testing::internal::UInt32;
using testing::internal::WideStringToUtf8; using testing::internal::WideStringToUtf8;
using testing::internal::kCopy;
using testing::internal::kMaxRandomSeed; using testing::internal::kMaxRandomSeed;
using testing::internal::kReference;
using testing::internal::kTestTypeIdInGoogleTest; using testing::internal::kTestTypeIdInGoogleTest;
using testing::internal::scoped_ptr; using testing::internal::scoped_ptr;
...@@ -184,6 +199,10 @@ using testing::internal::GetCapturedStdout; ...@@ -184,6 +199,10 @@ using testing::internal::GetCapturedStdout;
using testing::internal::ThreadWithParam; using testing::internal::ThreadWithParam;
#endif #endif
#if GTEST_HAS_PROTOBUF_
using ::testing::internal::TestMessage;
#endif // GTEST_HAS_PROTOBUF_
class TestingVector : public std::vector<int> { class TestingVector : public std::vector<int> {
}; };
...@@ -6725,3 +6744,319 @@ GTEST_TEST(AlternativeNameTest, Works) { // GTEST_TEST is the same as TEST. ...@@ -6725,3 +6744,319 @@ GTEST_TEST(AlternativeNameTest, Works) { // GTEST_TEST is the same as TEST.
EXPECT_FATAL_FAILURE(GTEST_FAIL() << "An expected failure", EXPECT_FATAL_FAILURE(GTEST_FAIL() << "An expected failure",
"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());
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment