Compare commits
76
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9d6f5e0ed | ||
|
|
97c452823c | ||
|
|
1b71f0b272 | ||
|
|
509b5339e9 | ||
|
|
eddd9e85a8 | ||
|
|
d21c142eb8 | ||
|
|
1e908873eb | ||
|
|
b9a7cead1c | ||
|
|
3569c3c86d | ||
|
|
2429dfc641 | ||
|
|
b2c1ee6d84 | ||
|
|
2346d25784 | ||
|
|
92344b762a | ||
|
|
17e4860871 | ||
|
|
e9f093ae15 | ||
|
|
75e2713e45 | ||
|
|
9f0824b0a6 | ||
|
|
90030d74c8 | ||
|
|
06d04c0945 | ||
|
|
a6978ecb4c | ||
|
|
a2534cb7a5 | ||
|
|
40604f891e | ||
|
|
79e11d7c7d | ||
|
|
f3feb338ef | ||
|
|
1ec9268dfd | ||
|
|
83589cca34 | ||
|
|
542b41e5d0 | ||
|
|
12a92c26fc | ||
|
|
0928f00c6b | ||
|
|
172b233a04 | ||
|
|
fe78760959 | ||
|
|
70eceaf8e7 | ||
|
|
c85a77a6ab | ||
|
|
4f874c187b | ||
|
|
6baed3c117 | ||
|
|
4879aac749 | ||
|
|
0d27868d0f | ||
|
|
3bef459eac | ||
|
|
dd280cfa8d | ||
|
|
6f50ccf32c | ||
|
|
9d965bbeef | ||
|
|
cfcbc298cd | ||
|
|
8d37331056 | ||
|
|
81e1cc73c8 | ||
|
|
fd6f2a8a4b | ||
|
|
27a65a9d67 | ||
|
|
e92ccedad9 | ||
|
|
ef37aa4074 | ||
|
|
276f4019c0 | ||
|
|
edbcd6294e | ||
|
|
c73d024193 | ||
|
|
38efa38f40 | ||
|
|
1d6df4be08 | ||
|
|
4d004650c9 | ||
|
|
2426542402 | ||
|
|
7b0c8dd3a9 | ||
|
|
940ce8a210 | ||
|
|
a3dd9d97c5 | ||
|
|
88e97c822c | ||
|
|
075b76bb96 | ||
|
|
cca227fe75 | ||
|
|
d56773b492 | ||
|
|
3508784108 | ||
|
|
44bafcb62d | ||
|
|
891b3716c4 | ||
|
|
2e075a7f60 | ||
|
|
b6fe6899be | ||
|
|
bf26ca01f2 | ||
|
|
24ccb2c3e0 | ||
|
|
b99c9eceab | ||
|
|
bcf926ec65 | ||
|
|
7e13e0f5dd | ||
|
|
edba5d808c | ||
|
|
6bfc4b2bd3 | ||
|
|
bad778caa3 | ||
|
|
060804deb8 |
@@ -1,3 +1,25 @@
|
||||
Changes for 1.5.0:
|
||||
|
||||
* New feature: assertions can be safely called in multiple threads
|
||||
where the pthreads library is available.
|
||||
* New feature: predicates used inside EXPECT_TRUE() and friends
|
||||
can now generate custom failure messages.
|
||||
* New feature: Google Test can now be compiled as a DLL.
|
||||
* New feature: fused source files are included.
|
||||
* New feature: prints help when encountering unrecognized Google Test flags.
|
||||
* Experimental feature: CMake build script (requires CMake 2.6.4+).
|
||||
* Experimental feature: the Pump script for meta programming.
|
||||
* double values streamed to an assertion are printed with enough precision
|
||||
to differentiate any two different values.
|
||||
* Google Test now works on Solaris and AIX.
|
||||
* Build and test script improvements.
|
||||
* Bug fixes and implementation clean-ups.
|
||||
|
||||
Potentially breaking changes:
|
||||
|
||||
* Stopped supporting VC++ 7.1 with exceptions disabled.
|
||||
* Dropped support for 'make install'.
|
||||
|
||||
Changes for 1.4.0:
|
||||
|
||||
* New feature: the event listener API
|
||||
|
||||
+384
@@ -0,0 +1,384 @@
|
||||
########################################################################
|
||||
# Experimental CMake build script for Google Test.
|
||||
#
|
||||
# Consider this a prototype. It will change drastically. For now,
|
||||
# this is only for people on the cutting edge.
|
||||
#
|
||||
# To run the tests for Google Test itself on Linux, use 'make test' or
|
||||
# ctest. You can select which tests to run using 'ctest -R regex'.
|
||||
# For more options, run 'ctest --help'.
|
||||
|
||||
# For hermetic builds, we may need to tell CMake to use compiler in a
|
||||
# specific location.
|
||||
if (gtest_compiler)
|
||||
include(CMakeForceCompiler)
|
||||
cmake_force_c_compiler("${gtest_compiler}" "")
|
||||
cmake_force_cxx_compiler("${gtest_compiler}" "")
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Project-wide settings
|
||||
|
||||
# Name of the project.
|
||||
#
|
||||
# CMake files in this project can refer to the root source directory
|
||||
# as ${gtest_SOURCE_DIR} and to the root binary directory as
|
||||
# ${gtest_BINARY_DIR}.
|
||||
# Language "C" is required for find_package(Threads).
|
||||
project(gtest CXX C)
|
||||
cmake_minimum_required(VERSION 2.6.4)
|
||||
|
||||
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)
|
||||
# In hermetic build environments, tests may not have access to MS runtime
|
||||
# DLLs, so this replaces /MD (CRT libraries in DLLs) with /MT (static CRT
|
||||
# libraries).
|
||||
string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
|
||||
# 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.
|
||||
include_directories(
|
||||
${gtest_SOURCE_DIR}/include
|
||||
${gtest_SOURCE_DIR})
|
||||
|
||||
# Where the gtest libraries can be found.
|
||||
link_directories(
|
||||
${gtest_BINARY_DIR}/src)
|
||||
|
||||
# Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
|
||||
find_package(Threads)
|
||||
|
||||
# Defines the compiler/linker flags used to build gtest. You can
|
||||
# tweak these definitions to suit your need. A variable's value is
|
||||
# empty before it's explicitly assigned to.
|
||||
|
||||
if (MSVC)
|
||||
# Newlines inside flags variables break CMake's NMake generator.
|
||||
set(cxx_base_flags "-GS -W4 -WX -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 (CMAKE_USE_PTHREADS_INIT)
|
||||
target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(cxx_static_library name cxx_flags)
|
||||
cxx_library_with_type(${name} STATIC "${cxx_flags}" ${ARGN})
|
||||
endfunction()
|
||||
|
||||
function(cxx_shared_library name cxx_flags)
|
||||
cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
|
||||
endfunction()
|
||||
|
||||
function(cxx_library name cxx_flags)
|
||||
# TODO(vladl@google.com): Make static/shared a user option.
|
||||
cxx_static_library(${name} "${cxx_flags}" ${ARGN})
|
||||
endfunction()
|
||||
|
||||
# Static versions of 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 aggressive about warnings.
|
||||
cxx_static_library(gtest "${cxx_strict}" src/gtest-all.cc)
|
||||
cxx_static_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
|
||||
target_link_libraries(gtest_main gtest)
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Samples on how to link user tests with gtest or gtest_main.
|
||||
#
|
||||
# They are not built by default. To build them, set the
|
||||
# build_gtest_samples option to ON. You can do it by running ccmake
|
||||
# or specifying the -Dbuild_gtest_samples=ON flag when running cmake.
|
||||
|
||||
option(build_gtest_samples "Build gtest's sample programs." OFF)
|
||||
|
||||
# cxx_executable_with_flags(name cxx_flags lib srcs...)
|
||||
#
|
||||
# creates a named C++ executable that depends on the given library and
|
||||
# is built from the given source files with the given compiler flags.
|
||||
function(cxx_executable_with_flags name cxx_flags lib)
|
||||
add_executable(${name} ${ARGN})
|
||||
if (cxx_flags)
|
||||
set_target_properties(${name}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "${cxx_flags}")
|
||||
endif()
|
||||
target_link_libraries(${name} ${lib})
|
||||
endfunction()
|
||||
|
||||
# cxx_executable(name dir lib srcs...)
|
||||
#
|
||||
# creates a named target that depends on the given lib and is built
|
||||
# from the given source files. dir/name.cc is implicitly included in
|
||||
# the source file list.
|
||||
function(cxx_executable name dir lib)
|
||||
cxx_executable_with_flags(
|
||||
${name} "${cxx_default}" ${lib} "${dir}/${name}.cc" ${ARGN})
|
||||
endfunction()
|
||||
|
||||
if (build_gtest_samples)
|
||||
cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
|
||||
cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
|
||||
cxx_executable(sample3_unittest samples gtest_main)
|
||||
cxx_executable(sample4_unittest samples gtest_main samples/sample4.cc)
|
||||
cxx_executable(sample5_unittest samples gtest_main samples/sample1.cc)
|
||||
cxx_executable(sample6_unittest samples gtest_main)
|
||||
cxx_executable(sample7_unittest samples gtest_main)
|
||||
cxx_executable(sample8_unittest samples gtest_main)
|
||||
cxx_executable(sample9_unittest samples gtest)
|
||||
cxx_executable(sample10_unittest samples gtest)
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Google Test's own tests.
|
||||
#
|
||||
# You can skip this section if you aren't interested in testing
|
||||
# Google Test itself.
|
||||
#
|
||||
# Most of the tests are not built by default. To build them, set the
|
||||
# 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.
|
||||
|
||||
option(build_all_gtest_tests "Build all of gtest's own tests." OFF)
|
||||
|
||||
# This must be set in the root directory for the tests to be run by
|
||||
# 'make test' or ctest.
|
||||
enable_testing()
|
||||
|
||||
# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
|
||||
find_package(PythonInterp)
|
||||
|
||||
############################################################
|
||||
# C++ tests built with standard compiler flags.
|
||||
|
||||
# cxx_test_with_flags(name cxx_flags libs srcs...)
|
||||
#
|
||||
# creates a named C++ test that depends on the given libs and is built
|
||||
# from the given source files with the given compiler flags.
|
||||
function(cxx_test_with_flags name cxx_flags libs)
|
||||
add_executable(${name} ${ARGN})
|
||||
set_target_properties(${name}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "${cxx_flags}")
|
||||
# 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()
|
||||
add_test(${name} ${name})
|
||||
endfunction()
|
||||
|
||||
# cxx_test(name libs srcs...)
|
||||
#
|
||||
# creates a named test target that depends on the given libs and is
|
||||
# built from the given source files. Unlike cxx_test_with_flags,
|
||||
# test/name.cc is already implicitly included in the source file list.
|
||||
function(cxx_test name libs)
|
||||
cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
|
||||
"test/${name}.cc" ${ARGN})
|
||||
endfunction()
|
||||
|
||||
cxx_test(gtest_unittest gtest_main)
|
||||
|
||||
if (build_all_gtest_tests)
|
||||
cxx_test(gtest-death-test_test gtest_main)
|
||||
cxx_test(gtest_environment_test gtest)
|
||||
cxx_test(gtest-filepath_test gtest_main)
|
||||
cxx_test(gtest-linked_ptr_test gtest_main)
|
||||
cxx_test(gtest-listener_test gtest_main)
|
||||
cxx_test(gtest_main_unittest gtest_main)
|
||||
cxx_test(gtest-message_test gtest_main)
|
||||
cxx_test(gtest_no_test_unittest gtest)
|
||||
cxx_test(gtest-options_test gtest_main)
|
||||
cxx_test(gtest-param-test_test gtest
|
||||
test/gtest-param-test2_test.cc)
|
||||
cxx_test(gtest-port_test gtest_main)
|
||||
cxx_test(gtest_pred_impl_unittest gtest_main)
|
||||
cxx_test(gtest_prod_test gtest_main
|
||||
test/production.cc)
|
||||
cxx_test(gtest_repeat_test gtest)
|
||||
cxx_test(gtest_sole_header_test gtest_main)
|
||||
cxx_test(gtest_stress_test gtest)
|
||||
cxx_test(gtest-test-part_test gtest_main)
|
||||
cxx_test(gtest_throw_on_failure_ex_test gtest)
|
||||
cxx_test(gtest-typed-test_test gtest_main
|
||||
test/gtest-typed-test2_test.cc)
|
||||
cxx_test(gtest-unittest-api_test gtest)
|
||||
endif()
|
||||
|
||||
############################################################
|
||||
# C++ tests built with non-standard compiler flags.
|
||||
|
||||
if (build_all_gtest_tests)
|
||||
cxx_library(gtest_no_exception "${cxx_no_exception}"
|
||||
src/gtest-all.cc)
|
||||
cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
|
||||
src/gtest-all.cc src/gtest_main.cc)
|
||||
|
||||
cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
|
||||
gtest_main_no_rtti test/gtest_unittest.cc)
|
||||
|
||||
set(cxx_use_shared_gtest "${cxx_default} -DGTEST_LINKED_AS_SHARED_LIBRARY=1")
|
||||
set(cxx_build_shared_gtest "${cxx_default} -DGTEST_CREATE_SHARED_LIBRARY=1")
|
||||
if (MSVC)
|
||||
# Disables the "class 'X' needs to have dll-interface to be used
|
||||
# by clients of class 'Y'" warning. This particularly concerns generic
|
||||
# classes like vector that MS doesn't mark as exported.
|
||||
set(cxx_use_shared_gtest "${cxx_use_shared_gtest} -wd4251")
|
||||
set(cxx_build_shared_gtest "${cxx_build_shared_gtest} -wd4251")
|
||||
endif()
|
||||
|
||||
cxx_shared_library(gtest_dll "${cxx_build_shared_gtest}"
|
||||
src/gtest-all.cc)
|
||||
|
||||
# TODO(vladl): This and the next tests may not run in the hermetic
|
||||
# environment on Windows. Re-evaluate and possibly make them
|
||||
# platform-conditional after implementing hermetic builds.
|
||||
cxx_executable_with_flags(gtest_dll_test_ "${cxx_use_shared_gtest}"
|
||||
gtest_dll test/gtest_all_test.cc)
|
||||
|
||||
if (NOT(MSVC AND (MSVC_VERSION EQUAL 1600)))
|
||||
# The C++ Standard specifies tuple_element<int, class>.
|
||||
# Yet MSVC 10's <utility> declares tuple_element<size_t, class>.
|
||||
# That declaration conflicts with our own standard-conforming
|
||||
# tuple implementation. Therefore using our own tuple with
|
||||
# MSVC 10 doesn't compile.
|
||||
cxx_library(gtest_main_use_own_tuple "${cxx_use_own_tuple}"
|
||||
src/gtest-all.cc src/gtest_main.cc)
|
||||
|
||||
cxx_test_with_flags(gtest-tuple_test "${cxx_use_own_tuple}"
|
||||
gtest_main_use_own_tuple test/gtest-tuple_test.cc)
|
||||
|
||||
cxx_test_with_flags(gtest_use_own_tuple_test "${cxx_use_own_tuple}"
|
||||
gtest_main_use_own_tuple
|
||||
test/gtest-param-test_test.cc test/gtest-param-test2_test.cc)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
############################################################
|
||||
# Python tests.
|
||||
|
||||
# py_test(name)
|
||||
#
|
||||
# creates a Python test with the given name whose main module is in
|
||||
# test/name.py. It does nothing if Python is not installed.
|
||||
function(py_test name)
|
||||
if (PYTHONINTERP_FOUND)
|
||||
# ${gtest_BINARY_DIR} is known at configuration time, so we can
|
||||
# directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
|
||||
# only at ctest runtime (by calling ctest -c <Configuration>), so
|
||||
# we have to escape $ to delay variable substitution here.
|
||||
add_test(${name}
|
||||
${PYTHON_EXECUTABLE} ${gtest_SOURCE_DIR}/test/${name}.py
|
||||
--gtest_build_dir=${gtest_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if (build_all_gtest_tests)
|
||||
cxx_executable(gtest_break_on_failure_unittest_ test gtest)
|
||||
py_test(gtest_break_on_failure_unittest)
|
||||
|
||||
cxx_executable(gtest_color_test_ test gtest)
|
||||
py_test(gtest_color_test)
|
||||
|
||||
cxx_executable(gtest_env_var_test_ test gtest)
|
||||
py_test(gtest_env_var_test)
|
||||
|
||||
cxx_executable(gtest_filter_unittest_ test gtest)
|
||||
py_test(gtest_filter_unittest)
|
||||
|
||||
cxx_executable(gtest_help_test_ test gtest_main)
|
||||
py_test(gtest_help_test)
|
||||
|
||||
cxx_executable(gtest_list_tests_unittest_ test gtest)
|
||||
py_test(gtest_list_tests_unittest)
|
||||
|
||||
cxx_executable(gtest_output_test_ test gtest)
|
||||
py_test(gtest_output_test)
|
||||
|
||||
cxx_executable(gtest_shuffle_test_ test gtest)
|
||||
py_test(gtest_shuffle_test)
|
||||
|
||||
cxx_executable(gtest_throw_on_failure_test_ test gtest_no_exception)
|
||||
set_target_properties(gtest_throw_on_failure_test_
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "${cxx_no_exception}")
|
||||
py_test(gtest_throw_on_failure_test)
|
||||
|
||||
cxx_executable(gtest_uninitialized_test_ test gtest)
|
||||
py_test(gtest_uninitialized_test)
|
||||
|
||||
cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
|
||||
cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
|
||||
py_test(gtest_xml_outfiles_test)
|
||||
|
||||
cxx_executable(gtest_xml_output_unittest_ test gtest)
|
||||
py_test(gtest_xml_output_unittest)
|
||||
endif()
|
||||
@@ -11,13 +11,16 @@ Chris Prince <cprince@google.com>
|
||||
Chris Taylor <taylorc@google.com>
|
||||
Dan Egnor <egnor@google.com>
|
||||
Eric Roman <eroman@chromium.org>
|
||||
Hady Zalek <hady.zalek@gmail.com>
|
||||
Jeffrey Yasskin <jyasskin@google.com>
|
||||
Jói Sigurðsson <joi@google.com>
|
||||
Keir Mierle <mierle@gmail.com>
|
||||
Keith Ray <keith.ray@gmail.com>
|
||||
Kenton Varda <kenton@google.com>
|
||||
Manuel Klimek <klimek@google.com>
|
||||
Markus Heule <markus.heule@gmail.com>
|
||||
Mika Raento <mikie@iki.fi>
|
||||
Miklós Fazekas <mfazekas@szemafor.com>
|
||||
Patrick Hanna <phanna@google.com>
|
||||
Patrick Riley <pfr@google.com>
|
||||
Peter Kaminski <piotrk@google.com>
|
||||
|
||||
+145
-302
@@ -1,7 +1,5 @@
|
||||
# Automake file
|
||||
|
||||
# TODO(chandlerc@google.com): automate the generation of *.h from *.h.pump.
|
||||
|
||||
# Nonstandard package files for distribution
|
||||
EXTRA_DIST = \
|
||||
CHANGES \
|
||||
@@ -11,13 +9,107 @@ EXTRA_DIST = \
|
||||
include/gtest/internal/gtest-type-util.h.pump \
|
||||
include/gtest/internal/gtest-param-util-generated.h.pump \
|
||||
make/Makefile \
|
||||
scons/SConscript \
|
||||
scons/SConstruct \
|
||||
scons/SConstruct.common \
|
||||
scripts/fuse_gtest_files.py \
|
||||
scripts/gen_gtest_pred_impl.py \
|
||||
scripts/test/Makefile \
|
||||
test/gtest_all_test.cc
|
||||
scripts/pump.py \
|
||||
scripts/test/Makefile
|
||||
|
||||
# gtest source files that we don't compile directly. They are
|
||||
# #included by gtest-all.cc.
|
||||
GTEST_SRC = \
|
||||
src/gtest.cc \
|
||||
src/gtest-death-test.cc \
|
||||
src/gtest-filepath.cc \
|
||||
src/gtest-internal-inl.h \
|
||||
src/gtest-port.cc \
|
||||
src/gtest-test-part.cc \
|
||||
src/gtest-typed-test.cc
|
||||
|
||||
EXTRA_DIST += $(GTEST_SRC)
|
||||
|
||||
# Sample files that we don't compile.
|
||||
EXTRA_DIST += \
|
||||
samples/prime_tables.h \
|
||||
samples/sample2_unittest.cc \
|
||||
samples/sample3_unittest.cc \
|
||||
samples/sample4_unittest.cc \
|
||||
samples/sample5_unittest.cc \
|
||||
samples/sample6_unittest.cc \
|
||||
samples/sample7_unittest.cc \
|
||||
samples/sample8_unittest.cc \
|
||||
samples/sample9_unittest.cc
|
||||
|
||||
# C++ test files that we don't compile directly.
|
||||
EXTRA_DIST += \
|
||||
test/gtest-death-test_test.cc \
|
||||
test/gtest_environment_test.cc \
|
||||
test/gtest-filepath_test.cc \
|
||||
test/gtest-linked_ptr_test.cc \
|
||||
test/gtest-message_test.cc \
|
||||
test/gtest_no_test_unittest.cc \
|
||||
test/gtest-options_test.cc \
|
||||
test/gtest-param-test_test.cc \
|
||||
test/gtest-param-test2_test.cc \
|
||||
test/gtest-param-test_test.h \
|
||||
test/gtest-port_test.cc \
|
||||
test/gtest_pred_impl_unittest.cc \
|
||||
test/gtest_prod_test.cc \
|
||||
test/production.cc \
|
||||
test/production.h \
|
||||
test/gtest_repeat_test.cc \
|
||||
test/gtest_sole_header_test.cc \
|
||||
test/gtest_stress_test.cc \
|
||||
test/gtest-test-part_test.cc \
|
||||
test/gtest_throw_on_failure_ex_test.cc \
|
||||
test/gtest-typed-test_test.cc \
|
||||
test/gtest-typed-test2_test.cc \
|
||||
test/gtest-typed-test_test.h \
|
||||
test/gtest_unittest.cc \
|
||||
test/gtest-unittest-api_test.cc \
|
||||
test/gtest-listener_test.cc \
|
||||
test/gtest_main_unittest.cc \
|
||||
test/gtest_unittest.cc \
|
||||
test/gtest-tuple_test.cc \
|
||||
test/gtest-param-test_test.cc \
|
||||
test/gtest-param-test2_test.cc \
|
||||
test/gtest_break_on_failure_unittest_.cc \
|
||||
test/gtest_color_test_.cc \
|
||||
test/gtest_env_var_test_.cc \
|
||||
test/gtest_filter_unittest_.cc \
|
||||
test/gtest_help_test_.cc \
|
||||
test/gtest_list_tests_unittest_.cc \
|
||||
test/gtest_output_test_.cc \
|
||||
test/gtest_shuffle_test_.cc \
|
||||
test/gtest_throw_on_failure_test_.cc \
|
||||
test/gtest_uninitialized_test_.cc \
|
||||
test/gtest_xml_outfile1_test_.cc \
|
||||
test/gtest_xml_outfile2_test_.cc \
|
||||
test/gtest_xml_output_unittest_.cc
|
||||
|
||||
# Python tests that we don't run.
|
||||
EXTRA_DIST += \
|
||||
test/gtest_test_utils.py \
|
||||
test/gtest_xml_test_utils.py \
|
||||
test/gtest_break_on_failure_unittest.py \
|
||||
test/gtest_color_test.py \
|
||||
test/gtest_env_var_test.py \
|
||||
test/gtest_filter_unittest.py \
|
||||
test/gtest_help_test.py \
|
||||
test/gtest_list_tests_unittest.py \
|
||||
test/gtest_output_test.py \
|
||||
test/gtest_output_test_golden_lin.txt \
|
||||
test/gtest_output_test_golden_win.txt \
|
||||
test/gtest_shuffle_test.py \
|
||||
test/gtest_throw_on_failure_test.py \
|
||||
test/gtest_uninitialized_test.py \
|
||||
test/gtest_xml_outfiles_test.py \
|
||||
test/gtest_xml_output_unittest.py \
|
||||
test/run_tests_util.py \
|
||||
test/run_tests_util_test.py
|
||||
|
||||
# CMake script
|
||||
EXTRA_DIST += \
|
||||
CMakeLists.txt
|
||||
|
||||
# MSVC project files
|
||||
EXTRA_DIST += \
|
||||
@@ -48,6 +140,7 @@ EXTRA_DIST += \
|
||||
# xcode sample files
|
||||
EXTRA_DIST += \
|
||||
xcode/Samples/FrameworkSample/Info.plist \
|
||||
xcode/Samples/FrameworkSample/runtests.sh \
|
||||
xcode/Samples/FrameworkSample/widget_test.cc \
|
||||
xcode/Samples/FrameworkSample/widget.cc \
|
||||
xcode/Samples/FrameworkSample/widget.h \
|
||||
@@ -62,11 +155,6 @@ EXTRA_DIST += \
|
||||
codegear/gtest_unittest.cbproj \
|
||||
codegear/gtest.groupproj
|
||||
|
||||
# TODO(wan@google.com): integrate scripts/gen_gtest_pred_impl.py into
|
||||
# the build system such that a user can specify the maximum predicate
|
||||
# arity here and have the script automatically generate the
|
||||
# corresponding .h and .cc files.
|
||||
|
||||
# Scripts and utilities
|
||||
bin_SCRIPTS = scripts/gtest-config
|
||||
CLEANFILES = $(bin_SCRIPTS)
|
||||
@@ -80,16 +168,18 @@ EXTRA_DIST += $(m4data_DATA)
|
||||
# directories.
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include
|
||||
|
||||
# Modifies compiler and linker flags for pthreads compatibility.
|
||||
if HAVE_PTHREADS
|
||||
AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1
|
||||
AM_LIBS = @PTHREAD_LIBS@
|
||||
else
|
||||
AM_CXXFLAGS = -DGTEST_HAS_PTHREAD=0
|
||||
endif
|
||||
|
||||
# Build rules for libraries.
|
||||
lib_LTLIBRARIES = lib/libgtest.la lib/libgtest_main.la
|
||||
|
||||
lib_libgtest_la_SOURCES = src/gtest.cc \
|
||||
src/gtest-death-test.cc \
|
||||
src/gtest-filepath.cc \
|
||||
src/gtest-internal-inl.h \
|
||||
src/gtest-port.cc \
|
||||
src/gtest-test-part.cc \
|
||||
src/gtest-typed-test.cc
|
||||
lib_libgtest_la_SOURCES = src/gtest-all.cc
|
||||
|
||||
pkginclude_HEADERS = include/gtest/gtest.h \
|
||||
include/gtest/gtest-death-test.h \
|
||||
@@ -139,303 +229,56 @@ TESTS_ENVIRONMENT = GTEST_SOURCE_DIR="$(srcdir)/test" \
|
||||
GTEST_BUILD_DIR="$(top_builddir)/test"
|
||||
check_PROGRAMS=
|
||||
|
||||
# A simple sample on using gtest.
|
||||
TESTS += samples/sample1_unittest
|
||||
check_PROGRAMS += samples/sample1_unittest
|
||||
samples_sample1_unittest_SOURCES = samples/sample1_unittest.cc
|
||||
samples_sample1_unittest_LDADD = lib/libgtest_main.la \
|
||||
samples/libsamples.la
|
||||
|
||||
TESTS += samples/sample2_unittest
|
||||
check_PROGRAMS += samples/sample2_unittest
|
||||
samples_sample2_unittest_SOURCES = samples/sample2_unittest.cc
|
||||
samples_sample2_unittest_LDADD = lib/libgtest_main.la \
|
||||
samples/libsamples.la
|
||||
|
||||
TESTS += samples/sample3_unittest
|
||||
check_PROGRAMS += samples/sample3_unittest
|
||||
samples_sample3_unittest_SOURCES = samples/sample3_unittest.cc
|
||||
samples_sample3_unittest_LDADD = lib/libgtest_main.la \
|
||||
samples/libsamples.la
|
||||
|
||||
TESTS += samples/sample4_unittest
|
||||
check_PROGRAMS += samples/sample4_unittest
|
||||
samples_sample4_unittest_SOURCES = samples/sample4_unittest.cc
|
||||
samples_sample4_unittest_LDADD = lib/libgtest_main.la \
|
||||
samples/libsamples.la
|
||||
|
||||
TESTS += samples/sample5_unittest
|
||||
check_PROGRAMS += samples/sample5_unittest
|
||||
samples_sample5_unittest_SOURCES = samples/sample5_unittest.cc
|
||||
samples_sample5_unittest_LDADD = lib/libgtest_main.la \
|
||||
samples/libsamples.la
|
||||
|
||||
TESTS += samples/sample6_unittest
|
||||
check_PROGRAMS += samples/sample6_unittest
|
||||
samples_sample6_unittest_SOURCES = samples/prime_tables.h \
|
||||
samples/sample6_unittest.cc
|
||||
samples_sample6_unittest_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += samples/sample7_unittest
|
||||
check_PROGRAMS += samples/sample7_unittest
|
||||
samples_sample7_unittest_SOURCES = samples/prime_tables.h \
|
||||
samples/sample7_unittest.cc
|
||||
samples_sample7_unittest_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += samples/sample8_unittest
|
||||
check_PROGRAMS += samples/sample8_unittest
|
||||
samples_sample8_unittest_SOURCES = samples/prime_tables.h \
|
||||
samples/sample8_unittest.cc
|
||||
samples_sample8_unittest_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += samples/sample9_unittest
|
||||
check_PROGRAMS += samples/sample9_unittest
|
||||
samples_sample9_unittest_SOURCES = samples/sample9_unittest.cc
|
||||
samples_sample9_unittest_LDADD = lib/libgtest.la
|
||||
|
||||
# Another sample. It also verifies that libgtest works.
|
||||
TESTS += samples/sample10_unittest
|
||||
check_PROGRAMS += samples/sample10_unittest
|
||||
samples_sample10_unittest_SOURCES = samples/sample10_unittest.cc
|
||||
samples_sample10_unittest_LDADD = lib/libgtest.la
|
||||
|
||||
TESTS += test/gtest-death-test_test
|
||||
check_PROGRAMS += test/gtest-death-test_test
|
||||
test_gtest_death_test_test_SOURCES = test/gtest-death-test_test.cc
|
||||
test_gtest_death_test_test_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
|
||||
test_gtest_death_test_test_LDADD = $(PTHREAD_LIBS) $(PTHREAD_CFLAGS) \
|
||||
lib/libgtest_main.la
|
||||
# This tests most constructs of gtest and verifies that libgtest_main
|
||||
# works.
|
||||
TESTS += test/gtest_all_test
|
||||
check_PROGRAMS += test/gtest_all_test
|
||||
test_gtest_all_test_SOURCES = test/gtest_all_test.cc
|
||||
test_gtest_all_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest_environment_test
|
||||
check_PROGRAMS += test/gtest_environment_test
|
||||
test_gtest_environment_test_SOURCES = test/gtest_environment_test.cc
|
||||
test_gtest_environment_test_LDADD = lib/libgtest.la
|
||||
# Tests that fused gtest files compile and work.
|
||||
FUSED_GTEST_SRC = \
|
||||
fused-src/gtest/gtest-all.cc \
|
||||
fused-src/gtest/gtest_main.cc \
|
||||
fused-src/gtest/gtest.h
|
||||
|
||||
TESTS += test/gtest-filepath_test
|
||||
check_PROGRAMS += test/gtest-filepath_test
|
||||
test_gtest_filepath_test_SOURCES = test/gtest-filepath_test.cc
|
||||
test_gtest_filepath_test_LDADD = lib/libgtest_main.la
|
||||
TESTS += test/fused_gtest_test
|
||||
check_PROGRAMS += test/fused_gtest_test
|
||||
test_fused_gtest_test_SOURCES = $(FUSED_GTEST_SRC) \
|
||||
samples/sample1.cc samples/sample1_unittest.cc
|
||||
test_fused_gtest_test_CPPFLAGS = -I"$(srcdir)/fused-src"
|
||||
|
||||
TESTS += test/gtest-linked_ptr_test
|
||||
check_PROGRAMS += test/gtest-linked_ptr_test
|
||||
test_gtest_linked_ptr_test_SOURCES = test/gtest-linked_ptr_test.cc
|
||||
test_gtest_linked_ptr_test_LDADD = lib/libgtest_main.la
|
||||
# Build rules for putting fused Google Test files into the distribution
|
||||
# package. The user can also create those files by manually running
|
||||
# scripts/fuse_gtest_files.py.
|
||||
$(test_fused_gtest_test_SOURCES): fused-gtest
|
||||
|
||||
TESTS += test/gtest_main_unittest
|
||||
check_PROGRAMS += test/gtest_main_unittest
|
||||
test_gtest_main_unittest_SOURCES = test/gtest_main_unittest.cc
|
||||
test_gtest_main_unittest_LDADD = lib/libgtest_main.la
|
||||
fused-gtest: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \
|
||||
$(GTEST_SRC) src/gtest-all.cc src/gtest_main.cc \
|
||||
scripts/fuse_gtest_files.py
|
||||
mkdir -p "$(srcdir)/fused-src"
|
||||
chmod -R u+w "$(srcdir)/fused-src"
|
||||
rm -f "$(srcdir)/fused-src/gtest/gtest-all.cc"
|
||||
rm -f "$(srcdir)/fused-src/gtest/gtest.h"
|
||||
"$(srcdir)/scripts/fuse_gtest_files.py" "$(srcdir)/fused-src"
|
||||
cp -f "$(srcdir)/src/gtest_main.cc" "$(srcdir)/fused-src/gtest/"
|
||||
|
||||
TESTS += test/gtest-message_test
|
||||
check_PROGRAMS += test/gtest-message_test
|
||||
test_gtest_message_test_SOURCES = test/gtest-message_test.cc
|
||||
test_gtest_message_test_LDADD = lib/libgtest_main.la
|
||||
maintainer-clean-local:
|
||||
rm -rf "$(srcdir)/fused-src"
|
||||
|
||||
TESTS += test/gtest_no_test_unittest
|
||||
check_PROGRAMS += test/gtest_no_test_unittest
|
||||
test_gtest_no_test_unittest_SOURCES = test/gtest_no_test_unittest.cc
|
||||
test_gtest_no_test_unittest_LDADD = lib/libgtest.la
|
||||
|
||||
TESTS += test/gtest-options_test
|
||||
check_PROGRAMS += test/gtest-options_test
|
||||
test_gtest_options_test_SOURCES = test/gtest-options_test.cc
|
||||
test_gtest_options_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest-param-test_test
|
||||
check_PROGRAMS += test/gtest-param-test_test
|
||||
test_gtest_param_test_test_SOURCES = test/gtest-param-test_test.cc \
|
||||
test/gtest-param-test2_test.cc \
|
||||
test/gtest-param-test_test.h
|
||||
test_gtest_param_test_test_LDADD = lib/libgtest.la
|
||||
|
||||
TESTS += test/gtest-port_test
|
||||
check_PROGRAMS += test/gtest-port_test
|
||||
test_gtest_port_test_SOURCES = test/gtest-port_test.cc
|
||||
test_gtest_port_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest_pred_impl_unittest
|
||||
check_PROGRAMS += test/gtest_pred_impl_unittest
|
||||
test_gtest_pred_impl_unittest_SOURCES = test/gtest_pred_impl_unittest.cc
|
||||
test_gtest_pred_impl_unittest_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest_prod_test
|
||||
check_PROGRAMS += test/gtest_prod_test
|
||||
test_gtest_prod_test_SOURCES = test/gtest_prod_test.cc \
|
||||
test/production.cc \
|
||||
test/production.h
|
||||
test_gtest_prod_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest_repeat_test
|
||||
check_PROGRAMS += test/gtest_repeat_test
|
||||
test_gtest_repeat_test_SOURCES = test/gtest_repeat_test.cc
|
||||
test_gtest_repeat_test_LDADD = lib/libgtest.la
|
||||
|
||||
TESTS += test/gtest_sole_header_test
|
||||
check_PROGRAMS += test/gtest_sole_header_test
|
||||
test_gtest_sole_header_test_SOURCES = test/gtest_sole_header_test.cc
|
||||
test_gtest_sole_header_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest_stress_test
|
||||
check_PROGRAMS += test/gtest_stress_test
|
||||
test_gtest_stress_test_SOURCES = test/gtest_stress_test.cc
|
||||
test_gtest_stress_test_LDADD = lib/libgtest.la
|
||||
|
||||
TESTS += test/gtest-test-part_test
|
||||
check_PROGRAMS += test/gtest-test-part_test
|
||||
test_gtest_test_part_test_SOURCES = test/gtest-test-part_test.cc
|
||||
test_gtest_test_part_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest_throw_on_failure_ex_test
|
||||
check_PROGRAMS += test/gtest_throw_on_failure_ex_test
|
||||
test_gtest_throw_on_failure_ex_test_SOURCES = \
|
||||
test/gtest_throw_on_failure_ex_test.cc \
|
||||
src/gtest-all.cc
|
||||
test_gtest_throw_on_failure_ex_test_CXXFLAGS = $(AM_CXXFLAGS) -fexceptions
|
||||
|
||||
TESTS += test/gtest-typed-test_test
|
||||
check_PROGRAMS += test/gtest-typed-test_test
|
||||
test_gtest_typed_test_test_SOURCES = test/gtest-typed-test_test.cc \
|
||||
test/gtest-typed-test2_test.cc \
|
||||
test/gtest-typed-test_test.h
|
||||
test_gtest_typed_test_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest_unittest
|
||||
check_PROGRAMS += test/gtest_unittest
|
||||
test_gtest_unittest_SOURCES = test/gtest_unittest.cc
|
||||
test_gtest_unittest_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest-unittest-api_test
|
||||
check_PROGRAMS += test/gtest-unittest-api_test
|
||||
test_gtest_unittest_api_test_SOURCES = test/gtest-unittest-api_test.cc
|
||||
test_gtest_unittest_api_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
TESTS += test/gtest-listener_test
|
||||
check_PROGRAMS += test/gtest-listener_test
|
||||
test_gtest_listener_test_SOURCES = test/gtest-listener_test.cc
|
||||
test_gtest_listener_test_LDADD = lib/libgtest_main.la
|
||||
|
||||
# Verifies that Google Test works when RTTI is disabled.
|
||||
TESTS += test/gtest_no_rtti_test
|
||||
check_PROGRAMS += test/gtest_no_rtti_test
|
||||
test_gtest_no_rtti_test_SOURCES = test/gtest_unittest.cc \
|
||||
src/gtest-all.cc \
|
||||
src/gtest_main.cc
|
||||
test_gtest_no_rtti_test_CXXFLAGS = $(AM_CXXFLAGS) -fno-rtti -DGTEST_HAS_RTTI=0
|
||||
|
||||
# Verifies that Google Test's own TR1 tuple implementation works.
|
||||
TESTS += test/gtest-tuple_test
|
||||
check_PROGRAMS += test/gtest-tuple_test
|
||||
test_gtest_tuple_test_SOURCES = test/gtest-tuple_test.cc \
|
||||
src/gtest-all.cc \
|
||||
src/gtest_main.cc
|
||||
test_gtest_tuple_test_CXXFLAGS = $(AM_CXXFLAGS) -DGTEST_USE_OWN_TR1_TUPLE=1
|
||||
|
||||
# Verifies that Google Test's features that use its own TR1 tuple work.
|
||||
TESTS += test/gtest_use_own_tuple_test
|
||||
check_PROGRAMS += test/gtest_use_own_tuple_test
|
||||
test_gtest_use_own_tuple_test_SOURCES = test/gtest-param-test_test.cc \
|
||||
test/gtest-param-test2_test.cc \
|
||||
src/gtest-all.cc
|
||||
test_gtest_use_own_tuple_test_CXXFLAGS = \
|
||||
$(AM_CXXFLAGS) -DGTEST_USE_OWN_TR1_TUPLE=1
|
||||
|
||||
# The following tests depend on the presence of a Python installation and are
|
||||
# keyed off of it. TODO(chandlerc@google.com): While we currently only attempt
|
||||
# to build and execute these tests if Autoconf has found Python v2.4 on the
|
||||
# system, we don't use the PYTHON variable it specified as the valid
|
||||
# interpreter. The problem is that TESTS_ENVIRONMENT is a global variable, and
|
||||
# thus we cannot distinguish between C++ unit tests and Python unit tests.
|
||||
if HAVE_PYTHON
|
||||
check_SCRIPTS =
|
||||
|
||||
# These two Python modules are used by multiple Python tests below.
|
||||
check_SCRIPTS += test/gtest_test_utils.py \
|
||||
test/gtest_xml_test_utils.py
|
||||
|
||||
check_PROGRAMS += test/gtest_break_on_failure_unittest_
|
||||
test_gtest_break_on_failure_unittest__SOURCES = \
|
||||
test/gtest_break_on_failure_unittest_.cc
|
||||
test_gtest_break_on_failure_unittest__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_break_on_failure_unittest.py
|
||||
TESTS += test/gtest_break_on_failure_unittest.py
|
||||
|
||||
check_PROGRAMS += test/gtest_color_test_
|
||||
test_gtest_color_test__SOURCES = test/gtest_color_test_.cc
|
||||
test_gtest_color_test__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_color_test.py
|
||||
TESTS += test/gtest_color_test.py
|
||||
|
||||
check_PROGRAMS += test/gtest_env_var_test_
|
||||
test_gtest_env_var_test__SOURCES = test/gtest_env_var_test_.cc
|
||||
test_gtest_env_var_test__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_env_var_test.py
|
||||
TESTS += test/gtest_env_var_test.py
|
||||
|
||||
check_PROGRAMS += test/gtest_filter_unittest_
|
||||
test_gtest_filter_unittest__SOURCES = test/gtest_filter_unittest_.cc
|
||||
test_gtest_filter_unittest__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_filter_unittest.py
|
||||
TESTS += test/gtest_filter_unittest.py
|
||||
|
||||
check_PROGRAMS += test/gtest_help_test_
|
||||
test_gtest_help_test__SOURCES = test/gtest_help_test_.cc
|
||||
test_gtest_help_test__LDADD = lib/libgtest_main.la
|
||||
check_SCRIPTS += test/gtest_help_test.py
|
||||
TESTS += test/gtest_help_test.py
|
||||
|
||||
check_PROGRAMS += test/gtest_list_tests_unittest_
|
||||
test_gtest_list_tests_unittest__SOURCES = test/gtest_list_tests_unittest_.cc
|
||||
test_gtest_list_tests_unittest__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_list_tests_unittest.py
|
||||
TESTS += test/gtest_list_tests_unittest.py
|
||||
|
||||
check_PROGRAMS += test/gtest_output_test_
|
||||
test_gtest_output_test__SOURCES = test/gtest_output_test_.cc
|
||||
test_gtest_output_test__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_output_test.py
|
||||
EXTRA_DIST += test/gtest_output_test_golden_lin.txt \
|
||||
test/gtest_output_test_golden_win.txt
|
||||
TESTS += test/gtest_output_test.py
|
||||
|
||||
check_PROGRAMS += test/gtest_shuffle_test_
|
||||
test_gtest_shuffle_test__SOURCES = test/gtest_shuffle_test_.cc
|
||||
test_gtest_shuffle_test__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_shuffle_test.py
|
||||
TESTS += test/gtest_shuffle_test.py
|
||||
|
||||
check_PROGRAMS += test/gtest_throw_on_failure_test_
|
||||
test_gtest_throw_on_failure_test__SOURCES = \
|
||||
test/gtest_throw_on_failure_test_.cc \
|
||||
src/gtest-all.cc
|
||||
test_gtest_throw_on_failure_test__CXXFLAGS = $(AM_CXXFLAGS) -fno-exceptions
|
||||
check_SCRIPTS += test/gtest_throw_on_failure_test.py
|
||||
TESTS += test/gtest_throw_on_failure_test.py
|
||||
|
||||
check_PROGRAMS += test/gtest_uninitialized_test_
|
||||
test_gtest_uninitialized_test__SOURCES = test/gtest_uninitialized_test_.cc
|
||||
test_gtest_uninitialized_test__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_uninitialized_test.py
|
||||
TESTS += test/gtest_uninitialized_test.py
|
||||
|
||||
check_PROGRAMS += test/gtest_xml_outfile1_test_
|
||||
test_gtest_xml_outfile1_test__SOURCES = test/gtest_xml_outfile1_test_.cc
|
||||
test_gtest_xml_outfile1_test__LDADD = lib/libgtest_main.la
|
||||
check_PROGRAMS += test/gtest_xml_outfile2_test_
|
||||
test_gtest_xml_outfile2_test__SOURCES = test/gtest_xml_outfile2_test_.cc
|
||||
test_gtest_xml_outfile2_test__LDADD = lib/libgtest_main.la
|
||||
check_SCRIPTS += test/gtest_xml_outfiles_test.py
|
||||
TESTS += test/gtest_xml_outfiles_test.py
|
||||
|
||||
check_PROGRAMS += test/gtest_xml_output_unittest_
|
||||
test_gtest_xml_output_unittest__SOURCES = test/gtest_xml_output_unittest_.cc
|
||||
test_gtest_xml_output_unittest__LDADD = lib/libgtest.la
|
||||
check_SCRIPTS += test/gtest_xml_output_unittest.py
|
||||
TESTS += test/gtest_xml_output_unittest.py
|
||||
|
||||
# TODO(wan@google.com): make the build script compile and run the
|
||||
# negative-compilation tests. (The test/gtest_nc* files are unfinished
|
||||
# implementation of tests for verifying that certain kinds of misuse
|
||||
# of Google Test don't compile.)
|
||||
EXTRA_DIST += $(check_SCRIPTS) \
|
||||
test/gtest_nc.cc \
|
||||
test/gtest_nc_test.py
|
||||
|
||||
endif
|
||||
# Death tests may produce core dumps in the build directory. In case
|
||||
# this happens, clean them to keep distcleancheck happy.
|
||||
CLEANFILES += core
|
||||
|
||||
@@ -1,285 +1,151 @@
|
||||
Google C++ Testing Framework
|
||||
============================
|
||||
|
||||
http://code.google.com/p/googletest/
|
||||
|
||||
Overview
|
||||
--------
|
||||
Google's framework for writing C++ tests on a variety of platforms (Linux, Mac
|
||||
OS X, Windows, Windows CE, Symbian, and etc). Based on the xUnit architecture.
|
||||
Supports automatic test discovery, a rich set of assertions, user-defined
|
||||
assertions, death tests, fatal and non-fatal failures, various options for
|
||||
running the tests, and XML test report generation.
|
||||
|
||||
Please see the project page above for more information as well as mailing lists
|
||||
for questions, discussions, and development. There is also an IRC channel on
|
||||
OFTC (irc.oftc.net) #gtest available. Please join us!
|
||||
Google's framework for writing C++ tests on a variety of platforms
|
||||
(Linux, Mac OS X, Windows, Windows CE, Symbian, etc). Based on the
|
||||
xUnit architecture. Supports automatic test discovery, a rich set of
|
||||
assertions, user-defined assertions, death tests, fatal and non-fatal
|
||||
failures, various options for running the tests, and XML test report
|
||||
generation.
|
||||
|
||||
Please see the project page above for more information as well as the
|
||||
mailing list for questions, discussions, and development. There is
|
||||
also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please
|
||||
join us!
|
||||
|
||||
Requirements for End Users
|
||||
--------------------------
|
||||
|
||||
Requirements
|
||||
------------
|
||||
Google Test is designed to have fairly minimal requirements to build
|
||||
and use with your projects, but there are some. Currently, we support
|
||||
building Google Test on Linux, Windows, Mac OS X, and Cygwin. We will
|
||||
also make our best effort to support other platforms (e.g. Solaris and
|
||||
IBM z/OS). However, since core members of the Google Test project
|
||||
have no access to them, Google Test may have outstanding issues on
|
||||
these platforms. If you notice any problems on your platform, please
|
||||
notify googletestframework@googlegroups.com (patches for fixing them
|
||||
are even more welcome!).
|
||||
and use with your projects, but there are some. Currently, we support
|
||||
Linux, Windows, Mac OS X, and Cygwin. We will also make our best
|
||||
effort to support other platforms (e.g. Solaris, AIX, and z/OS).
|
||||
However, since core members of the Google Test project have no access
|
||||
to these platforms, Google Test may have outstanding issues there. If
|
||||
you notice any problems on your platform, please notify
|
||||
googletestframework@googlegroups.com. Patches for fixing them are
|
||||
even more welcome!
|
||||
|
||||
### Linux Requirements ###
|
||||
|
||||
These are the base requirements to build and use Google Test from a source
|
||||
package (as described below):
|
||||
* GNU-compatible Make or "gmake"
|
||||
* GNU-compatible Make or gmake
|
||||
* POSIX-standard shell
|
||||
* POSIX(-2) Regular Expressions (regex.h)
|
||||
* A C++98 standards compliant compiler
|
||||
|
||||
Furthermore, if you are building Google Test from a VCS Checkout (also
|
||||
described below), there are further requirements:
|
||||
* Automake version 1.9 or newer
|
||||
* Autoconf version 2.59 or newer
|
||||
* Libtool / Libtoolize
|
||||
* Python version 2.4 or newer
|
||||
* A C++98-standard-compliant compiler
|
||||
|
||||
### Windows Requirements ###
|
||||
* Microsoft Visual Studio 7.1 or newer
|
||||
|
||||
* Microsoft Visual C++ 7.1 or newer
|
||||
|
||||
### Cygwin Requirements ###
|
||||
|
||||
* Cygwin 1.5.25-14 or newer
|
||||
|
||||
### Mac OS X Requirements ###
|
||||
|
||||
* Mac OS X 10.4 Tiger or newer
|
||||
* Developer Tools Installed
|
||||
* Optional: Xcode 2.5 or later for univeral-binary framework; see note below.
|
||||
|
||||
Also, you'll need CMake 2.6.4 or higher if you want to build the
|
||||
samples using the provided CMake script, regardless of the platform.
|
||||
|
||||
Requirements for Contributors
|
||||
-----------------------------
|
||||
|
||||
We welcome patches. If you plan to contribute a patch, you need to
|
||||
build Google Test and its own tests from an SVN checkout (described
|
||||
below), which has further requirements:
|
||||
|
||||
* Python version 2.3 or newer (for running some of the tests and
|
||||
re-generating certain source files from templates)
|
||||
* CMake 2.6.4 or newer
|
||||
|
||||
Getting the Source
|
||||
------------------
|
||||
There are two primary ways of getting Google Test's source code: you can
|
||||
download a source release in your preferred archive format, or directly check
|
||||
out the source from a Version Control System (VCS, we use Google Code's
|
||||
Subversion hosting). The VCS checkout requires a few extra steps and some extra
|
||||
software packages on your system, but lets you track development, and make
|
||||
patches to contribute much more easily, so we highly encourage it.
|
||||
|
||||
### VCS Checkout: ###
|
||||
The first step is to select whether you want to check out the main line of
|
||||
development on Google Test, or one of the released branches. The former will be
|
||||
much more active and have the latest features, but the latter provides much
|
||||
more stability and predictability. Choose whichever fits your needs best, and
|
||||
proceed with the following Subversion commands:
|
||||
There are two primary ways of getting Google Test's source code: you
|
||||
can download a stable source release in your preferred archive format,
|
||||
or directly check out the source from our Subversion (SVN) repositary.
|
||||
The SVN checkout requires a few extra steps and some extra software
|
||||
packages on your system, but lets you track the latest development and
|
||||
make patches much more easily, so we highly encourage it.
|
||||
|
||||
svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
|
||||
### Source Package ###
|
||||
|
||||
or for a release version X.Y.*'s branch:
|
||||
Google Test is released in versioned source packages which can be
|
||||
downloaded from the download page [1]. Several different archive
|
||||
formats are provided, but the only difference is the tools used to
|
||||
manipulate them, and the size of the resulting file. Download
|
||||
whichever you are most comfortable with.
|
||||
|
||||
svn checkout http://googletest.googlecode.com/svn/branches/release-X.Y/ \
|
||||
gtest-X.Y-svn
|
||||
[1] http://code.google.com/p/googletest/downloads/list
|
||||
|
||||
Next you will need to prepare the GNU Autotools build system, if you
|
||||
are using Linux, Mac OS X, or Cygwin. Enter the target directory of
|
||||
the checkout command you used ('gtest-svn' or 'gtest-X.Y-svn' above)
|
||||
and proceed with the following command:
|
||||
|
||||
autoreconf -fvi
|
||||
|
||||
Once you have completed this step, you are ready to build the library. Note
|
||||
that you should only need to complete this step once. The subsequent `make'
|
||||
invocations will automatically re-generate the bits of the build system that
|
||||
need to be changed.
|
||||
|
||||
If your system uses older versions of the autotools, the above command will
|
||||
fail. You may need to explicitly specify a version to use. For instance, if you
|
||||
have both GNU Automake 1.4 and 1.9 installed and `automake' would invoke the
|
||||
1.4, use instead:
|
||||
|
||||
AUTOMAKE=automake-1.9 ACLOCAL=aclocal-1.9 autoreconf -fvi
|
||||
|
||||
Make sure you're using the same version of automake and aclocal.
|
||||
|
||||
### Source Package: ###
|
||||
Google Test is also released in source packages which can be downloaded from
|
||||
its Google Code download page[1]. Several different archive formats are
|
||||
provided, but the only difference is the tools used to manipulate them, and the
|
||||
size of the resulting file. Download whichever you are most comfortable with.
|
||||
|
||||
[1] Google Test Downloads: http://code.google.com/p/googletest/downloads/list
|
||||
|
||||
Once downloaded expand the archive using whichever tools you prefer for that
|
||||
type. This will always result in a new directory with the name "gtest-X.Y.Z"
|
||||
which contains all of the source code. Here are some examples in Linux:
|
||||
Once the package is downloaded, expand it using whichever tools you
|
||||
prefer for that type. This will result in a new directory with the
|
||||
name "gtest-X.Y.Z" which contains all of the source code. Here are
|
||||
some examples on Linux:
|
||||
|
||||
tar -xvzf gtest-X.Y.Z.tar.gz
|
||||
tar -xvjf gtest-X.Y.Z.tar.bz2
|
||||
unzip gtest-X.Y.Z.zip
|
||||
|
||||
Choosing a TR1 Tuple Library
|
||||
----------------------------
|
||||
Some Google Test features require the C++ Technical Report 1 (TR1)
|
||||
tuple library, which is not yet widely available with all compilers.
|
||||
The good news is that Google Test implements a subset of TR1 tuple
|
||||
that's enough for its own need, and will automatically use this when
|
||||
the compiler doesn't provide TR1 tuple.
|
||||
### SVN Checkout ###
|
||||
|
||||
Usually you don't need to care about which tuple library Google Test
|
||||
uses. However, if your project already uses TR1 tuple, you need to
|
||||
tell Google Test to use the same TR1 tuple library the rest of your
|
||||
project uses (this requirement is new in Google Test 1.4.0, so you may
|
||||
need to take care of it when upgrading from an earlier version), or
|
||||
the two tuple implementations will clash. To do that, add
|
||||
To check out the main branch (also known as the "trunk") of Google
|
||||
Test, run the following Subversion command:
|
||||
|
||||
-DGTEST_USE_OWN_TR1_TUPLE=0
|
||||
svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
|
||||
|
||||
to the compiler flags while compiling Google Test and your tests.
|
||||
Setting up the Build
|
||||
--------------------
|
||||
|
||||
If you don't want Google Test to use tuple at all, add
|
||||
To build Google Test and your tests that use it, you need to tell your
|
||||
build system where to find its headers and source files. The exact
|
||||
way to do it depends on which build system you use, and is usually
|
||||
straightforward.
|
||||
|
||||
-DGTEST_HAS_TR1_TUPLE=0
|
||||
### Generic Build Instructions ###
|
||||
|
||||
to the compiler flags. All features using tuple will be disabled in
|
||||
this mode.
|
||||
Suppose you put Google Test in directory ${GTEST_DIR}. To build it,
|
||||
create a library build target (or a project as called by Visual Studio
|
||||
and Xcode) to compile
|
||||
|
||||
Building the Source
|
||||
-------------------
|
||||
### Linux, Mac OS X (without Xcode), and Cygwin ###
|
||||
There are two primary options for building the source at this point: build it
|
||||
inside the source code tree, or in a separate directory. We recommend building
|
||||
in a separate directory as that tends to produce both more consistent results
|
||||
and be easier to clean up should anything go wrong, but both patterns are
|
||||
supported. The only hard restriction is that while the build directory can be
|
||||
a subdirectory of the source directory, the opposite is not possible and will
|
||||
result in errors. Once you have selected where you wish to build Google Test,
|
||||
create the directory if necessary, and enter it. The following steps apply for
|
||||
either approach by simply substituting the shell variable SRCDIR with "." for
|
||||
building inside the source directory, and the relative path to the source
|
||||
directory otherwise.
|
||||
${GTEST_DIR}/src/gtest-all.cc
|
||||
|
||||
${SRCDIR}/configure # Standard GNU configure script, --help for more info
|
||||
make # Standard makefile following GNU conventions
|
||||
make check # Builds and runs all tests - all should pass
|
||||
with
|
||||
|
||||
Other programs will only be able to use Google Test's functionality if you
|
||||
install it in a location which they can access, in Linux this is typically
|
||||
under '/usr/local'. The following command will install all of the Google Test
|
||||
libraries, public headers, and utilities necessary for other programs and
|
||||
libraries to leverage it:
|
||||
${GTEST_DIR}/include and ${GTEST_DIR}
|
||||
|
||||
sudo make install # Not necessary, but allows use by other programs
|
||||
in the header search path. Assuming a Linux-like system and gcc,
|
||||
something like the following will do:
|
||||
|
||||
Should you need to remove Google Test from your system after having installed
|
||||
it, run the following command, and it will back out its changes. However, note
|
||||
carefully that you must run this command on the *same* Google Test build that
|
||||
you ran the install from, or the results are not predictable. If you install
|
||||
Google Test on your system, and are working from a VCS checkout, make sure you
|
||||
run this *before* updating your checkout of the source in order to uninstall
|
||||
the same version which you installed.
|
||||
g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
|
||||
ar -rv libgtest.a gtest-all.o
|
||||
|
||||
sudo make uninstall # Must be run against the exact same build as "install"
|
||||
Next, you should compile your test source file with
|
||||
${GTEST_DIR}/include in the header search path, and link it with gtest
|
||||
and any other necessary libraries:
|
||||
|
||||
Your project can build against Google Test simply by leveraging the
|
||||
'gtest-config' script. This script can be invoked directly out of the 'scripts'
|
||||
subdirectory of the build tree, and it will be installed in the binary
|
||||
directory specified during the 'configure'. Here are some examples of its use,
|
||||
see 'gtest-config --help' for more detailed information.
|
||||
g++ -I${GTEST_DIR}/include path/to/your_test.cc libgtest.a -o your_test
|
||||
|
||||
gtest-config --min-version=1.0 || echo "Insufficient Google Test version."
|
||||
|
||||
g++ $(gtest-config --cppflags --cxxflags) -o foo.o -c foo.cpp
|
||||
g++ $(gtest-config --ldflags --libs) -o foo foo.o
|
||||
|
||||
# When using a built but not installed Google Test:
|
||||
g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
|
||||
|
||||
### Windows ###
|
||||
The msvc\ folder contains two solutions with Visual C++ projects. Open the
|
||||
gtest.sln or gtest-md.sln file using Visual Studio, and you are ready to
|
||||
build Google Test the same way you build any Visual Studio project. Files
|
||||
that have names ending with -md use DLL versions of Microsoft runtime
|
||||
libraries (the /MD or the /MDd compiler option). Files without that suffix
|
||||
use static versions of the runtime libraries (the /MT or the /MTd option).
|
||||
Please note that one must use the same option to compile both gtest and his
|
||||
test code. If you use Visual Studio 2005 or above, we recommend the -md
|
||||
version as /MD is the default for new projects in these versions of Visual
|
||||
Studio.
|
||||
|
||||
### Mac OS X (universal-binary framework) ###
|
||||
Open the gtest.xcodeproj in the xcode/ folder using Xcode. Build the "gtest"
|
||||
target. The universal binary framework will end up in your selected build
|
||||
directory (selected in the Xcode "Preferences..." -> "Building" pane and
|
||||
defaults to xcode/build). Alternatively, at the command line, enter:
|
||||
|
||||
xcodebuild
|
||||
|
||||
This will build the "Release" configuration of gtest.framework in your
|
||||
default build location. See the "xcodebuild" man page for more information about
|
||||
building different configurations and building in different locations.
|
||||
|
||||
To test the gtest.framework in Xcode, change the active target to "Check" and
|
||||
then build. This target builds all of the tests and then runs them. Don't worry
|
||||
if you see some errors. Xcode reports all test failures (even the intentional
|
||||
ones) as errors. However, you should see a "Build succeeded" message at the end
|
||||
of the build log. To run all of the tests from the command line, enter:
|
||||
|
||||
xcodebuild -target Check
|
||||
|
||||
Installation with xcodebuild requires specifying an installation desitination
|
||||
directory, known as the DSTROOT. Three items will be installed when using
|
||||
xcodebuild:
|
||||
|
||||
$DSTROOT/Library/Frameworks/gtest.framework
|
||||
$DSTROOT/usr/local/lib/libgtest.a
|
||||
$DSTROOT/usr/local/lib/libgtest_main.a
|
||||
|
||||
You specify the installation directory on the command line with the other
|
||||
xcodebuild options. Here's how you would install in a user-visible location:
|
||||
|
||||
xcodebuild install DSTROOT=~
|
||||
|
||||
To perform a system-wide inistall, escalate to an administrator and specify
|
||||
the file system root as the DSTROOT:
|
||||
|
||||
sudo xcodebuild install DSTROOT=/
|
||||
|
||||
To uninstall gtest.framework via the command line, you need to delete the three
|
||||
items listed above. Remember to escalate to an administrator if deleting these
|
||||
from the system-wide location using the commands listed below:
|
||||
|
||||
sudo rm -r /Library/Frameworks/gtest.framework
|
||||
sudo rm /usr/local/lib/libgtest.a
|
||||
sudo rm /usr/local/lib/libgtest_main.a
|
||||
|
||||
It is also possible to build and execute individual tests within Xcode. Each
|
||||
test has its own Xcode "Target" and Xcode "Executable". To build any of the
|
||||
tests, change the active target and the active executable to the test of
|
||||
interest and then build and run.
|
||||
|
||||
Individual tests can be built from the command line using:
|
||||
|
||||
xcodebuild -target <test_name>
|
||||
|
||||
These tests can be executed from the command line by moving to the build
|
||||
directory and then (in bash)
|
||||
|
||||
export DYLD_FRAMEWORK_PATH=`pwd`
|
||||
./<test_name> # (e.g. ./gtest_unittest)
|
||||
|
||||
To use gtest.framework for your own tests, first, install the framework using
|
||||
the steps described above. Then add it to your Xcode project by selecting
|
||||
Project->Add to Project... from the main menu. Next, add libgtest_main.a from
|
||||
gtest.framework/Resources directory using the same menu command. Finally,
|
||||
create a new executable target and add gtest.framework and libgtest_main.a to
|
||||
the "Link Binary With Libraries" build phase.
|
||||
|
||||
### Using GNU Make ###
|
||||
The make/ directory contains a Makefile that you can use to build
|
||||
Google Test on systems where GNU make is available (e.g. Linux, Mac OS
|
||||
X, and Cygwin). It doesn't try to build Google Test's own tests.
|
||||
Instead, it just builds the Google Test library and a sample test.
|
||||
You can use it as a starting point for your own Makefile.
|
||||
As an example, the make/ directory contains a Makefile that you can
|
||||
use to build Google Test on systems where GNU make is available
|
||||
(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google
|
||||
Test's own tests. Instead, it just builds the Google Test library and
|
||||
a sample test. You can use it as a starting point for your own build
|
||||
script.
|
||||
|
||||
If the default settings are correct for your environment, the
|
||||
following commands should succeed:
|
||||
|
||||
cd ${SRCDIR}/make
|
||||
cd ${GTEST_DIR}/make
|
||||
make
|
||||
./sample1_unittest
|
||||
|
||||
@@ -287,19 +153,244 @@ If you see errors, try to tweak the contents of make/Makefile to make
|
||||
them go away. There are instructions in make/Makefile on how to do
|
||||
it.
|
||||
|
||||
### Using Your Own Build System ###
|
||||
If none of the build solutions we provide works for you, or if you
|
||||
prefer your own build system, you just need to compile
|
||||
src/gtest-all.cc into a library and link your tests with it. Assuming
|
||||
a Linux-like system and gcc, something like the following will do:
|
||||
### Using CMake ###
|
||||
|
||||
cd ${SRCDIR}
|
||||
g++ -I. -I./include -c src/gtest-all.cc
|
||||
ar -rv libgtest.a gtest-all.o
|
||||
g++ -I. -I./include path/to/your_test.cc libgtest.a -o your_test
|
||||
Google Test comes with a CMake build script (CMakeLists.txt) that can
|
||||
be used on a wide range of platforms ("C" stands for cross-platofrm.).
|
||||
If you don't have CMake installed already, you can download it for
|
||||
free from http://www.cmake.org/.
|
||||
|
||||
CMake works by generating native makefiles or build projects that can
|
||||
be used in the compiler environment of your choice. The typical
|
||||
workflow starts with:
|
||||
|
||||
mkdir mybuild # Create a directory to hold the build output.
|
||||
cd mybuild
|
||||
cmake ${GTEST_DIR} # Generate native build scripts.
|
||||
|
||||
If you want to build Google Test's samples, you should replace the
|
||||
last command with
|
||||
|
||||
cmake -Dbuild_gtest_samples=ON ${GTEST_DIR}
|
||||
|
||||
If you are on a *nix system, you should now see a Makefile in the
|
||||
current directory. Just type 'make' to build gtest.
|
||||
|
||||
If you use Windows and have Vistual Studio installed, a gtest.sln file
|
||||
and several .vcproj files will be created. You can then build them
|
||||
using Visual Studio.
|
||||
|
||||
On Mac OS X with Xcode installed, a .xcodeproj file will be generated.
|
||||
|
||||
### Legacy Build Scripts ###
|
||||
|
||||
Before settling on CMake, we have been providing hand-maintained build
|
||||
projects/scripts for Visual Studio, Xcode, and Autotools. While we
|
||||
continue to provide them for convenience, they are not actively
|
||||
maintained any more. We highly recommend that you follow the
|
||||
instructions in the previous two sections to integrate Google Test
|
||||
with your existing build system.
|
||||
|
||||
If you still need to use the legacy build scripts, here's how:
|
||||
|
||||
The msvc\ folder contains two solutions with Visual C++ projects.
|
||||
Open the gtest.sln or gtest-md.sln file using Visual Studio, and you
|
||||
are ready to build Google Test the same way you build any Visual
|
||||
Studio project. Files that have names ending with -md use DLL
|
||||
versions of Microsoft runtime libraries (the /MD or the /MDd compiler
|
||||
option). Files without that suffix use static versions of the runtime
|
||||
libraries (the /MT or the /MTd option). Please note that one must use
|
||||
the same option to compile both gtest and the test code. If you use
|
||||
Visual Studio 2005 or above, we recommend the -md version as /MD is
|
||||
the default for new projects in these versions of Visual Studio.
|
||||
|
||||
On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using
|
||||
Xcode. Build the "gtest" target. The universal binary framework will
|
||||
end up in your selected build directory (selected in the Xcode
|
||||
"Preferences..." -> "Building" pane and defaults to xcode/build).
|
||||
Alternatively, at the command line, enter:
|
||||
|
||||
xcodebuild
|
||||
|
||||
This will build the "Release" configuration of gtest.framework in your
|
||||
default build location. See the "xcodebuild" man page for more
|
||||
information about building different configurations and building in
|
||||
different locations.
|
||||
|
||||
Tweaking Google Test
|
||||
--------------------
|
||||
|
||||
Google Test can be used in diverse environments. The default
|
||||
configuration may not work (or may not work well) out of the box in
|
||||
some environments. However, you can easily tweak Google Test by
|
||||
defining control macros on the compiler command line. Generally,
|
||||
these macros are named like GTEST_XYZ and you define them to either 1
|
||||
or 0 to enable or disable a certain feature.
|
||||
|
||||
We list the most frequently used macros below. For a complete list,
|
||||
see file include/gtest/internal/gtest-port.h.
|
||||
|
||||
### Choosing a TR1 Tuple Library ###
|
||||
|
||||
Some Google Test features require the C++ Technical Report 1 (TR1)
|
||||
tuple library, which is not yet available with all compilers. The
|
||||
good news is that Google Test implements a subset of TR1 tuple that's
|
||||
enough for its own need, and will automatically use this when the
|
||||
compiler doesn't provide TR1 tuple.
|
||||
|
||||
Usually you don't need to care about which tuple library Google Test
|
||||
uses. However, if your project already uses TR1 tuple, you need to
|
||||
tell Google Test to use the same TR1 tuple library the rest of your
|
||||
project uses, or the two tuple implementations will clash. To do
|
||||
that, add
|
||||
|
||||
-DGTEST_USE_OWN_TR1_TUPLE=0
|
||||
|
||||
to the compiler flags while compiling Google Test and your tests. If
|
||||
you want to force Google Test to use its own tuple library, just add
|
||||
|
||||
-DGTEST_USE_OWN_TR1_TUPLE=1
|
||||
|
||||
to the compiler flags instead.
|
||||
|
||||
If you don't want Google Test to use tuple at all, add
|
||||
|
||||
-DGTEST_HAS_TR1_TUPLE=0
|
||||
|
||||
and all features using tuple will be disabled.
|
||||
|
||||
### Multi-threaded Tests ###
|
||||
|
||||
Google Test is thread-safe where the pthread library is available.
|
||||
After #include <gtest/gtest.h>, you can check the GTEST_IS_THREADSAFE
|
||||
macro to see whether this is the case (yes if the macro is #defined to
|
||||
1, no if it's undefined.).
|
||||
|
||||
If Google Test doesn't correctly detect whether pthread is available
|
||||
in your environment, you can force it with
|
||||
|
||||
-DGTEST_HAS_PTHREAD=1
|
||||
|
||||
or
|
||||
|
||||
-DGTEST_HAS_PTHREAD=0
|
||||
|
||||
When Google Test uses pthread, you may need to add flags to your
|
||||
compiler and/or linker to select the pthread library, or you'll get
|
||||
link errors. If you use the CMake script or the deprecated Autotools
|
||||
script, this is taken care of for you. If you use your own build
|
||||
script, you'll need to read your compiler and linker's manual to
|
||||
figure out what flags to add.
|
||||
|
||||
### As a Shared Library (DLL) ###
|
||||
|
||||
Google Test is compact, so most users can build and link it as a
|
||||
static library for the simplicity. You can choose to use Google Test
|
||||
as a shared library (known as a DLL on Windows) if you prefer.
|
||||
|
||||
To compile gtest as a shared library, add
|
||||
|
||||
-DGTEST_CREATE_SHARED_LIBRARY=1
|
||||
|
||||
to the compiler flags. You'll also need to tell the linker to produce
|
||||
a shared library instead - consult your linker's manual for how to do
|
||||
it.
|
||||
|
||||
To compile your tests that use the gtest shared library, add
|
||||
|
||||
-DGTEST_LINKED_AS_SHARED_LIBRARY=1
|
||||
|
||||
to the compiler flags.
|
||||
|
||||
### Avoiding Macro Name Clashes ###
|
||||
|
||||
In C++, macros don't obey namespaces. Therefore two libraries that
|
||||
both define a macro of the same name will clash if you #include both
|
||||
definitions. In case a Google Test macro clashes with another
|
||||
library, you can force Google Test to rename its macro to avoid the
|
||||
conflict.
|
||||
|
||||
Specifically, if both Google Test and some other code define macro
|
||||
FOO, you can add
|
||||
|
||||
-DGTEST_DONT_DEFINE_FOO=1
|
||||
|
||||
to the compiler flags to tell Google Test to change the macro's name
|
||||
from FOO to GTEST_FOO. Currently FOO can be FAIL, SUCCEED, or TEST.
|
||||
For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write
|
||||
|
||||
GTEST_TEST(SomeTest, DoesThis) { ... }
|
||||
|
||||
instead of
|
||||
|
||||
TEST(SomeTest, DoesThis) { ... }
|
||||
|
||||
in order to define a test.
|
||||
|
||||
Upgrating from an Earlier Version
|
||||
---------------------------------
|
||||
|
||||
We strive to keep Google Test releases backward compatible.
|
||||
Sometimes, though, we have to make some breaking changes for the
|
||||
users' long-term benefits. This section describes what you'll need to
|
||||
do if you are upgrading from an earlier version of Google Test.
|
||||
|
||||
### Upgrading from 1.3.0 or Earlier ###
|
||||
|
||||
You may need to explicitly enable or disable Google Test's own TR1
|
||||
tuple library. See the instructions in section "Choosing a TR1 Tuple
|
||||
Library".
|
||||
|
||||
### Upgrading from 1.4.0 or Earlier ###
|
||||
|
||||
The Autotools build script (configure + make) is no longer officially
|
||||
supportted. You are encouraged to migrate to your own build system or
|
||||
use CMake. If you still need to use Autotools, you can find
|
||||
instructions in the README file from Google Test 1.4.0.
|
||||
|
||||
On platforms where the pthread library is available, Google Test uses
|
||||
it in order to be thread-safe. See the "Multi-threaded Tests" section
|
||||
for what this means to your build script.
|
||||
|
||||
If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google
|
||||
Test will no longer compile. This should affect very few people, as a
|
||||
large portion of STL (including <string>) doesn't compile in this mode
|
||||
anyway. We decided to stop supporting it in order to greatly simplify
|
||||
Google Test's implementation.
|
||||
|
||||
Developing Google Test
|
||||
----------------------
|
||||
|
||||
This section discusses how to make your own changes to Google Test.
|
||||
|
||||
### Testing Google Test Itself ###
|
||||
|
||||
To make sure your changes work as intended and don't break existing
|
||||
functionality, you'll want to compile and run Google Test's own tests.
|
||||
For that you can use CMake:
|
||||
|
||||
mkdir mybuild
|
||||
cd mybuild
|
||||
cmake -Dbuild_all_gtest_tests=ON ${GTEST_DIR}
|
||||
|
||||
Make sure you have Python installed, as some of Google Test's tests
|
||||
are written in Python. If the cmake command complains about not being
|
||||
able to find Python ("Could NOT find PythonInterp (missing:
|
||||
PYTHON_EXECUTABLE)"), try telling it explicitly where your Python
|
||||
executable can be found:
|
||||
|
||||
cmake -DPYTHON_EXECUTABLE=path/to/python -Dbuild_all_gtest_tests=ON \
|
||||
${GTEST_DIR}
|
||||
|
||||
Next, you can build Google Test and all of its own tests. On *nix,
|
||||
this is usually done by 'make'. To run the tests, do
|
||||
|
||||
make test
|
||||
|
||||
All tests should pass.
|
||||
|
||||
### Regenerating Source Files ###
|
||||
|
||||
Regenerating Source Files
|
||||
-------------------------
|
||||
Some of Google Test's source files are generated from templates (not
|
||||
in the C++ sense) using a script. A template file is named FOO.pump,
|
||||
where FOO is the name of the file it will generate. For example, the
|
||||
@@ -307,12 +398,20 @@ file include/gtest/internal/gtest-type-util.h.pump is used to generate
|
||||
gtest-type-util.h in the same directory.
|
||||
|
||||
Normally you don't need to worry about regenerating the source files,
|
||||
unless you need to modify them (e.g. if you are working on a patch for
|
||||
Google Test). In that case, you should modify the corresponding .pump
|
||||
files instead and run the 'pump' script (for Pump is Useful for Meta
|
||||
Programming) to regenerate them. We are still working on releasing
|
||||
the script and its documentation. If you need it now, please email
|
||||
googletestframework@googlegroups.com such that we know to make it
|
||||
happen sooner.
|
||||
unless you need to modify them. In that case, you should modify the
|
||||
corresponding .pump files instead and run the pump.py Python script to
|
||||
regenerate them. You can find pump.py in the scripts/ directory.
|
||||
Read the Pump manual [2] for how to use it.
|
||||
|
||||
[2] http://code.google.com/p/googletest/wiki/PumpManual
|
||||
|
||||
### Contributing a Patch ###
|
||||
|
||||
We welcome patches. Please read the Google Test developer's guide [3]
|
||||
for how you can contribute. In particular, make sure you have signed
|
||||
the Contributor License Agreement, or we won't be able to accept the
|
||||
patch.
|
||||
|
||||
[3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide
|
||||
|
||||
Happy testing!
|
||||
|
||||
+12
-12
@@ -23,15 +23,6 @@
|
||||
<Target Name="gtest:Make">
|
||||
<MSBuild Projects="gtest.cbproj" Targets="Make" />
|
||||
</Target>
|
||||
<Target Name="gtest_unittest">
|
||||
<MSBuild Projects="gtest_unittest.cbproj" Targets="" />
|
||||
</Target>
|
||||
<Target Name="gtest_unittest:Clean">
|
||||
<MSBuild Projects="gtest_unittest.cbproj" Targets="Clean" />
|
||||
</Target>
|
||||
<Target Name="gtest_unittest:Make">
|
||||
<MSBuild Projects="gtest_unittest.cbproj" Targets="Make" />
|
||||
</Target>
|
||||
<Target Name="gtest_main">
|
||||
<MSBuild Projects="gtest_main.cbproj" Targets="" />
|
||||
</Target>
|
||||
@@ -41,14 +32,23 @@
|
||||
<Target Name="gtest_main:Make">
|
||||
<MSBuild Projects="gtest_main.cbproj" Targets="Make" />
|
||||
</Target>
|
||||
<Target Name="gtest_unittest">
|
||||
<MSBuild Projects="gtest_unittest.cbproj" Targets="" />
|
||||
</Target>
|
||||
<Target Name="gtest_unittest:Clean">
|
||||
<MSBuild Projects="gtest_unittest.cbproj" Targets="Clean" />
|
||||
</Target>
|
||||
<Target Name="gtest_unittest:Make">
|
||||
<MSBuild Projects="gtest_unittest.cbproj" Targets="Make" />
|
||||
</Target>
|
||||
<Target Name="Build">
|
||||
<CallTarget Targets="gtest;gtest_unittest;gtest_main" />
|
||||
<CallTarget Targets="gtest;gtest_main;gtest_unittest" />
|
||||
</Target>
|
||||
<Target Name="Clean">
|
||||
<CallTarget Targets="gtest:Clean;gtest_unittest:Clean;gtest_main:Clean" />
|
||||
<CallTarget Targets="gtest:Clean;gtest_main:Clean;gtest_unittest:Clean" />
|
||||
</Target>
|
||||
<Target Name="Make">
|
||||
<CallTarget Targets="gtest:Make;gtest_unittest:Make;gtest_main:Make" />
|
||||
<CallTarget Targets="gtest:Make;gtest_main:Make;gtest_unittest:Make" />
|
||||
</Target>
|
||||
<Import Condition="Exists('$(MSBuildBinPath)\Borland.Group.Targets')" Project="$(MSBuildBinPath)\Borland.Group.Targets" />
|
||||
</Project>
|
||||
@@ -18,27 +18,27 @@
|
||||
<CfgParent>Base</CfgParent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base)'!=''">
|
||||
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>
|
||||
<OutputExt>exe</OutputExt>
|
||||
<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
|
||||
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>
|
||||
<Defines>NO_STRICT</Defines>
|
||||
<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
|
||||
<DynamicRTL>true</DynamicRTL>
|
||||
<UsePackages>true</UsePackages>
|
||||
<ILINK_ObjectSearchPath>..\test</ILINK_ObjectSearchPath>
|
||||
<NoVCL>true</NoVCL>
|
||||
<UsePackages>true</UsePackages>
|
||||
<ProjectType>CppConsoleApplication</ProjectType>
|
||||
<NoVCL>true</NoVCL>
|
||||
<BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>
|
||||
<PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi</PackageImports>
|
||||
<PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi</PackageImports>
|
||||
<BCC_wpar>false</BCC_wpar>
|
||||
<IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</IncludePath>
|
||||
<ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</ILINK_LibraryPath>
|
||||
<Multithreaded>true</Multithreaded>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_1)'!=''">
|
||||
<DCC_Optimize>false</DCC_Optimize>
|
||||
<BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>
|
||||
<Defines>_DEBUG;$(Defines)</Defines>
|
||||
<DCC_Optimize>false</DCC_Optimize>
|
||||
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
|
||||
<Defines>_DEBUG;$(Defines)</Defines>
|
||||
<ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>
|
||||
<BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>
|
||||
<ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>
|
||||
@@ -48,8 +48,8 @@
|
||||
<IntermediateOutputDir>Debug</IntermediateOutputDir>
|
||||
<TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>
|
||||
<BCC_StackFrames>true</BCC_StackFrames>
|
||||
<ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>
|
||||
<BCC_DisableOptimizations>true</BCC_DisableOptimizations>
|
||||
<ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>
|
||||
<TASM_Debugging>Full</TASM_Debugging>
|
||||
<BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>
|
||||
</PropertyGroup>
|
||||
|
||||
+19
-3
@@ -5,7 +5,7 @@ m4_include(m4/acx_pthread.m4)
|
||||
# "[1.0.1]"). It also asumes that there won't be any closing parenthesis
|
||||
# between "AC_INIT(" and the closing ")" including comments and strings.
|
||||
AC_INIT([Google C++ Testing Framework],
|
||||
[1.4.0],
|
||||
[1.5.0],
|
||||
[googletestframework@googlegroups.com],
|
||||
[gtest])
|
||||
|
||||
@@ -39,8 +39,24 @@ AS_IF([test "$PYTHON" != ":"],
|
||||
[AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])])
|
||||
AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"])
|
||||
|
||||
# Check for pthreads.
|
||||
ACX_PTHREAD
|
||||
# Configure pthreads.
|
||||
AC_ARG_WITH([pthreads],
|
||||
[AS_HELP_STRING([--with-pthreads],
|
||||
[use pthreads (default is yes)])],
|
||||
[with_pthreads=$withval],
|
||||
[with_pthreads=check])
|
||||
|
||||
have_pthreads=no
|
||||
AS_IF([test "x$with_pthreads" != "xno"],
|
||||
[ACX_PTHREAD(
|
||||
[],
|
||||
[AS_IF([test "x$with_pthreads" != "xcheck"],
|
||||
[AC_MSG_FAILURE(
|
||||
[--with-pthreads was specified, but unable to be used])])])
|
||||
have_pthreads="$acx_pthread_ok"])
|
||||
AM_CONDITIONAL([HAVE_PTHREADS],[test "x$have_pthreads" == "xyes"])
|
||||
AC_SUBST(PTHREAD_CFLAGS)
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
|
||||
# TODO(chandlerc@google.com) Check for the necessary system headers.
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ GTEST_DECLARE_string_(death_test_style);
|
||||
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
||||
|
||||
// Tests that an exit code describes a normal exit with a given exit code.
|
||||
class ExitedWithCode {
|
||||
class GTEST_API_ ExitedWithCode {
|
||||
public:
|
||||
explicit ExitedWithCode(int exit_code);
|
||||
bool operator()(int exit_status) const;
|
||||
@@ -190,7 +190,7 @@ class ExitedWithCode {
|
||||
#if !GTEST_OS_WINDOWS
|
||||
// Tests that an exit code describes an exit due to termination by a
|
||||
// given signal.
|
||||
class KilledBySignal {
|
||||
class GTEST_API_ KilledBySignal {
|
||||
public:
|
||||
explicit KilledBySignal(int signum);
|
||||
bool operator()(int exit_status) const;
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <gtest/internal/gtest-string.h>
|
||||
#include <gtest/internal/gtest-internal.h>
|
||||
|
||||
@@ -77,7 +79,7 @@ namespace testing {
|
||||
// latter (it causes an access violation if you do). The Message
|
||||
// class hides this difference by treating a NULL char pointer as
|
||||
// "(null)".
|
||||
class Message {
|
||||
class GTEST_API_ Message {
|
||||
private:
|
||||
// The type of basic IO manipulators (endl, ends, and flush) for
|
||||
// narrow streams.
|
||||
@@ -89,7 +91,11 @@ class Message {
|
||||
// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
|
||||
// stack frame leading to huge stack frames in some cases; gcc does not reuse
|
||||
// the stack space.
|
||||
Message() : ss_(new internal::StrStream) {}
|
||||
Message() : ss_(new internal::StrStream) {
|
||||
// By default, we want there to be enough precision when printing
|
||||
// a double to a Message.
|
||||
*ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
|
||||
}
|
||||
|
||||
// Copy constructor.
|
||||
Message(const Message& msg) : ss_(new internal::StrStream) { // NOLINT
|
||||
|
||||
@@ -133,9 +133,12 @@ INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
|
||||
// in the given test case, whether their definitions come before or
|
||||
// AFTER the INSTANTIATE_TEST_CASE_P statement.
|
||||
//
|
||||
// Please also note that generator expressions are evaluated in
|
||||
// RUN_ALL_TESTS(), after main() has started. This allows evaluation of
|
||||
// parameter list based on command line parameters.
|
||||
// Please also note that generator expressions (including parameters to the
|
||||
// generators) are evaluated in InitGoogleTest(), after main() has started.
|
||||
// This allows the user on one hand, to adjust generator parameters in order
|
||||
// to dynamically determine a set of tests to run and on the other hand,
|
||||
// give the user a chance to inspect the generated tests with Google Test
|
||||
// reflection API before RUN_ALL_TESTS() is executed.
|
||||
//
|
||||
// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
|
||||
// for more examples.
|
||||
@@ -152,12 +155,15 @@ INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
|
||||
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||
// *unconditionally*. Therefore these #includes cannot be moved
|
||||
// inside #if GTEST_HAS_PARAM_TEST.
|
||||
#include <gtest/internal/gtest-internal.h>
|
||||
#include <gtest/internal/gtest-param-util.h>
|
||||
#include <gtest/internal/gtest-param-util-generated.h>
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Functions producing parameter generators.
|
||||
|
||||
@@ -52,7 +52,7 @@ $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
|
||||
// class. It must be derived from testing::TestWithParam<T>, where T is
|
||||
// the type of your parameter values. TestWithParam<T> is itself derived
|
||||
// from testing::Test. T can be any copyable type. If it's a raw pointer,
|
||||
// you are responsible for managing the lifespan of the pointed values.
|
||||
// you are responsible for managing the lifespan of the pointed values.
|
||||
|
||||
class FooTest : public ::testing::TestWithParam<const char*> {
|
||||
// You can implement all the usual class fixture members here.
|
||||
@@ -60,7 +60,7 @@ class FooTest : public ::testing::TestWithParam<const char*> {
|
||||
|
||||
// Then, use the TEST_P macro to define as many parameterized tests
|
||||
// for this fixture as you want. The _P suffix is for "parameterized"
|
||||
// or "pattern", whichever you prefer to think.
|
||||
// or "pattern", whichever you prefer to think.
|
||||
|
||||
TEST_P(FooTest, DoesBlah) {
|
||||
// Inside a test, access the test parameter with the GetParam() method
|
||||
@@ -124,7 +124,7 @@ const char* pets[] = {"cat", "dog"};
|
||||
INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
|
||||
|
||||
// The tests from the instantiation above will have these names:
|
||||
//
|
||||
//
|
||||
// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
|
||||
// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
|
||||
// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
|
||||
@@ -147,17 +147,21 @@ INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
|
||||
|
||||
#endif // 0
|
||||
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <gtest/internal/gtest-port.h>
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
#if !GTEST_OS_SYMBIAN
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||
// *unconditionally*. Therefore these #includes cannot be moved
|
||||
// inside #if GTEST_HAS_PARAM_TEST.
|
||||
#include <gtest/internal/gtest-internal.h>
|
||||
#include <gtest/internal/gtest-param-util.h>
|
||||
#include <gtest/internal/gtest-param-util-generated.h>
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Functions producing parameter generators.
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace testing {
|
||||
// generated in the same thread that created this object or it can intercept
|
||||
// all generated failures. The scope of this mock object can be controlled with
|
||||
// the second argument to the two arguments constructor.
|
||||
class ScopedFakeTestPartResultReporter
|
||||
class GTEST_API_ ScopedFakeTestPartResultReporter
|
||||
: public TestPartResultReporterInterface {
|
||||
public:
|
||||
// The two possible mocking modes of this object.
|
||||
@@ -93,7 +93,7 @@ namespace internal {
|
||||
// TestPartResultArray contains exactly one failure that has the given
|
||||
// type and contains the given substring. If that's not the case, a
|
||||
// non-fatal failure will be generated.
|
||||
class SingleFailureChecker {
|
||||
class GTEST_API_ SingleFailureChecker {
|
||||
public:
|
||||
// The constructor remembers the arguments.
|
||||
SingleFailureChecker(const TestPartResultArray* results,
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
#include <gtest/internal/gtest-internal.h>
|
||||
#include <gtest/internal/gtest-string.h>
|
||||
|
||||
@@ -43,7 +44,7 @@ namespace testing {
|
||||
// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
|
||||
//
|
||||
// Don't inherit from TestPartResult as its destructor is not virtual.
|
||||
class TestPartResult {
|
||||
class GTEST_API_ TestPartResult {
|
||||
public:
|
||||
// The possible outcomes of a test part (i.e. an assertion or an
|
||||
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
|
||||
@@ -56,15 +57,15 @@ class TestPartResult {
|
||||
// C'tor. TestPartResult does NOT have a default constructor.
|
||||
// Always use this constructor (with parameters) to create a
|
||||
// TestPartResult object.
|
||||
TestPartResult(Type type,
|
||||
const char* file_name,
|
||||
int line_number,
|
||||
const char* message)
|
||||
: type_(type),
|
||||
file_name_(file_name),
|
||||
line_number_(line_number),
|
||||
summary_(ExtractSummary(message)),
|
||||
message_(message) {
|
||||
TestPartResult(Type a_type,
|
||||
const char* a_file_name,
|
||||
int a_line_number,
|
||||
const char* a_message)
|
||||
: type_(a_type),
|
||||
file_name_(a_file_name),
|
||||
line_number_(a_line_number),
|
||||
summary_(ExtractSummary(a_message)),
|
||||
message_(a_message) {
|
||||
}
|
||||
|
||||
// Gets the outcome of the test part.
|
||||
@@ -117,15 +118,11 @@ std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
|
||||
|
||||
// An array of TestPartResult objects.
|
||||
//
|
||||
// We define this class as we cannot use STL containers when compiling
|
||||
// Google Test with MSVC 7.1 and exceptions disabled.
|
||||
//
|
||||
// Don't inherit from TestPartResultArray as its destructor is not
|
||||
// virtual.
|
||||
class TestPartResultArray {
|
||||
class GTEST_API_ TestPartResultArray {
|
||||
public:
|
||||
TestPartResultArray();
|
||||
~TestPartResultArray();
|
||||
TestPartResultArray() {}
|
||||
|
||||
// Appends the given TestPartResult to the array.
|
||||
void Append(const TestPartResult& result);
|
||||
@@ -135,9 +132,9 @@ class TestPartResultArray {
|
||||
|
||||
// Returns the number of TestPartResult objects in the array.
|
||||
int size() const;
|
||||
|
||||
private:
|
||||
// Internally we use a Vector to implement the array.
|
||||
internal::Vector<TestPartResult>* const array_;
|
||||
std::vector<TestPartResult> array_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
|
||||
};
|
||||
@@ -158,7 +155,8 @@ namespace internal {
|
||||
// reported, it only delegates the reporting to the former result reporter.
|
||||
// The original result reporter is restored in the destructor.
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
class HasNewFatalFailureHelper : public TestPartResultReporterInterface {
|
||||
class GTEST_API_ HasNewFatalFailureHelper
|
||||
: public TestPartResultReporterInterface {
|
||||
public:
|
||||
HasNewFatalFailureHelper();
|
||||
virtual ~HasNewFatalFailureHelper();
|
||||
|
||||
@@ -159,8 +159,11 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
||||
// given test case.
|
||||
#define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
|
||||
|
||||
// The 'Types' template argument below must have spaces around it
|
||||
// since some compilers may choke on '>>' when passing a template
|
||||
// instance (e.g. Types<int>)
|
||||
#define TYPED_TEST_CASE(CaseName, Types) \
|
||||
typedef ::testing::internal::TypeList<Types>::type \
|
||||
typedef ::testing::internal::TypeList< Types >::type \
|
||||
GTEST_TYPE_PARAMS_(CaseName)
|
||||
|
||||
#define TYPED_TEST(CaseName, TestName) \
|
||||
@@ -241,11 +244,14 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
|
||||
__FILE__, __LINE__, #__VA_ARGS__)
|
||||
|
||||
// The 'Types' template argument below must have spaces around it
|
||||
// since some compilers may choke on '>>' when passing a template
|
||||
// instance (e.g. Types<int>)
|
||||
#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
|
||||
bool gtest_##Prefix##_##CaseName = \
|
||||
::testing::internal::TypeParameterizedTestCase<CaseName, \
|
||||
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
|
||||
::testing::internal::TypeList<Types>::type>::Register(\
|
||||
::testing::internal::TypeList< Types >::type>::Register(\
|
||||
#Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
+226
-132
@@ -52,6 +52,8 @@
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_H_
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/internal/gtest-internal.h>
|
||||
#include <gtest/internal/gtest-string.h>
|
||||
#include <gtest/gtest-death-test.h>
|
||||
@@ -62,24 +64,19 @@
|
||||
#include <gtest/gtest-typed-test.h>
|
||||
|
||||
// Depending on the platform, different string classes are available.
|
||||
// On Windows, ::std::string compiles only when exceptions are
|
||||
// enabled. On Linux, in addition to ::std::string, Google also makes
|
||||
// use of class ::string, which has the same interface as
|
||||
// ::std::string, but has a different implementation.
|
||||
// On Linux, in addition to ::std::string, Google also makes use of
|
||||
// class ::string, which has the same interface as ::std::string, but
|
||||
// has a different implementation.
|
||||
//
|
||||
// The user can tell us whether ::std::string is available in his
|
||||
// environment by defining the macro GTEST_HAS_STD_STRING to either 1
|
||||
// or 0 on the compiler command line. He can also define
|
||||
// GTEST_HAS_GLOBAL_STRING to 1 to indicate that ::string is available
|
||||
// AND is a distinct type to ::std::string, or define it to 0 to
|
||||
// indicate otherwise.
|
||||
// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
|
||||
// ::string is available AND is a distinct type to ::std::string, or
|
||||
// define it to 0 to indicate otherwise.
|
||||
//
|
||||
// If the user's ::std::string and ::string are the same class due to
|
||||
// aliasing, he should define GTEST_HAS_STD_STRING to 1 and
|
||||
// GTEST_HAS_GLOBAL_STRING to 0.
|
||||
// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
|
||||
//
|
||||
// If the user doesn't define GTEST_HAS_STD_STRING and/or
|
||||
// GTEST_HAS_GLOBAL_STRING, they are defined heuristically.
|
||||
// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
|
||||
// heuristically.
|
||||
|
||||
namespace testing {
|
||||
|
||||
@@ -177,64 +174,146 @@ String StreamableToString(const T& streamable) {
|
||||
|
||||
// A class for indicating whether an assertion was successful. When
|
||||
// the assertion wasn't successful, the AssertionResult object
|
||||
// remembers a non-empty message that described how it failed.
|
||||
// remembers a non-empty message that describes how it failed.
|
||||
//
|
||||
// This class is useful for defining predicate-format functions to be
|
||||
// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
|
||||
//
|
||||
// The constructor of AssertionResult is private. To create an
|
||||
// instance of this class, use one of the factory functions
|
||||
// To create an instance of this class, use one of the factory functions
|
||||
// (AssertionSuccess() and AssertionFailure()).
|
||||
//
|
||||
// For example, in order to be able to write:
|
||||
// This class is useful for two purposes:
|
||||
// 1. Defining predicate functions to be used with Boolean test assertions
|
||||
// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
|
||||
// 2. Defining predicate-format functions to be
|
||||
// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
|
||||
//
|
||||
// For example, if you define IsEven predicate:
|
||||
//
|
||||
// testing::AssertionResult IsEven(int n) {
|
||||
// if ((n % 2) == 0)
|
||||
// return testing::AssertionSuccess();
|
||||
// else
|
||||
// return testing::AssertionFailure() << n << " is odd";
|
||||
// }
|
||||
//
|
||||
// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
|
||||
// will print the message
|
||||
//
|
||||
// Value of: IsEven(Fib(5))
|
||||
// Actual: false (5 is odd)
|
||||
// Expected: true
|
||||
//
|
||||
// instead of a more opaque
|
||||
//
|
||||
// Value of: IsEven(Fib(5))
|
||||
// Actual: false
|
||||
// Expected: true
|
||||
//
|
||||
// in case IsEven is a simple Boolean predicate.
|
||||
//
|
||||
// If you expect your predicate to be reused and want to support informative
|
||||
// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
|
||||
// about half as often as positive ones in our tests), supply messages for
|
||||
// both success and failure cases:
|
||||
//
|
||||
// testing::AssertionResult IsEven(int n) {
|
||||
// if ((n % 2) == 0)
|
||||
// return testing::AssertionSuccess() << n << " is even";
|
||||
// else
|
||||
// return testing::AssertionFailure() << n << " is odd";
|
||||
// }
|
||||
//
|
||||
// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
|
||||
//
|
||||
// Value of: IsEven(Fib(6))
|
||||
// Actual: true (8 is even)
|
||||
// Expected: false
|
||||
//
|
||||
// NB: Predicates that support negative Boolean assertions have reduced
|
||||
// performance in positive ones so be careful not to use them in tests
|
||||
// that have lots (tens of thousands) of positive Boolean assertions.
|
||||
//
|
||||
// To use this class with EXPECT_PRED_FORMAT assertions such as:
|
||||
//
|
||||
// // Verifies that Foo() returns an even number.
|
||||
// EXPECT_PRED_FORMAT1(IsEven, Foo());
|
||||
//
|
||||
// you just need to define:
|
||||
// you need to define:
|
||||
//
|
||||
// testing::AssertionResult IsEven(const char* expr, int n) {
|
||||
// if ((n % 2) == 0) return testing::AssertionSuccess();
|
||||
//
|
||||
// Message msg;
|
||||
// msg << "Expected: " << expr << " is even\n"
|
||||
// << " Actual: it's " << n;
|
||||
// return testing::AssertionFailure(msg);
|
||||
// if ((n % 2) == 0)
|
||||
// return testing::AssertionSuccess();
|
||||
// else
|
||||
// return testing::AssertionFailure()
|
||||
// << "Expected: " << expr << " is even\n Actual: it's " << n;
|
||||
// }
|
||||
//
|
||||
// If Foo() returns 5, you will see the following message:
|
||||
//
|
||||
// Expected: Foo() is even
|
||||
// Actual: it's 5
|
||||
class AssertionResult {
|
||||
//
|
||||
class GTEST_API_ AssertionResult {
|
||||
public:
|
||||
// Declares factory functions for making successful and failed
|
||||
// assertion results as friends.
|
||||
friend AssertionResult AssertionSuccess();
|
||||
friend AssertionResult AssertionFailure(const Message&);
|
||||
// Copy constructor.
|
||||
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||
AssertionResult(const AssertionResult& other);
|
||||
// Used in the EXPECT_TRUE/FALSE(bool_expression).
|
||||
explicit AssertionResult(bool success) : success_(success) {}
|
||||
|
||||
// Returns true iff the assertion succeeded.
|
||||
operator bool() const { return failure_message_.c_str() == NULL; } // NOLINT
|
||||
operator bool() const { return success_; } // NOLINT
|
||||
|
||||
// Returns the assertion's failure message.
|
||||
const char* failure_message() const { return failure_message_.c_str(); }
|
||||
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
|
||||
AssertionResult operator!() const;
|
||||
|
||||
// Returns the text streamed into this AssertionResult. Test assertions
|
||||
// use it when they fail (i.e., the predicate's outcome doesn't match the
|
||||
// assertion's expectation). When nothing has been streamed into the
|
||||
// object, returns an empty string.
|
||||
const char* message() const {
|
||||
return message_.get() != NULL && message_->c_str() != NULL ?
|
||||
message_->c_str() : "";
|
||||
}
|
||||
// TODO(vladl@google.com): Remove this after making sure no clients use it.
|
||||
// Deprecated; please use message() instead.
|
||||
const char* failure_message() const { return message(); }
|
||||
|
||||
// Streams a custom failure message into this object.
|
||||
template <typename T> AssertionResult& operator<<(const T& value);
|
||||
|
||||
private:
|
||||
// The default constructor. It is used when the assertion succeeded.
|
||||
AssertionResult() {}
|
||||
// No implementation - we want AssertionResult to be
|
||||
// copy-constructible but not assignable.
|
||||
void operator=(const AssertionResult& other);
|
||||
|
||||
// The constructor used when the assertion failed.
|
||||
explicit AssertionResult(const internal::String& failure_message);
|
||||
// Stores result of the assertion predicate.
|
||||
bool success_;
|
||||
// Stores the message describing the condition in case the expectation
|
||||
// construct is not satisfied with the predicate's outcome.
|
||||
// Referenced via a pointer to avoid taking too much stack frame space
|
||||
// with test assertions.
|
||||
internal::scoped_ptr<internal::String> message_;
|
||||
}; // class AssertionResult
|
||||
|
||||
// Stores the assertion's failure message.
|
||||
internal::String failure_message_;
|
||||
};
|
||||
// Streams a custom failure message into this object.
|
||||
template <typename T>
|
||||
AssertionResult& AssertionResult::operator<<(const T& value) {
|
||||
Message msg;
|
||||
if (message_.get() != NULL)
|
||||
msg << *message_;
|
||||
msg << value;
|
||||
message_.reset(new internal::String(msg.GetString()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Makes a successful assertion result.
|
||||
AssertionResult AssertionSuccess();
|
||||
GTEST_API_ AssertionResult AssertionSuccess();
|
||||
|
||||
// Makes a failed assertion result.
|
||||
GTEST_API_ AssertionResult AssertionFailure();
|
||||
|
||||
// Makes a failed assertion result with the given failure message.
|
||||
AssertionResult AssertionFailure(const Message& msg);
|
||||
// Deprecated; use AssertionFailure() << msg.
|
||||
GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
|
||||
|
||||
// The abstract class that all tests inherit from.
|
||||
//
|
||||
@@ -259,7 +338,7 @@ AssertionResult AssertionFailure(const Message& msg);
|
||||
// TEST_F(FooTest, Baz) { ... }
|
||||
//
|
||||
// Test is not copyable.
|
||||
class Test {
|
||||
class GTEST_API_ Test {
|
||||
public:
|
||||
friend class internal::TestInfoImpl;
|
||||
|
||||
@@ -375,8 +454,8 @@ class TestProperty {
|
||||
// C'tor. TestProperty does NOT have a default constructor.
|
||||
// Always use this constructor (with parameters) to create a
|
||||
// TestProperty object.
|
||||
TestProperty(const char* key, const char* value) :
|
||||
key_(key), value_(value) {
|
||||
TestProperty(const char* a_key, const char* a_value) :
|
||||
key_(a_key), value_(a_value) {
|
||||
}
|
||||
|
||||
// Gets the user supplied key.
|
||||
@@ -407,7 +486,7 @@ class TestProperty {
|
||||
// the Test.
|
||||
//
|
||||
// TestResult is not copyable.
|
||||
class TestResult {
|
||||
class GTEST_API_ TestResult {
|
||||
public:
|
||||
// Creates an empty TestResult.
|
||||
TestResult();
|
||||
@@ -458,13 +537,13 @@ class TestResult {
|
||||
friend class internal::WindowsDeathTest;
|
||||
|
||||
// Gets the vector of TestPartResults.
|
||||
const internal::Vector<TestPartResult>& test_part_results() const {
|
||||
return *test_part_results_;
|
||||
const std::vector<TestPartResult>& test_part_results() const {
|
||||
return test_part_results_;
|
||||
}
|
||||
|
||||
// Gets the vector of TestProperties.
|
||||
const internal::Vector<TestProperty>& test_properties() const {
|
||||
return *test_properties_;
|
||||
const std::vector<TestProperty>& test_properties() const {
|
||||
return test_properties_;
|
||||
}
|
||||
|
||||
// Sets the elapsed time.
|
||||
@@ -502,9 +581,9 @@ class TestResult {
|
||||
internal::Mutex test_properites_mutex_;
|
||||
|
||||
// The vector of TestPartResults
|
||||
internal::scoped_ptr<internal::Vector<TestPartResult> > test_part_results_;
|
||||
std::vector<TestPartResult> test_part_results_;
|
||||
// The vector of TestProperties
|
||||
internal::scoped_ptr<internal::Vector<TestProperty> > test_properties_;
|
||||
std::vector<TestProperty> test_properties_;
|
||||
// Running count of death tests.
|
||||
int death_test_count_;
|
||||
// The elapsed time, in milliseconds.
|
||||
@@ -525,7 +604,7 @@ class TestResult {
|
||||
// The constructor of TestInfo registers itself with the UnitTest
|
||||
// singleton such that the RUN_ALL_TESTS() macro knows which tests to
|
||||
// run.
|
||||
class TestInfo {
|
||||
class GTEST_API_ TestInfo {
|
||||
public:
|
||||
// Destructs a TestInfo object. This function is not virtual, so
|
||||
// don't inherit from TestInfo.
|
||||
@@ -607,7 +686,7 @@ class TestInfo {
|
||||
// A test case, which consists of a vector of TestInfos.
|
||||
//
|
||||
// TestCase is not copyable.
|
||||
class TestCase {
|
||||
class GTEST_API_ TestCase {
|
||||
public:
|
||||
// Creates a TestCase with the given name.
|
||||
//
|
||||
@@ -668,11 +747,11 @@ class TestCase {
|
||||
friend class internal::UnitTestImpl;
|
||||
|
||||
// Gets the (mutable) vector of TestInfos in this TestCase.
|
||||
internal::Vector<TestInfo*>& test_info_list() { return *test_info_list_; }
|
||||
std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
|
||||
|
||||
// Gets the (immutable) vector of TestInfos in this TestCase.
|
||||
const internal::Vector<TestInfo *> & test_info_list() const {
|
||||
return *test_info_list_;
|
||||
const std::vector<TestInfo*>& test_info_list() const {
|
||||
return test_info_list_;
|
||||
}
|
||||
|
||||
// Returns the i-th test among all the tests. i can range from 0 to
|
||||
@@ -721,11 +800,11 @@ class TestCase {
|
||||
internal::String comment_;
|
||||
// The vector of TestInfos in their original order. It owns the
|
||||
// elements in the vector.
|
||||
const internal::scoped_ptr<internal::Vector<TestInfo*> > test_info_list_;
|
||||
std::vector<TestInfo*> test_info_list_;
|
||||
// Provides a level of indirection for the test list to allow easy
|
||||
// shuffling and restoring the test order. The i-th element in this
|
||||
// vector is the index of the i-th test in the shuffled test list.
|
||||
const internal::scoped_ptr<internal::Vector<int> > test_indices_;
|
||||
std::vector<int> test_indices_;
|
||||
// Pointer to the function that sets up the test case.
|
||||
Test::SetUpTestCaseFunc set_up_tc_;
|
||||
// Pointer to the function that tears down the test case.
|
||||
@@ -845,7 +924,7 @@ class EmptyTestEventListener : public TestEventListener {
|
||||
};
|
||||
|
||||
// TestEventListeners lets users add listeners to track events in Google Test.
|
||||
class TestEventListeners {
|
||||
class GTEST_API_ TestEventListeners {
|
||||
public:
|
||||
TestEventListeners();
|
||||
~TestEventListeners();
|
||||
@@ -932,7 +1011,7 @@ class TestEventListeners {
|
||||
//
|
||||
// This class is thread-safe as long as the methods are called
|
||||
// according to their specification.
|
||||
class UnitTest {
|
||||
class GTEST_API_ UnitTest {
|
||||
public:
|
||||
// Gets the singleton UnitTest object. The first time this method
|
||||
// is called, a UnitTest object is constructed and returned.
|
||||
@@ -1119,36 +1198,34 @@ inline Environment* AddGlobalTestEnvironment(Environment* env) {
|
||||
// updated.
|
||||
//
|
||||
// Calling the function for the second time has no user-visible effect.
|
||||
void InitGoogleTest(int* argc, char** argv);
|
||||
GTEST_API_ void InitGoogleTest(int* argc, char** argv);
|
||||
|
||||
// This overloaded version can be used in Windows programs compiled in
|
||||
// UNICODE mode.
|
||||
void InitGoogleTest(int* argc, wchar_t** argv);
|
||||
GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
|
||||
|
||||
namespace internal {
|
||||
|
||||
// These overloaded versions handle ::std::string and ::std::wstring.
|
||||
#if GTEST_HAS_STD_STRING
|
||||
inline String FormatForFailureMessage(const ::std::string& str) {
|
||||
GTEST_API_ inline String FormatForFailureMessage(const ::std::string& str) {
|
||||
return (Message() << '"' << str << '"').GetString();
|
||||
}
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
inline String FormatForFailureMessage(const ::std::wstring& wstr) {
|
||||
GTEST_API_ inline String FormatForFailureMessage(const ::std::wstring& wstr) {
|
||||
return (Message() << "L\"" << wstr << '"').GetString();
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// These overloaded versions handle ::string and ::wstring.
|
||||
#if GTEST_HAS_GLOBAL_STRING
|
||||
inline String FormatForFailureMessage(const ::string& str) {
|
||||
GTEST_API_ inline String FormatForFailureMessage(const ::string& str) {
|
||||
return (Message() << '"' << str << '"').GetString();
|
||||
}
|
||||
#endif // GTEST_HAS_GLOBAL_STRING
|
||||
|
||||
#if GTEST_HAS_GLOBAL_WSTRING
|
||||
inline String FormatForFailureMessage(const ::wstring& wstr) {
|
||||
GTEST_API_ inline String FormatForFailureMessage(const ::wstring& wstr) {
|
||||
return (Message() << "L\"" << wstr << '"').GetString();
|
||||
}
|
||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||
@@ -1201,10 +1278,10 @@ AssertionResult CmpHelperEQ(const char* expected_expression,
|
||||
// With this overloaded version, we allow anonymous enums to be used
|
||||
// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
|
||||
// can be implicitly cast to BiggestInt.
|
||||
AssertionResult CmpHelperEQ(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
BiggestInt expected,
|
||||
BiggestInt actual);
|
||||
GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
BiggestInt expected,
|
||||
BiggestInt actual);
|
||||
|
||||
// The helper class for {ASSERT|EXPECT}_EQ. The template argument
|
||||
// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
|
||||
@@ -1293,72 +1370,72 @@ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
|
||||
return AssertionFailure(msg);\
|
||||
}\
|
||||
}\
|
||||
AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
|
||||
BiggestInt val1, BiggestInt val2);
|
||||
GTEST_API_ AssertionResult CmpHelper##op_name(\
|
||||
const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
|
||||
// Implements the helper function for {ASSERT|EXPECT}_NE
|
||||
GTEST_IMPL_CMP_HELPER_(NE, !=)
|
||||
GTEST_IMPL_CMP_HELPER_(NE, !=);
|
||||
// Implements the helper function for {ASSERT|EXPECT}_LE
|
||||
GTEST_IMPL_CMP_HELPER_(LE, <=)
|
||||
GTEST_IMPL_CMP_HELPER_(LE, <=);
|
||||
// Implements the helper function for {ASSERT|EXPECT}_LT
|
||||
GTEST_IMPL_CMP_HELPER_(LT, < )
|
||||
GTEST_IMPL_CMP_HELPER_(LT, < );
|
||||
// Implements the helper function for {ASSERT|EXPECT}_GE
|
||||
GTEST_IMPL_CMP_HELPER_(GE, >=)
|
||||
GTEST_IMPL_CMP_HELPER_(GE, >=);
|
||||
// Implements the helper function for {ASSERT|EXPECT}_GT
|
||||
GTEST_IMPL_CMP_HELPER_(GT, > )
|
||||
GTEST_IMPL_CMP_HELPER_(GT, > );
|
||||
|
||||
#undef GTEST_IMPL_CMP_HELPER_
|
||||
|
||||
// The helper function for {ASSERT|EXPECT}_STREQ.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
AssertionResult CmpHelperSTREQ(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
const char* expected,
|
||||
const char* actual);
|
||||
GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
const char* expected,
|
||||
const char* actual);
|
||||
|
||||
// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
const char* expected,
|
||||
const char* actual);
|
||||
GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
const char* expected,
|
||||
const char* actual);
|
||||
|
||||
// The helper function for {ASSERT|EXPECT}_STRNE.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1,
|
||||
const char* s2);
|
||||
GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1,
|
||||
const char* s2);
|
||||
|
||||
// The helper function for {ASSERT|EXPECT}_STRCASENE.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1,
|
||||
const char* s2);
|
||||
GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1,
|
||||
const char* s2);
|
||||
|
||||
|
||||
// Helper function for *_STREQ on wide strings.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
AssertionResult CmpHelperSTREQ(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
const wchar_t* expected,
|
||||
const wchar_t* actual);
|
||||
GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
const wchar_t* expected,
|
||||
const wchar_t* actual);
|
||||
|
||||
// Helper function for *_STRNE on wide strings.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const wchar_t* s1,
|
||||
const wchar_t* s2);
|
||||
GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const wchar_t* s1,
|
||||
const wchar_t* s2);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -1370,32 +1447,30 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
//
|
||||
// The {needle,haystack}_expr arguments are the stringified
|
||||
// expressions that generated the two real arguments.
|
||||
AssertionResult IsSubstring(
|
||||
GTEST_API_ AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const char* needle, const char* haystack);
|
||||
AssertionResult IsSubstring(
|
||||
GTEST_API_ AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const wchar_t* needle, const wchar_t* haystack);
|
||||
AssertionResult IsNotSubstring(
|
||||
GTEST_API_ AssertionResult IsNotSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const char* needle, const char* haystack);
|
||||
AssertionResult IsNotSubstring(
|
||||
GTEST_API_ AssertionResult IsNotSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const wchar_t* needle, const wchar_t* haystack);
|
||||
#if GTEST_HAS_STD_STRING
|
||||
AssertionResult IsSubstring(
|
||||
GTEST_API_ AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::string& needle, const ::std::string& haystack);
|
||||
AssertionResult IsNotSubstring(
|
||||
GTEST_API_ AssertionResult IsNotSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::string& needle, const ::std::string& haystack);
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
AssertionResult IsSubstring(
|
||||
GTEST_API_ AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::wstring& needle, const ::std::wstring& haystack);
|
||||
AssertionResult IsNotSubstring(
|
||||
GTEST_API_ AssertionResult IsNotSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::wstring& needle, const ::std::wstring& haystack);
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
@@ -1438,16 +1513,16 @@ AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
|
||||
// Helper function for implementing ASSERT_NEAR.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
AssertionResult DoubleNearPredFormat(const char* expr1,
|
||||
const char* expr2,
|
||||
const char* abs_error_expr,
|
||||
double val1,
|
||||
double val2,
|
||||
double abs_error);
|
||||
GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
|
||||
const char* expr2,
|
||||
const char* abs_error_expr,
|
||||
double val1,
|
||||
double val2,
|
||||
double abs_error);
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
// A class that enables one to stream messages to assertion macros
|
||||
class AssertHelper {
|
||||
class GTEST_API_ AssertHelper {
|
||||
public:
|
||||
// Constructor.
|
||||
AssertHelper(TestPartResult::Type type,
|
||||
@@ -1576,10 +1651,22 @@ const T* TestWithParam<T>::parameter_ = NULL;
|
||||
#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
|
||||
|
||||
// Generates a fatal failure with a generic message.
|
||||
#define FAIL() GTEST_FATAL_FAILURE_("Failed")
|
||||
#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
|
||||
|
||||
// Define this macro to 1 to omit the definition of FAIL(), which is a
|
||||
// generic name and clashes with some other libraries.
|
||||
#if !GTEST_DONT_DEFINE_FAIL
|
||||
#define FAIL() GTEST_FAIL()
|
||||
#endif
|
||||
|
||||
// Generates a success with a generic message.
|
||||
#define SUCCEED() GTEST_SUCCESS_("Succeeded")
|
||||
#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
|
||||
|
||||
// Define this macro to 1 to omit the definition of SUCCEED(), which
|
||||
// is a generic name and clashes with some other libraries.
|
||||
#if !GTEST_DONT_DEFINE_SUCCEED
|
||||
#define SUCCEED() GTEST_SUCCEED()
|
||||
#endif
|
||||
|
||||
// Macros for testing exceptions.
|
||||
//
|
||||
@@ -1603,7 +1690,9 @@ const T* TestWithParam<T>::parameter_ = NULL;
|
||||
#define ASSERT_ANY_THROW(statement) \
|
||||
GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
|
||||
|
||||
// Boolean assertions.
|
||||
// Boolean assertions. Condition can be either a Boolean expression or an
|
||||
// AssertionResult. For more information on how to use AssertionResult with
|
||||
// these macros see comments on that class.
|
||||
#define EXPECT_TRUE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
|
||||
GTEST_NONFATAL_FAILURE_)
|
||||
@@ -1776,10 +1865,10 @@ const T* TestWithParam<T>::parameter_ = NULL;
|
||||
|
||||
// Asserts that val1 is less than, or almost equal to, val2. Fails
|
||||
// otherwise. In particular, it fails if either val1 or val2 is NaN.
|
||||
AssertionResult FloatLE(const char* expr1, const char* expr2,
|
||||
float val1, float val2);
|
||||
AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
||||
double val1, double val2);
|
||||
GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
|
||||
float val1, float val2);
|
||||
GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
||||
double val1, double val2);
|
||||
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
@@ -1909,10 +1998,15 @@ bool StaticAssertTypeEq() {
|
||||
// code. GetTestTypeId() is guaranteed to always return the same
|
||||
// value, as it always calls GetTypeId<>() from the Google Test
|
||||
// framework.
|
||||
#define TEST(test_case_name, test_name)\
|
||||
#define GTEST_TEST(test_case_name, test_name)\
|
||||
GTEST_TEST_(test_case_name, test_name, \
|
||||
::testing::Test, ::testing::internal::GetTestTypeId())
|
||||
|
||||
// Define this macro to 1 to omit the definition of TEST(), which
|
||||
// is a generic name and clashes with some other libraries.
|
||||
#if !GTEST_DONT_DEFINE_TEST
|
||||
#define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
|
||||
#endif
|
||||
|
||||
// Defines a test that uses a test fixture.
|
||||
//
|
||||
|
||||
@@ -64,7 +64,7 @@ const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
|
||||
// by wait(2)
|
||||
// exit code: The integer code passed to exit(3), _exit(2), or
|
||||
// returned from main()
|
||||
class DeathTest {
|
||||
class GTEST_API_ DeathTest {
|
||||
public:
|
||||
// Create returns false if there was an error determining the
|
||||
// appropriate action to take for the current death test; for example,
|
||||
@@ -147,7 +147,7 @@ class DefaultDeathTestFactory : public DeathTestFactory {
|
||||
|
||||
// Returns true if exit_status describes a process that was terminated
|
||||
// by a signal, or exited normally with a nonzero exit code.
|
||||
bool ExitedUnsuccessfully(int exit_status);
|
||||
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
||||
|
||||
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
||||
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
||||
@@ -189,11 +189,12 @@ bool ExitedUnsuccessfully(int exit_status);
|
||||
// RUN_ALL_TESTS was called.
|
||||
class InternalRunDeathTestFlag {
|
||||
public:
|
||||
InternalRunDeathTestFlag(const String& file,
|
||||
int line,
|
||||
int index,
|
||||
int write_fd)
|
||||
: file_(file), line_(line), index_(index), write_fd_(write_fd) {}
|
||||
InternalRunDeathTestFlag(const String& a_file,
|
||||
int a_line,
|
||||
int an_index,
|
||||
int a_write_fd)
|
||||
: file_(a_file), line_(a_line), index_(an_index),
|
||||
write_fd_(a_write_fd) {}
|
||||
|
||||
~InternalRunDeathTestFlag() {
|
||||
if (write_fd_ >= 0)
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace internal {
|
||||
// Names are NOT checked for syntax correctness -- no checking for illegal
|
||||
// characters, malformed paths, etc.
|
||||
|
||||
class FilePath {
|
||||
class GTEST_API_ FilePath {
|
||||
public:
|
||||
FilePath() : pathname_("") { }
|
||||
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
|
||||
@@ -189,9 +189,18 @@ class FilePath {
|
||||
// particular, RemoveTrailingPathSeparator() only removes one separator, and
|
||||
// it is called in CreateDirectoriesRecursively() assuming that it will change
|
||||
// a pathname from directory syntax (trailing separator) to filename syntax.
|
||||
//
|
||||
// On Windows this method also replaces the alternate path separator '/' with
|
||||
// the primary path separator '\\', so that for example "bar\\/\\foo" becomes
|
||||
// "bar\\foo".
|
||||
|
||||
void Normalize();
|
||||
|
||||
// Returns a pointer to the last occurence of a valid path separator in
|
||||
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||
// separators. Returns NULL if no path separator was found.
|
||||
const char* FindLastPathSeparator() const;
|
||||
|
||||
String pathname_;
|
||||
}; // class FilePath
|
||||
|
||||
|
||||
@@ -114,14 +114,13 @@ struct TraceInfo; // Information about a trace point.
|
||||
class ScopedTrace; // Implements scoped trace.
|
||||
class TestInfoImpl; // Opaque implementation of TestInfo
|
||||
class UnitTestImpl; // Opaque implementation of UnitTest
|
||||
template <typename E> class Vector; // A generic vector.
|
||||
|
||||
// How many times InitGoogleTest() has been called.
|
||||
extern int g_init_gtest_count;
|
||||
|
||||
// The text used in failure messages to indicate the start of the
|
||||
// stack trace.
|
||||
extern const char kStackTraceMarker[];
|
||||
GTEST_API_ extern const char kStackTraceMarker[];
|
||||
|
||||
// A secret type that Google Test users don't know about. It has no
|
||||
// definition on purpose. Therefore it's impossible to create a
|
||||
@@ -148,24 +147,21 @@ char (&IsNullLiteralHelper(...))[2]; // NOLINT
|
||||
// A compile-time bool constant that is true if and only if x is a
|
||||
// null pointer literal (i.e. NULL or any 0-valued compile-time
|
||||
// integral constant).
|
||||
#ifdef GTEST_ELLIPSIS_NEEDS_COPY_
|
||||
// Passing non-POD classes through ellipsis (...) crashes the ARM
|
||||
// compiler. The Nokia Symbian and the IBM XL C/C++ compiler try to
|
||||
// instantiate a copy constructor for objects passed through ellipsis
|
||||
// (...), failing for uncopyable objects. Hence we define this to
|
||||
// false (and lose support for NULL detection).
|
||||
#ifdef GTEST_ELLIPSIS_NEEDS_POD_
|
||||
// We lose support for NULL detection where the compiler doesn't like
|
||||
// passing non-POD classes through ellipsis (...).
|
||||
#define GTEST_IS_NULL_LITERAL_(x) false
|
||||
#else
|
||||
#define GTEST_IS_NULL_LITERAL_(x) \
|
||||
(sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
|
||||
#endif // GTEST_ELLIPSIS_NEEDS_COPY_
|
||||
#endif // GTEST_ELLIPSIS_NEEDS_POD_
|
||||
|
||||
// Appends the user-supplied message to the Google-Test-generated message.
|
||||
String AppendUserMessage(const String& gtest_msg,
|
||||
const Message& user_msg);
|
||||
GTEST_API_ String AppendUserMessage(const String& gtest_msg,
|
||||
const Message& user_msg);
|
||||
|
||||
// A helper class for creating scoped traces in user programs.
|
||||
class ScopedTrace {
|
||||
class GTEST_API_ ScopedTrace {
|
||||
public:
|
||||
// The c'tor pushes the given source file location and message onto
|
||||
// a trace stack maintained by Google Test.
|
||||
@@ -244,8 +240,8 @@ inline String FormatForFailureMessage(T* pointer) {
|
||||
#endif // GTEST_NEEDS_IS_POINTER_
|
||||
|
||||
// These overloaded versions handle narrow and wide characters.
|
||||
String FormatForFailureMessage(char ch);
|
||||
String FormatForFailureMessage(wchar_t wchar);
|
||||
GTEST_API_ String FormatForFailureMessage(char ch);
|
||||
GTEST_API_ String FormatForFailureMessage(wchar_t wchar);
|
||||
|
||||
// When this operand is a const char* or char*, and the other operand
|
||||
// is a ::std::string or ::string, we print this operand as a C string
|
||||
@@ -262,9 +258,7 @@ inline String FormatForComparisonFailureMessage(\
|
||||
return operand1_printer(str);\
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_STRING
|
||||
GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted)
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted)
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
@@ -293,12 +287,18 @@ GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted)
|
||||
// The ignoring_case parameter is true iff the assertion is a
|
||||
// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
|
||||
// be inserted into the message.
|
||||
AssertionResult EqFailure(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
const String& expected_value,
|
||||
const String& actual_value,
|
||||
bool ignoring_case);
|
||||
GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
|
||||
const char* actual_expression,
|
||||
const String& expected_value,
|
||||
const String& actual_value,
|
||||
bool ignoring_case);
|
||||
|
||||
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
|
||||
GTEST_API_ String GetBoolAssertionFailureMessage(
|
||||
const AssertionResult& assertion_result,
|
||||
const char* expression_text,
|
||||
const char* actual_predicate_value,
|
||||
const char* expected_predicate_value);
|
||||
|
||||
// This template class represents an IEEE floating-point number
|
||||
// (either single-precision or double-precision, depending on the
|
||||
@@ -518,7 +518,7 @@ TypeId GetTypeId() {
|
||||
// ::testing::Test, as the latter may give the wrong result due to a
|
||||
// suspected linker bug when compiling Google Test as a Mac OS X
|
||||
// framework.
|
||||
TypeId GetTestTypeId();
|
||||
GTEST_API_ TypeId GetTestTypeId();
|
||||
|
||||
// Defines the abstract factory interface that creates instances
|
||||
// of a Test object.
|
||||
@@ -551,8 +551,10 @@ class TestFactoryImpl : public TestFactoryBase {
|
||||
// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
|
||||
// We pass a long instead of HRESULT to avoid causing an
|
||||
// include dependency for the HRESULT type.
|
||||
AssertionResult IsHRESULTSuccess(const char* expr, long hr); // NOLINT
|
||||
AssertionResult IsHRESULTFailure(const char* expr, long hr); // NOLINT
|
||||
GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
|
||||
long hr); // NOLINT
|
||||
GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
|
||||
long hr); // NOLINT
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
@@ -591,7 +593,7 @@ typedef void (*TearDownTestCaseFunc)();
|
||||
// factory: pointer to the factory that creates a test object.
|
||||
// The newly created TestInfo instance will assume
|
||||
// ownership of the factory object.
|
||||
TestInfo* MakeAndRegisterTestInfo(
|
||||
GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
|
||||
const char* test_case_name, const char* name,
|
||||
const char* test_case_comment, const char* comment,
|
||||
TypeId fixture_class_id,
|
||||
@@ -599,10 +601,15 @@ TestInfo* MakeAndRegisterTestInfo(
|
||||
TearDownTestCaseFunc tear_down_tc,
|
||||
TestFactoryBase* factory);
|
||||
|
||||
// If *pstr starts with the given prefix, modifies *pstr to be right
|
||||
// past the prefix and returns true; otherwise leaves *pstr unchanged
|
||||
// and returns false. None of pstr, *pstr, and prefix can be NULL.
|
||||
bool SkipPrefix(const char* prefix, const char** pstr);
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// State of the definition of a type-parameterized test case.
|
||||
class TypedTestCasePState {
|
||||
class GTEST_API_ TypedTestCasePState {
|
||||
public:
|
||||
TypedTestCasePState() : registered_(false) {}
|
||||
|
||||
@@ -743,13 +750,14 @@ class TypeParameterizedTestCase<Fixture, Templates0, Types> {
|
||||
// For example, if Foo() calls Bar(), which in turn calls
|
||||
// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
|
||||
// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
|
||||
String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test, int skip_count);
|
||||
GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test,
|
||||
int skip_count);
|
||||
|
||||
// Helpers for suppressing warnings on unreachable code or constant
|
||||
// condition.
|
||||
|
||||
// Always returns true.
|
||||
bool AlwaysTrue();
|
||||
GTEST_API_ bool AlwaysTrue();
|
||||
|
||||
// Always returns false.
|
||||
inline bool AlwaysFalse() { return !AlwaysTrue(); }
|
||||
@@ -759,7 +767,7 @@ inline bool AlwaysFalse() { return !AlwaysTrue(); }
|
||||
// doesn't use global state (and therefore can't interfere with user
|
||||
// code). Unlike rand_r(), it's portable. An LCG isn't very random,
|
||||
// but it's good enough for our purposes.
|
||||
class Random {
|
||||
class GTEST_API_ Random {
|
||||
public:
|
||||
static const UInt32 kMaxRange = 1u << 31;
|
||||
|
||||
@@ -858,12 +866,17 @@ class Random {
|
||||
fail(gtest_msg)
|
||||
|
||||
|
||||
#define GTEST_TEST_BOOLEAN_(boolexpr, booltext, actual, expected, fail) \
|
||||
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
|
||||
// either a boolean expression or an AssertionResult. text is a textual
|
||||
// represenation of expression as it was passed into the EXPECT_TRUE.
|
||||
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::IsTrue(boolexpr)) \
|
||||
if (const ::testing::AssertionResult gtest_ar_ = \
|
||||
::testing::AssertionResult(expression)) \
|
||||
; \
|
||||
else \
|
||||
fail("Value of: " booltext "\n Actual: " #actual "\nExpected: " #expected)
|
||||
fail(::testing::internal::GetBoolAssertionFailureMessage(\
|
||||
gtest_ar_, text, #actual, #expected).c_str())
|
||||
|
||||
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Protects copying of all linked_ptr objects.
|
||||
extern Mutex g_linked_ptr_mutex;
|
||||
GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||
|
||||
// This is used internally by all instances of linked_ptr<>. It needs to be
|
||||
// a non-template class because different types of linked_ptr<> can refer to
|
||||
|
||||
@@ -44,13 +44,30 @@
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||
|
||||
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||
// *unconditionally*. Therefore these #includes cannot be moved
|
||||
// inside #if GTEST_HAS_PARAM_TEST.
|
||||
#include <gtest/internal/gtest-param-util.h>
|
||||
#include <gtest/internal/gtest-port.h>
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
|
||||
#include <gtest/internal/gtest-param-util.h>
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Forward declarations of ValuesIn(), which is implemented in
|
||||
// include/gtest/gtest-param-test.h.
|
||||
template <typename ForwardIterator>
|
||||
internal::ParamGenerator<
|
||||
typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
|
||||
ForwardIterator begin, ForwardIterator end);
|
||||
|
||||
template <typename T, size_t N>
|
||||
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
|
||||
|
||||
template <class Container>
|
||||
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
||||
const Container& container);
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Used in the Values() function to provide polymorphic capabilities.
|
||||
|
||||
@@ -45,13 +45,30 @@ $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||
|
||||
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||
// *unconditionally*. Therefore these #includes cannot be moved
|
||||
// inside #if GTEST_HAS_PARAM_TEST.
|
||||
#include <gtest/internal/gtest-param-util.h>
|
||||
#include <gtest/internal/gtest-port.h>
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
|
||||
#include <gtest/internal/gtest-param-util.h>
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Forward declarations of ValuesIn(), which is implemented in
|
||||
// include/gtest/gtest-param-test.h.
|
||||
template <typename ForwardIterator>
|
||||
internal::ParamGenerator<
|
||||
typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
|
||||
ForwardIterator begin, ForwardIterator end);
|
||||
|
||||
template <typename T, size_t N>
|
||||
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
|
||||
|
||||
template <class Container>
|
||||
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
||||
const Container& container);
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Used in the Values() function to provide polymorphic capabilities.
|
||||
|
||||
@@ -38,17 +38,15 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||
// *unconditionally*. Therefore these #includes cannot be moved
|
||||
// inside #if GTEST_HAS_PARAM_TEST.
|
||||
#include <gtest/internal/gtest-internal.h>
|
||||
#include <gtest/internal/gtest-linked_ptr.h>
|
||||
#include <gtest/internal/gtest-port.h>
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
|
||||
#if GTEST_HAS_RTTI
|
||||
#include <typeinfo>
|
||||
#endif // GTEST_HAS_RTTI
|
||||
|
||||
#include <gtest/internal/gtest-linked_ptr.h>
|
||||
#include <gtest/internal/gtest-internal.h>
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
@@ -58,26 +56,8 @@ namespace internal {
|
||||
// fixture class for the same test case. This may happen when
|
||||
// TEST_P macro is used to define two tests with the same name
|
||||
// but in different namespaces.
|
||||
void ReportInvalidTestCaseType(const char* test_case_name,
|
||||
const char* file, int line);
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Downcasts the pointer of type Base to Derived.
|
||||
// Derived must be a subclass of Base. The parameter MUST
|
||||
// point to a class of type Derived, not any subclass of it.
|
||||
// When RTTI is available, the function performs a runtime
|
||||
// check to enforce this.
|
||||
template <class Derived, class Base>
|
||||
Derived* CheckedDowncastToActualType(Base* base) {
|
||||
#if GTEST_HAS_RTTI
|
||||
GTEST_CHECK_(typeid(*base) == typeid(Derived));
|
||||
Derived* derived = dynamic_cast<Derived*>(base); // NOLINT
|
||||
#else
|
||||
Derived* derived = static_cast<Derived*>(base); // Poor man's downcast.
|
||||
#endif // GTEST_HAS_RTTI
|
||||
return derived;
|
||||
}
|
||||
GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
|
||||
const char* file, int line);
|
||||
|
||||
template <typename> class ParamGeneratorInterface;
|
||||
template <typename> class ParamGenerator;
|
||||
@@ -169,7 +149,7 @@ class ParamGeneratorInterface {
|
||||
virtual ParamIteratorInterface<T>* End() const = 0;
|
||||
};
|
||||
|
||||
// Wraps ParamGeneratorInetrface<T> and provides general generator syntax
|
||||
// Wraps ParamGeneratorInterface<T> and provides general generator syntax
|
||||
// compatible with the STL Container concept.
|
||||
// This class implements copy initialization semantics and the contained
|
||||
// ParamGeneratorInterface<T> instance is shared among all copies
|
||||
@@ -245,7 +225,8 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||
|
||||
private:
|
||||
Iterator(const Iterator& other)
|
||||
: base_(other.base_), value_(other.value_), index_(other.index_),
|
||||
: ParamIteratorInterface<T>(),
|
||||
base_(other.base_), value_(other.value_), index_(other.index_),
|
||||
step_(other.step_) {}
|
||||
|
||||
// No implementation - assignment is unsupported.
|
||||
@@ -542,12 +523,12 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||
// LocalTestInfo structure keeps information about a single test registered
|
||||
// with TEST_P macro.
|
||||
struct TestInfo {
|
||||
TestInfo(const char* test_case_base_name,
|
||||
const char* test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* test_meta_factory) :
|
||||
test_case_base_name(test_case_base_name),
|
||||
test_base_name(test_base_name),
|
||||
test_meta_factory(test_meta_factory) {}
|
||||
TestInfo(const char* a_test_case_base_name,
|
||||
const char* a_test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
|
||||
test_case_base_name(a_test_case_base_name),
|
||||
test_base_name(a_test_base_name),
|
||||
test_meta_factory(a_test_meta_factory) {}
|
||||
|
||||
const String test_case_base_name;
|
||||
const String test_base_name;
|
||||
|
||||
+570
-157
File diff suppressed because it is too large
Load Diff
@@ -41,26 +41,28 @@
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
// string.h is not guaranteed to provide strcpy on C++ Builder.
|
||||
#include <mem.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <gtest/internal/gtest-port.h>
|
||||
|
||||
#if GTEST_HAS_GLOBAL_STRING || GTEST_HAS_STD_STRING
|
||||
#include <string>
|
||||
#endif // GTEST_HAS_GLOBAL_STRING || GTEST_HAS_STD_STRING
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// String - a UTF-8 string class.
|
||||
//
|
||||
// We cannot use std::string as Microsoft's STL implementation in
|
||||
// Visual C++ 7.1 has problems when exception is disabled. There is a
|
||||
// hack to work around this, but we've seen cases where the hack fails
|
||||
// to work.
|
||||
// For historic reasons, we don't use std::string.
|
||||
//
|
||||
// Also, String is different from std::string in that it can represent
|
||||
// both NULL and the empty string, while std::string cannot represent
|
||||
// NULL.
|
||||
// TODO(wan@google.com): replace this class with std::string or
|
||||
// implement it in terms of the latter.
|
||||
//
|
||||
// Note that String can represent both NULL and the empty string,
|
||||
// while std::string cannot represent NULL.
|
||||
//
|
||||
// NULL and the empty string are considered different. NULL is less
|
||||
// than anything (including the empty string) except itself.
|
||||
@@ -76,7 +78,7 @@ namespace internal {
|
||||
//
|
||||
// In order to make the representation efficient, the d'tor of String
|
||||
// is not virtual. Therefore DO NOT INHERIT FROM String.
|
||||
class String {
|
||||
class GTEST_API_ String {
|
||||
public:
|
||||
// Static utility methods
|
||||
|
||||
@@ -190,12 +192,12 @@ class String {
|
||||
String() : c_str_(NULL), length_(0) {}
|
||||
|
||||
// Constructs a String by cloning a 0-terminated C string.
|
||||
String(const char* c_str) { // NOLINT
|
||||
if (c_str == NULL) {
|
||||
String(const char* a_c_str) { // NOLINT
|
||||
if (a_c_str == NULL) {
|
||||
c_str_ = NULL;
|
||||
length_ = 0;
|
||||
} else {
|
||||
ConstructNonNull(c_str, strlen(c_str));
|
||||
ConstructNonNull(a_c_str, strlen(a_c_str));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,8 +205,8 @@ class String {
|
||||
// buffer. E.g. String("hello", 3) creates the string "hel",
|
||||
// String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "",
|
||||
// and String(NULL, 1) results in access violation.
|
||||
String(const char* buffer, size_t length) {
|
||||
ConstructNonNull(buffer, length);
|
||||
String(const char* buffer, size_t a_length) {
|
||||
ConstructNonNull(buffer, a_length);
|
||||
}
|
||||
|
||||
// The copy c'tor creates a new copy of the string. The two
|
||||
@@ -221,13 +223,11 @@ class String {
|
||||
// Converting a ::std::string or ::string containing an embedded NUL
|
||||
// character to a String will result in the prefix up to the first
|
||||
// NUL character.
|
||||
#if GTEST_HAS_STD_STRING
|
||||
String(const ::std::string& str) {
|
||||
ConstructNonNull(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
operator ::std::string() const { return ::std::string(c_str(), length()); }
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
|
||||
#if GTEST_HAS_GLOBAL_STRING
|
||||
String(const ::string& str) {
|
||||
@@ -247,7 +247,7 @@ class String {
|
||||
|
||||
// Returns true iff this String equals the given C string. A NULL
|
||||
// string and a non-NULL string are considered not equal.
|
||||
bool operator==(const char* c_str) const { return Compare(c_str) == 0; }
|
||||
bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; }
|
||||
|
||||
// Returns true iff this String is less than the given String. A
|
||||
// NULL string is considered less than "".
|
||||
@@ -255,7 +255,7 @@ class String {
|
||||
|
||||
// Returns true iff this String doesn't equal the given C string. A NULL
|
||||
// string and a non-NULL string are considered not equal.
|
||||
bool operator!=(const char* c_str) const { return !(*this == c_str); }
|
||||
bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); }
|
||||
|
||||
// Returns true iff this String ends with the given suffix. *Any*
|
||||
// String is considered to end with a NULL or empty suffix.
|
||||
@@ -275,7 +275,9 @@ class String {
|
||||
const char* c_str() const { return c_str_; }
|
||||
|
||||
// Assigns a C string to this object. Self-assignment works.
|
||||
const String& operator=(const char* c_str) { return *this = String(c_str); }
|
||||
const String& operator=(const char* a_c_str) {
|
||||
return *this = String(a_c_str);
|
||||
}
|
||||
|
||||
// Assigns a String object to this object. Self-assignment works.
|
||||
const String& operator=(const String& rhs) {
|
||||
@@ -297,12 +299,12 @@ class String {
|
||||
// function can only be called when data_ has not been allocated.
|
||||
// ConstructNonNull(NULL, 0) results in an empty string ("").
|
||||
// ConstructNonNull(NULL, non_zero) is undefined behavior.
|
||||
void ConstructNonNull(const char* buffer, size_t length) {
|
||||
char* const str = new char[length + 1];
|
||||
memcpy(str, buffer, length);
|
||||
str[length] = '\0';
|
||||
void ConstructNonNull(const char* buffer, size_t a_length) {
|
||||
char* const str = new char[a_length + 1];
|
||||
memcpy(str, buffer, a_length);
|
||||
str[a_length] = '\0';
|
||||
c_str_ = str;
|
||||
length_ = length;
|
||||
length_ = a_length;
|
||||
}
|
||||
|
||||
const char* c_str_;
|
||||
@@ -329,7 +331,7 @@ inline ::std::ostream& operator<<(::std::ostream& os, const String& str) {
|
||||
|
||||
// Gets the content of the StrStream's buffer as a String. Each '\0'
|
||||
// character in the buffer is replaced with "\\0".
|
||||
String StrStreamToString(StrStream* stream);
|
||||
GTEST_API_ String StrStreamToString(StrStream* stream);
|
||||
|
||||
// Converts a streamable value to a String. A NULL pointer is
|
||||
// converted to "(null)". When the input value is a ::string,
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
// tuple template as a friend (it complains that tuple is redefined). This
|
||||
// hack bypasses the bug by declaring the members that should otherwise be
|
||||
// private as public.
|
||||
#if defined(__SYMBIAN32__)
|
||||
// Sun Studio versions < 12 also have the above bug.
|
||||
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
|
||||
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
|
||||
#else
|
||||
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
|
||||
@@ -183,7 +184,7 @@ class GTEST_1_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
|
||||
|
||||
@@ -215,7 +216,7 @@ class GTEST_2_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
|
||||
f1_(f1) {}
|
||||
@@ -258,7 +259,7 @@ class GTEST_3_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_(), f2_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||
GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
|
||||
@@ -295,7 +296,7 @@ class GTEST_4_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_(), f2_(), f3_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
|
||||
@@ -336,7 +337,7 @@ class GTEST_5_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
|
||||
@@ -380,7 +381,7 @@ class GTEST_6_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||
@@ -427,7 +428,7 @@ class GTEST_7_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||
@@ -476,7 +477,7 @@ class GTEST_8_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||
@@ -528,7 +529,7 @@ class GTEST_9_TUPLE_(T) {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||
@@ -582,7 +583,8 @@ class tuple {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
|
||||
f9_() {}
|
||||
|
||||
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||
|
||||
@@ -39,11 +39,12 @@ $$ This meta comment fixes auto-indentation in Emacs. }}
|
||||
|
||||
#include <utility> // For ::std::pair.
|
||||
|
||||
// The compiler used in Symbian 5th Edition (__S60_50__) has a bug
|
||||
// that prevents us from declaring the tuple template as a friend (it
|
||||
// complains that tuple is redefined). This hack bypasses the bug by
|
||||
// declaring the members that should otherwise be private as public.
|
||||
#if defined(__SYMBIAN32__) && __S60_50__
|
||||
// The compiler used in Symbian has a bug that prevents us from declaring the
|
||||
// tuple template as a friend (it complains that tuple is redefined). This
|
||||
// hack bypasses the bug by declaring the members that should otherwise be
|
||||
// private as public.
|
||||
// Sun Studio versions < 12 also have the above bug.
|
||||
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
|
||||
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
|
||||
#else
|
||||
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
|
||||
@@ -140,7 +141,7 @@ class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
|
||||
public:
|
||||
template <int k> friend class gtest_internal::Get;
|
||||
|
||||
tuple() {}
|
||||
tuple() : $for m, [[f$(m)_()]] {}
|
||||
|
||||
explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
|
||||
$for m, [[f$(m)_(f$m)]] {}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
|
||||
// This file was GENERATED by command:
|
||||
// pump.py gtest-type-util.h.pump
|
||||
// DO NOT EDIT BY HAND!!!
|
||||
|
||||
// Copyright 2008 Google Inc.
|
||||
// All Rights Reserved.
|
||||
@@ -53,8 +55,6 @@
|
||||
#include <cxxabi.h>
|
||||
#endif // __GLIBCXX__
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
|
||||
@@ -53,8 +53,6 @@ $var n = 50 $$ Maximum length of type lists we want to support.
|
||||
#include <cxxabi.h>
|
||||
#endif // __GLIBCXX__
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
|
||||
+6
-4
@@ -20,7 +20,7 @@ GTEST_DIR = ..
|
||||
USER_DIR = ../samples
|
||||
|
||||
# Flags passed to the preprocessor.
|
||||
CPPFLAGS += -I$(GTEST_DIR) -I$(GTEST_DIR)/include
|
||||
CPPFLAGS += -I$(GTEST_DIR)/include
|
||||
|
||||
# Flags passed to the C++ compiler.
|
||||
CXXFLAGS += -g -Wall -Wextra
|
||||
@@ -52,10 +52,12 @@ GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
|
||||
# conservative and not optimized. This is fine as Google Test
|
||||
# compiles fast and for ordinary users its source rarely changes.
|
||||
gtest-all.o : $(GTEST_SRCS_)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest-all.cc
|
||||
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
|
||||
$(GTEST_DIR)/src/gtest-all.cc
|
||||
|
||||
gtest_main.o : $(GTEST_SRCS_)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest_main.cc
|
||||
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
|
||||
$(GTEST_DIR)/src/gtest_main.cc
|
||||
|
||||
gtest.a : gtest-all.o
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
@@ -75,4 +77,4 @@ sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc \
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc
|
||||
|
||||
sample1_unittest : sample1.o sample1_unittest.o gtest_main.a
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
|
||||
|
||||
+8
-386
@@ -28,404 +28,26 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Runs specified tests for Google Test.
|
||||
"""Runs the specified tests for Google Test.
|
||||
|
||||
SYNOPSIS
|
||||
run_tests.py [OPTION]... [BUILD_DIR]... [TEST]...
|
||||
|
||||
DESCRIPTION
|
||||
Runs the specified tests (either binary or Python), and prints a
|
||||
summary of the results. BUILD_DIRS will be used to search for the
|
||||
binaries. If no TESTs are specified, all binary tests found in
|
||||
BUILD_DIRs and all Python tests found in the directory test/ (in the
|
||||
gtest root) are run.
|
||||
|
||||
TEST is a name of either a binary or a Python test. A binary test is
|
||||
an executable file named *_test or *_unittest (with the .exe
|
||||
extension on Windows) A Python test is a script named *_test.py or
|
||||
*_unittest.py.
|
||||
|
||||
OPTIONS
|
||||
-c CONFIGURATIONS
|
||||
Specify build directories via build configurations.
|
||||
CONFIGURATIONS is either a comma-separated list of build
|
||||
configurations or 'all'. Each configuration is equivalent to
|
||||
adding 'scons/build/<configuration>/scons' to BUILD_DIRs.
|
||||
Specifying -c=all is equivalent to providing all directories
|
||||
listed in KNOWN BUILD DIRECTORIES section below.
|
||||
|
||||
-a
|
||||
Equivalent to -c=all
|
||||
|
||||
-b
|
||||
Equivalent to -c=all with the exception that the script will not
|
||||
fail if some of the KNOWN BUILD DIRECTORIES do not exists; the
|
||||
script will simply not run the tests there. 'b' stands for
|
||||
'built directories'.
|
||||
|
||||
RETURN VALUE
|
||||
Returns 0 if all tests are successful; otherwise returns 1.
|
||||
|
||||
EXAMPLES
|
||||
run_tests.py
|
||||
Runs all tests for the default build configuration.
|
||||
|
||||
run_tests.py -a
|
||||
Runs all tests with binaries in KNOWN BUILD DIRECTORIES.
|
||||
|
||||
run_tests.py -b
|
||||
Runs all tests in KNOWN BUILD DIRECTORIES that have been
|
||||
built.
|
||||
|
||||
run_tests.py foo/
|
||||
Runs all tests in the foo/ directory and all Python tests in
|
||||
the directory test. The Python tests are instructed to look
|
||||
for binaries in foo/.
|
||||
|
||||
run_tests.py bar_test.exe test/baz_test.exe foo/ bar/
|
||||
Runs foo/bar_test.exe, bar/bar_test.exe, foo/baz_test.exe, and
|
||||
bar/baz_test.exe.
|
||||
|
||||
run_tests.py foo bar test/foo_test.py
|
||||
Runs test/foo_test.py twice instructing it to look for its
|
||||
test binaries in the directories foo and bar,
|
||||
correspondingly.
|
||||
|
||||
KNOWN BUILD DIRECTORIES
|
||||
run_tests.py knows about directories where the SCons build script
|
||||
deposits its products. These are the directories where run_tests.py
|
||||
will be looking for its binaries. Currently, gtest's SConstruct file
|
||||
defines them as follows (the default build directory is the first one
|
||||
listed in each group):
|
||||
On Windows:
|
||||
<gtest root>/scons/build/win-dbg8/scons/
|
||||
<gtest root>/scons/build/win-opt8/scons/
|
||||
<gtest root>/scons/build/win-dbg/scons/
|
||||
<gtest root>/scons/build/win-opt/scons/
|
||||
On Mac:
|
||||
<gtest root>/scons/build/mac-dbg/scons/
|
||||
<gtest root>/scons/build/mac-opt/scons/
|
||||
On other platforms:
|
||||
<gtest root>/scons/build/dbg/scons/
|
||||
<gtest root>/scons/build/opt/scons/
|
||||
|
||||
AUTHOR
|
||||
Written by Zhanyong Wan (wan@google.com)
|
||||
and Vlad Losev(vladl@google.com).
|
||||
|
||||
REQUIREMENTS
|
||||
This script requires Python 2.3 or higher.
|
||||
This script requires Python 2.3 or higher. To learn the usage, run it
|
||||
with -h.
|
||||
"""
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import re
|
||||
import sets
|
||||
import sys
|
||||
|
||||
try:
|
||||
# subrocess module is a preferable way to invoke subprocesses but it may
|
||||
# not be available on MacOS X 10.4.
|
||||
import subprocess
|
||||
except ImportError:
|
||||
subprocess = None
|
||||
SCRIPT_DIR = os.path.dirname(__file__) or '.'
|
||||
|
||||
IS_WINDOWS = os.name == 'nt'
|
||||
IS_MAC = os.name == 'posix' and os.uname()[0] == 'Darwin'
|
||||
IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
|
||||
|
||||
# Definition of CONFIGS must match that of the build directory names in the
|
||||
# SConstruct script. The first list item is the default build configuration.
|
||||
if IS_WINDOWS:
|
||||
CONFIGS = ('win-dbg8', 'win-opt8', 'win-dbg', 'win-opt')
|
||||
elif IS_MAC:
|
||||
CONFIGS = ('mac-dbg', 'mac-opt')
|
||||
else:
|
||||
CONFIGS = ('dbg', 'opt')
|
||||
|
||||
if IS_WINDOWS or IS_CYGWIN:
|
||||
PYTHON_TEST_REGEX = re.compile(r'_(unit)?test\.py$', re.IGNORECASE)
|
||||
BINARY_TEST_REGEX = re.compile(r'_(unit)?test(\.exe)?$', re.IGNORECASE)
|
||||
BINARY_TEST_SEARCH_REGEX = re.compile(r'_(unit)?test\.exe$', re.IGNORECASE)
|
||||
else:
|
||||
PYTHON_TEST_REGEX = re.compile(r'_(unit)?test\.py$')
|
||||
BINARY_TEST_REGEX = re.compile(r'_(unit)?test$')
|
||||
BINARY_TEST_SEARCH_REGEX = BINARY_TEST_REGEX
|
||||
|
||||
GTEST_BUILD_DIR = 'GTEST_BUILD_DIR'
|
||||
|
||||
|
||||
# All paths in this script are either absolute or relative to the current
|
||||
# working directory, unless otherwise specified.
|
||||
class TestRunner(object):
|
||||
"""Provides facilities for running Python and binary tests for Google Test."""
|
||||
|
||||
def __init__(self,
|
||||
injected_os=os,
|
||||
injected_subprocess=subprocess,
|
||||
injected_script_dir=os.path.dirname(__file__)):
|
||||
self.os = injected_os
|
||||
self.subprocess = injected_subprocess
|
||||
# If a program using this file is invoked via a relative path, the
|
||||
# script directory will be relative to the path of the main program
|
||||
# file. It may be '.' when this script is invoked directly or '..' when
|
||||
# it is imported for testing. To simplify testing we inject the script
|
||||
# directory into TestRunner.
|
||||
self.script_dir = injected_script_dir
|
||||
|
||||
def GetBuildDirForConfig(self, config):
|
||||
"""Returns the build directory for a given configuration."""
|
||||
|
||||
return self.os.path.normpath(
|
||||
self.os.path.join(self.script_dir, 'scons/build', config, 'scons'))
|
||||
|
||||
def Run(self, args):
|
||||
"""Runs the executable with given args (args[0] is the executable name).
|
||||
|
||||
Args:
|
||||
args: Command line arguments for the process.
|
||||
|
||||
Returns:
|
||||
Process's exit code if it exits normally, or -signal if the process is
|
||||
killed by a signal.
|
||||
"""
|
||||
|
||||
if self.subprocess:
|
||||
return self.subprocess.Popen(args).wait()
|
||||
else:
|
||||
return self.os.spawnv(self.os.P_WAIT, args[0], args)
|
||||
|
||||
def RunBinaryTest(self, test):
|
||||
"""Runs the binary test given its path.
|
||||
|
||||
Args:
|
||||
test: Path to the test binary.
|
||||
|
||||
Returns:
|
||||
Process's exit code if it exits normally, or -signal if the process is
|
||||
killed by a signal.
|
||||
"""
|
||||
|
||||
return self.Run([test])
|
||||
|
||||
def RunPythonTest(self, test, build_dir):
|
||||
"""Runs the Python test script with the specified build directory.
|
||||
|
||||
Args:
|
||||
test: Path to the test's Python script.
|
||||
build_dir: Path to the directory where the test binary is to be found.
|
||||
|
||||
Returns:
|
||||
Process's exit code if it exits normally, or -signal if the process is
|
||||
killed by a signal.
|
||||
"""
|
||||
|
||||
old_build_dir = self.os.environ.get(GTEST_BUILD_DIR)
|
||||
|
||||
try:
|
||||
self.os.environ[GTEST_BUILD_DIR] = build_dir
|
||||
|
||||
# If this script is run on a Windows machine that has no association
|
||||
# between the .py extension and a python interpreter, simply passing
|
||||
# the script name into subprocess.Popen/os.spawn will not work.
|
||||
print 'Running %s . . .' % (test,)
|
||||
return self.Run([sys.executable, test])
|
||||
|
||||
finally:
|
||||
if old_build_dir is None:
|
||||
del self.os.environ[GTEST_BUILD_DIR]
|
||||
else:
|
||||
self.os.environ[GTEST_BUILD_DIR] = old_build_dir
|
||||
|
||||
def FindFilesByRegex(self, directory, regex):
|
||||
"""Returns files in a directory whose names match a regular expression.
|
||||
|
||||
Args:
|
||||
directory: Path to the directory to search for files.
|
||||
regex: Regular expression to filter file names.
|
||||
|
||||
Returns:
|
||||
The list of the paths to the files in the directory.
|
||||
"""
|
||||
|
||||
return [self.os.path.join(directory, file_name)
|
||||
for file_name in self.os.listdir(directory)
|
||||
if re.search(regex, file_name)]
|
||||
|
||||
# TODO(vladl@google.com): Implement parsing of scons/SConscript to run all
|
||||
# tests defined there when no tests are specified.
|
||||
# TODO(vladl@google.com): Update the docstring after the code is changed to
|
||||
# try to test all builds defined in scons/SConscript.
|
||||
def GetTestsToRun(self,
|
||||
args,
|
||||
named_configurations,
|
||||
built_configurations,
|
||||
available_configurations=CONFIGS):
|
||||
"""Determines what tests should be run.
|
||||
|
||||
Args:
|
||||
args: The list of non-option arguments from the command line.
|
||||
named_configurations: The list of configurations specified via -c or -a.
|
||||
built_configurations: True if -b has been specified.
|
||||
available_configurations: a list of configurations available on the
|
||||
current platform, injectable for testing.
|
||||
|
||||
Returns:
|
||||
A tuple with 2 elements: the list of Python tests to run and the list of
|
||||
binary tests to run.
|
||||
"""
|
||||
|
||||
if named_configurations == 'all':
|
||||
named_configurations = ','.join(available_configurations)
|
||||
|
||||
normalized_args = [self.os.path.normpath(arg) for arg in args]
|
||||
|
||||
# A final list of build directories which will be searched for the test
|
||||
# binaries. First, add directories specified directly on the command
|
||||
# line.
|
||||
build_dirs = filter(self.os.path.isdir, normalized_args)
|
||||
|
||||
# Adds build directories specified via their build configurations using
|
||||
# the -c or -a options.
|
||||
if named_configurations:
|
||||
build_dirs += [self.GetBuildDirForConfig(config)
|
||||
for config in named_configurations.split(',')]
|
||||
|
||||
# Adds KNOWN BUILD DIRECTORIES if -b is specified.
|
||||
if built_configurations:
|
||||
build_dirs += [self.GetBuildDirForConfig(config)
|
||||
for config in available_configurations
|
||||
if self.os.path.isdir(self.GetBuildDirForConfig(config))]
|
||||
|
||||
# If no directories were specified either via -a, -b, -c, or directly, use
|
||||
# the default configuration.
|
||||
elif not build_dirs:
|
||||
build_dirs = [self.GetBuildDirForConfig(available_configurations[0])]
|
||||
|
||||
# Makes sure there are no duplications.
|
||||
build_dirs = sets.Set(build_dirs)
|
||||
|
||||
errors_found = False
|
||||
listed_python_tests = [] # All Python tests listed on the command line.
|
||||
listed_binary_tests = [] # All binary tests listed on the command line.
|
||||
|
||||
test_dir = self.os.path.normpath(self.os.path.join(self.script_dir, 'test'))
|
||||
|
||||
# Sifts through non-directory arguments fishing for any Python or binary
|
||||
# tests and detecting errors.
|
||||
for argument in sets.Set(normalized_args) - build_dirs:
|
||||
if re.search(PYTHON_TEST_REGEX, argument):
|
||||
python_path = self.os.path.join(test_dir,
|
||||
self.os.path.basename(argument))
|
||||
if self.os.path.isfile(python_path):
|
||||
listed_python_tests.append(python_path)
|
||||
else:
|
||||
sys.stderr.write('Unable to find Python test %s' % argument)
|
||||
errors_found = True
|
||||
elif re.search(BINARY_TEST_REGEX, argument):
|
||||
# This script also accepts binary test names prefixed with test/ for
|
||||
# the convenience of typing them (can use path completions in the
|
||||
# shell). Strips test/ prefix from the binary test names.
|
||||
listed_binary_tests.append(self.os.path.basename(argument))
|
||||
else:
|
||||
sys.stderr.write('%s is neither test nor build directory' % argument)
|
||||
errors_found = True
|
||||
|
||||
if errors_found:
|
||||
return None
|
||||
|
||||
user_has_listed_tests = listed_python_tests or listed_binary_tests
|
||||
|
||||
if user_has_listed_tests:
|
||||
selected_python_tests = listed_python_tests
|
||||
else:
|
||||
selected_python_tests = self.FindFilesByRegex(test_dir, PYTHON_TEST_REGEX)
|
||||
|
||||
# TODO(vladl@google.com): skip unbuilt Python tests when -b is specified.
|
||||
python_test_pairs = []
|
||||
for directory in build_dirs:
|
||||
for test in selected_python_tests:
|
||||
python_test_pairs.append((directory, test))
|
||||
|
||||
binary_test_pairs = []
|
||||
for directory in build_dirs:
|
||||
if user_has_listed_tests:
|
||||
binary_test_pairs.extend(
|
||||
[(directory, self.os.path.join(directory, test))
|
||||
for test in listed_binary_tests])
|
||||
else:
|
||||
tests = self.FindFilesByRegex(directory, BINARY_TEST_SEARCH_REGEX)
|
||||
binary_test_pairs.extend([(directory, test) for test in tests])
|
||||
|
||||
return (python_test_pairs, binary_test_pairs)
|
||||
|
||||
def RunTests(self, python_tests, binary_tests):
|
||||
"""Runs Python and binary tests and reports results to the standard output.
|
||||
|
||||
Args:
|
||||
python_tests: List of Python tests to run in the form of tuples
|
||||
(build directory, Python test script).
|
||||
binary_tests: List of binary tests to run in the form of tuples
|
||||
(build directory, binary file).
|
||||
|
||||
Returns:
|
||||
The exit code the program should pass into sys.exit().
|
||||
"""
|
||||
|
||||
if python_tests or binary_tests:
|
||||
results = []
|
||||
for directory, test in python_tests:
|
||||
results.append((directory,
|
||||
test,
|
||||
self.RunPythonTest(test, directory) == 0))
|
||||
for directory, test in binary_tests:
|
||||
results.append((directory,
|
||||
self.os.path.basename(test),
|
||||
self.RunBinaryTest(test) == 0))
|
||||
|
||||
failed = [(directory, test)
|
||||
for (directory, test, success) in results
|
||||
if not success]
|
||||
print
|
||||
print '%d tests run.' % len(results)
|
||||
if failed:
|
||||
print 'The following %d tests failed:' % len(failed)
|
||||
for (directory, test) in failed:
|
||||
print '%s in %s' % (test, directory)
|
||||
return 1
|
||||
else:
|
||||
print 'All tests passed!'
|
||||
else: # No tests defined
|
||||
print 'Nothing to test - no tests specified!'
|
||||
|
||||
return 0
|
||||
sys.path.append(os.path.join(SCRIPT_DIR, 'test'))
|
||||
import run_tests_util
|
||||
|
||||
|
||||
def _Main():
|
||||
"""Runs all tests for Google Test."""
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-c',
|
||||
action='store',
|
||||
dest='configurations',
|
||||
default=None,
|
||||
help='Test in the specified build directories')
|
||||
parser.add_option('-a',
|
||||
action='store_const',
|
||||
dest='configurations',
|
||||
default=None,
|
||||
const='all',
|
||||
help='Test in all default build directories')
|
||||
parser.add_option('-b',
|
||||
action='store_const',
|
||||
dest='built_configurations',
|
||||
default=False,
|
||||
const=True,
|
||||
help=('Test in all default build directories, do not fail'
|
||||
'if some of them do not exist'))
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
test_runner = TestRunner()
|
||||
options, args = run_tests_util.ParseArgs('gtest')
|
||||
test_runner = run_tests_util.TestRunner(script_dir=SCRIPT_DIR)
|
||||
tests = test_runner.GetTestsToRun(args,
|
||||
options.configurations,
|
||||
options.built_configurations)
|
||||
|
||||
@@ -115,6 +115,9 @@ class PreCalculatedPrimeTable : public PrimeTable {
|
||||
|
||||
const int is_prime_size_;
|
||||
bool* const is_prime_;
|
||||
|
||||
// Disables compiler warning "assignment operator could not be generated."
|
||||
void operator=(const PreCalculatedPrimeTable& rhs);
|
||||
};
|
||||
|
||||
#endif // GTEST_SAMPLES_PRIME_TABLES_H_
|
||||
|
||||
@@ -58,7 +58,7 @@ class Water {
|
||||
return malloc(allocation_size);
|
||||
}
|
||||
|
||||
void operator delete(void* block, size_t allocation_size) {
|
||||
void operator delete(void* block, size_t /* allocation_size */) {
|
||||
allocated_--;
|
||||
free(block);
|
||||
}
|
||||
@@ -78,12 +78,12 @@ int Water::allocated_ = 0;
|
||||
class LeakChecker : public EmptyTestEventListener {
|
||||
private:
|
||||
// Called before a test starts.
|
||||
virtual void OnTestStart(const TestInfo& test_info) {
|
||||
virtual void OnTestStart(const TestInfo& /* test_info */) {
|
||||
initially_allocated_ = Water::allocated();
|
||||
}
|
||||
|
||||
// Called after a test ends.
|
||||
virtual void OnTestEnd(const TestInfo& test_info) {
|
||||
virtual void OnTestEnd(const TestInfo& /* test_info */) {
|
||||
int difference = Water::allocated() - initially_allocated_;
|
||||
|
||||
// You can generate a failure in any event handler except
|
||||
|
||||
+7
-7
@@ -36,21 +36,21 @@
|
||||
#include <string.h>
|
||||
|
||||
// Clones a 0-terminated C string, allocating memory using new.
|
||||
const char * MyString::CloneCString(const char * c_string) {
|
||||
if (c_string == NULL) return NULL;
|
||||
const char* MyString::CloneCString(const char* a_c_string) {
|
||||
if (a_c_string == NULL) return NULL;
|
||||
|
||||
const size_t len = strlen(c_string);
|
||||
char * const clone = new char[ len + 1 ];
|
||||
memcpy(clone, c_string, len + 1);
|
||||
const size_t len = strlen(a_c_string);
|
||||
char* const clone = new char[ len + 1 ];
|
||||
memcpy(clone, a_c_string, len + 1);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Sets the 0-terminated C string this MyString object
|
||||
// represents.
|
||||
void MyString::Set(const char * c_string) {
|
||||
void MyString::Set(const char* a_c_string) {
|
||||
// Makes sure this works when c_string == c_string_
|
||||
const char * const temp = MyString::CloneCString(c_string);
|
||||
const char* const temp = MyString::CloneCString(a_c_string);
|
||||
delete[] c_string_;
|
||||
c_string_ = temp;
|
||||
}
|
||||
|
||||
+6
-6
@@ -40,13 +40,13 @@
|
||||
// A simple string class.
|
||||
class MyString {
|
||||
private:
|
||||
const char * c_string_;
|
||||
const char* c_string_;
|
||||
const MyString& operator=(const MyString& rhs);
|
||||
|
||||
public:
|
||||
|
||||
// Clones a 0-terminated C string, allocating memory using new.
|
||||
static const char * CloneCString(const char * c_string);
|
||||
static const char* CloneCString(const char* a_c_string);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -56,8 +56,8 @@ class MyString {
|
||||
MyString() : c_string_(NULL) {}
|
||||
|
||||
// Constructs a MyString by cloning a 0-terminated C string.
|
||||
explicit MyString(const char * c_string) : c_string_(NULL) {
|
||||
Set(c_string);
|
||||
explicit MyString(const char* a_c_string) : c_string_(NULL) {
|
||||
Set(a_c_string);
|
||||
}
|
||||
|
||||
// Copy c'tor
|
||||
@@ -72,14 +72,14 @@ class MyString {
|
||||
~MyString() { delete[] c_string_; }
|
||||
|
||||
// Gets the 0-terminated C string this MyString object represents.
|
||||
const char * c_string() const { return c_string_; }
|
||||
const char* c_string() const { return c_string_; }
|
||||
|
||||
size_t Length() const {
|
||||
return c_string_ == NULL ? 0 : strlen(c_string_);
|
||||
}
|
||||
|
||||
// Sets the 0-terminated C string this MyString object represents.
|
||||
void Set(const char * c_string);
|
||||
void Set(const char* c_string);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ TEST(MyString, DefaultConstructor) {
|
||||
// </TechnicalDetails>
|
||||
EXPECT_STREQ(NULL, s.c_string());
|
||||
|
||||
EXPECT_EQ(0, s.Length());
|
||||
EXPECT_EQ(0u, s.Length());
|
||||
}
|
||||
|
||||
const char kHelloString[] = "Hello, world!";
|
||||
|
||||
+25
-25
@@ -51,23 +51,23 @@ class QueueNode {
|
||||
|
||||
public:
|
||||
// Gets the element in this node.
|
||||
const E & element() const { return element_; }
|
||||
const E& element() const { return element_; }
|
||||
|
||||
// Gets the next node in the queue.
|
||||
QueueNode * next() { return next_; }
|
||||
const QueueNode * next() const { return next_; }
|
||||
QueueNode* next() { return next_; }
|
||||
const QueueNode* next() const { return next_; }
|
||||
|
||||
private:
|
||||
// Creates a node with a given element value. The next pointer is
|
||||
// set to NULL.
|
||||
QueueNode(const E & element) : element_(element), next_(NULL) {}
|
||||
QueueNode(const E& an_element) : element_(an_element), next_(NULL) {}
|
||||
|
||||
// We disable the default assignment operator and copy c'tor.
|
||||
const QueueNode & operator = (const QueueNode &);
|
||||
QueueNode(const QueueNode &);
|
||||
const QueueNode& operator = (const QueueNode&);
|
||||
QueueNode(const QueueNode&);
|
||||
|
||||
E element_;
|
||||
QueueNode * next_;
|
||||
QueueNode* next_;
|
||||
};
|
||||
|
||||
template <typename E> // E is the element type.
|
||||
@@ -84,8 +84,8 @@ public:
|
||||
void Clear() {
|
||||
if (size_ > 0) {
|
||||
// 1. Deletes every node.
|
||||
QueueNode<E> * node = head_;
|
||||
QueueNode<E> * next = node->next();
|
||||
QueueNode<E>* node = head_;
|
||||
QueueNode<E>* next = node->next();
|
||||
for (; ;) {
|
||||
delete node;
|
||||
node = next;
|
||||
@@ -103,19 +103,19 @@ public:
|
||||
size_t Size() const { return size_; }
|
||||
|
||||
// Gets the first element of the queue, or NULL if the queue is empty.
|
||||
QueueNode<E> * Head() { return head_; }
|
||||
const QueueNode<E> * Head() const { return head_; }
|
||||
QueueNode<E>* Head() { return head_; }
|
||||
const QueueNode<E>* Head() const { return head_; }
|
||||
|
||||
// Gets the last element of the queue, or NULL if the queue is empty.
|
||||
QueueNode<E> * Last() { return last_; }
|
||||
const QueueNode<E> * Last() const { return last_; }
|
||||
QueueNode<E>* Last() { return last_; }
|
||||
const QueueNode<E>* Last() const { return last_; }
|
||||
|
||||
// Adds an element to the end of the queue. A copy of the element is
|
||||
// created using the copy constructor, and then stored in the queue.
|
||||
// Changes made to the element in the queue doesn't affect the source
|
||||
// object, and vice versa.
|
||||
void Enqueue(const E & element) {
|
||||
QueueNode<E> * new_node = new QueueNode<E>(element);
|
||||
void Enqueue(const E& element) {
|
||||
QueueNode<E>* new_node = new QueueNode<E>(element);
|
||||
|
||||
if (size_ == 0) {
|
||||
head_ = last_ = new_node;
|
||||
@@ -129,19 +129,19 @@ public:
|
||||
|
||||
// Removes the head of the queue and returns it. Returns NULL if
|
||||
// the queue is empty.
|
||||
E * Dequeue() {
|
||||
E* Dequeue() {
|
||||
if (size_ == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const QueueNode<E> * const old_head = head_;
|
||||
const QueueNode<E>* const old_head = head_;
|
||||
head_ = head_->next_;
|
||||
size_--;
|
||||
if (size_ == 0) {
|
||||
last_ = NULL;
|
||||
}
|
||||
|
||||
E * element = new E(old_head->element());
|
||||
E* element = new E(old_head->element());
|
||||
delete old_head;
|
||||
|
||||
return element;
|
||||
@@ -151,9 +151,9 @@ public:
|
||||
// returns the result in a new queue. The original queue is not
|
||||
// affected.
|
||||
template <typename F>
|
||||
Queue * Map(F function) const {
|
||||
Queue * new_queue = new Queue();
|
||||
for (const QueueNode<E> * node = head_; node != NULL; node = node->next_) {
|
||||
Queue* Map(F function) const {
|
||||
Queue* new_queue = new Queue();
|
||||
for (const QueueNode<E>* node = head_; node != NULL; node = node->next_) {
|
||||
new_queue->Enqueue(function(node->element()));
|
||||
}
|
||||
|
||||
@@ -161,13 +161,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
QueueNode<E> * head_; // The first node of the queue.
|
||||
QueueNode<E> * last_; // The last node of the queue.
|
||||
QueueNode<E>* head_; // The first node of the queue.
|
||||
QueueNode<E>* last_; // The last node of the queue.
|
||||
size_t size_; // The number of elements in the queue.
|
||||
|
||||
// We disallow copying a queue.
|
||||
Queue(const Queue &);
|
||||
const Queue & operator = (const Queue &);
|
||||
Queue(const Queue&);
|
||||
const Queue& operator = (const Queue&);
|
||||
};
|
||||
|
||||
#endif // GTEST_SAMPLES_SAMPLE3_INL_H_
|
||||
|
||||
@@ -122,7 +122,7 @@ class QueueTest : public testing::Test {
|
||||
// Tests the default c'tor.
|
||||
TEST_F(QueueTest, DefaultConstructor) {
|
||||
// You can access data in the test fixture here.
|
||||
EXPECT_EQ(0, q0_.Size());
|
||||
EXPECT_EQ(0u, q0_.Size());
|
||||
}
|
||||
|
||||
// Tests Dequeue().
|
||||
@@ -133,13 +133,13 @@ TEST_F(QueueTest, Dequeue) {
|
||||
n = q1_.Dequeue();
|
||||
ASSERT_TRUE(n != NULL);
|
||||
EXPECT_EQ(1, *n);
|
||||
EXPECT_EQ(0, q1_.Size());
|
||||
EXPECT_EQ(0u, q1_.Size());
|
||||
delete n;
|
||||
|
||||
n = q2_.Dequeue();
|
||||
ASSERT_TRUE(n != NULL);
|
||||
EXPECT_EQ(2, *n);
|
||||
EXPECT_EQ(1, q2_.Size());
|
||||
EXPECT_EQ(1u, q2_.Size());
|
||||
delete n;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,24 +171,24 @@ class QueueTest : public QuickTest {
|
||||
|
||||
// Tests the default constructor.
|
||||
TEST_F(QueueTest, DefaultConstructor) {
|
||||
EXPECT_EQ(0, q0_.Size());
|
||||
EXPECT_EQ(0u, q0_.Size());
|
||||
}
|
||||
|
||||
// Tests Dequeue().
|
||||
TEST_F(QueueTest, Dequeue) {
|
||||
int * n = q0_.Dequeue();
|
||||
int* n = q0_.Dequeue();
|
||||
EXPECT_TRUE(n == NULL);
|
||||
|
||||
n = q1_.Dequeue();
|
||||
EXPECT_TRUE(n != NULL);
|
||||
EXPECT_EQ(1, *n);
|
||||
EXPECT_EQ(0, q1_.Size());
|
||||
EXPECT_EQ(0u, q1_.Size());
|
||||
delete n;
|
||||
|
||||
n = q2_.Dequeue();
|
||||
EXPECT_TRUE(n != NULL);
|
||||
EXPECT_EQ(2, *n);
|
||||
EXPECT_EQ(1, q2_.Size());
|
||||
EXPECT_EQ(1u, q2_.Size());
|
||||
delete n;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,12 +121,12 @@ INSTANTIATE_TEST_CASE_P(
|
||||
|
||||
#else
|
||||
|
||||
// Google Test doesn't support value-parameterized tests on some platforms
|
||||
// and compilers, such as MSVC 7.1. If we use conditional compilation to
|
||||
// compile out all code referring to the gtest_main library, MSVC linker
|
||||
// will not link that library at all and consequently complain about
|
||||
// missing entry point defined in that library (fatal error LNK1561:
|
||||
// entry point must be defined). This dummy test keeps gtest_main linked in.
|
||||
// Google Test may not support value-parameterized tests with some
|
||||
// compilers. If we use conditional compilation to compile out all
|
||||
// code referring to the gtest_main library, MSVC linker will not link
|
||||
// that library at all and consequently complain about missing entry
|
||||
// point defined in that library (fatal error LNK1561: entry point
|
||||
// must be defined). This dummy test keeps gtest_main linked in.
|
||||
TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
|
||||
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
|
||||
@@ -162,12 +162,12 @@ INSTANTIATE_TEST_CASE_P(MeaningfulTestParameters,
|
||||
|
||||
#else
|
||||
|
||||
// Google Test doesn't support Combine() on some platforms and compilers,
|
||||
// such as MSVC 7.1. If we use conditional compilation to compile out
|
||||
// all code referring to the gtest_main library, MSVC linker will not
|
||||
// link that library at all and consequently complain about missing entry
|
||||
// point defined in that library (fatal error LNK1561: entry point must
|
||||
// be defined). This dummy test keeps gtest_main linked in.
|
||||
// Google Test may not support Combine() with some compilers. If we
|
||||
// use conditional compilation to compile out all code referring to
|
||||
// the gtest_main library, MSVC linker will not link that library at
|
||||
// all and consequently complain about missing entry point defined in
|
||||
// that library (fatal error LNK1561: entry point must be
|
||||
// defined). This dummy test keeps gtest_main linked in.
|
||||
TEST(DummyTest, CombineIsNotSupportedOnThisPlatform) {}
|
||||
|
||||
#endif // GTEST_HAS_COMBINE
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace {
|
||||
class TersePrinter : public EmptyTestEventListener {
|
||||
private:
|
||||
// Called before any test activity starts.
|
||||
virtual void OnTestProgramStart(const UnitTest& unit_test) {}
|
||||
virtual void OnTestProgramStart(const UnitTest& /* unit_test */) {}
|
||||
|
||||
// Called after all test activities have ended.
|
||||
virtual void OnTestProgramEnd(const UnitTest& unit_test) {
|
||||
|
||||
@@ -1,325 +0,0 @@
|
||||
# -*- Python -*-
|
||||
# Copyright 2008 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.
|
||||
|
||||
|
||||
"""Builds the Google Test (gtest) lib. This has been tested on Windows,
|
||||
Linux, Mac OS X, and Cygwin. The compilation settings from your project
|
||||
will be used, with some specific flags required for gtest added.
|
||||
|
||||
You should be able to call this file from more or less any SConscript
|
||||
file.
|
||||
|
||||
You can optionally set a variable on the construction environment to
|
||||
have the unit test executables copied to your output directory. The
|
||||
variable should be env['EXE_OUTPUT'].
|
||||
|
||||
Another optional variable is env['LIB_OUTPUT']. If set, the generated
|
||||
libraries are copied to the folder indicated by the variable.
|
||||
|
||||
If you place the gtest sources within your own project's source
|
||||
directory, you should be able to call this SConscript file simply as
|
||||
follows:
|
||||
|
||||
# -- cut here --
|
||||
# Build gtest library; first tell it where to copy executables.
|
||||
env['EXE_OUTPUT'] = '#/mybuilddir/mybuildmode' # example, optional
|
||||
env['LIB_OUTPUT'] = '#/mybuilddir/mybuildmode/lib'
|
||||
env.SConscript('whateverpath/gtest/scons/SConscript')
|
||||
# -- cut here --
|
||||
|
||||
If on the other hand you place the gtest sources in a directory
|
||||
outside of your project's source tree, you would use a snippet similar
|
||||
to the following:
|
||||
|
||||
# -- cut here --
|
||||
|
||||
# The following assumes that $BUILD_DIR refers to the root of the
|
||||
# directory for your current build mode, e.g. "#/mybuilddir/mybuildmode"
|
||||
|
||||
# Build gtest library; as it is outside of our source root, we need to
|
||||
# tell SCons that the directory it will refer to as
|
||||
# e.g. $BUILD_DIR/gtest is actually on disk in original form as
|
||||
# ../../gtest (relative to your project root directory). Recall that
|
||||
# SCons by default copies all source files into the build directory
|
||||
# before building.
|
||||
gtest_dir = env.Dir('$BUILD_DIR/gtest')
|
||||
|
||||
# Modify this part to point to gtest relative to the current
|
||||
# SConscript or SConstruct file's directory. The ../.. path would
|
||||
# be different per project, to locate the base directory for gtest.
|
||||
gtest_dir.addRepository(env.Dir('../../gtest'))
|
||||
|
||||
# Tell the gtest SCons file where to copy executables.
|
||||
env['EXE_OUTPUT'] = '$BUILD_DIR' # example, optional
|
||||
|
||||
# Call the gtest SConscript to build gtest.lib and unit tests. The
|
||||
# location of the library should end up as
|
||||
# '$BUILD_DIR/gtest/scons/gtest.lib'
|
||||
env.SConscript(env.File('scons/SConscript', gtest_dir))
|
||||
|
||||
# -- cut here --
|
||||
"""
|
||||
|
||||
|
||||
__author__ = 'joi@google.com (Joi Sigurdsson)'
|
||||
|
||||
|
||||
import os
|
||||
|
||||
############################################################
|
||||
# Environments for building the targets, sorted by name.
|
||||
|
||||
Import('env', 'EnvCreator')
|
||||
|
||||
env = EnvCreator.Create(env)
|
||||
|
||||
# Note: The relative paths in SConscript files are relative to the location
|
||||
# of the SConscript file itself. To make a path relative to the location of
|
||||
# the main SConstruct file, prepend the path with the # sign.
|
||||
#
|
||||
# But if a project uses variant builds without source duplication, the above
|
||||
# rule gets muddied a bit. In that case the paths must be counted from the
|
||||
# location of the copy of the SConscript file in scons/build/<config>/scons.
|
||||
#
|
||||
# Include paths to gtest headers are relative to either the gtest
|
||||
# directory or the 'include' subdirectory of it, and this SConscript
|
||||
# file is one directory deeper than the gtest directory.
|
||||
env.Prepend(CPPPATH = ['..', '../include'])
|
||||
|
||||
env_use_own_tuple = EnvCreator.Create(env, EnvCreator.UseOwnTuple)
|
||||
env_less_optimized = EnvCreator.Create(env, EnvCreator.LessOptimized)
|
||||
env_with_threads = EnvCreator.Create(env, EnvCreator.WithThreads)
|
||||
# The following environments are used to compile gtest_unittest.cc, which
|
||||
# triggers a warning in all but the most recent GCC versions when compiling
|
||||
# the EXPECT_EQ(NULL, ptr) statement.
|
||||
env_warning_ok = EnvCreator.Create(env, EnvCreator.WarningOk)
|
||||
env_with_exceptions = EnvCreator.Create(env_warning_ok,
|
||||
EnvCreator.WithExceptions)
|
||||
env_without_rtti = EnvCreator.Create(env_warning_ok, EnvCreator.NoRtti)
|
||||
|
||||
############################################################
|
||||
# Helpers for creating build targets.
|
||||
|
||||
# Caches object file targets built by GtestObject to allow passing the
|
||||
# same source file with the same environment twice into the function as a
|
||||
# convenience.
|
||||
_all_objects = {}
|
||||
|
||||
def GtestObject(build_env, source):
|
||||
"""Returns a target to build an object file from the given .cc source file."""
|
||||
|
||||
object_name = os.path.basename(source).rstrip('.cc') + build_env['OBJ_SUFFIX']
|
||||
if object_name not in _all_objects:
|
||||
_all_objects[object_name] = build_env.Object(target=object_name,
|
||||
source=source)
|
||||
return _all_objects[object_name]
|
||||
|
||||
|
||||
def GtestStaticLibraries(build_env):
|
||||
"""Builds static libraries for gtest and gtest_main in build_env.
|
||||
|
||||
Args:
|
||||
build_env: An environment in which to build libraries.
|
||||
|
||||
Returns:
|
||||
A pair (gtest library, gtest_main library) built in the given environment.
|
||||
"""
|
||||
|
||||
gtest_object = GtestObject(build_env, '../src/gtest-all.cc')
|
||||
gtest_main_object = GtestObject(build_env, '../src/gtest_main.cc')
|
||||
|
||||
return (build_env.StaticLibrary(target='gtest' + build_env['OBJ_SUFFIX'],
|
||||
source=[gtest_object]),
|
||||
build_env.StaticLibrary(target='gtest_main' + build_env['OBJ_SUFFIX'],
|
||||
source=[gtest_object, gtest_main_object]))
|
||||
|
||||
|
||||
def GtestBinary(build_env, target, gtest_libs, sources):
|
||||
"""Creates a target to build a binary (either test or sample).
|
||||
|
||||
Args:
|
||||
build_env: The SCons construction environment to use to build.
|
||||
target: The basename of the target's main source file, also used as the
|
||||
target name.
|
||||
gtest_libs: The gtest library or the list of libraries to link.
|
||||
sources: A list of source files in the target.
|
||||
"""
|
||||
srcs = [] # The object targets corresponding to sources.
|
||||
for src in sources:
|
||||
if type(src) is str:
|
||||
srcs.append(GtestObject(build_env, src))
|
||||
else:
|
||||
srcs.append(src)
|
||||
|
||||
if not gtest_libs:
|
||||
gtest_libs = []
|
||||
elif type(gtest_libs) != type(list()):
|
||||
gtest_libs = [gtest_libs]
|
||||
binary = build_env.Program(target=target, source=srcs, LIBS=gtest_libs)
|
||||
if 'EXE_OUTPUT' in build_env.Dictionary():
|
||||
build_env.Install('$EXE_OUTPUT', source=[binary])
|
||||
|
||||
|
||||
def GtestTest(build_env, target, gtest_libs, additional_sources=None):
|
||||
"""Creates a target to build the given test.
|
||||
|
||||
Args:
|
||||
build_env: The SCons construction environment to use to build.
|
||||
target: The basename of the target test .cc file.
|
||||
gtest_libs: The gtest library or the list of libraries to use.
|
||||
additional_sources: A list of additional source files in the target.
|
||||
"""
|
||||
|
||||
GtestBinary(build_env, target, gtest_libs,
|
||||
['../test/%s.cc' % target] + (additional_sources or []))
|
||||
|
||||
|
||||
def GtestSample(build_env, target, additional_sources=None):
|
||||
"""Creates a target to build the given sample.
|
||||
|
||||
Args:
|
||||
build_env: The SCons construction environment to use to build.
|
||||
target: The basename of the target sample .cc file.
|
||||
gtest_libs: The gtest library or the list of libraries to use.
|
||||
additional_sources: A list of additional source files in the target.
|
||||
"""
|
||||
GtestBinary(build_env, target, gtest_main,
|
||||
['../samples/%s.cc' % target] + (additional_sources or []))
|
||||
|
||||
|
||||
############################################################
|
||||
# Object and library targets.
|
||||
|
||||
# gtest.lib to be used by most apps (if you have your own main function).
|
||||
# gtest_main.lib can be used if you just want a basic main function; it is also
|
||||
# used by some tests for Google Test itself.
|
||||
gtest, gtest_main = GtestStaticLibraries(env)
|
||||
gtest_ex, gtest_main_ex = GtestStaticLibraries(env_with_exceptions)
|
||||
gtest_no_rtti, gtest_main_no_rtti = GtestStaticLibraries(env_without_rtti)
|
||||
gtest_use_own_tuple, gtest_use_own_tuple_main = GtestStaticLibraries(
|
||||
env_use_own_tuple)
|
||||
|
||||
# Install the libraries if needed.
|
||||
if 'LIB_OUTPUT' in env.Dictionary():
|
||||
env.Install('$LIB_OUTPUT', source=[gtest, gtest_main,
|
||||
gtest_ex, gtest_main_ex,
|
||||
gtest_no_rtti, gtest_main_no_rtti,
|
||||
gtest_use_own_tuple,
|
||||
gtest_use_own_tuple_main])
|
||||
|
||||
############################################################
|
||||
# Test targets using the standard environment.
|
||||
|
||||
GtestTest(env, 'gtest-filepath_test', gtest_main)
|
||||
GtestTest(env, 'gtest-message_test', gtest_main)
|
||||
GtestTest(env, 'gtest-options_test', gtest_main)
|
||||
GtestTest(env, 'gtest_environment_test', gtest)
|
||||
GtestTest(env, 'gtest_main_unittest', gtest_main)
|
||||
GtestTest(env, 'gtest_no_test_unittest', gtest)
|
||||
GtestTest(env, 'gtest_pred_impl_unittest', gtest_main)
|
||||
GtestTest(env, 'gtest_prod_test', gtest_main,
|
||||
additional_sources=['../test/production.cc'])
|
||||
GtestTest(env, 'gtest_repeat_test', gtest)
|
||||
GtestTest(env, 'gtest_sole_header_test', gtest_main)
|
||||
GtestTest(env, 'gtest-test-part_test', gtest_main)
|
||||
GtestTest(env, 'gtest-typed-test_test', gtest_main,
|
||||
additional_sources=['../test/gtest-typed-test2_test.cc'])
|
||||
GtestTest(env, 'gtest-param-test_test', gtest,
|
||||
additional_sources=['../test/gtest-param-test2_test.cc'])
|
||||
GtestTest(env, 'gtest_color_test_', gtest)
|
||||
GtestTest(env, 'gtest-linked_ptr_test', gtest_main)
|
||||
GtestTest(env, 'gtest-port_test', gtest_main)
|
||||
GtestTest(env, 'gtest_break_on_failure_unittest_', gtest)
|
||||
GtestTest(env, 'gtest_filter_unittest_', gtest)
|
||||
GtestTest(env, 'gtest_help_test_', gtest_main)
|
||||
GtestTest(env, 'gtest_list_tests_unittest_', gtest)
|
||||
GtestTest(env, 'gtest_throw_on_failure_test_', gtest)
|
||||
GtestTest(env, 'gtest_xml_outfile1_test_', gtest_main)
|
||||
GtestTest(env, 'gtest_xml_outfile2_test_', gtest_main)
|
||||
GtestTest(env, 'gtest_xml_output_unittest_', gtest)
|
||||
GtestTest(env, 'gtest-unittest-api_test', gtest)
|
||||
GtestTest(env, 'gtest-listener_test', gtest)
|
||||
GtestTest(env, 'gtest_shuffle_test_', gtest)
|
||||
|
||||
############################################################
|
||||
# Tests targets using custom environments.
|
||||
|
||||
GtestTest(env_warning_ok, 'gtest_unittest', gtest_main)
|
||||
GtestTest(env_with_exceptions, 'gtest_output_test_', gtest_ex)
|
||||
GtestTest(env_with_exceptions, 'gtest_throw_on_failure_ex_test', gtest_ex)
|
||||
GtestTest(env_with_threads, 'gtest-death-test_test', gtest_main)
|
||||
GtestTest(env_less_optimized, 'gtest_env_var_test_', gtest)
|
||||
GtestTest(env_less_optimized, 'gtest_uninitialized_test_', gtest)
|
||||
GtestTest(env_use_own_tuple, 'gtest-tuple_test', gtest_use_own_tuple_main)
|
||||
GtestBinary(env_use_own_tuple,
|
||||
'gtest_use_own_tuple_test',
|
||||
gtest_use_own_tuple_main,
|
||||
['../test/gtest-param-test_test.cc',
|
||||
'../test/gtest-param-test2_test.cc'])
|
||||
GtestBinary(env_with_exceptions, 'gtest_ex_unittest', gtest_main_ex,
|
||||
['../test/gtest_unittest.cc'])
|
||||
GtestBinary(env_without_rtti, 'gtest_no_rtti_test', gtest_main_no_rtti,
|
||||
['../test/gtest_unittest.cc'])
|
||||
|
||||
############################################################
|
||||
# Sample targets.
|
||||
|
||||
# Use the GTEST_BUILD_SAMPLES build variable to control building of samples.
|
||||
# In your SConstruct file, add
|
||||
# vars = Variables()
|
||||
# vars.Add(BoolVariable('GTEST_BUILD_SAMPLES', 'Build samples', False))
|
||||
# my_environment = Environment(variables = vars, ...)
|
||||
# Then, in the command line use GTEST_BUILD_SAMPLES=true to enable them.
|
||||
if env.get('GTEST_BUILD_SAMPLES', False):
|
||||
GtestSample(env, 'sample1_unittest',
|
||||
additional_sources=['../samples/sample1.cc'])
|
||||
GtestSample(env, 'sample2_unittest',
|
||||
additional_sources=['../samples/sample2.cc'])
|
||||
GtestSample(env, 'sample3_unittest')
|
||||
GtestSample(env, 'sample4_unittest',
|
||||
additional_sources=['../samples/sample4.cc'])
|
||||
GtestSample(env, 'sample5_unittest',
|
||||
additional_sources=['../samples/sample1.cc'])
|
||||
GtestSample(env, 'sample6_unittest')
|
||||
GtestSample(env, 'sample7_unittest')
|
||||
GtestSample(env, 'sample8_unittest')
|
||||
GtestSample(env, 'sample9_unittest')
|
||||
GtestSample(env, 'sample10_unittest')
|
||||
|
||||
# These exports are used by Google Mock.
|
||||
gtest_exports = {'gtest': gtest,
|
||||
'gtest_ex': gtest_ex,
|
||||
'gtest_no_rtti': gtest_no_rtti,
|
||||
'gtest_use_own_tuple': gtest_use_own_tuple,
|
||||
'EnvCreator': EnvCreator,
|
||||
'GtestObject': GtestObject,
|
||||
'GtestBinary': GtestBinary,
|
||||
'GtestTest': GtestTest}
|
||||
# Makes the gtest_exports dictionary available to the invoking SConstruct.
|
||||
Return('gtest_exports')
|
||||
@@ -1,356 +0,0 @@
|
||||
# -*- Python -*-
|
||||
# Copyright 2008 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: joi@google.com (Joi Sigurdsson)
|
||||
# Author: vladl@google.com (Vlad Losev)
|
||||
#
|
||||
# Shared SCons utilities for building Google Test inside and outside of
|
||||
# Google's environment.
|
||||
#
|
||||
|
||||
EnsurePythonVersion(2, 3)
|
||||
|
||||
|
||||
BUILD_DIR_PREFIX = 'build'
|
||||
|
||||
|
||||
class SConstructHelper:
|
||||
def __init__(self):
|
||||
# A dictionary to look up an environment by its name.
|
||||
self.env_dict = {}
|
||||
|
||||
def Initialize(self, build_root_path, support_multiple_win_builds=False):
|
||||
test_env = Environment()
|
||||
platform = test_env['PLATFORM']
|
||||
if platform == 'win32':
|
||||
if support_multiple_win_builds:
|
||||
available_build_types = ['win-dbg8', 'win-opt8', 'win-dbg', 'win-opt']
|
||||
else:
|
||||
available_build_types = ['win-dbg', 'win-opt']
|
||||
elif platform == 'darwin': # MacOSX
|
||||
available_build_types = ['mac-dbg', 'mac-opt']
|
||||
else:
|
||||
available_build_types = ['dbg', 'opt'] # Assuming POSIX-like environment
|
||||
# with GCC by default.
|
||||
|
||||
vars = Variables()
|
||||
vars.Add(ListVariable('BUILD', 'Build type', available_build_types[0],
|
||||
available_build_types))
|
||||
vars.Add(BoolVariable('GTEST_BUILD_SAMPLES', 'Build samples', False))
|
||||
|
||||
# Create base environment.
|
||||
self.env_base = Environment(variables=vars,
|
||||
BUILD_MODE={'BUILD' : '"${BUILD}"'})
|
||||
|
||||
# Leave around a variable pointing at the build root so that SConscript
|
||||
# files from outside our project root can find their bearings. Trick
|
||||
# borrowed from Hammer in Software Construction Toolkit
|
||||
# (http://code.google.com/p/swtoolkit/); if/when we switch to using the
|
||||
# Hammer idioms instead of just Hammer's version of SCons, we should be
|
||||
# able to remove this line.
|
||||
self.env_base['SOURCE_ROOT'] = self.env_base.Dir(build_root_path)
|
||||
|
||||
# And another that definitely always points to the project root.
|
||||
self.env_base['PROJECT_ROOT'] = self.env_base.Dir('.').abspath
|
||||
|
||||
# Enable scons -h
|
||||
Help(vars.GenerateHelpText(self.env_base))
|
||||
|
||||
class EnvCreator:
|
||||
"""Creates new customized environments from a base one."""
|
||||
|
||||
def _Remove(cls, env, attribute, value):
|
||||
"""Removes the given attribute value from the environment."""
|
||||
|
||||
attribute_values = env[attribute]
|
||||
if value in attribute_values:
|
||||
attribute_values.remove(value)
|
||||
_Remove = classmethod(_Remove)
|
||||
|
||||
def Create(cls, base_env, modifier=None):
|
||||
# User should NOT create more than one environment with the same
|
||||
# modifier (including None).
|
||||
env = base_env.Clone()
|
||||
if modifier:
|
||||
modifier(env)
|
||||
else:
|
||||
env['OBJ_SUFFIX'] = '' # Default suffix for unchanged environment.
|
||||
return env;
|
||||
Create = classmethod(Create)
|
||||
|
||||
# Each of the following methods modifies the environment for a particular
|
||||
# purpose and can be used by clients for creating new environments. Each
|
||||
# one needs to set the OBJ_SUFFIX variable to a unique suffix to
|
||||
# differentiate targets built with that environment. Otherwise, SCons may
|
||||
# complain about same target built with different settings.
|
||||
|
||||
def UseOwnTuple(cls, env):
|
||||
"""Instructs Google Test to use its internal implementation of tuple."""
|
||||
|
||||
env['OBJ_SUFFIX'] = '_use_own_tuple'
|
||||
env.Append(CPPDEFINES = 'GTEST_USE_OWN_TR1_TUPLE=1')
|
||||
UseOwnTuple = classmethod(UseOwnTuple)
|
||||
|
||||
def WarningOk(cls, env):
|
||||
"""Does not treat warnings as errors.
|
||||
|
||||
Necessary for compiling gtest_unittest.cc, which triggers a gcc
|
||||
warning when testing EXPECT_EQ(NULL, ptr)."""
|
||||
|
||||
env['OBJ_SUFFIX'] = '_warning_ok'
|
||||
if env['PLATFORM'] == 'win32':
|
||||
cls._Remove(env, 'CCFLAGS', '-WX')
|
||||
else:
|
||||
cls._Remove(env, 'CCFLAGS', '-Werror')
|
||||
WarningOk = classmethod(WarningOk)
|
||||
|
||||
def WithExceptions(cls, env):
|
||||
"""Re-enables exceptions."""
|
||||
|
||||
env['OBJ_SUFFIX'] = '_ex'
|
||||
if env['PLATFORM'] == 'win32':
|
||||
env.Append(CCFLAGS=['/EHsc'])
|
||||
env.Append(CPPDEFINES='_HAS_EXCEPTIONS=1')
|
||||
# Undoes the _TYPEINFO_ hack, which is unnecessary and only creates
|
||||
# trouble when exceptions are enabled.
|
||||
cls._Remove(env, 'CPPDEFINES', '_TYPEINFO_')
|
||||
cls._Remove(env, 'CPPDEFINES', '_HAS_EXCEPTIONS=0')
|
||||
else:
|
||||
env.Append(CCFLAGS='-fexceptions')
|
||||
cls._Remove(env, 'CCFLAGS', '-fno-exceptions')
|
||||
WithExceptions = classmethod(WithExceptions)
|
||||
|
||||
def LessOptimized(cls, env):
|
||||
"""Disables certain optimizations on Windows.
|
||||
|
||||
We need to disable some optimization flags for some tests on
|
||||
Windows; otherwise the redirection of stdout does not work
|
||||
(apparently because of a compiler bug)."""
|
||||
|
||||
env['OBJ_SUFFIX'] = '_less_optimized'
|
||||
if env['PLATFORM'] == 'win32':
|
||||
for flag in ['/O1', '/Os', '/Og', '/Oy']:
|
||||
cls._Remove(env, 'LINKFLAGS', flag)
|
||||
LessOptimized = classmethod(LessOptimized)
|
||||
|
||||
def WithThreads(cls, env):
|
||||
"""Allows use of threads.
|
||||
|
||||
Currently only enables pthreads under GCC."""
|
||||
|
||||
env['OBJ_SUFFIX'] = '_with_threads'
|
||||
if env['PLATFORM'] != 'win32':
|
||||
# Assuming POSIX-like environment with GCC.
|
||||
# TODO(vladl@google.com): sniff presence of pthread_atfork instead of
|
||||
# selecting on a platform.
|
||||
env.Append(CCFLAGS=['-pthread'])
|
||||
env.Append(LINKFLAGS=['-pthread'])
|
||||
WithThreads = classmethod(WithThreads)
|
||||
|
||||
def NoRtti(cls, env):
|
||||
"""Disables RTTI support."""
|
||||
|
||||
env['OBJ_SUFFIX'] = '_no_rtti'
|
||||
if env['PLATFORM'] == 'win32':
|
||||
env.Append(CCFLAGS=['/GR-'])
|
||||
else:
|
||||
env.Append(CCFLAGS=['-fno-rtti'])
|
||||
env.Append(CPPDEFINES='GTEST_HAS_RTTI=0')
|
||||
NoRtti = classmethod(NoRtti)
|
||||
|
||||
def AllowVc71StlWithoutExceptions(self, env):
|
||||
env.Append(
|
||||
CPPDEFINES = [# needed for using some parts of STL with exception
|
||||
# disabled. The scoop is given here, with comments
|
||||
# from P.J. Plauger at
|
||||
# http://groups.google.com/group/microsoft.public.vc.stl/browse_thread/thread/5e719833c6bdb177?q=_HAS_EXCEPTIONS+using+namespace+std&pli=1
|
||||
'_TYPEINFO_'])
|
||||
|
||||
def MakeWinBaseEnvironment(self):
|
||||
win_base = self.env_base.Clone(
|
||||
platform='win32',
|
||||
CCFLAGS=['-GS', # Enable buffer security check
|
||||
'-W4', # Warning level
|
||||
|
||||
# Disables warnings that are either uninteresting or
|
||||
# hard to fix.
|
||||
|
||||
'-WX', # Treat warning as errors
|
||||
#'-GR-', # Disable runtime type information
|
||||
'-RTCs', # Enable stack-frame run-time error checks
|
||||
'-RTCu', # Report when variable used without init.
|
||||
#'-EHs', # enable C++ EH (no SEH exceptions)
|
||||
'-nologo', # Suppress logo line
|
||||
'-J', # All chars unsigned
|
||||
#'-Wp64', # Detect 64-bit portability issues. This
|
||||
# flag has been deprecated by VS 2008.
|
||||
'-Zi', # Produce debug information in PDB files.
|
||||
],
|
||||
CCPDBFLAGS='',
|
||||
CPPDEFINES=['_UNICODE', 'UNICODE',
|
||||
'WIN32', '_WIN32',
|
||||
'STRICT',
|
||||
'WIN32_LEAN_AND_MEAN',
|
||||
'_HAS_EXCEPTIONS=0',
|
||||
],
|
||||
LIBPATH=['#/$MAIN_DIR/lib'],
|
||||
LINKFLAGS=['-MACHINE:x86', # Enable safe SEH (not supp. on x64)
|
||||
'-DEBUG', # Generate debug info
|
||||
'-NOLOGO', # Suppress logo line
|
||||
],
|
||||
# All strings in string tables zero terminated.
|
||||
RCFLAGS=['-n'])
|
||||
|
||||
return win_base
|
||||
|
||||
def SetBuildNameAndDir(self, env, name):
|
||||
env['BUILD_NAME'] = name;
|
||||
env['BUILD_DIR'] = '%s/%s' % (BUILD_DIR_PREFIX, name)
|
||||
self.env_dict[name] = env
|
||||
|
||||
def MakeWinDebugEnvironment(self, base_environment, name):
|
||||
"""Takes a VC71 or VC80 base environment and adds debug settings."""
|
||||
debug_env = base_environment.Clone()
|
||||
self.SetBuildNameAndDir(debug_env, name)
|
||||
debug_env.Append(
|
||||
CCFLAGS = ['-Od', # Disable optimizations
|
||||
'-MTd', # Multithreaded, static link (debug)
|
||||
# Path for PDB files
|
||||
'-Fd%s\\' % debug_env.Dir(debug_env['BUILD_DIR']),
|
||||
],
|
||||
CPPDEFINES = ['DEBUG',
|
||||
'_DEBUG',
|
||||
],
|
||||
LIBPATH = [],
|
||||
LINKFLAGS = ['-INCREMENTAL:yes',
|
||||
'/OPT:NOICF',
|
||||
]
|
||||
)
|
||||
return debug_env
|
||||
|
||||
def MakeWinOptimizedEnvironment(self, base_environment, name):
|
||||
"""Takes a VC71 or VC80 base environment and adds release settings."""
|
||||
optimized_env = base_environment.Clone()
|
||||
self.SetBuildNameAndDir(optimized_env, name)
|
||||
optimized_env.Append(
|
||||
CCFLAGS = ['-GL', # Enable link-time code generation (/GL)
|
||||
'-GF', # Enable String Pooling (/GF)
|
||||
'-MT', # Multithreaded, static link
|
||||
# Path for PDB files
|
||||
'-Fd%s\\' % optimized_env.Dir(optimized_env['BUILD_DIR']),
|
||||
|
||||
# Favor small code (this is /O1 minus /Og)
|
||||
'-Os',
|
||||
'-Oy',
|
||||
'-Ob2',
|
||||
'-Gs',
|
||||
'-GF',
|
||||
'-Gy',
|
||||
],
|
||||
CPPDEFINES = ['NDEBUG',
|
||||
'_NDEBUG',
|
||||
],
|
||||
LIBPATH = [],
|
||||
ARFLAGS = ['-LTCG'], # Link-time Code Generation
|
||||
LINKFLAGS = ['-LTCG', # Link-time Code Generation
|
||||
'-OPT:REF', # Optimize by reference.
|
||||
'-OPT:ICF=32', # Optimize by identical COMDAT folding
|
||||
'-OPT:NOWIN98', # Optimize by not aligning section for
|
||||
# Win98
|
||||
'-INCREMENTAL:NO', # No incremental linking as we don't
|
||||
# want padding bytes in release build.
|
||||
],
|
||||
)
|
||||
return optimized_env
|
||||
|
||||
def AddGccFlagsTo(self, env, optimized):
|
||||
env.Append(CCFLAGS=['-fno-exceptions',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
])
|
||||
if optimized:
|
||||
env.Append(CCFLAGS=['-O2'], CPPDEFINES=['NDEBUG', '_NDEBUG'])
|
||||
else:
|
||||
env.Append(CCFLAGS=['-g'], CPPDEFINES=['DEBUG', '_DEBUG'])
|
||||
|
||||
def ConfigureGccEnvironments(self):
|
||||
# Mac environments.
|
||||
mac_base = self.env_base.Clone(platform='darwin')
|
||||
|
||||
mac_dbg = mac_base.Clone()
|
||||
self.AddGccFlagsTo(mac_dbg, optimized=False)
|
||||
self.SetBuildNameAndDir(mac_dbg, 'mac-dbg')
|
||||
|
||||
mac_opt = mac_base.Clone()
|
||||
self.AddGccFlagsTo(mac_opt, optimized=True)
|
||||
self.SetBuildNameAndDir(mac_opt, 'mac-opt')
|
||||
|
||||
# Generic GCC environments.
|
||||
gcc_dbg = self.env_base.Clone()
|
||||
self.AddGccFlagsTo(gcc_dbg, optimized=False)
|
||||
self.SetBuildNameAndDir(gcc_dbg, 'dbg')
|
||||
|
||||
gcc_opt = self.env_base.Clone()
|
||||
self.AddGccFlagsTo(gcc_opt, optimized=True)
|
||||
self.SetBuildNameAndDir(gcc_opt, 'opt')
|
||||
|
||||
def BuildSelectedEnvironments(self):
|
||||
EnvCreator = SConstructHelper.EnvCreator
|
||||
Export('EnvCreator')
|
||||
# Build using whichever environments the 'BUILD' option selected
|
||||
for build_name in self.env_base['BUILD']:
|
||||
print 'BUILDING %s' % build_name
|
||||
env = self.env_dict[build_name]
|
||||
|
||||
# Make sure SConscript files can refer to base build dir
|
||||
env['MAIN_DIR'] = env.Dir(env['BUILD_DIR'])
|
||||
|
||||
#print 'CCFLAGS: %s' % env.subst('$CCFLAGS')
|
||||
#print 'LINK: %s' % env.subst('$LINK')
|
||||
#print 'AR: %s' % env.subst('$AR')
|
||||
#print 'CC: %s' % env.subst('$CC')
|
||||
#print 'CXX: %s' % env.subst('$CXX')
|
||||
#print 'LIBPATH: %s' % env.subst('$LIBPATH')
|
||||
#print 'ENV:PATH: %s' % env['ENV']['PATH']
|
||||
#print 'ENV:INCLUDE: %s' % env['ENV']['INCLUDE']
|
||||
#print 'ENV:LIB: %s' % env['ENV']['LIB']
|
||||
#print 'ENV:TEMP: %s' % env['ENV']['TEMP']
|
||||
|
||||
Export('env')
|
||||
# Invokes SConscript with variant_dir being build/<config name>.
|
||||
# Counter-intuitively, src_dir is relative to the build dir and has
|
||||
# to be '..' to point to the scons directory.
|
||||
SConscript('SConscript',
|
||||
src_dir='..',
|
||||
variant_dir=env['BUILD_DIR'],
|
||||
duplicate=0)
|
||||
|
||||
|
||||
sconstruct_helper = SConstructHelper()
|
||||
Return('sconstruct_helper')
|
||||
@@ -214,7 +214,7 @@ if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
|
||||
# TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
|
||||
# should work to remove it, and/or remove libtool altogether, replacing it
|
||||
# with direct references to the library and a link path.
|
||||
gtest_libs="${build_dir}/lib/libgtest.la"
|
||||
gtest_libs="${build_dir}/lib/libgtest.la @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
|
||||
gtest_ldflags=""
|
||||
|
||||
# We provide hooks to include from either the source or build dir, where the
|
||||
@@ -222,15 +222,15 @@ if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
|
||||
# build rules for generated headers and have them automatically be preferred
|
||||
# over provided versions.
|
||||
gtest_cppflags="-I${build_dir}/include -I${src_dir}/include"
|
||||
gtest_cxxflags=""
|
||||
gtest_cxxflags="@PTHREAD_CFLAGS@"
|
||||
else
|
||||
# We're using an installed gtest, although it may be staged under some
|
||||
# prefix. Assume (as our own libraries do) that we can resolve the prefix,
|
||||
# and are present in the dynamic link paths.
|
||||
gtest_ldflags="-L${libdir}"
|
||||
gtest_libs="-l${name}"
|
||||
gtest_libs="-l${name} @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
|
||||
gtest_cppflags="-I${includedir}"
|
||||
gtest_cxxflags=""
|
||||
gtest_cxxflags="@PTHREAD_CFLAGS@"
|
||||
fi
|
||||
|
||||
# Do an installation query if requested.
|
||||
|
||||
Executable
+835
@@ -0,0 +1,835 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2008, 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.
|
||||
|
||||
"""pump v0.1 - Pretty Useful for Meta Programming.
|
||||
|
||||
A tool for preprocessor meta programming. Useful for generating
|
||||
repetitive boilerplate code. Especially useful for writing C++
|
||||
classes, functions, macros, and templates that need to work with
|
||||
various number of arguments.
|
||||
|
||||
USAGE:
|
||||
pump.py SOURCE_FILE
|
||||
|
||||
EXAMPLES:
|
||||
pump.py foo.cc.pump
|
||||
Converts foo.cc.pump to foo.cc.
|
||||
|
||||
GRAMMAR:
|
||||
CODE ::= ATOMIC_CODE*
|
||||
ATOMIC_CODE ::= $var ID = EXPRESSION
|
||||
| $var ID = [[ CODE ]]
|
||||
| $range ID EXPRESSION..EXPRESSION
|
||||
| $for ID SEPARATOR [[ CODE ]]
|
||||
| $($)
|
||||
| $ID
|
||||
| $(EXPRESSION)
|
||||
| $if EXPRESSION [[ CODE ]] ELSE_BRANCH
|
||||
| [[ CODE ]]
|
||||
| RAW_CODE
|
||||
SEPARATOR ::= RAW_CODE | EMPTY
|
||||
ELSE_BRANCH ::= $else [[ CODE ]]
|
||||
| $elif EXPRESSION [[ CODE ]] ELSE_BRANCH
|
||||
| EMPTY
|
||||
EXPRESSION has Python syntax.
|
||||
"""
|
||||
|
||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
TOKEN_TABLE = [
|
||||
(re.compile(r'\$var\s+'), '$var'),
|
||||
(re.compile(r'\$elif\s+'), '$elif'),
|
||||
(re.compile(r'\$else\s+'), '$else'),
|
||||
(re.compile(r'\$for\s+'), '$for'),
|
||||
(re.compile(r'\$if\s+'), '$if'),
|
||||
(re.compile(r'\$range\s+'), '$range'),
|
||||
(re.compile(r'\$[_A-Za-z]\w*'), '$id'),
|
||||
(re.compile(r'\$\(\$\)'), '$($)'),
|
||||
(re.compile(r'\$\$.*'), '$$'),
|
||||
(re.compile(r'\$'), '$'),
|
||||
(re.compile(r'\[\[\n?'), '[['),
|
||||
(re.compile(r'\]\]\n?'), ']]'),
|
||||
]
|
||||
|
||||
|
||||
class Cursor:
|
||||
"""Represents a position (line and column) in a text file."""
|
||||
|
||||
def __init__(self, line=-1, column=-1):
|
||||
self.line = line
|
||||
self.column = column
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return self.line == rhs.line and self.column == rhs.column
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return not self == rhs
|
||||
|
||||
def __lt__(self, rhs):
|
||||
return self.line < rhs.line or (
|
||||
self.line == rhs.line and self.column < rhs.column)
|
||||
|
||||
def __le__(self, rhs):
|
||||
return self < rhs or self == rhs
|
||||
|
||||
def __gt__(self, rhs):
|
||||
return rhs < self
|
||||
|
||||
def __ge__(self, rhs):
|
||||
return rhs <= self
|
||||
|
||||
def __str__(self):
|
||||
if self == Eof():
|
||||
return 'EOF'
|
||||
else:
|
||||
return '%s(%s)' % (self.line + 1, self.column)
|
||||
|
||||
def __add__(self, offset):
|
||||
return Cursor(self.line, self.column + offset)
|
||||
|
||||
def __sub__(self, offset):
|
||||
return Cursor(self.line, self.column - offset)
|
||||
|
||||
def Clone(self):
|
||||
"""Returns a copy of self."""
|
||||
|
||||
return Cursor(self.line, self.column)
|
||||
|
||||
|
||||
# Special cursor to indicate the end-of-file.
|
||||
def Eof():
|
||||
"""Returns the special cursor to denote the end-of-file."""
|
||||
return Cursor(-1, -1)
|
||||
|
||||
|
||||
class Token:
|
||||
"""Represents a token in a Pump source file."""
|
||||
|
||||
def __init__(self, start=None, end=None, value=None, token_type=None):
|
||||
if start is None:
|
||||
self.start = Eof()
|
||||
else:
|
||||
self.start = start
|
||||
if end is None:
|
||||
self.end = Eof()
|
||||
else:
|
||||
self.end = end
|
||||
self.value = value
|
||||
self.token_type = token_type
|
||||
|
||||
def __str__(self):
|
||||
return 'Token @%s: \'%s\' type=%s' % (
|
||||
self.start, self.value, self.token_type)
|
||||
|
||||
def Clone(self):
|
||||
"""Returns a copy of self."""
|
||||
|
||||
return Token(self.start.Clone(), self.end.Clone(), self.value,
|
||||
self.token_type)
|
||||
|
||||
|
||||
def StartsWith(lines, pos, string):
|
||||
"""Returns True iff the given position in lines starts with 'string'."""
|
||||
|
||||
return lines[pos.line][pos.column:].startswith(string)
|
||||
|
||||
|
||||
def FindFirstInLine(line, token_table):
|
||||
best_match_start = -1
|
||||
for (regex, token_type) in token_table:
|
||||
m = regex.search(line)
|
||||
if m:
|
||||
# We found regex in lines
|
||||
if best_match_start < 0 or m.start() < best_match_start:
|
||||
best_match_start = m.start()
|
||||
best_match_length = m.end() - m.start()
|
||||
best_match_token_type = token_type
|
||||
|
||||
if best_match_start < 0:
|
||||
return None
|
||||
|
||||
return (best_match_start, best_match_length, best_match_token_type)
|
||||
|
||||
|
||||
def FindFirst(lines, token_table, cursor):
|
||||
"""Finds the first occurrence of any string in strings in lines."""
|
||||
|
||||
start = cursor.Clone()
|
||||
cur_line_number = cursor.line
|
||||
for line in lines[start.line:]:
|
||||
if cur_line_number == start.line:
|
||||
line = line[start.column:]
|
||||
m = FindFirstInLine(line, token_table)
|
||||
if m:
|
||||
# We found a regex in line.
|
||||
(start_column, length, token_type) = m
|
||||
if cur_line_number == start.line:
|
||||
start_column += start.column
|
||||
found_start = Cursor(cur_line_number, start_column)
|
||||
found_end = found_start + length
|
||||
return MakeToken(lines, found_start, found_end, token_type)
|
||||
cur_line_number += 1
|
||||
# We failed to find str in lines
|
||||
return None
|
||||
|
||||
|
||||
def SubString(lines, start, end):
|
||||
"""Returns a substring in lines."""
|
||||
|
||||
if end == Eof():
|
||||
end = Cursor(len(lines) - 1, len(lines[-1]))
|
||||
|
||||
if start >= end:
|
||||
return ''
|
||||
|
||||
if start.line == end.line:
|
||||
return lines[start.line][start.column:end.column]
|
||||
|
||||
result_lines = ([lines[start.line][start.column:]] +
|
||||
lines[start.line + 1:end.line] +
|
||||
[lines[end.line][:end.column]])
|
||||
return ''.join(result_lines)
|
||||
|
||||
|
||||
def MakeToken(lines, start, end, token_type):
|
||||
"""Creates a new instance of Token."""
|
||||
|
||||
return Token(start, end, SubString(lines, start, end), token_type)
|
||||
|
||||
|
||||
def ParseToken(lines, pos, regex, token_type):
|
||||
line = lines[pos.line][pos.column:]
|
||||
m = regex.search(line)
|
||||
if m and not m.start():
|
||||
return MakeToken(lines, pos, pos + m.end(), token_type)
|
||||
else:
|
||||
print 'ERROR: %s expected at %s.' % (token_type, pos)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
ID_REGEX = re.compile(r'[_A-Za-z]\w*')
|
||||
EQ_REGEX = re.compile(r'=')
|
||||
REST_OF_LINE_REGEX = re.compile(r'.*?(?=$|\$\$)')
|
||||
OPTIONAL_WHITE_SPACES_REGEX = re.compile(r'\s*')
|
||||
WHITE_SPACE_REGEX = re.compile(r'\s')
|
||||
DOT_DOT_REGEX = re.compile(r'\.\.')
|
||||
|
||||
|
||||
def Skip(lines, pos, regex):
|
||||
line = lines[pos.line][pos.column:]
|
||||
m = re.search(regex, line)
|
||||
if m and not m.start():
|
||||
return pos + m.end()
|
||||
else:
|
||||
return pos
|
||||
|
||||
|
||||
def SkipUntil(lines, pos, regex, token_type):
|
||||
line = lines[pos.line][pos.column:]
|
||||
m = re.search(regex, line)
|
||||
if m:
|
||||
return pos + m.start()
|
||||
else:
|
||||
print ('ERROR: %s expected on line %s after column %s.' %
|
||||
(token_type, pos.line + 1, pos.column))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def ParseExpTokenInParens(lines, pos):
|
||||
def ParseInParens(pos):
|
||||
pos = Skip(lines, pos, OPTIONAL_WHITE_SPACES_REGEX)
|
||||
pos = Skip(lines, pos, r'\(')
|
||||
pos = Parse(pos)
|
||||
pos = Skip(lines, pos, r'\)')
|
||||
return pos
|
||||
|
||||
def Parse(pos):
|
||||
pos = SkipUntil(lines, pos, r'\(|\)', ')')
|
||||
if SubString(lines, pos, pos + 1) == '(':
|
||||
pos = Parse(pos + 1)
|
||||
pos = Skip(lines, pos, r'\)')
|
||||
return Parse(pos)
|
||||
else:
|
||||
return pos
|
||||
|
||||
start = pos.Clone()
|
||||
pos = ParseInParens(pos)
|
||||
return MakeToken(lines, start, pos, 'exp')
|
||||
|
||||
|
||||
def RStripNewLineFromToken(token):
|
||||
if token.value.endswith('\n'):
|
||||
return Token(token.start, token.end, token.value[:-1], token.token_type)
|
||||
else:
|
||||
return token
|
||||
|
||||
|
||||
def TokenizeLines(lines, pos):
|
||||
while True:
|
||||
found = FindFirst(lines, TOKEN_TABLE, pos)
|
||||
if not found:
|
||||
yield MakeToken(lines, pos, Eof(), 'code')
|
||||
return
|
||||
|
||||
if found.start == pos:
|
||||
prev_token = None
|
||||
prev_token_rstripped = None
|
||||
else:
|
||||
prev_token = MakeToken(lines, pos, found.start, 'code')
|
||||
prev_token_rstripped = RStripNewLineFromToken(prev_token)
|
||||
|
||||
if found.token_type == '$$': # A meta comment.
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
pos = Cursor(found.end.line + 1, 0)
|
||||
elif found.token_type == '$var':
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
yield found
|
||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
||||
yield id_token
|
||||
pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
|
||||
|
||||
eq_token = ParseToken(lines, pos, EQ_REGEX, '=')
|
||||
yield eq_token
|
||||
pos = Skip(lines, eq_token.end, r'\s*')
|
||||
|
||||
if SubString(lines, pos, pos + 2) != '[[':
|
||||
exp_token = ParseToken(lines, pos, REST_OF_LINE_REGEX, 'exp')
|
||||
yield exp_token
|
||||
pos = Cursor(exp_token.end.line + 1, 0)
|
||||
elif found.token_type == '$for':
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
yield found
|
||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
||||
yield id_token
|
||||
pos = Skip(lines, id_token.end, WHITE_SPACE_REGEX)
|
||||
elif found.token_type == '$range':
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
yield found
|
||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
||||
yield id_token
|
||||
pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
|
||||
|
||||
dots_pos = SkipUntil(lines, pos, DOT_DOT_REGEX, '..')
|
||||
yield MakeToken(lines, pos, dots_pos, 'exp')
|
||||
yield MakeToken(lines, dots_pos, dots_pos + 2, '..')
|
||||
pos = dots_pos + 2
|
||||
new_pos = Cursor(pos.line + 1, 0)
|
||||
yield MakeToken(lines, pos, new_pos, 'exp')
|
||||
pos = new_pos
|
||||
elif found.token_type == '$':
|
||||
if prev_token:
|
||||
yield prev_token
|
||||
yield found
|
||||
exp_token = ParseExpTokenInParens(lines, found.end)
|
||||
yield exp_token
|
||||
pos = exp_token.end
|
||||
elif (found.token_type == ']]' or found.token_type == '$if' or
|
||||
found.token_type == '$elif' or found.token_type == '$else'):
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
yield found
|
||||
pos = found.end
|
||||
else:
|
||||
if prev_token:
|
||||
yield prev_token
|
||||
yield found
|
||||
pos = found.end
|
||||
|
||||
|
||||
def Tokenize(s):
|
||||
lines = s.splitlines(True)
|
||||
return TokenizeLines(lines, Cursor(0, 0))
|
||||
|
||||
|
||||
class CodeNode:
|
||||
def __init__(self, atomic_code_list=None):
|
||||
self.atomic_code = atomic_code_list
|
||||
|
||||
|
||||
class VarNode:
|
||||
def __init__(self, identifier=None, atomic_code=None):
|
||||
self.identifier = identifier
|
||||
self.atomic_code = atomic_code
|
||||
|
||||
|
||||
class RangeNode:
|
||||
def __init__(self, identifier=None, exp1=None, exp2=None):
|
||||
self.identifier = identifier
|
||||
self.exp1 = exp1
|
||||
self.exp2 = exp2
|
||||
|
||||
|
||||
class ForNode:
|
||||
def __init__(self, identifier=None, sep=None, code=None):
|
||||
self.identifier = identifier
|
||||
self.sep = sep
|
||||
self.code = code
|
||||
|
||||
|
||||
class ElseNode:
|
||||
def __init__(self, else_branch=None):
|
||||
self.else_branch = else_branch
|
||||
|
||||
|
||||
class IfNode:
|
||||
def __init__(self, exp=None, then_branch=None, else_branch=None):
|
||||
self.exp = exp
|
||||
self.then_branch = then_branch
|
||||
self.else_branch = else_branch
|
||||
|
||||
|
||||
class RawCodeNode:
|
||||
def __init__(self, token=None):
|
||||
self.raw_code = token
|
||||
|
||||
|
||||
class LiteralDollarNode:
|
||||
def __init__(self, token):
|
||||
self.token = token
|
||||
|
||||
|
||||
class ExpNode:
|
||||
def __init__(self, token, python_exp):
|
||||
self.token = token
|
||||
self.python_exp = python_exp
|
||||
|
||||
|
||||
def PopFront(a_list):
|
||||
head = a_list[0]
|
||||
a_list[:1] = []
|
||||
return head
|
||||
|
||||
|
||||
def PushFront(a_list, elem):
|
||||
a_list[:0] = [elem]
|
||||
|
||||
|
||||
def PopToken(a_list, token_type=None):
|
||||
token = PopFront(a_list)
|
||||
if token_type is not None and token.token_type != token_type:
|
||||
print 'ERROR: %s expected at %s' % (token_type, token.start)
|
||||
print 'ERROR: %s found instead' % (token,)
|
||||
sys.exit(1)
|
||||
|
||||
return token
|
||||
|
||||
|
||||
def PeekToken(a_list):
|
||||
if not a_list:
|
||||
return None
|
||||
|
||||
return a_list[0]
|
||||
|
||||
|
||||
def ParseExpNode(token):
|
||||
python_exp = re.sub(r'([_A-Za-z]\w*)', r'self.GetValue("\1")', token.value)
|
||||
return ExpNode(token, python_exp)
|
||||
|
||||
|
||||
def ParseElseNode(tokens):
|
||||
def Pop(token_type=None):
|
||||
return PopToken(tokens, token_type)
|
||||
|
||||
next = PeekToken(tokens)
|
||||
if not next:
|
||||
return None
|
||||
if next.token_type == '$else':
|
||||
Pop('$else')
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
return code_node
|
||||
elif next.token_type == '$elif':
|
||||
Pop('$elif')
|
||||
exp = Pop('code')
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
inner_else_node = ParseElseNode(tokens)
|
||||
return CodeNode([IfNode(ParseExpNode(exp), code_node, inner_else_node)])
|
||||
elif not next.value.strip():
|
||||
Pop('code')
|
||||
return ParseElseNode(tokens)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def ParseAtomicCodeNode(tokens):
|
||||
def Pop(token_type=None):
|
||||
return PopToken(tokens, token_type)
|
||||
|
||||
head = PopFront(tokens)
|
||||
t = head.token_type
|
||||
if t == 'code':
|
||||
return RawCodeNode(head)
|
||||
elif t == '$var':
|
||||
id_token = Pop('id')
|
||||
Pop('=')
|
||||
next = PeekToken(tokens)
|
||||
if next.token_type == 'exp':
|
||||
exp_token = Pop()
|
||||
return VarNode(id_token, ParseExpNode(exp_token))
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
return VarNode(id_token, code_node)
|
||||
elif t == '$for':
|
||||
id_token = Pop('id')
|
||||
next_token = PeekToken(tokens)
|
||||
if next_token.token_type == 'code':
|
||||
sep_token = next_token
|
||||
Pop('code')
|
||||
else:
|
||||
sep_token = None
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
return ForNode(id_token, sep_token, code_node)
|
||||
elif t == '$if':
|
||||
exp_token = Pop('code')
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
else_node = ParseElseNode(tokens)
|
||||
return IfNode(ParseExpNode(exp_token), code_node, else_node)
|
||||
elif t == '$range':
|
||||
id_token = Pop('id')
|
||||
exp1_token = Pop('exp')
|
||||
Pop('..')
|
||||
exp2_token = Pop('exp')
|
||||
return RangeNode(id_token, ParseExpNode(exp1_token),
|
||||
ParseExpNode(exp2_token))
|
||||
elif t == '$id':
|
||||
return ParseExpNode(Token(head.start + 1, head.end, head.value[1:], 'id'))
|
||||
elif t == '$($)':
|
||||
return LiteralDollarNode(head)
|
||||
elif t == '$':
|
||||
exp_token = Pop('exp')
|
||||
return ParseExpNode(exp_token)
|
||||
elif t == '[[':
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
return code_node
|
||||
else:
|
||||
PushFront(tokens, head)
|
||||
return None
|
||||
|
||||
|
||||
def ParseCodeNode(tokens):
|
||||
atomic_code_list = []
|
||||
while True:
|
||||
if not tokens:
|
||||
break
|
||||
atomic_code_node = ParseAtomicCodeNode(tokens)
|
||||
if atomic_code_node:
|
||||
atomic_code_list.append(atomic_code_node)
|
||||
else:
|
||||
break
|
||||
return CodeNode(atomic_code_list)
|
||||
|
||||
|
||||
def Convert(file_path):
|
||||
s = file(file_path, 'r').read()
|
||||
tokens = []
|
||||
for token in Tokenize(s):
|
||||
tokens.append(token)
|
||||
code_node = ParseCodeNode(tokens)
|
||||
return code_node
|
||||
|
||||
|
||||
class Env:
|
||||
def __init__(self):
|
||||
self.variables = []
|
||||
self.ranges = []
|
||||
|
||||
def Clone(self):
|
||||
clone = Env()
|
||||
clone.variables = self.variables[:]
|
||||
clone.ranges = self.ranges[:]
|
||||
return clone
|
||||
|
||||
def PushVariable(self, var, value):
|
||||
# If value looks like an int, store it as an int.
|
||||
try:
|
||||
int_value = int(value)
|
||||
if ('%s' % int_value) == value:
|
||||
value = int_value
|
||||
except Exception:
|
||||
pass
|
||||
self.variables[:0] = [(var, value)]
|
||||
|
||||
def PopVariable(self):
|
||||
self.variables[:1] = []
|
||||
|
||||
def PushRange(self, var, lower, upper):
|
||||
self.ranges[:0] = [(var, lower, upper)]
|
||||
|
||||
def PopRange(self):
|
||||
self.ranges[:1] = []
|
||||
|
||||
def GetValue(self, identifier):
|
||||
for (var, value) in self.variables:
|
||||
if identifier == var:
|
||||
return value
|
||||
|
||||
print 'ERROR: meta variable %s is undefined.' % (identifier,)
|
||||
sys.exit(1)
|
||||
|
||||
def EvalExp(self, exp):
|
||||
try:
|
||||
result = eval(exp.python_exp)
|
||||
except Exception, e:
|
||||
print 'ERROR: caught exception %s: %s' % (e.__class__.__name__, e)
|
||||
print ('ERROR: failed to evaluate meta expression %s at %s' %
|
||||
(exp.python_exp, exp.token.start))
|
||||
sys.exit(1)
|
||||
return result
|
||||
|
||||
def GetRange(self, identifier):
|
||||
for (var, lower, upper) in self.ranges:
|
||||
if identifier == var:
|
||||
return (lower, upper)
|
||||
|
||||
print 'ERROR: range %s is undefined.' % (identifier,)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class Output:
|
||||
def __init__(self):
|
||||
self.string = ''
|
||||
|
||||
def GetLastLine(self):
|
||||
index = self.string.rfind('\n')
|
||||
if index < 0:
|
||||
return ''
|
||||
|
||||
return self.string[index + 1:]
|
||||
|
||||
def Append(self, s):
|
||||
self.string += s
|
||||
|
||||
|
||||
def RunAtomicCode(env, node, output):
|
||||
if isinstance(node, VarNode):
|
||||
identifier = node.identifier.value.strip()
|
||||
result = Output()
|
||||
RunAtomicCode(env.Clone(), node.atomic_code, result)
|
||||
value = result.string
|
||||
env.PushVariable(identifier, value)
|
||||
elif isinstance(node, RangeNode):
|
||||
identifier = node.identifier.value.strip()
|
||||
lower = int(env.EvalExp(node.exp1))
|
||||
upper = int(env.EvalExp(node.exp2))
|
||||
env.PushRange(identifier, lower, upper)
|
||||
elif isinstance(node, ForNode):
|
||||
identifier = node.identifier.value.strip()
|
||||
if node.sep is None:
|
||||
sep = ''
|
||||
else:
|
||||
sep = node.sep.value
|
||||
(lower, upper) = env.GetRange(identifier)
|
||||
for i in range(lower, upper + 1):
|
||||
new_env = env.Clone()
|
||||
new_env.PushVariable(identifier, i)
|
||||
RunCode(new_env, node.code, output)
|
||||
if i != upper:
|
||||
output.Append(sep)
|
||||
elif isinstance(node, RawCodeNode):
|
||||
output.Append(node.raw_code.value)
|
||||
elif isinstance(node, IfNode):
|
||||
cond = env.EvalExp(node.exp)
|
||||
if cond:
|
||||
RunCode(env.Clone(), node.then_branch, output)
|
||||
elif node.else_branch is not None:
|
||||
RunCode(env.Clone(), node.else_branch, output)
|
||||
elif isinstance(node, ExpNode):
|
||||
value = env.EvalExp(node)
|
||||
output.Append('%s' % (value,))
|
||||
elif isinstance(node, LiteralDollarNode):
|
||||
output.Append('$')
|
||||
elif isinstance(node, CodeNode):
|
||||
RunCode(env.Clone(), node, output)
|
||||
else:
|
||||
print 'BAD'
|
||||
print node
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def RunCode(env, code_node, output):
|
||||
for atomic_code in code_node.atomic_code:
|
||||
RunAtomicCode(env, atomic_code, output)
|
||||
|
||||
|
||||
def IsComment(cur_line):
|
||||
return '//' in cur_line
|
||||
|
||||
|
||||
def IsInPreprocessorDirevative(prev_lines, cur_line):
|
||||
if cur_line.lstrip().startswith('#'):
|
||||
return True
|
||||
return prev_lines != [] and prev_lines[-1].endswith('\\')
|
||||
|
||||
|
||||
def WrapComment(line, output):
|
||||
loc = line.find('//')
|
||||
before_comment = line[:loc].rstrip()
|
||||
if before_comment == '':
|
||||
indent = loc
|
||||
else:
|
||||
output.append(before_comment)
|
||||
indent = len(before_comment) - len(before_comment.lstrip())
|
||||
prefix = indent*' ' + '// '
|
||||
max_len = 80 - len(prefix)
|
||||
comment = line[loc + 2:].strip()
|
||||
segs = [seg for seg in re.split(r'(\w+\W*)', comment) if seg != '']
|
||||
cur_line = ''
|
||||
for seg in segs:
|
||||
if len((cur_line + seg).rstrip()) < max_len:
|
||||
cur_line += seg
|
||||
else:
|
||||
if cur_line.strip() != '':
|
||||
output.append(prefix + cur_line.rstrip())
|
||||
cur_line = seg.lstrip()
|
||||
if cur_line.strip() != '':
|
||||
output.append(prefix + cur_line.strip())
|
||||
|
||||
|
||||
def WrapCode(line, line_concat, output):
|
||||
indent = len(line) - len(line.lstrip())
|
||||
prefix = indent*' ' # Prefix of the current line
|
||||
max_len = 80 - indent - len(line_concat) # Maximum length of the current line
|
||||
new_prefix = prefix + 4*' ' # Prefix of a continuation line
|
||||
new_max_len = max_len - 4 # Maximum length of a continuation line
|
||||
# Prefers to wrap a line after a ',' or ';'.
|
||||
segs = [seg for seg in re.split(r'([^,;]+[,;]?)', line.strip()) if seg != '']
|
||||
cur_line = '' # The current line without leading spaces.
|
||||
for seg in segs:
|
||||
# If the line is still too long, wrap at a space.
|
||||
while cur_line == '' and len(seg.strip()) > max_len:
|
||||
seg = seg.lstrip()
|
||||
split_at = seg.rfind(' ', 0, max_len)
|
||||
output.append(prefix + seg[:split_at].strip() + line_concat)
|
||||
seg = seg[split_at + 1:]
|
||||
prefix = new_prefix
|
||||
max_len = new_max_len
|
||||
|
||||
if len((cur_line + seg).rstrip()) < max_len:
|
||||
cur_line = (cur_line + seg).lstrip()
|
||||
else:
|
||||
output.append(prefix + cur_line.rstrip() + line_concat)
|
||||
prefix = new_prefix
|
||||
max_len = new_max_len
|
||||
cur_line = seg.lstrip()
|
||||
if cur_line.strip() != '':
|
||||
output.append(prefix + cur_line.strip())
|
||||
|
||||
|
||||
def WrapPreprocessorDirevative(line, output):
|
||||
WrapCode(line, ' \\', output)
|
||||
|
||||
|
||||
def WrapPlainCode(line, output):
|
||||
WrapCode(line, '', output)
|
||||
|
||||
|
||||
def IsHeaderGuardOrInclude(line):
|
||||
return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or
|
||||
re.match(r'^#include\s', line))
|
||||
|
||||
|
||||
def WrapLongLine(line, output):
|
||||
line = line.rstrip()
|
||||
if len(line) <= 80:
|
||||
output.append(line)
|
||||
elif IsComment(line):
|
||||
if IsHeaderGuardOrInclude(line):
|
||||
# The style guide made an exception to allow long header guard lines
|
||||
# and includes.
|
||||
output.append(line)
|
||||
else:
|
||||
WrapComment(line, output)
|
||||
elif IsInPreprocessorDirevative(output, line):
|
||||
if IsHeaderGuardOrInclude(line):
|
||||
# The style guide made an exception to allow long header guard lines
|
||||
# and includes.
|
||||
output.append(line)
|
||||
else:
|
||||
WrapPreprocessorDirevative(line, output)
|
||||
else:
|
||||
WrapPlainCode(line, output)
|
||||
|
||||
|
||||
def BeautifyCode(string):
|
||||
lines = string.splitlines()
|
||||
output = []
|
||||
for line in lines:
|
||||
WrapLongLine(line, output)
|
||||
output2 = [line.rstrip() for line in output]
|
||||
return '\n'.join(output2) + '\n'
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) == 1:
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
|
||||
file_path = argv[-1]
|
||||
ast = Convert(file_path)
|
||||
output = Output()
|
||||
RunCode(Env(), ast, output)
|
||||
output_str = BeautifyCode(output.string)
|
||||
if file_path.endswith('.pump'):
|
||||
output_file_path = file_path[:-5]
|
||||
else:
|
||||
output_file_path = '-'
|
||||
if output_file_path == '-':
|
||||
print output_str,
|
||||
else:
|
||||
output_file = file(output_file_path, 'w')
|
||||
output_file.write('// This file was GENERATED by command:\n')
|
||||
output_file.write('// %s %s\n' %
|
||||
(os.path.basename(__file__), os.path.basename(file_path)))
|
||||
output_file.write('// DO NOT EDIT BY HAND!!!\n\n')
|
||||
output_file.write(output_str)
|
||||
output_file.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
@@ -33,6 +33,12 @@
|
||||
//
|
||||
// Sometimes it's desirable to build Google Test by compiling a single file.
|
||||
// This file serves this purpose.
|
||||
|
||||
// This line ensures that gtest.h can be compiled on its own, even
|
||||
// when it's fused.
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// The following lines pull in the real gtest *.cc files.
|
||||
#include "src/gtest.cc"
|
||||
#include "src/gtest-death-test.cc"
|
||||
#include "src/gtest-filepath.cc"
|
||||
|
||||
+16
-18
@@ -308,9 +308,9 @@ String DeathTest::last_death_test_message_;
|
||||
// Provides cross platform implementation for some death functionality.
|
||||
class DeathTestImpl : public DeathTest {
|
||||
protected:
|
||||
DeathTestImpl(const char* statement, const RE* regex)
|
||||
: statement_(statement),
|
||||
regex_(regex),
|
||||
DeathTestImpl(const char* a_statement, const RE* a_regex)
|
||||
: statement_(a_statement),
|
||||
regex_(a_regex),
|
||||
spawned_(false),
|
||||
status_(-1),
|
||||
outcome_(IN_PROGRESS),
|
||||
@@ -326,11 +326,11 @@ class DeathTestImpl : public DeathTest {
|
||||
const char* statement() const { return statement_; }
|
||||
const RE* regex() const { return regex_; }
|
||||
bool spawned() const { return spawned_; }
|
||||
void set_spawned(bool spawned) { spawned_ = spawned; }
|
||||
void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
|
||||
int status() const { return status_; }
|
||||
void set_status(int status) { status_ = status; }
|
||||
void set_status(int a_status) { status_ = a_status; }
|
||||
DeathTestOutcome outcome() const { return outcome_; }
|
||||
void set_outcome(DeathTestOutcome outcome) { outcome_ = outcome; }
|
||||
void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
|
||||
int read_fd() const { return read_fd_; }
|
||||
void set_read_fd(int fd) { read_fd_ = fd; }
|
||||
int write_fd() const { return write_fd_; }
|
||||
@@ -705,8 +705,8 @@ class ForkingDeathTest : public DeathTestImpl {
|
||||
};
|
||||
|
||||
// Constructs a ForkingDeathTest.
|
||||
ForkingDeathTest::ForkingDeathTest(const char* statement, const RE* regex)
|
||||
: DeathTestImpl(statement, regex),
|
||||
ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
|
||||
: DeathTestImpl(a_statement, a_regex),
|
||||
child_pid_(-1) {}
|
||||
|
||||
// Waits for the child in a death test to exit, returning its exit
|
||||
@@ -718,18 +718,18 @@ int ForkingDeathTest::Wait() {
|
||||
|
||||
ReadAndInterpretStatusByte();
|
||||
|
||||
int status;
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status, 0));
|
||||
set_status(status);
|
||||
return status;
|
||||
int status_value;
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
|
||||
set_status(status_value);
|
||||
return status_value;
|
||||
}
|
||||
|
||||
// A concrete death test class that forks, then immediately runs the test
|
||||
// in the child process.
|
||||
class NoExecDeathTest : public ForkingDeathTest {
|
||||
public:
|
||||
NoExecDeathTest(const char* statement, const RE* regex) :
|
||||
ForkingDeathTest(statement, regex) { }
|
||||
NoExecDeathTest(const char* a_statement, const RE* a_regex) :
|
||||
ForkingDeathTest(a_statement, a_regex) { }
|
||||
virtual TestRole AssumeRole();
|
||||
};
|
||||
|
||||
@@ -782,9 +782,9 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
|
||||
// only this specific death test to be run.
|
||||
class ExecDeathTest : public ForkingDeathTest {
|
||||
public:
|
||||
ExecDeathTest(const char* statement, const RE* regex,
|
||||
ExecDeathTest(const char* a_statement, const RE* a_regex,
|
||||
const char* file, int line) :
|
||||
ForkingDeathTest(statement, regex), file_(file), line_(line) { }
|
||||
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
|
||||
virtual TestRole AssumeRole();
|
||||
private:
|
||||
// The name of the file in which the death test is located.
|
||||
@@ -1037,8 +1037,6 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
||||
// Splits a given string on a given delimiter, populating a given
|
||||
// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have
|
||||
// ::std::string, so we can use it here.
|
||||
// TODO(vladl@google.com): Get rid of std::vector to be able to build on
|
||||
// Visual C++ 7.1 with exceptions disabled.
|
||||
static void SplitString(const ::std::string& str, char delimiter,
|
||||
::std::vector< ::std::string>* dest) {
|
||||
::std::vector< ::std::string> parsed;
|
||||
|
||||
+52
-12
@@ -63,8 +63,14 @@ namespace testing {
|
||||
namespace internal {
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// On Windows, '\\' is the standard path separator, but many tools and the
|
||||
// Windows API also accept '/' as an alternate path separator. Unless otherwise
|
||||
// noted, a file path can contain either kind of path separators, or a mixture
|
||||
// of them.
|
||||
const char kPathSeparator = '\\';
|
||||
const char kAlternatePathSeparator = '/';
|
||||
const char kPathSeparatorString[] = "\\";
|
||||
const char kAlternatePathSeparatorString[] = "/";
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
// Windows CE doesn't have a current directory. You should not use
|
||||
// the current directory in tests on Windows CE, but this at least
|
||||
@@ -81,6 +87,15 @@ const char kPathSeparatorString[] = "/";
|
||||
const char kCurrentDirectoryString[] = "./";
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Returns whether the given character is a valid path separator.
|
||||
static bool IsPathSeparator(char c) {
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
return (c == kPathSeparator) || (c == kAlternatePathSeparator);
|
||||
#else
|
||||
return c == kPathSeparator;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the current working directory, or "" if unsuccessful.
|
||||
FilePath FilePath::GetCurrentDir() {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
@@ -108,6 +123,22 @@ FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Returns a pointer to the last occurence of a valid path separator in
|
||||
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||
// separators. Returns NULL if no path separator was found.
|
||||
const char* FilePath::FindLastPathSeparator() const {
|
||||
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
||||
// Comparing two pointers of which only one is NULL is undefined.
|
||||
if (last_alt_sep != NULL &&
|
||||
(last_sep == NULL || last_alt_sep > last_sep)) {
|
||||
return last_alt_sep;
|
||||
}
|
||||
#endif
|
||||
return last_sep;
|
||||
}
|
||||
|
||||
// Returns a copy of the FilePath with the directory part removed.
|
||||
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
||||
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
||||
@@ -115,7 +146,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||
// returns an empty FilePath ("").
|
||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||
FilePath FilePath::RemoveDirectoryName() const {
|
||||
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||
const char* const last_sep = FindLastPathSeparator();
|
||||
return last_sep ? FilePath(String(last_sep + 1)) : *this;
|
||||
}
|
||||
|
||||
@@ -126,7 +157,7 @@ FilePath FilePath::RemoveDirectoryName() const {
|
||||
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||
FilePath FilePath::RemoveFileName() const {
|
||||
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||
const char* const last_sep = FindLastPathSeparator();
|
||||
String dir;
|
||||
if (last_sep) {
|
||||
dir = String(c_str(), last_sep + 1 - c_str());
|
||||
@@ -219,7 +250,7 @@ bool FilePath::IsRootDirectory() const {
|
||||
// current directory. Handle this properly.
|
||||
return pathname_.length() == 3 && IsAbsolutePath();
|
||||
#else
|
||||
return pathname_ == kPathSeparatorString;
|
||||
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -231,9 +262,9 @@ bool FilePath::IsAbsolutePath() const {
|
||||
((name[0] >= 'a' && name[0] <= 'z') ||
|
||||
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
||||
name[1] == ':' &&
|
||||
name[2] == kPathSeparator;
|
||||
IsPathSeparator(name[2]);
|
||||
#else
|
||||
return name[0] == kPathSeparator;
|
||||
return IsPathSeparator(name[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -260,7 +291,8 @@ FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
|
||||
// it is intended to represent a directory. Returns false otherwise.
|
||||
// This does NOT check that a directory (or file) actually exists.
|
||||
bool FilePath::IsDirectory() const {
|
||||
return pathname_.EndsWith(kPathSeparatorString);
|
||||
return !pathname_.empty() &&
|
||||
IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
|
||||
}
|
||||
|
||||
// Create directories so that path exists. Returns true if successful or if
|
||||
@@ -305,14 +337,15 @@ bool FilePath::CreateFolder() const {
|
||||
// name, otherwise return the name string unmodified.
|
||||
// On Windows platform, uses \ as the separator, other platforms use /.
|
||||
FilePath FilePath::RemoveTrailingPathSeparator() const {
|
||||
return pathname_.EndsWith(kPathSeparatorString)
|
||||
return IsDirectory()
|
||||
? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
|
||||
: *this;
|
||||
}
|
||||
|
||||
// Normalize removes any redundant separators that might be in the pathname.
|
||||
// Removes any redundant separators that might be in the pathname.
|
||||
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||
// redundancies that might be in a pathname involving "." or "..".
|
||||
// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
|
||||
void FilePath::Normalize() {
|
||||
if (pathname_.c_str() == NULL) {
|
||||
pathname_ = "";
|
||||
@@ -324,12 +357,19 @@ void FilePath::Normalize() {
|
||||
memset(dest_ptr, 0, pathname_.length() + 1);
|
||||
|
||||
while (*src != '\0') {
|
||||
*dest_ptr++ = *src;
|
||||
if (*src != kPathSeparator)
|
||||
*dest_ptr = *src;
|
||||
if (!IsPathSeparator(*src)) {
|
||||
src++;
|
||||
else
|
||||
while (*src == kPathSeparator)
|
||||
} else {
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
if (*dest_ptr == kAlternatePathSeparator) {
|
||||
*dest_ptr = kPathSeparator;
|
||||
}
|
||||
#endif
|
||||
while (IsPathSeparator(*src))
|
||||
src++;
|
||||
}
|
||||
dest_ptr++;
|
||||
}
|
||||
*dest_ptr = '\0';
|
||||
pathname_ = dest;
|
||||
|
||||
+121
-294
@@ -52,7 +52,9 @@
|
||||
#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
|
||||
#include <string.h> // For memmove.
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/internal/gtest-port.h>
|
||||
|
||||
@@ -60,7 +62,7 @@
|
||||
#include <windows.h> // For DWORD.
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gtest/gtest.h> // NOLINT
|
||||
#include <gtest/gtest-spi.h>
|
||||
|
||||
namespace testing {
|
||||
@@ -76,7 +78,7 @@ namespace internal {
|
||||
|
||||
// The value of GetTestTypeId() as seen from within the Google Test
|
||||
// library. This is solely for testing GetTestTypeId().
|
||||
extern const TypeId kTestTypeIdInGoogleTest;
|
||||
GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
|
||||
|
||||
// Names of the flags (needed for parsing Google Test flags).
|
||||
const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
|
||||
@@ -90,13 +92,31 @@ const char kPrintTimeFlag[] = "print_time";
|
||||
const char kRandomSeedFlag[] = "random_seed";
|
||||
const char kRepeatFlag[] = "repeat";
|
||||
const char kShuffleFlag[] = "shuffle";
|
||||
const char kStackTraceDepthFlag[] = "stack_trace_depth";
|
||||
const char kThrowOnFailureFlag[] = "throw_on_failure";
|
||||
|
||||
// A valid random seed must be in [1, kMaxRandomSeed].
|
||||
const int kMaxRandomSeed = 99999;
|
||||
|
||||
// g_help_flag is true iff the --help flag or an equivalent form is
|
||||
// specified on the command line.
|
||||
GTEST_API_ extern bool g_help_flag;
|
||||
|
||||
// Returns the current time in milliseconds.
|
||||
TimeInMillis GetTimeInMillis();
|
||||
GTEST_API_ TimeInMillis GetTimeInMillis();
|
||||
|
||||
// Returns true iff Google Test should use colors in the output.
|
||||
GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
|
||||
|
||||
// Formats the given time in milliseconds as seconds.
|
||||
GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
|
||||
|
||||
// Parses a string for an Int32 flag, in the form of "--flag=value".
|
||||
//
|
||||
// On success, stores the value of the flag in *value, and returns
|
||||
// true. On failure, returns false without changing *value.
|
||||
GTEST_API_ bool ParseInt32Flag(
|
||||
const char* str, const char* flag, Int32* value);
|
||||
|
||||
// Returns a random seed in range [1, kMaxRandomSeed] based on the
|
||||
// given --gtest_random_seed flag value.
|
||||
@@ -144,6 +164,7 @@ class GTestFlagSaver {
|
||||
random_seed_ = GTEST_FLAG(random_seed);
|
||||
repeat_ = GTEST_FLAG(repeat);
|
||||
shuffle_ = GTEST_FLAG(shuffle);
|
||||
stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
|
||||
throw_on_failure_ = GTEST_FLAG(throw_on_failure);
|
||||
}
|
||||
|
||||
@@ -163,6 +184,7 @@ class GTestFlagSaver {
|
||||
GTEST_FLAG(random_seed) = random_seed_;
|
||||
GTEST_FLAG(repeat) = repeat_;
|
||||
GTEST_FLAG(shuffle) = shuffle_;
|
||||
GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
|
||||
GTEST_FLAG(throw_on_failure) = throw_on_failure_;
|
||||
}
|
||||
private:
|
||||
@@ -182,6 +204,7 @@ class GTestFlagSaver {
|
||||
internal::Int32 random_seed_;
|
||||
internal::Int32 repeat_;
|
||||
bool shuffle_;
|
||||
internal::Int32 stack_trace_depth_;
|
||||
bool throw_on_failure_;
|
||||
} GTEST_ATTRIBUTE_UNUSED_;
|
||||
|
||||
@@ -193,7 +216,7 @@ class GTestFlagSaver {
|
||||
// If the code_point is not a valid Unicode code point
|
||||
// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
|
||||
// as '(Invalid Unicode 0xXXXXXXXX)'.
|
||||
char* CodePointToUtf8(UInt32 code_point, char* str);
|
||||
GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str);
|
||||
|
||||
// Converts a wide string to a narrow string in UTF-8 encoding.
|
||||
// The wide string is assumed to have the following encoding:
|
||||
@@ -208,10 +231,7 @@ char* CodePointToUtf8(UInt32 code_point, char* str);
|
||||
// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
|
||||
// and contains invalid UTF-16 surrogate pairs, values in those pairs
|
||||
// will be encoded as individual Unicode characters from Basic Normal Plane.
|
||||
String WideStringToUtf8(const wchar_t* str, int num_chars);
|
||||
|
||||
// Returns the number of active threads, or 0 when there is an error.
|
||||
size_t GetThreadCount();
|
||||
GTEST_API_ String WideStringToUtf8(const wchar_t* str, int num_chars);
|
||||
|
||||
// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
|
||||
// if the variable is present. If a file already exists at this location, this
|
||||
@@ -225,269 +245,78 @@ void WriteToShardStatusFileIfNeeded();
|
||||
// an error and exits. If in_subprocess_for_death_test, sharding is
|
||||
// disabled because it must only be applied to the original test
|
||||
// process. Otherwise, we could filter out death tests we intended to execute.
|
||||
bool ShouldShard(const char* total_shards_str, const char* shard_index_str,
|
||||
bool in_subprocess_for_death_test);
|
||||
GTEST_API_ bool ShouldShard(const char* total_shards_str,
|
||||
const char* shard_index_str,
|
||||
bool in_subprocess_for_death_test);
|
||||
|
||||
// Parses the environment variable var as an Int32. If it is unset,
|
||||
// returns default_val. If it is not an Int32, prints an error and
|
||||
// and aborts.
|
||||
Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
|
||||
GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
|
||||
|
||||
// Given the total number of shards, the shard index, and the test id,
|
||||
// returns true iff the test should be run on this shard. The test id is
|
||||
// some arbitrary but unique non-negative integer assigned to each test
|
||||
// method. Assumes that 0 <= shard_index < total_shards.
|
||||
bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id);
|
||||
GTEST_API_ bool ShouldRunTestOnShard(
|
||||
int total_shards, int shard_index, int test_id);
|
||||
|
||||
// Vector is an ordered container that supports random access to the
|
||||
// elements.
|
||||
//
|
||||
// We cannot use std::vector, as Visual C++ 7.1's implementation of
|
||||
// STL has problems compiling when exceptions are disabled. There is
|
||||
// a hack to work around the problems, but we've seen cases where the
|
||||
// hack fails to work.
|
||||
//
|
||||
// The element type must support copy constructor and operator=.
|
||||
template <typename E> // E is the element type.
|
||||
class Vector {
|
||||
public:
|
||||
// Creates an empty Vector.
|
||||
Vector() : elements_(NULL), capacity_(0), size_(0) {}
|
||||
// STL container utilities.
|
||||
|
||||
// D'tor.
|
||||
virtual ~Vector() { Clear(); }
|
||||
// Returns the number of elements in the given container that satisfy
|
||||
// the given predicate.
|
||||
template <class Container, typename Predicate>
|
||||
inline int CountIf(const Container& c, Predicate predicate) {
|
||||
return static_cast<int>(std::count_if(c.begin(), c.end(), predicate));
|
||||
}
|
||||
|
||||
// Clears the Vector.
|
||||
void Clear() {
|
||||
if (elements_ != NULL) {
|
||||
for (int i = 0; i < size_; i++) {
|
||||
delete elements_[i];
|
||||
}
|
||||
// Applies a function/functor to each element in the container.
|
||||
template <class Container, typename Functor>
|
||||
void ForEach(const Container& c, Functor functor) {
|
||||
std::for_each(c.begin(), c.end(), functor);
|
||||
}
|
||||
|
||||
free(elements_);
|
||||
elements_ = NULL;
|
||||
capacity_ = size_ = 0;
|
||||
}
|
||||
// Returns the i-th element of the vector, or default_value if i is not
|
||||
// in range [0, v.size()).
|
||||
template <typename E>
|
||||
inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
|
||||
return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
|
||||
}
|
||||
|
||||
// Performs an in-place shuffle of a range of the vector's elements.
|
||||
// 'begin' and 'end' are element indices as an STL-style range;
|
||||
// i.e. [begin, end) are shuffled, where 'end' == size() means to
|
||||
// shuffle to the end of the vector.
|
||||
template <typename E>
|
||||
void ShuffleRange(internal::Random* random, int begin, int end,
|
||||
std::vector<E>* v) {
|
||||
const int size = static_cast<int>(v->size());
|
||||
GTEST_CHECK_(0 <= begin && begin <= size)
|
||||
<< "Invalid shuffle range start " << begin << ": must be in range [0, "
|
||||
<< size << "].";
|
||||
GTEST_CHECK_(begin <= end && end <= size)
|
||||
<< "Invalid shuffle range finish " << end << ": must be in range ["
|
||||
<< begin << ", " << size << "].";
|
||||
|
||||
// Fisher-Yates shuffle, from
|
||||
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
|
||||
for (int range_width = end - begin; range_width >= 2; range_width--) {
|
||||
const int last_in_range = begin + range_width - 1;
|
||||
const int selected = begin + random->Generate(range_width);
|
||||
std::swap((*v)[selected], (*v)[last_in_range]);
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the number of elements.
|
||||
int size() const { return size_; }
|
||||
|
||||
// Adds an element to the end of the Vector. A copy of the element
|
||||
// is created using the copy constructor, and then stored in the
|
||||
// Vector. Changes made to the element in the Vector doesn't affect
|
||||
// the source object, and vice versa.
|
||||
void PushBack(const E& element) { Insert(element, size_); }
|
||||
|
||||
// Adds an element to the beginning of this Vector.
|
||||
void PushFront(const E& element) { Insert(element, 0); }
|
||||
|
||||
// Removes an element from the beginning of this Vector. If the
|
||||
// result argument is not NULL, the removed element is stored in the
|
||||
// memory it points to. Otherwise the element is thrown away.
|
||||
// Returns true iff the vector wasn't empty before the operation.
|
||||
bool PopFront(E* result) {
|
||||
if (size_ == 0)
|
||||
return false;
|
||||
|
||||
if (result != NULL)
|
||||
*result = GetElement(0);
|
||||
|
||||
Erase(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Inserts an element at the given index. It's the caller's
|
||||
// responsibility to ensure that the given index is in the range [0,
|
||||
// size()].
|
||||
void Insert(const E& element, int index) {
|
||||
GrowIfNeeded();
|
||||
MoveElements(index, size_ - index, index + 1);
|
||||
elements_[index] = new E(element);
|
||||
size_++;
|
||||
}
|
||||
|
||||
// Erases the element at the specified index, or aborts the program if the
|
||||
// index is not in range [0, size()).
|
||||
void Erase(int index) {
|
||||
GTEST_CHECK_(0 <= index && index < size_)
|
||||
<< "Invalid Vector index " << index << ": must be in range [0, "
|
||||
<< (size_ - 1) << "].";
|
||||
|
||||
delete elements_[index];
|
||||
MoveElements(index + 1, size_ - index - 1, index);
|
||||
size_--;
|
||||
}
|
||||
|
||||
// Returns the number of elements that satisfy a given predicate.
|
||||
// The parameter 'predicate' is a Boolean function or functor that
|
||||
// accepts a 'const E &', where E is the element type.
|
||||
template <typename P> // P is the type of the predicate function/functor
|
||||
int CountIf(P predicate) const {
|
||||
int count = 0;
|
||||
for (int i = 0; i < size_; i++) {
|
||||
if (predicate(*(elements_[i]))) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Applies a function/functor to each element in the Vector. The
|
||||
// parameter 'functor' is a function/functor that accepts a 'const
|
||||
// E &', where E is the element type. This method does not change
|
||||
// the elements.
|
||||
template <typename F> // F is the type of the function/functor
|
||||
void ForEach(F functor) const {
|
||||
for (int i = 0; i < size_; i++) {
|
||||
functor(*(elements_[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the first node whose element satisfies a given predicate,
|
||||
// or NULL if none is found. The parameter 'predicate' is a
|
||||
// function/functor that accepts a 'const E &', where E is the
|
||||
// element type. This method does not change the elements.
|
||||
template <typename P> // P is the type of the predicate function/functor.
|
||||
const E* FindIf(P predicate) const {
|
||||
for (int i = 0; i < size_; i++) {
|
||||
if (predicate(*elements_[i])) {
|
||||
return elements_[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
E* FindIf(P predicate) {
|
||||
for (int i = 0; i < size_; i++) {
|
||||
if (predicate(*elements_[i])) {
|
||||
return elements_[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Returns the i-th element of the Vector, or aborts the program if i
|
||||
// is not in range [0, size()).
|
||||
const E& GetElement(int i) const {
|
||||
GTEST_CHECK_(0 <= i && i < size_)
|
||||
<< "Invalid Vector index " << i << ": must be in range [0, "
|
||||
<< (size_ - 1) << "].";
|
||||
|
||||
return *(elements_[i]);
|
||||
}
|
||||
|
||||
// Returns a mutable reference to the i-th element of the Vector, or
|
||||
// aborts the program if i is not in range [0, size()).
|
||||
E& GetMutableElement(int i) {
|
||||
GTEST_CHECK_(0 <= i && i < size_)
|
||||
<< "Invalid Vector index " << i << ": must be in range [0, "
|
||||
<< (size_ - 1) << "].";
|
||||
|
||||
return *(elements_[i]);
|
||||
}
|
||||
|
||||
// Returns the i-th element of the Vector, or default_value if i is not
|
||||
// in range [0, size()).
|
||||
E GetElementOr(int i, E default_value) const {
|
||||
return (i < 0 || i >= size_) ? default_value : *(elements_[i]);
|
||||
}
|
||||
|
||||
// Swaps the i-th and j-th elements of the Vector. Crashes if i or
|
||||
// j is invalid.
|
||||
void Swap(int i, int j) {
|
||||
GTEST_CHECK_(0 <= i && i < size_)
|
||||
<< "Invalid first swap element " << i << ": must be in range [0, "
|
||||
<< (size_ - 1) << "].";
|
||||
GTEST_CHECK_(0 <= j && j < size_)
|
||||
<< "Invalid second swap element " << j << ": must be in range [0, "
|
||||
<< (size_ - 1) << "].";
|
||||
|
||||
E* const temp = elements_[i];
|
||||
elements_[i] = elements_[j];
|
||||
elements_[j] = temp;
|
||||
}
|
||||
|
||||
// Performs an in-place shuffle of a range of this Vector's nodes.
|
||||
// 'begin' and 'end' are element indices as an STL-style range;
|
||||
// i.e. [begin, end) are shuffled, where 'end' == size() means to
|
||||
// shuffle to the end of the Vector.
|
||||
void ShuffleRange(internal::Random* random, int begin, int end) {
|
||||
GTEST_CHECK_(0 <= begin && begin <= size_)
|
||||
<< "Invalid shuffle range start " << begin << ": must be in range [0, "
|
||||
<< size_ << "].";
|
||||
GTEST_CHECK_(begin <= end && end <= size_)
|
||||
<< "Invalid shuffle range finish " << end << ": must be in range ["
|
||||
<< begin << ", " << size_ << "].";
|
||||
|
||||
// Fisher-Yates shuffle, from
|
||||
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
|
||||
for (int range_width = end - begin; range_width >= 2; range_width--) {
|
||||
const int last_in_range = begin + range_width - 1;
|
||||
const int selected = begin + random->Generate(range_width);
|
||||
Swap(selected, last_in_range);
|
||||
}
|
||||
}
|
||||
|
||||
// Performs an in-place shuffle of this Vector's nodes.
|
||||
void Shuffle(internal::Random* random) {
|
||||
ShuffleRange(random, 0, size());
|
||||
}
|
||||
|
||||
// Returns a copy of this Vector.
|
||||
Vector* Clone() const {
|
||||
Vector* const clone = new Vector;
|
||||
clone->Reserve(size_);
|
||||
for (int i = 0; i < size_; i++) {
|
||||
clone->PushBack(GetElement(i));
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
private:
|
||||
// Makes sure this Vector's capacity is at least the given value.
|
||||
void Reserve(int new_capacity) {
|
||||
if (new_capacity <= capacity_)
|
||||
return;
|
||||
|
||||
capacity_ = new_capacity;
|
||||
elements_ = static_cast<E**>(
|
||||
realloc(elements_, capacity_*sizeof(elements_[0])));
|
||||
}
|
||||
|
||||
// Grows the buffer if it is not big enough to hold one more element.
|
||||
void GrowIfNeeded() {
|
||||
if (size_ < capacity_)
|
||||
return;
|
||||
|
||||
// Exponential bump-up is necessary to ensure that inserting N
|
||||
// elements is O(N) instead of O(N^2). The factor 3/2 means that
|
||||
// no more than 1/3 of the slots are wasted.
|
||||
const int new_capacity = 3*(capacity_/2 + 1);
|
||||
GTEST_CHECK_(new_capacity > capacity_) // Does the new capacity overflow?
|
||||
<< "Cannot grow a Vector with " << capacity_ << " elements already.";
|
||||
Reserve(new_capacity);
|
||||
}
|
||||
|
||||
// Moves the give consecutive elements to a new index in the Vector.
|
||||
void MoveElements(int source, int count, int dest) {
|
||||
memmove(elements_ + dest, elements_ + source, count*sizeof(elements_[0]));
|
||||
}
|
||||
|
||||
E** elements_;
|
||||
int capacity_; // The number of elements allocated for elements_.
|
||||
int size_; // The number of elements; in the range [0, capacity_].
|
||||
|
||||
// We disallow copying Vector.
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Vector);
|
||||
}; // class Vector
|
||||
// Performs an in-place shuffle of the vector's elements.
|
||||
template <typename E>
|
||||
inline void Shuffle(internal::Random* random, std::vector<E>* v) {
|
||||
ShuffleRange(random, 0, static_cast<int>(v->size()), v);
|
||||
}
|
||||
|
||||
// A function for deleting an object. Handy for being used as a
|
||||
// functor.
|
||||
template <typename T>
|
||||
static void Delete(T * x) {
|
||||
static void Delete(T* x) {
|
||||
delete x;
|
||||
}
|
||||
|
||||
@@ -600,7 +429,7 @@ class TestInfoImpl {
|
||||
// test filter using either GTEST_FILTER or --gtest_filter. If both
|
||||
// the variable and the flag are present, the latter overrides the
|
||||
// former.
|
||||
class UnitTestOptions {
|
||||
class GTEST_API_ UnitTestOptions {
|
||||
public:
|
||||
// Functions for processing the gtest_output flag.
|
||||
|
||||
@@ -642,7 +471,7 @@ class UnitTestOptions {
|
||||
|
||||
// Returns the current application's name, removing directory path if that
|
||||
// is present. Used by UnitTestOptions::GetOutputFile.
|
||||
FilePath GetCurrentExecutableName();
|
||||
GTEST_API_ FilePath GetCurrentExecutableName();
|
||||
|
||||
// The role interface for getting the OS stack trace as a string.
|
||||
class OsStackTraceGetterInterface {
|
||||
@@ -733,7 +562,7 @@ class DefaultPerThreadTestPartResultReporter
|
||||
// the methods under a mutex, as this class is not accessible by a
|
||||
// user and the UnitTest class that delegates work to this class does
|
||||
// proper locking.
|
||||
class UnitTestImpl {
|
||||
class GTEST_API_ UnitTestImpl {
|
||||
public:
|
||||
explicit UnitTestImpl(UnitTest* parent);
|
||||
virtual ~UnitTestImpl();
|
||||
@@ -802,15 +631,15 @@ class UnitTestImpl {
|
||||
// Gets the i-th test case among all the test cases. i can range from 0 to
|
||||
// total_test_case_count() - 1. If i is not in that range, returns NULL.
|
||||
const TestCase* GetTestCase(int i) const {
|
||||
const int index = test_case_indices_.GetElementOr(i, -1);
|
||||
return index < 0 ? NULL : test_cases_.GetElement(i);
|
||||
const int index = GetElementOr(test_case_indices_, i, -1);
|
||||
return index < 0 ? NULL : test_cases_[i];
|
||||
}
|
||||
|
||||
// Gets the i-th test case among all the test cases. i can range from 0 to
|
||||
// total_test_case_count() - 1. If i is not in that range, returns NULL.
|
||||
TestCase* GetMutableTestCase(int i) {
|
||||
const int index = test_case_indices_.GetElementOr(i, -1);
|
||||
return index < 0 ? NULL : test_cases_.GetElement(index);
|
||||
const int index = GetElementOr(test_case_indices_, i, -1);
|
||||
return index < 0 ? NULL : test_cases_[index];
|
||||
}
|
||||
|
||||
// Provides access to the event listener list.
|
||||
@@ -898,15 +727,15 @@ class UnitTestImpl {
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
|
||||
// Sets the TestCase object for the test that's currently running.
|
||||
void set_current_test_case(TestCase* current_test_case) {
|
||||
current_test_case_ = current_test_case;
|
||||
void set_current_test_case(TestCase* a_current_test_case) {
|
||||
current_test_case_ = a_current_test_case;
|
||||
}
|
||||
|
||||
// Sets the TestInfo object for the test that's currently running. If
|
||||
// current_test_info is NULL, the assertion results will be stored in
|
||||
// ad_hoc_test_result_.
|
||||
void set_current_test_info(TestInfo* current_test_info) {
|
||||
current_test_info_ = current_test_info;
|
||||
void set_current_test_info(TestInfo* a_current_test_info) {
|
||||
current_test_info_ = a_current_test_info;
|
||||
}
|
||||
|
||||
// Registers all parameterized tests defined using TEST_P and
|
||||
@@ -927,7 +756,7 @@ class UnitTestImpl {
|
||||
|
||||
// Clears the results of all tests, including the ad hoc test.
|
||||
void ClearResult() {
|
||||
test_cases_.ForEach(TestCase::ClearTestCaseResult);
|
||||
ForEach(test_cases_, TestCase::ClearTestCaseResult);
|
||||
ad_hoc_test_result_.Clear();
|
||||
}
|
||||
|
||||
@@ -953,17 +782,14 @@ class UnitTestImpl {
|
||||
|
||||
// Returns the vector of environments that need to be set-up/torn-down
|
||||
// before/after the tests are run.
|
||||
internal::Vector<Environment*>* environments() { return &environments_; }
|
||||
internal::Vector<Environment*>* environments_in_reverse_order() {
|
||||
return &environments_in_reverse_order_;
|
||||
}
|
||||
std::vector<Environment*>& environments() { return environments_; }
|
||||
|
||||
// Getters for the per-thread Google Test trace stack.
|
||||
internal::Vector<TraceInfo>* gtest_trace_stack() {
|
||||
return gtest_trace_stack_.pointer();
|
||||
std::vector<TraceInfo>& gtest_trace_stack() {
|
||||
return *(gtest_trace_stack_.pointer());
|
||||
}
|
||||
const internal::Vector<TraceInfo>* gtest_trace_stack() const {
|
||||
return gtest_trace_stack_.pointer();
|
||||
const std::vector<TraceInfo>& gtest_trace_stack() const {
|
||||
return gtest_trace_stack_.get();
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
@@ -1038,20 +864,18 @@ class UnitTestImpl {
|
||||
per_thread_test_part_result_reporter_;
|
||||
|
||||
// The vector of environments that need to be set-up/torn-down
|
||||
// before/after the tests are run. environments_in_reverse_order_
|
||||
// simply mirrors environments_ in reverse order.
|
||||
internal::Vector<Environment*> environments_;
|
||||
internal::Vector<Environment*> environments_in_reverse_order_;
|
||||
// before/after the tests are run.
|
||||
std::vector<Environment*> environments_;
|
||||
|
||||
// The vector of TestCases in their original order. It owns the
|
||||
// elements in the vector.
|
||||
internal::Vector<TestCase*> test_cases_;
|
||||
std::vector<TestCase*> test_cases_;
|
||||
|
||||
// Provides a level of indirection for the test case list to allow
|
||||
// easy shuffling and restoring the test case order. The i-th
|
||||
// element of this vector is the index of the i-th test case in the
|
||||
// shuffled order.
|
||||
internal::Vector<int> test_case_indices_;
|
||||
std::vector<int> test_case_indices_;
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
// ParameterizedTestRegistry object used to register value-parameterized
|
||||
@@ -1117,7 +941,7 @@ class UnitTestImpl {
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
// A per-thread stack of traces created by the SCOPED_TRACE() macro.
|
||||
internal::ThreadLocal<internal::Vector<TraceInfo> > gtest_trace_stack_;
|
||||
internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
|
||||
}; // class UnitTestImpl
|
||||
@@ -1130,24 +954,24 @@ inline UnitTestImpl* GetUnitTestImpl() {
|
||||
|
||||
// Internal helper functions for implementing the simple regular
|
||||
// expression matcher.
|
||||
bool IsInSet(char ch, const char* str);
|
||||
bool IsDigit(char ch);
|
||||
bool IsPunct(char ch);
|
||||
bool IsRepeat(char ch);
|
||||
bool IsWhiteSpace(char ch);
|
||||
bool IsWordChar(char ch);
|
||||
bool IsValidEscape(char ch);
|
||||
bool AtomMatchesChar(bool escaped, char pattern, char ch);
|
||||
bool ValidateRegex(const char* regex);
|
||||
bool MatchRegexAtHead(const char* regex, const char* str);
|
||||
bool MatchRepetitionAndRegexAtHead(
|
||||
GTEST_API_ bool IsInSet(char ch, const char* str);
|
||||
GTEST_API_ bool IsDigit(char ch);
|
||||
GTEST_API_ bool IsPunct(char ch);
|
||||
GTEST_API_ bool IsRepeat(char ch);
|
||||
GTEST_API_ bool IsWhiteSpace(char ch);
|
||||
GTEST_API_ bool IsWordChar(char ch);
|
||||
GTEST_API_ bool IsValidEscape(char ch);
|
||||
GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
|
||||
GTEST_API_ bool ValidateRegex(const char* regex);
|
||||
GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
|
||||
GTEST_API_ bool MatchRepetitionAndRegexAtHead(
|
||||
bool escaped, char ch, char repeat, const char* regex, const char* str);
|
||||
bool MatchRegexAnywhere(const char* regex, const char* str);
|
||||
GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
|
||||
|
||||
// Parses the command line for Google Test flags, without initializing
|
||||
// other parts of Google Test.
|
||||
void ParseGoogleTestFlagsOnly(int* argc, char** argv);
|
||||
void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
|
||||
GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
|
||||
GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
@@ -1224,6 +1048,9 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
|
||||
// TestResult contains some private methods that should be hidden from
|
||||
// Google Test user but are required for testing. This class allow our tests
|
||||
// to access them.
|
||||
//
|
||||
// This class is supplied only for the purpose of testing Google Test's own
|
||||
// constructs. Do not use it in user tests, either directly or indirectly.
|
||||
class TestResultAccessor {
|
||||
public:
|
||||
static void RecordProperty(TestResult* test_result,
|
||||
@@ -1235,7 +1062,7 @@ class TestResultAccessor {
|
||||
test_result->ClearTestPartResults();
|
||||
}
|
||||
|
||||
static const Vector<testing::TestPartResult>& test_part_results(
|
||||
static const std::vector<testing::TestPartResult>& test_part_results(
|
||||
const TestResult& test_result) {
|
||||
return test_result.test_part_results();
|
||||
}
|
||||
|
||||
+91
-60
@@ -68,8 +68,10 @@ namespace internal {
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
|
||||
const int kStdOutFileno = 1;
|
||||
const int kStdErrFileno = 2;
|
||||
#else
|
||||
const int kStdOutFileno = STDOUT_FILENO;
|
||||
const int kStdErrFileno = STDERR_FILENO;
|
||||
#endif // _MSC_VER
|
||||
|
||||
@@ -109,8 +111,14 @@ size_t GetThreadCount() {
|
||||
// Implements RE. Currently only needed for death tests.
|
||||
|
||||
RE::~RE() {
|
||||
regfree(&partial_regex_);
|
||||
regfree(&full_regex_);
|
||||
if (is_valid_) {
|
||||
// regfree'ing an invalid regex might crash because the content
|
||||
// of the regex is undefined. Since the regex's are essentially
|
||||
// the same, one cannot be valid (or invalid) without the other
|
||||
// being so too.
|
||||
regfree(&partial_regex_);
|
||||
regfree(&full_regex_);
|
||||
}
|
||||
free(const_cast<char*>(pattern_));
|
||||
}
|
||||
|
||||
@@ -150,9 +158,10 @@ void RE::Init(const char* regex) {
|
||||
// Some implementation of POSIX regex (e.g. on at least some
|
||||
// versions of Cygwin) doesn't accept the empty string as a valid
|
||||
// regex. We change it to an equivalent form "()" to be safe.
|
||||
const char* const partial_regex = (*regex == '\0') ? "()" : regex;
|
||||
is_valid_ = (regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0)
|
||||
&& is_valid_;
|
||||
if (is_valid_) {
|
||||
const char* const partial_regex = (*regex == '\0') ? "()" : regex;
|
||||
is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
|
||||
}
|
||||
EXPECT_TRUE(is_valid_)
|
||||
<< "Regular expression \"" << regex
|
||||
<< "\" is not a valid POSIX Extended regular expression.";
|
||||
@@ -439,81 +448,83 @@ GTestLog::~GTestLog() {
|
||||
#pragma warning(disable: 4996)
|
||||
#endif // _MSC_VER
|
||||
|
||||
// Defines the stderr capturer.
|
||||
#if GTEST_HAS_STREAM_REDIRECTION_
|
||||
|
||||
class CapturedStderr {
|
||||
// Object that captures an output stream (stdout/stderr).
|
||||
class CapturedStream {
|
||||
public:
|
||||
// The ctor redirects stderr to a temporary file.
|
||||
CapturedStderr() {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
// Not supported on Windows CE.
|
||||
posix::Abort();
|
||||
#else
|
||||
uncaptured_fd_ = dup(kStdErrFileno);
|
||||
|
||||
// The ctor redirects the stream to a temporary file.
|
||||
CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
|
||||
#if GTEST_OS_WINDOWS
|
||||
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
||||
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
||||
|
||||
::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
|
||||
::GetTempFileNameA(temp_dir_path, "gtest_redir", 0, temp_file_path);
|
||||
const UINT success = ::GetTempFileNameA(temp_dir_path,
|
||||
"gtest_redir",
|
||||
0, // Generate unique file name.
|
||||
temp_file_path);
|
||||
GTEST_CHECK_(success != 0)
|
||||
<< "Unable to create a temporary file in " << temp_dir_path;
|
||||
const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
|
||||
GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
|
||||
<< temp_file_path;
|
||||
filename_ = temp_file_path;
|
||||
#else
|
||||
// There's no guarantee that a test has write access to the
|
||||
// current directory, so we create the temporary file in the /tmp
|
||||
// directory instead.
|
||||
char name_template[] = "/tmp/captured_stderr.XXXXXX";
|
||||
char name_template[] = "/tmp/captured_stream.XXXXXX";
|
||||
const int captured_fd = mkstemp(name_template);
|
||||
filename_ = name_template;
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
fflush(NULL);
|
||||
dup2(captured_fd, kStdErrFileno);
|
||||
dup2(captured_fd, fd_);
|
||||
close(captured_fd);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
||||
~CapturedStderr() {
|
||||
#if !GTEST_OS_WINDOWS_MOBILE
|
||||
~CapturedStream() {
|
||||
remove(filename_.c_str());
|
||||
#endif // !GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
||||
// Stops redirecting stderr.
|
||||
void StopCapture() {
|
||||
#if !GTEST_OS_WINDOWS_MOBILE
|
||||
// Restores the original stream.
|
||||
fflush(NULL);
|
||||
dup2(uncaptured_fd_, kStdErrFileno);
|
||||
close(uncaptured_fd_);
|
||||
uncaptured_fd_ = -1;
|
||||
#endif // !GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
String GetCapturedString() {
|
||||
if (uncaptured_fd_ != -1) {
|
||||
// Restores the original stream.
|
||||
fflush(NULL);
|
||||
dup2(uncaptured_fd_, fd_);
|
||||
close(uncaptured_fd_);
|
||||
uncaptured_fd_ = -1;
|
||||
}
|
||||
|
||||
// Returns the name of the temporary file holding the stderr output.
|
||||
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
|
||||
// can use it here.
|
||||
::std::string filename() const { return filename_; }
|
||||
FILE* const file = posix::FOpen(filename_.c_str(), "r");
|
||||
const String content = ReadEntireFile(file);
|
||||
posix::FClose(file);
|
||||
return content;
|
||||
}
|
||||
|
||||
private:
|
||||
// Reads the entire content of a file as a String.
|
||||
static String ReadEntireFile(FILE* file);
|
||||
|
||||
// Returns the size (in bytes) of a file.
|
||||
static size_t GetFileSize(FILE* file);
|
||||
|
||||
const int fd_; // A stream to capture.
|
||||
int uncaptured_fd_;
|
||||
// Name of the temporary file holding the stderr output.
|
||||
::std::string filename_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
static CapturedStderr* g_captured_stderr = NULL;
|
||||
|
||||
// Returns the size (in bytes) of a file.
|
||||
static size_t GetFileSize(FILE * file) {
|
||||
size_t CapturedStream::GetFileSize(FILE* file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
return static_cast<size_t>(ftell(file));
|
||||
}
|
||||
|
||||
// Reads the entire content of a file as a string.
|
||||
static String ReadEntireFile(FILE * file) {
|
||||
String CapturedStream::ReadEntireFile(FILE* file) {
|
||||
const size_t file_size = GetFileSize(file);
|
||||
char* const buffer = new char[file_size];
|
||||
|
||||
@@ -535,30 +546,50 @@ static String ReadEntireFile(FILE * file) {
|
||||
return content;
|
||||
}
|
||||
|
||||
// Starts capturing stderr.
|
||||
void CaptureStderr() {
|
||||
if (g_captured_stderr != NULL) {
|
||||
GTEST_LOG_(FATAL) << "Only one stderr capturer can exist at one time.";
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
static CapturedStream* g_captured_stderr = NULL;
|
||||
static CapturedStream* g_captured_stdout = NULL;
|
||||
|
||||
// Starts capturing an output stream (stdout/stderr).
|
||||
void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
|
||||
if (*stream != NULL) {
|
||||
GTEST_LOG_(FATAL) << "Only one " << stream_name
|
||||
<< " capturer can exist at a time.";
|
||||
}
|
||||
g_captured_stderr = new CapturedStderr;
|
||||
*stream = new CapturedStream(fd);
|
||||
}
|
||||
|
||||
// Stops capturing stderr and returns the captured string.
|
||||
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
|
||||
// use it here.
|
||||
String GetCapturedStderr() {
|
||||
g_captured_stderr->StopCapture();
|
||||
// Stops capturing the output stream and returns the captured string.
|
||||
String GetCapturedStream(CapturedStream** captured_stream) {
|
||||
const String content = (*captured_stream)->GetCapturedString();
|
||||
|
||||
FILE* const file = posix::FOpen(g_captured_stderr->filename().c_str(), "r");
|
||||
const String content = ReadEntireFile(file);
|
||||
posix::FClose(file);
|
||||
|
||||
delete g_captured_stderr;
|
||||
g_captured_stderr = NULL;
|
||||
delete *captured_stream;
|
||||
*captured_stream = NULL;
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
// Starts capturing stdout.
|
||||
void CaptureStdout() {
|
||||
CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
|
||||
}
|
||||
|
||||
// Starts capturing stderr.
|
||||
void CaptureStderr() {
|
||||
CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
|
||||
}
|
||||
|
||||
// Stops capturing stdout and returns the captured string.
|
||||
String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
|
||||
|
||||
// Stops capturing stderr and returns the captured string.
|
||||
String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
|
||||
|
||||
#endif // GTEST_HAS_STREAM_REDIRECTION_
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
// A copy of all command line arguments. Set by InitGoogleTest().
|
||||
|
||||
+3
-13
@@ -64,19 +64,9 @@ std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
||||
<< result.message() << std::endl;
|
||||
}
|
||||
|
||||
// Constructs an empty TestPartResultArray.
|
||||
TestPartResultArray::TestPartResultArray()
|
||||
: array_(new internal::Vector<TestPartResult>) {
|
||||
}
|
||||
|
||||
// Destructs a TestPartResultArray.
|
||||
TestPartResultArray::~TestPartResultArray() {
|
||||
delete array_;
|
||||
}
|
||||
|
||||
// Appends a TestPartResult to the array.
|
||||
void TestPartResultArray::Append(const TestPartResult& result) {
|
||||
array_->PushBack(result);
|
||||
array_.push_back(result);
|
||||
}
|
||||
|
||||
// Returns the TestPartResult at the given index (0-based).
|
||||
@@ -86,12 +76,12 @@ const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
|
||||
internal::posix::Abort();
|
||||
}
|
||||
|
||||
return array_->GetElement(index);
|
||||
return array_[index];
|
||||
}
|
||||
|
||||
// Returns the number of TestPartResult objects in the array.
|
||||
int TestPartResultArray::size() const {
|
||||
return array_->size();
|
||||
return static_cast<int>(array_.size());
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -37,6 +37,14 @@ namespace internal {
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// Skips to the first non-space char in str. Returns an empty string if str
|
||||
// contains only whitespace characters.
|
||||
static const char* SkipSpaces(const char* str) {
|
||||
while (isspace(*str))
|
||||
str++;
|
||||
return str;
|
||||
}
|
||||
|
||||
// Verifies that registered_tests match the test names in
|
||||
// defined_test_names_; returns registered_tests if successful, or
|
||||
// aborts the program otherwise.
|
||||
@@ -45,6 +53,10 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||
typedef ::std::set<const char*>::const_iterator DefinedTestIter;
|
||||
registered_ = true;
|
||||
|
||||
// Skip initial whitespace in registered_tests since some
|
||||
// preprocessors prefix stringizied literals with whitespace.
|
||||
registered_tests = SkipSpaces(registered_tests);
|
||||
|
||||
Message errors;
|
||||
::std::set<String> tests;
|
||||
for (const char* names = registered_tests; names != NULL;
|
||||
|
||||
+212
-150
@@ -42,7 +42,10 @@
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#if GTEST_OS_LINUX
|
||||
|
||||
@@ -131,6 +134,11 @@
|
||||
|
||||
namespace testing {
|
||||
|
||||
using internal::CountIf;
|
||||
using internal::ForEach;
|
||||
using internal::GetElementOr;
|
||||
using internal::Shuffle;
|
||||
|
||||
// Constants.
|
||||
|
||||
// A test whose test case name or test name matches this filter is
|
||||
@@ -161,6 +169,10 @@ namespace internal {
|
||||
// stack trace.
|
||||
const char kStackTraceMarker[] = "\nStack trace:\n";
|
||||
|
||||
// g_help_flag is true iff the --help flag or an equivalent form is
|
||||
// specified on the command line.
|
||||
bool g_help_flag = false;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
GTEST_DEFINE_bool_(
|
||||
@@ -242,7 +254,7 @@ GTEST_DEFINE_bool_(
|
||||
|
||||
GTEST_DEFINE_int32_(
|
||||
stack_trace_depth,
|
||||
internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
|
||||
internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
|
||||
"The maximum number of stack frames to print when an "
|
||||
"assertion fails. The valid range is 0 through 100, inclusive.");
|
||||
|
||||
@@ -274,10 +286,6 @@ UInt32 Random::Generate(UInt32 range) {
|
||||
return state_ % range;
|
||||
}
|
||||
|
||||
// g_help_flag is true iff the --help flag or an equivalent form is
|
||||
// specified on the command line.
|
||||
static bool g_help_flag = false;
|
||||
|
||||
// GTestIsInitialized() returns true iff the user has initialized
|
||||
// Google Test. Useful for catching the user mistake of not initializing
|
||||
// Google Test before calling RUN_ALL_TESTS().
|
||||
@@ -292,11 +300,11 @@ static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
|
||||
// Iterates over a vector of TestCases, keeping a running sum of the
|
||||
// results of calling a given int-returning method on each.
|
||||
// Returns the sum.
|
||||
static int SumOverTestCaseList(const internal::Vector<TestCase*>& case_list,
|
||||
static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
|
||||
int (TestCase::*method)() const) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < case_list.size(); i++) {
|
||||
sum += (case_list.GetElement(i)->*method)();
|
||||
for (size_t i = 0; i < case_list.size(); i++) {
|
||||
sum += (case_list[i]->*method)();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
@@ -341,7 +349,7 @@ void AssertHelper::operator=(const Message& message) const {
|
||||
}
|
||||
|
||||
// Mutex for linked pointers.
|
||||
Mutex g_linked_ptr_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX);
|
||||
GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||
|
||||
// Application pathname gotten in InitGoogleTest.
|
||||
String g_executable_path;
|
||||
@@ -672,23 +680,23 @@ void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
|
||||
|
||||
// Gets the number of successful test cases.
|
||||
int UnitTestImpl::successful_test_case_count() const {
|
||||
return test_cases_.CountIf(TestCasePassed);
|
||||
return CountIf(test_cases_, TestCasePassed);
|
||||
}
|
||||
|
||||
// Gets the number of failed test cases.
|
||||
int UnitTestImpl::failed_test_case_count() const {
|
||||
return test_cases_.CountIf(TestCaseFailed);
|
||||
return CountIf(test_cases_, TestCaseFailed);
|
||||
}
|
||||
|
||||
// Gets the number of all test cases.
|
||||
int UnitTestImpl::total_test_case_count() const {
|
||||
return test_cases_.size();
|
||||
return static_cast<int>(test_cases_.size());
|
||||
}
|
||||
|
||||
// Gets the number of all test cases that contain at least one test
|
||||
// that should run.
|
||||
int UnitTestImpl::test_case_to_run_count() const {
|
||||
return test_cases_.CountIf(ShouldRunTestCase);
|
||||
return CountIf(test_cases_, ShouldRunTestCase);
|
||||
}
|
||||
|
||||
// Gets the number of successful tests.
|
||||
@@ -952,21 +960,37 @@ String FormatForFailureMessage(wchar_t wchar) {
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// AssertionResult constructor.
|
||||
AssertionResult::AssertionResult(const internal::String& failure_message)
|
||||
: failure_message_(failure_message) {
|
||||
// AssertionResult constructors.
|
||||
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||
AssertionResult::AssertionResult(const AssertionResult& other)
|
||||
: success_(other.success_),
|
||||
message_(other.message_.get() != NULL ?
|
||||
new internal::String(*other.message_) :
|
||||
static_cast<internal::String*>(NULL)) {
|
||||
}
|
||||
|
||||
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
|
||||
AssertionResult AssertionResult::operator!() const {
|
||||
AssertionResult negation(!success_);
|
||||
if (message_.get() != NULL)
|
||||
negation << *message_;
|
||||
return negation;
|
||||
}
|
||||
|
||||
// Makes a successful assertion result.
|
||||
AssertionResult AssertionSuccess() {
|
||||
return AssertionResult();
|
||||
return AssertionResult(true);
|
||||
}
|
||||
|
||||
// Makes a failed assertion result.
|
||||
AssertionResult AssertionFailure() {
|
||||
return AssertionResult(false);
|
||||
}
|
||||
|
||||
// Makes a failed assertion result with the given failure message.
|
||||
// Deprecated; use AssertionFailure() << message.
|
||||
AssertionResult AssertionFailure(const Message& message) {
|
||||
return AssertionResult(message.GetString());
|
||||
return AssertionFailure() << message;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
@@ -1008,6 +1032,20 @@ AssertionResult EqFailure(const char* expected_expression,
|
||||
return AssertionFailure(msg);
|
||||
}
|
||||
|
||||
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
|
||||
String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result,
|
||||
const char* expression_text,
|
||||
const char* actual_predicate_value,
|
||||
const char* expected_predicate_value) {
|
||||
const char* actual_message = assertion_result.message();
|
||||
Message msg;
|
||||
msg << "Value of: " << expression_text
|
||||
<< "\n Actual: " << actual_predicate_value;
|
||||
if (actual_message[0] != '\0')
|
||||
msg << " (" << actual_message << ")";
|
||||
msg << "\nExpected: " << expected_predicate_value;
|
||||
return msg.GetString();
|
||||
}
|
||||
|
||||
// Helper function for implementing ASSERT_NEAR.
|
||||
AssertionResult DoubleNearPredFormat(const char* expr1,
|
||||
@@ -1286,7 +1324,6 @@ AssertionResult IsNotSubstring(
|
||||
return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_STRING
|
||||
AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::string& needle, const ::std::string& haystack) {
|
||||
@@ -1298,7 +1335,6 @@ AssertionResult IsNotSubstring(
|
||||
const ::std::string& needle, const ::std::string& haystack) {
|
||||
return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
AssertionResult IsSubstring(
|
||||
@@ -1718,14 +1754,9 @@ String String::Format(const char * format, ...) {
|
||||
// Converts the buffer in a StrStream to a String, converting NUL
|
||||
// bytes to "\\0" along the way.
|
||||
String StrStreamToString(StrStream* ss) {
|
||||
#if GTEST_HAS_STD_STRING
|
||||
const ::std::string& str = ss->str();
|
||||
const char* const start = str.c_str();
|
||||
const char* const end = start + str.length();
|
||||
#else
|
||||
const char* const start = ss->str();
|
||||
const char* const end = start + ss->pcount();
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
|
||||
// We need to use a helper StrStream to do this transformation
|
||||
// because String doesn't support push_back().
|
||||
@@ -1738,14 +1769,7 @@ String StrStreamToString(StrStream* ss) {
|
||||
}
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_STRING
|
||||
return String(helper.str().c_str());
|
||||
#else
|
||||
const String str(helper.str(), helper.pcount());
|
||||
helper.freeze(false);
|
||||
ss->freeze(false);
|
||||
return str;
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
}
|
||||
|
||||
// Appends the user-supplied message to the Google-Test-generated message.
|
||||
@@ -1769,9 +1793,7 @@ String AppendUserMessage(const String& gtest_msg,
|
||||
|
||||
// Creates an empty TestResult.
|
||||
TestResult::TestResult()
|
||||
: test_part_results_(new internal::Vector<TestPartResult>),
|
||||
test_properties_(new internal::Vector<TestProperty>),
|
||||
death_test_count_(0),
|
||||
: death_test_count_(0),
|
||||
elapsed_time_(0) {
|
||||
}
|
||||
|
||||
@@ -1783,24 +1805,28 @@ TestResult::~TestResult() {
|
||||
// range from 0 to total_part_count() - 1. If i is not in that range,
|
||||
// aborts the program.
|
||||
const TestPartResult& TestResult::GetTestPartResult(int i) const {
|
||||
return test_part_results_->GetElement(i);
|
||||
if (i < 0 || i >= total_part_count())
|
||||
internal::posix::Abort();
|
||||
return test_part_results_.at(i);
|
||||
}
|
||||
|
||||
// Returns the i-th test property. i can range from 0 to
|
||||
// test_property_count() - 1. If i is not in that range, aborts the
|
||||
// program.
|
||||
const TestProperty& TestResult::GetTestProperty(int i) const {
|
||||
return test_properties_->GetElement(i);
|
||||
if (i < 0 || i >= test_property_count())
|
||||
internal::posix::Abort();
|
||||
return test_properties_.at(i);
|
||||
}
|
||||
|
||||
// Clears the test part results.
|
||||
void TestResult::ClearTestPartResults() {
|
||||
test_part_results_->Clear();
|
||||
test_part_results_.clear();
|
||||
}
|
||||
|
||||
// Adds a test part result to the list.
|
||||
void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
|
||||
test_part_results_->PushBack(test_part_result);
|
||||
test_part_results_.push_back(test_part_result);
|
||||
}
|
||||
|
||||
// Adds a test property to the list. If a property with the same key as the
|
||||
@@ -1811,11 +1837,11 @@ void TestResult::RecordProperty(const TestProperty& test_property) {
|
||||
return;
|
||||
}
|
||||
internal::MutexLock lock(&test_properites_mutex_);
|
||||
TestProperty* const property_with_matching_key =
|
||||
test_properties_->FindIf(
|
||||
internal::TestPropertyKeyIs(test_property.key()));
|
||||
if (property_with_matching_key == NULL) {
|
||||
test_properties_->PushBack(test_property);
|
||||
const std::vector<TestProperty>::iterator property_with_matching_key =
|
||||
std::find_if(test_properties_.begin(), test_properties_.end(),
|
||||
internal::TestPropertyKeyIs(test_property.key()));
|
||||
if (property_with_matching_key == test_properties_.end()) {
|
||||
test_properties_.push_back(test_property);
|
||||
return;
|
||||
}
|
||||
property_with_matching_key->SetValue(test_property.value());
|
||||
@@ -1838,8 +1864,8 @@ bool TestResult::ValidateTestProperty(const TestProperty& test_property) {
|
||||
|
||||
// Clears the object.
|
||||
void TestResult::Clear() {
|
||||
test_part_results_->Clear();
|
||||
test_properties_->Clear();
|
||||
test_part_results_.clear();
|
||||
test_properties_.clear();
|
||||
death_test_count_ = 0;
|
||||
elapsed_time_ = 0;
|
||||
}
|
||||
@@ -1860,7 +1886,7 @@ static bool TestPartFatallyFailed(const TestPartResult& result) {
|
||||
|
||||
// Returns true iff the test fatally failed.
|
||||
bool TestResult::HasFatalFailure() const {
|
||||
return test_part_results_->CountIf(TestPartFatallyFailed) > 0;
|
||||
return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
|
||||
}
|
||||
|
||||
// Returns true iff the test part non-fatally failed.
|
||||
@@ -1870,18 +1896,18 @@ static bool TestPartNonfatallyFailed(const TestPartResult& result) {
|
||||
|
||||
// Returns true iff the test has a non-fatal failure.
|
||||
bool TestResult::HasNonfatalFailure() const {
|
||||
return test_part_results_->CountIf(TestPartNonfatallyFailed) > 0;
|
||||
return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
|
||||
}
|
||||
|
||||
// Gets the number of all test parts. This is the sum of the number
|
||||
// of successful test parts and the number of failed test parts.
|
||||
int TestResult::total_part_count() const {
|
||||
return test_part_results_->size();
|
||||
return static_cast<int>(test_part_results_.size());
|
||||
}
|
||||
|
||||
// Returns the number of the test properties.
|
||||
int TestResult::test_property_count() const {
|
||||
return test_properties_->size();
|
||||
return static_cast<int>(test_properties_.size());
|
||||
}
|
||||
|
||||
// class Test
|
||||
@@ -1965,7 +1991,7 @@ bool Test::HasSameFixtureClass() {
|
||||
|
||||
// Info about the first test in the current test case.
|
||||
const internal::TestInfoImpl* const first_test_info =
|
||||
test_case->test_info_list().GetElement(0)->impl();
|
||||
test_case->test_info_list()[0]->impl();
|
||||
const internal::TypeId first_fixture_id = first_test_info->fixture_class_id();
|
||||
const char* const first_test_name = first_test_info->name();
|
||||
|
||||
@@ -2093,14 +2119,14 @@ bool Test::HasNonfatalFailure() {
|
||||
|
||||
// Constructs a TestInfo object. It assumes ownership of the test factory
|
||||
// object via impl_.
|
||||
TestInfo::TestInfo(const char* test_case_name,
|
||||
const char* name,
|
||||
const char* test_case_comment,
|
||||
const char* comment,
|
||||
TestInfo::TestInfo(const char* a_test_case_name,
|
||||
const char* a_name,
|
||||
const char* a_test_case_comment,
|
||||
const char* a_comment,
|
||||
internal::TypeId fixture_class_id,
|
||||
internal::TestFactoryBase* factory) {
|
||||
impl_ = new internal::TestInfoImpl(this, test_case_name, name,
|
||||
test_case_comment, comment,
|
||||
impl_ = new internal::TestInfoImpl(this, a_test_case_name, a_name,
|
||||
a_test_case_comment, a_comment,
|
||||
fixture_class_id, factory);
|
||||
}
|
||||
|
||||
@@ -2309,26 +2335,26 @@ void TestInfoImpl::Run() {
|
||||
|
||||
// Gets the number of successful tests in this test case.
|
||||
int TestCase::successful_test_count() const {
|
||||
return test_info_list_->CountIf(TestPassed);
|
||||
return CountIf(test_info_list_, TestPassed);
|
||||
}
|
||||
|
||||
// Gets the number of failed tests in this test case.
|
||||
int TestCase::failed_test_count() const {
|
||||
return test_info_list_->CountIf(TestFailed);
|
||||
return CountIf(test_info_list_, TestFailed);
|
||||
}
|
||||
|
||||
int TestCase::disabled_test_count() const {
|
||||
return test_info_list_->CountIf(TestDisabled);
|
||||
return CountIf(test_info_list_, TestDisabled);
|
||||
}
|
||||
|
||||
// Get the number of tests in this test case that should run.
|
||||
int TestCase::test_to_run_count() const {
|
||||
return test_info_list_->CountIf(ShouldRunTest);
|
||||
return CountIf(test_info_list_, ShouldRunTest);
|
||||
}
|
||||
|
||||
// Gets the number of all tests.
|
||||
int TestCase::total_test_count() const {
|
||||
return test_info_list_->size();
|
||||
return static_cast<int>(test_info_list_.size());
|
||||
}
|
||||
|
||||
// Creates a TestCase with the given name.
|
||||
@@ -2338,13 +2364,11 @@ int TestCase::total_test_count() const {
|
||||
// name: name of the test case
|
||||
// set_up_tc: pointer to the function that sets up the test case
|
||||
// tear_down_tc: pointer to the function that tears down the test case
|
||||
TestCase::TestCase(const char* name, const char* comment,
|
||||
TestCase::TestCase(const char* a_name, const char* a_comment,
|
||||
Test::SetUpTestCaseFunc set_up_tc,
|
||||
Test::TearDownTestCaseFunc tear_down_tc)
|
||||
: name_(name),
|
||||
comment_(comment),
|
||||
test_info_list_(new internal::Vector<TestInfo*>),
|
||||
test_indices_(new internal::Vector<int>),
|
||||
: name_(a_name),
|
||||
comment_(a_comment),
|
||||
set_up_tc_(set_up_tc),
|
||||
tear_down_tc_(tear_down_tc),
|
||||
should_run_(false),
|
||||
@@ -2354,28 +2378,28 @@ TestCase::TestCase(const char* name, const char* comment,
|
||||
// Destructor of TestCase.
|
||||
TestCase::~TestCase() {
|
||||
// Deletes every Test in the collection.
|
||||
test_info_list_->ForEach(internal::Delete<TestInfo>);
|
||||
ForEach(test_info_list_, internal::Delete<TestInfo>);
|
||||
}
|
||||
|
||||
// Returns the i-th test among all the tests. i can range from 0 to
|
||||
// total_test_count() - 1. If i is not in that range, returns NULL.
|
||||
const TestInfo* TestCase::GetTestInfo(int i) const {
|
||||
const int index = test_indices_->GetElementOr(i, -1);
|
||||
return index < 0 ? NULL : test_info_list_->GetElement(index);
|
||||
const int index = GetElementOr(test_indices_, i, -1);
|
||||
return index < 0 ? NULL : test_info_list_[index];
|
||||
}
|
||||
|
||||
// Returns the i-th test among all the tests. i can range from 0 to
|
||||
// total_test_count() - 1. If i is not in that range, returns NULL.
|
||||
TestInfo* TestCase::GetMutableTestInfo(int i) {
|
||||
const int index = test_indices_->GetElementOr(i, -1);
|
||||
return index < 0 ? NULL : test_info_list_->GetElement(index);
|
||||
const int index = GetElementOr(test_indices_, i, -1);
|
||||
return index < 0 ? NULL : test_info_list_[index];
|
||||
}
|
||||
|
||||
// Adds a test to this test case. Will delete the test upon
|
||||
// destruction of the TestCase object.
|
||||
void TestCase::AddTestInfo(TestInfo * test_info) {
|
||||
test_info_list_->PushBack(test_info);
|
||||
test_indices_->PushBack(test_indices_->size());
|
||||
test_info_list_.push_back(test_info);
|
||||
test_indices_.push_back(static_cast<int>(test_indices_.size()));
|
||||
}
|
||||
|
||||
// Runs every test in this TestCase.
|
||||
@@ -2405,7 +2429,7 @@ void TestCase::Run() {
|
||||
|
||||
// Clears the results of all tests in this test case.
|
||||
void TestCase::ClearResult() {
|
||||
test_info_list_->ForEach(internal::TestInfoImpl::ClearTestResult);
|
||||
ForEach(test_info_list_, internal::TestInfoImpl::ClearTestResult);
|
||||
}
|
||||
|
||||
// Returns true iff test passed.
|
||||
@@ -2432,13 +2456,13 @@ bool TestCase::ShouldRunTest(const TestInfo *test_info) {
|
||||
|
||||
// Shuffles the tests in this test case.
|
||||
void TestCase::ShuffleTests(internal::Random* random) {
|
||||
test_indices_->Shuffle(random);
|
||||
Shuffle(random, &test_indices_);
|
||||
}
|
||||
|
||||
// Restores the test order to before the first shuffle.
|
||||
void TestCase::UnshuffleTests() {
|
||||
for (int i = 0; i < test_indices_->size(); i++) {
|
||||
test_indices_->GetMutableElement(i) = i;
|
||||
for (size_t i = 0; i < test_indices_.size(); i++) {
|
||||
test_indices_[i] = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2614,10 +2638,15 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
|
||||
GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
|
||||
const WORD old_color_attrs = buffer_info.wAttributes;
|
||||
|
||||
// We need to flush the stream buffers into the console before each
|
||||
// SetConsoleTextAttribute call lest it affect the text that is already
|
||||
// printed but has not yet reached the console.
|
||||
fflush(stdout);
|
||||
SetConsoleTextAttribute(stdout_handle,
|
||||
GetColorAttribute(color) | FOREGROUND_INTENSITY);
|
||||
vprintf(fmt, args);
|
||||
|
||||
fflush(stdout);
|
||||
// Restores the text color.
|
||||
SetConsoleTextAttribute(stdout_handle, old_color_attrs);
|
||||
#else
|
||||
@@ -2880,26 +2909,24 @@ class TestEventRepeater : public TestEventListener {
|
||||
// in death test child processes.
|
||||
bool forwarding_enabled_;
|
||||
// The list of listeners that receive events.
|
||||
Vector<TestEventListener*> listeners_;
|
||||
std::vector<TestEventListener*> listeners_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
|
||||
};
|
||||
|
||||
TestEventRepeater::~TestEventRepeater() {
|
||||
for (int i = 0; i < listeners_.size(); i++) {
|
||||
delete listeners_.GetElement(i);
|
||||
}
|
||||
ForEach(listeners_, Delete<TestEventListener>);
|
||||
}
|
||||
|
||||
void TestEventRepeater::Append(TestEventListener *listener) {
|
||||
listeners_.PushBack(listener);
|
||||
listeners_.push_back(listener);
|
||||
}
|
||||
|
||||
// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
|
||||
TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
|
||||
for (int i = 0; i < listeners_.size(); ++i) {
|
||||
if (listeners_.GetElement(i) == listener) {
|
||||
listeners_.Erase(i);
|
||||
for (size_t i = 0; i < listeners_.size(); ++i) {
|
||||
if (listeners_[i] == listener) {
|
||||
listeners_.erase(listeners_.begin() + i);
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
@@ -2912,8 +2939,8 @@ TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
|
||||
#define GTEST_REPEATER_METHOD_(Name, Type) \
|
||||
void TestEventRepeater::Name(const Type& parameter) { \
|
||||
if (forwarding_enabled_) { \
|
||||
for (int i = 0; i < listeners_.size(); i++) { \
|
||||
listeners_.GetElement(i)->Name(parameter); \
|
||||
for (size_t i = 0; i < listeners_.size(); i++) { \
|
||||
listeners_[i]->Name(parameter); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
@@ -2923,7 +2950,7 @@ void TestEventRepeater::Name(const Type& parameter) { \
|
||||
void TestEventRepeater::Name(const Type& parameter) { \
|
||||
if (forwarding_enabled_) { \
|
||||
for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
|
||||
listeners_.GetElement(i)->Name(parameter); \
|
||||
listeners_[i]->Name(parameter); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
@@ -2946,8 +2973,8 @@ GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
|
||||
void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
|
||||
int iteration) {
|
||||
if (forwarding_enabled_) {
|
||||
for (int i = 0; i < listeners_.size(); i++) {
|
||||
listeners_.GetElement(i)->OnTestIterationStart(unit_test, iteration);
|
||||
for (size_t i = 0; i < listeners_.size(); i++) {
|
||||
listeners_[i]->OnTestIterationStart(unit_test, iteration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2956,7 +2983,7 @@ void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
|
||||
int iteration) {
|
||||
if (forwarding_enabled_) {
|
||||
for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
|
||||
listeners_.GetElement(i)->OnTestIterationEnd(unit_test, iteration);
|
||||
listeners_[i]->OnTestIterationEnd(unit_test, iteration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3152,14 +3179,11 @@ String XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const char* str) {
|
||||
// </testsuite>
|
||||
// </testsuites>
|
||||
|
||||
// Formats the given time in milliseconds as seconds. The returned
|
||||
// C-string is owned by this function and cannot be released by the
|
||||
// caller. Calling the function again invalidates the previous
|
||||
// result.
|
||||
const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) {
|
||||
static String str;
|
||||
str = (Message() << (ms/1000.0)).GetString();
|
||||
return str.c_str();
|
||||
// Formats the given time in milliseconds as seconds.
|
||||
std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
|
||||
::std::stringstream ss;
|
||||
ss << ms/1000.0;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
|
||||
@@ -3170,7 +3194,8 @@ void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
|
||||
for (;;) {
|
||||
const char* const next_segment = strstr(segment, "]]>");
|
||||
if (next_segment != NULL) {
|
||||
stream->write(segment, next_segment - segment);
|
||||
stream->write(
|
||||
segment, static_cast<std::streamsize>(next_segment - segment));
|
||||
*stream << "]]>]]><![CDATA[";
|
||||
segment = next_segment + strlen("]]>");
|
||||
} else {
|
||||
@@ -3232,7 +3257,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
|
||||
test_case.disabled_test_count());
|
||||
fprintf(out,
|
||||
"errors=\"0\" time=\"%s\">\n",
|
||||
FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
|
||||
FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str());
|
||||
for (int i = 0; i < test_case.total_test_count(); ++i) {
|
||||
StrStream stream;
|
||||
OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i));
|
||||
@@ -3251,7 +3276,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
|
||||
unit_test.total_test_count(),
|
||||
unit_test.failed_test_count(),
|
||||
unit_test.disabled_test_count(),
|
||||
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
|
||||
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str());
|
||||
if (GTEST_FLAG(shuffle)) {
|
||||
fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
|
||||
}
|
||||
@@ -3512,8 +3537,7 @@ Environment* UnitTest::AddEnvironment(Environment* env) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
impl_->environments()->PushBack(env);
|
||||
impl_->environments_in_reverse_order()->PushFront(env);
|
||||
impl_->environments().push_back(env);
|
||||
return env;
|
||||
}
|
||||
|
||||
@@ -3544,12 +3568,12 @@ void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
|
||||
msg << message;
|
||||
|
||||
internal::MutexLock lock(&mutex_);
|
||||
if (impl_->gtest_trace_stack()->size() > 0) {
|
||||
if (impl_->gtest_trace_stack().size() > 0) {
|
||||
msg << "\n" << GTEST_NAME_ << " trace:";
|
||||
|
||||
for (int i = 0; i < impl_->gtest_trace_stack()->size(); i++) {
|
||||
const internal::TraceInfo& trace =
|
||||
impl_->gtest_trace_stack()->GetElement(i);
|
||||
for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
|
||||
i > 0; --i) {
|
||||
const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
|
||||
msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
|
||||
<< " " << trace.message;
|
||||
}
|
||||
@@ -3714,14 +3738,14 @@ UnitTest::~UnitTest() {
|
||||
// L < mutex_
|
||||
void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
impl_->gtest_trace_stack()->PushFront(trace);
|
||||
impl_->gtest_trace_stack().push_back(trace);
|
||||
}
|
||||
|
||||
// Pops a trace from the per-thread Google Test trace stack.
|
||||
// L < mutex_
|
||||
void UnitTest::PopGTestTrace() {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
impl_->gtest_trace_stack()->PopFront(NULL);
|
||||
impl_->gtest_trace_stack().pop_back();
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
@@ -3767,10 +3791,10 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
|
||||
|
||||
UnitTestImpl::~UnitTestImpl() {
|
||||
// Deletes every TestCase.
|
||||
test_cases_.ForEach(internal::Delete<TestCase>);
|
||||
ForEach(test_cases_, internal::Delete<TestCase>);
|
||||
|
||||
// Deletes every Environment.
|
||||
environments_.ForEach(internal::Delete<Environment>);
|
||||
ForEach(environments_, internal::Delete<Environment>);
|
||||
|
||||
delete os_stack_trace_getter_;
|
||||
}
|
||||
@@ -3862,9 +3886,11 @@ TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
|
||||
Test::SetUpTestCaseFunc set_up_tc,
|
||||
Test::TearDownTestCaseFunc tear_down_tc) {
|
||||
// Can we find a TestCase with the given name?
|
||||
TestCase** test_case = test_cases_.FindIf(TestCaseNameIs(test_case_name));
|
||||
const std::vector<TestCase*>::const_iterator test_case =
|
||||
std::find_if(test_cases_.begin(), test_cases_.end(),
|
||||
TestCaseNameIs(test_case_name));
|
||||
|
||||
if (test_case != NULL)
|
||||
if (test_case != test_cases_.end())
|
||||
return *test_case;
|
||||
|
||||
// No. Let's create one.
|
||||
@@ -3878,18 +3904,20 @@ TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
|
||||
// defined so far. This only works when the test cases haven't
|
||||
// been shuffled. Otherwise we may end up running a death test
|
||||
// after a non-death test.
|
||||
test_cases_.Insert(new_test_case, ++last_death_test_case_);
|
||||
++last_death_test_case_;
|
||||
test_cases_.insert(test_cases_.begin() + last_death_test_case_,
|
||||
new_test_case);
|
||||
} else {
|
||||
// No. Appends to the end of the list.
|
||||
test_cases_.PushBack(new_test_case);
|
||||
test_cases_.push_back(new_test_case);
|
||||
}
|
||||
|
||||
test_case_indices_.PushBack(test_case_indices_.size());
|
||||
test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
|
||||
return new_test_case;
|
||||
}
|
||||
|
||||
// Helpers for setting up / tearing down the given environment. They
|
||||
// are for use in the Vector::ForEach() method.
|
||||
// are for use in the ForEach() function.
|
||||
static void SetUpEnvironment(Environment* env) { env->SetUp(); }
|
||||
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
|
||||
|
||||
@@ -3985,20 +4013,22 @@ int UnitTestImpl::RunAllTests() {
|
||||
if (has_tests_to_run) {
|
||||
// Sets up all environments beforehand.
|
||||
repeater->OnEnvironmentsSetUpStart(*parent_);
|
||||
environments_.ForEach(SetUpEnvironment);
|
||||
ForEach(environments_, SetUpEnvironment);
|
||||
repeater->OnEnvironmentsSetUpEnd(*parent_);
|
||||
|
||||
// Runs the tests only if there was no fatal failure during global
|
||||
// set-up.
|
||||
if (!Test::HasFatalFailure()) {
|
||||
for (int i = 0; i < total_test_case_count(); i++) {
|
||||
GetMutableTestCase(i)->Run();
|
||||
for (int test_index = 0; test_index < total_test_case_count();
|
||||
test_index++) {
|
||||
GetMutableTestCase(test_index)->Run();
|
||||
}
|
||||
}
|
||||
|
||||
// Tears down all environments in reverse order afterwards.
|
||||
repeater->OnEnvironmentsTearDownStart(*parent_);
|
||||
environments_in_reverse_order_.ForEach(TearDownEnvironment);
|
||||
std::for_each(environments_.rbegin(), environments_.rend(),
|
||||
TearDownEnvironment);
|
||||
repeater->OnEnvironmentsTearDownEnd(*parent_);
|
||||
}
|
||||
|
||||
@@ -4144,13 +4174,13 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
|
||||
// this shard.
|
||||
int num_runnable_tests = 0;
|
||||
int num_selected_tests = 0;
|
||||
for (int i = 0; i < test_cases_.size(); i++) {
|
||||
TestCase* const test_case = test_cases_.GetElement(i);
|
||||
for (size_t i = 0; i < test_cases_.size(); i++) {
|
||||
TestCase* const test_case = test_cases_[i];
|
||||
const String &test_case_name = test_case->name();
|
||||
test_case->set_should_run(false);
|
||||
|
||||
for (int j = 0; j < test_case->test_info_list().size(); j++) {
|
||||
TestInfo* const test_info = test_case->test_info_list().GetElement(j);
|
||||
for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
|
||||
TestInfo* const test_info = test_case->test_info_list()[j];
|
||||
const String test_name(test_info->name());
|
||||
// A test is disabled if test case name or test name matches
|
||||
// kDisableTestFilter.
|
||||
@@ -4187,13 +4217,13 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
|
||||
|
||||
// Prints the names of the tests matching the user-specified filter flag.
|
||||
void UnitTestImpl::ListTestsMatchingFilter() {
|
||||
for (int i = 0; i < test_cases_.size(); i++) {
|
||||
const TestCase* const test_case = test_cases_.GetElement(i);
|
||||
for (size_t i = 0; i < test_cases_.size(); i++) {
|
||||
const TestCase* const test_case = test_cases_[i];
|
||||
bool printed_test_case_name = false;
|
||||
|
||||
for (int j = 0; j < test_case->test_info_list().size(); j++) {
|
||||
for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
|
||||
const TestInfo* const test_info =
|
||||
test_case->test_info_list().GetElement(j);
|
||||
test_case->test_info_list()[j];
|
||||
if (test_info->matches_filter()) {
|
||||
if (!printed_test_case_name) {
|
||||
printed_test_case_name = true;
|
||||
@@ -4241,43 +4271,43 @@ TestResult* UnitTestImpl::current_test_result() {
|
||||
// making sure that death tests are still run first.
|
||||
void UnitTestImpl::ShuffleTests() {
|
||||
// Shuffles the death test cases.
|
||||
test_case_indices_.ShuffleRange(random(), 0, last_death_test_case_ + 1);
|
||||
ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
|
||||
|
||||
// Shuffles the non-death test cases.
|
||||
test_case_indices_.ShuffleRange(random(), last_death_test_case_ + 1,
|
||||
test_cases_.size());
|
||||
ShuffleRange(random(), last_death_test_case_ + 1,
|
||||
static_cast<int>(test_cases_.size()), &test_case_indices_);
|
||||
|
||||
// Shuffles the tests inside each test case.
|
||||
for (int i = 0; i < test_cases_.size(); i++) {
|
||||
test_cases_.GetElement(i)->ShuffleTests(random());
|
||||
for (size_t i = 0; i < test_cases_.size(); i++) {
|
||||
test_cases_[i]->ShuffleTests(random());
|
||||
}
|
||||
}
|
||||
|
||||
// Restores the test cases and tests to their order before the first shuffle.
|
||||
void UnitTestImpl::UnshuffleTests() {
|
||||
for (int i = 0; i < test_cases_.size(); i++) {
|
||||
for (size_t i = 0; i < test_cases_.size(); i++) {
|
||||
// Unshuffles the tests in each test case.
|
||||
test_cases_.GetElement(i)->UnshuffleTests();
|
||||
test_cases_[i]->UnshuffleTests();
|
||||
// Resets the index of each test case.
|
||||
test_case_indices_.GetMutableElement(i) = i;
|
||||
test_case_indices_[i] = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
// TestInfoImpl constructor. The new instance assumes ownership of the test
|
||||
// factory object.
|
||||
TestInfoImpl::TestInfoImpl(TestInfo* parent,
|
||||
const char* test_case_name,
|
||||
const char* name,
|
||||
const char* test_case_comment,
|
||||
const char* comment,
|
||||
TypeId fixture_class_id,
|
||||
const char* a_test_case_name,
|
||||
const char* a_name,
|
||||
const char* a_test_case_comment,
|
||||
const char* a_comment,
|
||||
TypeId a_fixture_class_id,
|
||||
internal::TestFactoryBase* factory) :
|
||||
parent_(parent),
|
||||
test_case_name_(String(test_case_name)),
|
||||
name_(String(name)),
|
||||
test_case_comment_(String(test_case_comment)),
|
||||
comment_(String(comment)),
|
||||
fixture_class_id_(fixture_class_id),
|
||||
test_case_name_(String(a_test_case_name)),
|
||||
name_(String(a_name)),
|
||||
test_case_comment_(String(a_test_case_comment)),
|
||||
comment_(String(a_comment)),
|
||||
fixture_class_id_(a_fixture_class_id),
|
||||
should_run_(false),
|
||||
is_disabled_(false),
|
||||
matches_filter_(false),
|
||||
@@ -4324,6 +4354,18 @@ bool AlwaysTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If *pstr starts with the given prefix, modifies *pstr to be right
|
||||
// past the prefix and returns true; otherwise leaves *pstr unchanged
|
||||
// and returns false. None of pstr, *pstr, and prefix can be NULL.
|
||||
bool SkipPrefix(const char* prefix, const char** pstr) {
|
||||
const size_t prefix_len = strlen(prefix);
|
||||
if (strncmp(*pstr, prefix, prefix_len) == 0) {
|
||||
*pstr += prefix_len;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parses a string as a command line flag. The string should have
|
||||
// the format "--flag=value". When def_optional is true, the "=value"
|
||||
// part can be omitted.
|
||||
@@ -4413,6 +4455,21 @@ bool ParseStringFlag(const char* str, const char* flag, String* value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determines whether a string has a prefix that Google Test uses for its
|
||||
// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
|
||||
// If Google Test detects that a command line flag has its prefix but is not
|
||||
// recognized, it will print its help message. Flags starting with
|
||||
// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
|
||||
// internal flags and do not trigger the help message.
|
||||
static bool HasGoogleTestFlagPrefix(const char* str) {
|
||||
return (SkipPrefix("--", &str) ||
|
||||
SkipPrefix("-", &str) ||
|
||||
SkipPrefix("/", &str)) &&
|
||||
!SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
|
||||
(SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
|
||||
SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
|
||||
}
|
||||
|
||||
// Prints a string containing code-encoded text. The following escape
|
||||
// sequences can be used in the string to control the text color:
|
||||
//
|
||||
@@ -4553,6 +4610,8 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
|
||||
ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) ||
|
||||
ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) ||
|
||||
ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) ||
|
||||
ParseInt32Flag(arg, kStackTraceDepthFlag,
|
||||
>EST_FLAG(stack_trace_depth)) ||
|
||||
ParseBoolFlag(arg, kThrowOnFailureFlag, >EST_FLAG(throw_on_failure))
|
||||
) {
|
||||
// Yes. Shift the remainder of the argv list left by one. Note
|
||||
@@ -4570,7 +4629,10 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
|
||||
// an element.
|
||||
i--;
|
||||
} else if (arg_string == "--help" || arg_string == "-h" ||
|
||||
arg_string == "-?" || arg_string == "/?") {
|
||||
arg_string == "-?" || arg_string == "/?" ||
|
||||
HasGoogleTestFlagPrefix(arg)) {
|
||||
// Both help flag and unrecognized Google Test flags (excluding
|
||||
// internal ones) trigger help display.
|
||||
g_help_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,21 @@ class ReplaceDeathTestFactory {
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
void DieInside(const char* function) {
|
||||
fprintf(stderr, "death inside %s().", function);
|
||||
fflush(stderr);
|
||||
// We call _exit() instead of exit(), as the former is a direct
|
||||
// system call and thus safer in the presence of threads. exit()
|
||||
// will invoke user-defined exit-hooks, which may do dangerous
|
||||
// things that conflict with death tests.
|
||||
//
|
||||
// Some compilers can recognize that _exit() never returns and issue the
|
||||
// 'unreachable code' warning for code following this function, unless
|
||||
// fooled by a fake condition.
|
||||
if (AlwaysTrue())
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
// Tests that death tests work.
|
||||
|
||||
class TestForDeathTest : public testing::Test {
|
||||
@@ -114,23 +129,12 @@ class TestForDeathTest : public testing::Test {
|
||||
}
|
||||
|
||||
// A static member function that's expected to die.
|
||||
static void StaticMemberFunction() {
|
||||
fprintf(stderr, "%s", "death inside StaticMemberFunction().");
|
||||
fflush(stderr);
|
||||
// We call _exit() instead of exit(), as the former is a direct
|
||||
// system call and thus safer in the presence of threads. exit()
|
||||
// will invoke user-defined exit-hooks, which may do dangerous
|
||||
// things that conflict with death tests.
|
||||
_exit(1);
|
||||
}
|
||||
static void StaticMemberFunction() { DieInside("StaticMemberFunction"); }
|
||||
|
||||
// A method of the test fixture that may die.
|
||||
void MemberFunction() {
|
||||
if (should_die_) {
|
||||
fprintf(stderr, "%s", "death inside MemberFunction().");
|
||||
fflush(stderr);
|
||||
_exit(1);
|
||||
}
|
||||
if (should_die_)
|
||||
DieInside("MemberFunction");
|
||||
}
|
||||
|
||||
// True iff MemberFunction() should die.
|
||||
@@ -145,9 +149,8 @@ class MayDie {
|
||||
|
||||
// A member function that may die.
|
||||
void MemberFunction() const {
|
||||
if (should_die_) {
|
||||
GTEST_LOG_(FATAL) << "death inside MayDie::MemberFunction().";
|
||||
}
|
||||
if (should_die_)
|
||||
DieInside("MayDie::MemberFunction");
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -156,27 +159,24 @@ class MayDie {
|
||||
};
|
||||
|
||||
// A global function that's expected to die.
|
||||
void GlobalFunction() {
|
||||
GTEST_LOG_(FATAL) << "death inside GlobalFunction().";
|
||||
}
|
||||
void GlobalFunction() { DieInside("GlobalFunction"); }
|
||||
|
||||
// A non-void function that's expected to die.
|
||||
int NonVoidFunction() {
|
||||
GTEST_LOG_(FATAL) << "death inside NonVoidFunction().";
|
||||
DieInside("NonVoidFunction");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// A unary function that may die.
|
||||
void DieIf(bool should_die) {
|
||||
if (should_die) {
|
||||
GTEST_LOG_(FATAL) << "death inside DieIf().";
|
||||
}
|
||||
if (should_die)
|
||||
DieInside("DieIf");
|
||||
}
|
||||
|
||||
// A binary function that may die.
|
||||
bool DieIfLessThan(int x, int y) {
|
||||
if (x < y) {
|
||||
GTEST_LOG_(FATAL) << "death inside DieIfLessThan().";
|
||||
DieInside("DieIfLessThan");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ void DeathTestSubroutine() {
|
||||
int DieInDebugElse12(int* sideeffect) {
|
||||
if (sideeffect) *sideeffect = 12;
|
||||
#ifndef NDEBUG
|
||||
GTEST_LOG_(FATAL) << "debug death inside DieInDebugElse12()";
|
||||
DieInside("DieInDebugElse12");
|
||||
#endif // NDEBUG
|
||||
return 12;
|
||||
}
|
||||
@@ -410,7 +410,7 @@ void SetPthreadFlag() {
|
||||
|
||||
} // namespace
|
||||
|
||||
#if GTEST_HAS_CLONE
|
||||
#if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
|
||||
|
||||
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
|
||||
if (!testing::GTEST_FLAG(death_test_use_fork)) {
|
||||
@@ -422,7 +422,7 @@ TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_CLONE
|
||||
#endif // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
|
||||
|
||||
// Tests that a method of another class can be used in a death test.
|
||||
TEST_F(TestForDeathTest, MethodOfAnotherClass) {
|
||||
@@ -449,10 +449,8 @@ TEST_F(TestForDeathTest, AcceptsAnythingConvertibleToRE) {
|
||||
EXPECT_DEATH(GlobalFunction(), regex_str);
|
||||
#endif // GTEST_HAS_GLOBAL_STRING
|
||||
|
||||
#if GTEST_HAS_STD_STRING
|
||||
const ::std::string regex_std_str(regex_c_str);
|
||||
EXPECT_DEATH(GlobalFunction(), regex_std_str);
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
}
|
||||
|
||||
// Tests that a non-void function can be used in a death test.
|
||||
@@ -659,24 +657,6 @@ static void TestExitMacros() {
|
||||
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
|
||||
ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
|
||||
|
||||
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
|
||||
// MinGW (as of MinGW 5.1.6 and MSYS 1.0.11) does not tag crashed
|
||||
// processes with non-zero exit code and does not honor calls to
|
||||
// SetErrorMode(SEM_NOGPFAULTERRORBOX) that are supposed to suppress
|
||||
// error pop-ups.
|
||||
EXPECT_EXIT({
|
||||
testing::GTEST_FLAG(catch_exceptions) = false;
|
||||
*static_cast<int*>(NULL) = 1;
|
||||
}, testing::ExitedWithCode(0xC0000005), "") << "foo";
|
||||
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
EXPECT_EXIT({
|
||||
testing::GTEST_FLAG(catch_exceptions) = false;
|
||||
*static_cast<int*>(NULL) = 1;
|
||||
}, testing::ExitedWithCode(0), "") << "This failure is expected.";
|
||||
}, "This failure is expected.");
|
||||
#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Of all signals effects on the process exit code, only those of SIGABRT
|
||||
// are documented on Windows.
|
||||
@@ -1131,8 +1111,10 @@ TEST(EnvironmentTest, HandleFitsIntoSizeT) {
|
||||
// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED trigger
|
||||
// failures when death tests are available on the system.
|
||||
TEST(ConditionalDeathMacrosDeathTest, ExpectsDeathWhenDeathTestsAvailable) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(false) << "failure", "false.*failure");
|
||||
ASSERT_DEATH_IF_SUPPORTED(GTEST_CHECK_(false) << "failure", "false.*failure");
|
||||
EXPECT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestExpectMacro"),
|
||||
"death inside CondDeathTestExpectMacro");
|
||||
ASSERT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestAssertMacro"),
|
||||
"death inside CondDeathTestAssertMacro");
|
||||
|
||||
// Empty statement will not crash, which must trigger a failure.
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_DEATH_IF_SUPPORTED(;, ""), "");
|
||||
|
||||
+104
-2
@@ -151,6 +151,36 @@ TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileName) {
|
||||
.RemoveDirectoryName().c_str());
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
|
||||
// Tests that RemoveDirectoryName() works with the alternate separator
|
||||
// on Windows.
|
||||
|
||||
// RemoveDirectoryName("/afile") -> "afile"
|
||||
TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileNameForAlternateSeparator) {
|
||||
EXPECT_STREQ("afile",
|
||||
FilePath("/afile").RemoveDirectoryName().c_str());
|
||||
}
|
||||
|
||||
// RemoveDirectoryName("adir/") -> ""
|
||||
TEST(RemoveDirectoryNameTest, WhereThereIsNoFileNameForAlternateSeparator) {
|
||||
EXPECT_STREQ("",
|
||||
FilePath("adir/").RemoveDirectoryName().c_str());
|
||||
}
|
||||
|
||||
// RemoveDirectoryName("adir/afile") -> "afile"
|
||||
TEST(RemoveDirectoryNameTest, ShouldGiveFileNameForAlternateSeparator) {
|
||||
EXPECT_STREQ("afile",
|
||||
FilePath("adir/afile").RemoveDirectoryName().c_str());
|
||||
}
|
||||
|
||||
// RemoveDirectoryName("adir/subdir/afile") -> "afile"
|
||||
TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileNameForAlternateSeparator) {
|
||||
EXPECT_STREQ("afile",
|
||||
FilePath("adir/subdir/afile").RemoveDirectoryName().c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// RemoveFileName "" -> "./"
|
||||
TEST(RemoveFileNameTest, EmptyName) {
|
||||
@@ -190,6 +220,36 @@ TEST(RemoveFileNameTest, GivesRootDir) {
|
||||
FilePath(GTEST_PATH_SEP_ "afile").RemoveFileName().c_str());
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
|
||||
// Tests that RemoveFileName() works with the alternate separator on
|
||||
// Windows.
|
||||
|
||||
// RemoveFileName("adir/") -> "adir/"
|
||||
TEST(RemoveFileNameTest, ButNoFileForAlternateSeparator) {
|
||||
EXPECT_STREQ("adir" GTEST_PATH_SEP_,
|
||||
FilePath("adir/").RemoveFileName().c_str());
|
||||
}
|
||||
|
||||
// RemoveFileName("adir/afile") -> "adir/"
|
||||
TEST(RemoveFileNameTest, GivesDirNameForAlternateSeparator) {
|
||||
EXPECT_STREQ("adir" GTEST_PATH_SEP_,
|
||||
FilePath("adir/afile").RemoveFileName().c_str());
|
||||
}
|
||||
|
||||
// RemoveFileName("adir/subdir/afile") -> "adir/subdir/"
|
||||
TEST(RemoveFileNameTest, GivesDirAndSubDirNameForAlternateSeparator) {
|
||||
EXPECT_STREQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
|
||||
FilePath("adir/subdir/afile").RemoveFileName().c_str());
|
||||
}
|
||||
|
||||
// RemoveFileName("/afile") -> "\"
|
||||
TEST(RemoveFileNameTest, GivesRootDirForAlternateSeparator) {
|
||||
EXPECT_STREQ(GTEST_PATH_SEP_,
|
||||
FilePath("/afile").RemoveFileName().c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(MakeFileNameTest, GenerateWhenNumberIsZero) {
|
||||
FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
|
||||
@@ -295,6 +355,10 @@ TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveTrailingSeparator) {
|
||||
EXPECT_STREQ(
|
||||
"foo",
|
||||
FilePath("foo" GTEST_PATH_SEP_).RemoveTrailingPathSeparator().c_str());
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
EXPECT_STREQ("foo",
|
||||
FilePath("foo/").RemoveTrailingPathSeparator().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// RemoveTrailingPathSeparator "foo/bar/" -> "foo/bar/"
|
||||
@@ -397,6 +461,22 @@ TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringEnd) {
|
||||
FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_).c_str());
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
|
||||
// Tests that separators at the end of the string are normalized
|
||||
// regardless of their combination (e.g. "foo\" =="foo/\" ==
|
||||
// "foo\\/").
|
||||
TEST(NormalizeTest, MixAlternateSeparatorAtStringEnd) {
|
||||
EXPECT_STREQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo/").c_str());
|
||||
EXPECT_STREQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo" GTEST_PATH_SEP_ "/").c_str());
|
||||
EXPECT_STREQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo//" GTEST_PATH_SEP_).c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(AssignmentOperatorTest, DefaultAssignedToNonDefault) {
|
||||
FilePath default_path;
|
||||
FilePath non_default_path("path");
|
||||
@@ -566,6 +646,9 @@ TEST(FilePathTest, RemoveExtensionWhenThereIsNoExtension) {
|
||||
TEST(FilePathTest, IsDirectory) {
|
||||
EXPECT_FALSE(FilePath("cola").IsDirectory());
|
||||
EXPECT_TRUE(FilePath("koala" GTEST_PATH_SEP_).IsDirectory());
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
EXPECT_TRUE(FilePath("koala/").IsDirectory());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(FilePathTest, IsAbsolutePath) {
|
||||
@@ -575,14 +658,33 @@ TEST(FilePathTest, IsAbsolutePath) {
|
||||
EXPECT_TRUE(FilePath("c:\\" GTEST_PATH_SEP_ "is_not"
|
||||
GTEST_PATH_SEP_ "relative").IsAbsolutePath());
|
||||
EXPECT_FALSE(FilePath("c:foo" GTEST_PATH_SEP_ "bar").IsAbsolutePath());
|
||||
EXPECT_TRUE(FilePath("c:/" GTEST_PATH_SEP_ "is_not"
|
||||
GTEST_PATH_SEP_ "relative").IsAbsolutePath());
|
||||
#else
|
||||
EXPECT_TRUE(FilePath(GTEST_PATH_SEP_ "is_not" GTEST_PATH_SEP_ "relative")
|
||||
.IsAbsolutePath());
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
}
|
||||
|
||||
TEST(FilePathTest, IsRootDirectory) {
|
||||
#if GTEST_OS_WINDOWS
|
||||
EXPECT_TRUE(FilePath("a:\\").IsRootDirectory());
|
||||
EXPECT_TRUE(FilePath("Z:/").IsRootDirectory());
|
||||
EXPECT_TRUE(FilePath("e://").IsRootDirectory());
|
||||
EXPECT_FALSE(FilePath("").IsRootDirectory());
|
||||
EXPECT_FALSE(FilePath("b:").IsRootDirectory());
|
||||
EXPECT_FALSE(FilePath("b:a").IsRootDirectory());
|
||||
EXPECT_FALSE(FilePath("8:/").IsRootDirectory());
|
||||
EXPECT_FALSE(FilePath("c|/").IsRootDirectory());
|
||||
#else
|
||||
EXPECT_TRUE(FilePath("/").IsRootDirectory());
|
||||
EXPECT_TRUE(FilePath("//").IsRootDirectory());
|
||||
EXPECT_FALSE(FilePath("").IsRootDirectory());
|
||||
EXPECT_FALSE(FilePath("\\").IsRootDirectory());
|
||||
EXPECT_FALSE(FilePath("/x").IsRootDirectory());
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#undef GTEST_PATH_SEP_
|
||||
|
||||
+27
-36
@@ -34,15 +34,7 @@
|
||||
// right times.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Indicates that this translation unit is part of Google Test's
|
||||
// implementation. It must come before gtest-internal-inl.h is
|
||||
// included, or there will be a compiler error. This trick is to
|
||||
// prevent a user from accidentally including gtest-internal-inl.h in
|
||||
// his code.
|
||||
#define GTEST_IMPLEMENTATION_ 1
|
||||
#include "src/gtest-internal-inl.h" // For Vector.
|
||||
#undef GTEST_IMPLEMENTATION_
|
||||
#include <vector>
|
||||
|
||||
using ::testing::AddGlobalTestEnvironment;
|
||||
using ::testing::Environment;
|
||||
@@ -54,10 +46,9 @@ using ::testing::TestInfo;
|
||||
using ::testing::TestPartResult;
|
||||
using ::testing::UnitTest;
|
||||
using ::testing::internal::String;
|
||||
using ::testing::internal::Vector;
|
||||
|
||||
// Used by tests to register their events.
|
||||
Vector<String>* g_events = NULL;
|
||||
std::vector<String>* g_events = NULL;
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
@@ -68,7 +59,7 @@ class EventRecordingListener : public TestEventListener {
|
||||
|
||||
protected:
|
||||
virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnTestProgramStart"));
|
||||
g_events->push_back(GetFullMethodName("OnTestProgramStart"));
|
||||
}
|
||||
|
||||
virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
|
||||
@@ -76,43 +67,43 @@ class EventRecordingListener : public TestEventListener {
|
||||
Message message;
|
||||
message << GetFullMethodName("OnTestIterationStart")
|
||||
<< "(" << iteration << ")";
|
||||
g_events->PushBack(message.GetString());
|
||||
g_events->push_back(message.GetString());
|
||||
}
|
||||
|
||||
virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnEnvironmentsSetUpStart"));
|
||||
g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpStart"));
|
||||
}
|
||||
|
||||
virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnEnvironmentsSetUpEnd"));
|
||||
g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpEnd"));
|
||||
}
|
||||
|
||||
virtual void OnTestCaseStart(const TestCase& /*test_case*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnTestCaseStart"));
|
||||
g_events->push_back(GetFullMethodName("OnTestCaseStart"));
|
||||
}
|
||||
|
||||
virtual void OnTestStart(const TestInfo& /*test_info*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnTestStart"));
|
||||
g_events->push_back(GetFullMethodName("OnTestStart"));
|
||||
}
|
||||
|
||||
virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnTestPartResult"));
|
||||
g_events->push_back(GetFullMethodName("OnTestPartResult"));
|
||||
}
|
||||
|
||||
virtual void OnTestEnd(const TestInfo& /*test_info*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnTestEnd"));
|
||||
g_events->push_back(GetFullMethodName("OnTestEnd"));
|
||||
}
|
||||
|
||||
virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnTestCaseEnd"));
|
||||
g_events->push_back(GetFullMethodName("OnTestCaseEnd"));
|
||||
}
|
||||
|
||||
virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnEnvironmentsTearDownStart"));
|
||||
g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownStart"));
|
||||
}
|
||||
|
||||
virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnEnvironmentsTearDownEnd"));
|
||||
g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownEnd"));
|
||||
}
|
||||
|
||||
virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
|
||||
@@ -120,11 +111,11 @@ class EventRecordingListener : public TestEventListener {
|
||||
Message message;
|
||||
message << GetFullMethodName("OnTestIterationEnd")
|
||||
<< "(" << iteration << ")";
|
||||
g_events->PushBack(message.GetString());
|
||||
g_events->push_back(message.GetString());
|
||||
}
|
||||
|
||||
virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {
|
||||
g_events->PushBack(GetFullMethodName("OnTestProgramEnd"));
|
||||
g_events->push_back(GetFullMethodName("OnTestProgramEnd"));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -140,42 +131,42 @@ class EventRecordingListener : public TestEventListener {
|
||||
class EnvironmentInvocationCatcher : public Environment {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
g_events->PushBack(String("Environment::SetUp"));
|
||||
g_events->push_back(String("Environment::SetUp"));
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
g_events->PushBack(String("Environment::TearDown"));
|
||||
g_events->push_back(String("Environment::TearDown"));
|
||||
}
|
||||
};
|
||||
|
||||
class ListenerTest : public Test {
|
||||
protected:
|
||||
static void SetUpTestCase() {
|
||||
g_events->PushBack(String("ListenerTest::SetUpTestCase"));
|
||||
g_events->push_back(String("ListenerTest::SetUpTestCase"));
|
||||
}
|
||||
|
||||
static void TearDownTestCase() {
|
||||
g_events->PushBack(String("ListenerTest::TearDownTestCase"));
|
||||
g_events->push_back(String("ListenerTest::TearDownTestCase"));
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
g_events->PushBack(String("ListenerTest::SetUp"));
|
||||
g_events->push_back(String("ListenerTest::SetUp"));
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
g_events->PushBack(String("ListenerTest::TearDown"));
|
||||
g_events->push_back(String("ListenerTest::TearDown"));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ListenerTest, DoesFoo) {
|
||||
// Test execution order within a test case is not guaranteed so we are not
|
||||
// recording the test name.
|
||||
g_events->PushBack(String("ListenerTest::* Test Body"));
|
||||
g_events->push_back(String("ListenerTest::* Test Body"));
|
||||
SUCCEED(); // Triggers OnTestPartResult.
|
||||
}
|
||||
|
||||
TEST_F(ListenerTest, DoesBar) {
|
||||
g_events->PushBack(String("ListenerTest::* Test Body"));
|
||||
g_events->push_back(String("ListenerTest::* Test Body"));
|
||||
SUCCEED(); // Triggers OnTestPartResult.
|
||||
}
|
||||
|
||||
@@ -186,7 +177,7 @@ TEST_F(ListenerTest, DoesBar) {
|
||||
using ::testing::internal::EnvironmentInvocationCatcher;
|
||||
using ::testing::internal::EventRecordingListener;
|
||||
|
||||
void VerifyResults(const Vector<String>& data,
|
||||
void VerifyResults(const std::vector<String>& data,
|
||||
const char* const* expected_data,
|
||||
int expected_data_size) {
|
||||
const int actual_size = data.size();
|
||||
@@ -199,18 +190,18 @@ void VerifyResults(const Vector<String>& data,
|
||||
expected_data_size : actual_size;
|
||||
int i = 0;
|
||||
for (; i < shorter_size; ++i) {
|
||||
ASSERT_STREQ(expected_data[i], data.GetElement(i).c_str())
|
||||
ASSERT_STREQ(expected_data[i], data[i].c_str())
|
||||
<< "at position " << i;
|
||||
}
|
||||
|
||||
// Prints extra elements in the actual data.
|
||||
for (; i < actual_size; ++i) {
|
||||
printf(" Actual event #%d: %s\n", i, data.GetElement(i).c_str());
|
||||
printf(" Actual event #%d: %s\n", i, data[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Vector<String> events;
|
||||
std::vector<String> events;
|
||||
g_events = &events;
|
||||
InitGoogleTest(&argc, argv);
|
||||
|
||||
|
||||
@@ -68,6 +68,23 @@ TEST(MessageTest, ConstructsFromCString) {
|
||||
EXPECT_STREQ("Hello", ToCString(msg));
|
||||
}
|
||||
|
||||
// Tests streaming a float.
|
||||
TEST(MessageTest, StreamsFloat) {
|
||||
const char* const s = ToCString(Message() << 1.23456F << " " << 2.34567F);
|
||||
// Both numbers should be printed with enough precision.
|
||||
EXPECT_PRED_FORMAT2(testing::IsSubstring, "1.234560", s);
|
||||
EXPECT_PRED_FORMAT2(testing::IsSubstring, " 2.345669", s);
|
||||
}
|
||||
|
||||
// Tests streaming a double.
|
||||
TEST(MessageTest, StreamsDouble) {
|
||||
const char* const s = ToCString(Message() << 1260570880.4555497 << " "
|
||||
<< 1260572265.1954534);
|
||||
// Both numbers should be printed with enough precision.
|
||||
EXPECT_PRED_FORMAT2(testing::IsSubstring, "1260570880.45", s);
|
||||
EXPECT_PRED_FORMAT2(testing::IsSubstring, " 1260572265.19", s);
|
||||
}
|
||||
|
||||
// Tests streaming a non-char pointer.
|
||||
TEST(MessageTest, StreamsPointer) {
|
||||
int n = 0;
|
||||
@@ -92,12 +109,7 @@ TEST(MessageTest, StreamsNullCString) {
|
||||
EXPECT_STREQ("(null)", ToCString(Message() << p));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_STRING
|
||||
|
||||
// Tests streaming std::string.
|
||||
//
|
||||
// As std::string has problem in MSVC when exception is disabled, we only
|
||||
// test this where std::string can be used.
|
||||
TEST(MessageTest, StreamsString) {
|
||||
const ::std::string str("Hello");
|
||||
EXPECT_STREQ("Hello", ToCString(Message() << str));
|
||||
@@ -113,8 +125,6 @@ TEST(MessageTest, StreamsStringWithEmbeddedNUL) {
|
||||
ToCString(Message() << string_with_nul));
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
|
||||
// Tests streaming a NUL char.
|
||||
TEST(MessageTest, StreamsNULChar) {
|
||||
EXPECT_STREQ("\\0", ToCString(Message() << '\0'));
|
||||
|
||||
+42
-97
@@ -89,61 +89,38 @@ TEST(XmlOutputTest, GetOutputFileSingleFile) {
|
||||
}
|
||||
|
||||
TEST(XmlOutputTest, GetOutputFileFromDirectoryPath) {
|
||||
GTEST_FLAG(output) = "xml:path" GTEST_PATH_SEP_;
|
||||
const std::string expected_output_file =
|
||||
GetAbsolutePathOf(
|
||||
FilePath(std::string("path") + GTEST_PATH_SEP_ +
|
||||
GetCurrentExecutableName().c_str() + ".xml")).c_str();
|
||||
const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
#if GTEST_OS_WINDOWS
|
||||
GTEST_FLAG(output) = "xml:path\\";
|
||||
const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
EXPECT_TRUE(
|
||||
_strcmpi(output_file.c_str(),
|
||||
GetAbsolutePathOf(
|
||||
FilePath("path\\gtest-options_test.xml")).c_str()) == 0 ||
|
||||
_strcmpi(output_file.c_str(),
|
||||
GetAbsolutePathOf(
|
||||
FilePath("path\\gtest-options-ex_test.xml")).c_str()) == 0 ||
|
||||
_strcmpi(output_file.c_str(),
|
||||
GetAbsolutePathOf(
|
||||
FilePath("path\\gtest_all_test.xml")).c_str()) == 0)
|
||||
<< " output_file = " << output_file;
|
||||
EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
|
||||
#else
|
||||
GTEST_FLAG(output) = "xml:path/";
|
||||
const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
// TODO(wan@google.com): libtool causes the test binary file to be
|
||||
// named lt-gtest-options_test. Therefore the output file may be
|
||||
// named .../lt-gtest-options_test.xml. We should remove this
|
||||
// hard-coded logic when Chandler Carruth's libtool replacement is
|
||||
// ready.
|
||||
EXPECT_TRUE(output_file ==
|
||||
GetAbsolutePathOf(
|
||||
FilePath("path/gtest-options_test.xml")).c_str() ||
|
||||
output_file ==
|
||||
GetAbsolutePathOf(
|
||||
FilePath("path/lt-gtest-options_test.xml")).c_str() ||
|
||||
output_file ==
|
||||
GetAbsolutePathOf(
|
||||
FilePath("path/gtest_all_test.xml")).c_str() ||
|
||||
output_file ==
|
||||
GetAbsolutePathOf(
|
||||
FilePath("path/lt-gtest_all_test.xml")).c_str())
|
||||
<< " output_file = " << output_file;
|
||||
EXPECT_EQ(expected_output_file, output_file.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(OutputFileHelpersTest, GetCurrentExecutableName) {
|
||||
const FilePath executable = GetCurrentExecutableName();
|
||||
const char* const exe_str = executable.c_str();
|
||||
const std::string exe_str = GetCurrentExecutableName().c_str();
|
||||
#if GTEST_OS_WINDOWS
|
||||
ASSERT_TRUE(_strcmpi("gtest-options_test", exe_str) == 0 ||
|
||||
_strcmpi("gtest-options-ex_test", exe_str) == 0 ||
|
||||
_strcmpi("gtest_all_test", exe_str) == 0)
|
||||
<< "GetCurrentExecutableName() returns " << exe_str;
|
||||
const bool success =
|
||||
_strcmpi("gtest-options_test", exe_str.c_str()) == 0 ||
|
||||
_strcmpi("gtest-options-ex_test", exe_str.c_str()) == 0 ||
|
||||
_strcmpi("gtest_all_test", exe_str.c_str()) == 0 ||
|
||||
_strcmpi("gtest_dll_test", exe_str.c_str()) == 0;
|
||||
#else
|
||||
// TODO(wan@google.com): remove the hard-coded "lt-" prefix when
|
||||
// Chandler Carruth's libtool replacement is ready.
|
||||
EXPECT_TRUE(String(exe_str) == "gtest-options_test" ||
|
||||
String(exe_str) == "lt-gtest-options_test" ||
|
||||
String(exe_str) == "gtest_all_test" ||
|
||||
String(exe_str) == "lt-gtest_all_test")
|
||||
<< "GetCurrentExecutableName() returns " << exe_str;
|
||||
const bool success =
|
||||
exe_str == "gtest-options_test" ||
|
||||
exe_str == "gtest_all_test" ||
|
||||
exe_str == "lt-gtest_all_test" ||
|
||||
exe_str == "gtest_dll_test";
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
if (!success)
|
||||
FAIL() << "GetCurrentExecutableName() returns " << exe_str;
|
||||
}
|
||||
|
||||
class XmlOutputChangeDirTest : public Test {
|
||||
@@ -185,40 +162,17 @@ TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativeFile) {
|
||||
}
|
||||
|
||||
TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativePath) {
|
||||
GTEST_FLAG(output) = "xml:path" GTEST_PATH_SEP_;
|
||||
const std::string expected_output_file =
|
||||
FilePath::ConcatPaths(
|
||||
original_working_dir_,
|
||||
FilePath(std::string("path") + GTEST_PATH_SEP_ +
|
||||
GetCurrentExecutableName().c_str() + ".xml")).c_str();
|
||||
const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
#if GTEST_OS_WINDOWS
|
||||
GTEST_FLAG(output) = "xml:path\\";
|
||||
const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
EXPECT_TRUE(
|
||||
_strcmpi(output_file.c_str(),
|
||||
FilePath::ConcatPaths(
|
||||
original_working_dir_,
|
||||
FilePath("path\\gtest-options_test.xml")).c_str()) == 0 ||
|
||||
_strcmpi(output_file.c_str(),
|
||||
FilePath::ConcatPaths(
|
||||
original_working_dir_,
|
||||
FilePath("path\\gtest-options-ex_test.xml")).c_str()) == 0 ||
|
||||
_strcmpi(output_file.c_str(),
|
||||
FilePath::ConcatPaths(
|
||||
original_working_dir_,
|
||||
FilePath("path\\gtest_all_test.xml")).c_str()) == 0)
|
||||
<< " output_file = " << output_file;
|
||||
EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
|
||||
#else
|
||||
GTEST_FLAG(output) = "xml:path/";
|
||||
const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
// TODO(wan@google.com): libtool causes the test binary file to be
|
||||
// named lt-gtest-options_test. Therefore the output file may be
|
||||
// named .../lt-gtest-options_test.xml. We should remove this
|
||||
// hard-coded logic when Chandler Carruth's libtool replacement is
|
||||
// ready.
|
||||
EXPECT_TRUE(output_file == FilePath::ConcatPaths(original_working_dir_,
|
||||
FilePath("path/gtest-options_test.xml")).c_str() ||
|
||||
output_file == FilePath::ConcatPaths(original_working_dir_,
|
||||
FilePath("path/lt-gtest-options_test.xml")).c_str() ||
|
||||
output_file == FilePath::ConcatPaths(original_working_dir_,
|
||||
FilePath("path/gtest_all_test.xml")).c_str() ||
|
||||
output_file == FilePath::ConcatPaths(original_working_dir_,
|
||||
FilePath("path/lt-gtest_all_test.xml")).c_str())
|
||||
<< " output_file = " << output_file;
|
||||
EXPECT_EQ(expected_output_file, output_file.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -236,29 +190,20 @@ TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsoluteFile) {
|
||||
|
||||
TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsolutePath) {
|
||||
#if GTEST_OS_WINDOWS
|
||||
GTEST_FLAG(output) = "xml:c:\\tmp\\";
|
||||
const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
EXPECT_TRUE(
|
||||
_strcmpi(output_file.c_str(),
|
||||
FilePath("c:\\tmp\\gtest-options_test.xml").c_str()) == 0 ||
|
||||
_strcmpi(output_file.c_str(),
|
||||
FilePath("c:\\tmp\\gtest-options-ex_test.xml").c_str()) == 0 ||
|
||||
_strcmpi(output_file.c_str(),
|
||||
FilePath("c:\\tmp\\gtest_all_test.xml").c_str()) == 0)
|
||||
<< " output_file = " << output_file;
|
||||
const std::string path = "c:\\tmp\\";
|
||||
#else
|
||||
GTEST_FLAG(output) = "xml:/tmp/";
|
||||
const std::string path = "/tmp/";
|
||||
#endif
|
||||
|
||||
GTEST_FLAG(output) = "xml:" + path;
|
||||
const std::string expected_output_file =
|
||||
path + GetCurrentExecutableName().c_str() + ".xml";
|
||||
const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
// TODO(wan@google.com): libtool causes the test binary file to be
|
||||
// named lt-gtest-options_test. Therefore the output file may be
|
||||
// named .../lt-gtest-options_test.xml. We should remove this
|
||||
// hard-coded logic when Chandler Carruth's libtool replacement is
|
||||
// ready.
|
||||
EXPECT_TRUE(output_file == "/tmp/gtest-options_test.xml" ||
|
||||
output_file == "/tmp/lt-gtest-options_test.xml" ||
|
||||
output_file == "/tmp/gtest_all_test.xml" ||
|
||||
output_file == "/tmp/lt-gtest_all_test.xml")
|
||||
<< " output_file = " << output_file;
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
|
||||
#else
|
||||
EXPECT_EQ(expected_output_file, output_file.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// To include gtest-internal-inl.h.
|
||||
@@ -70,6 +72,57 @@ using ::std::tr1::tuple;
|
||||
using ::testing::internal::ParamGenerator;
|
||||
using ::testing::internal::UnitTestOptions;
|
||||
|
||||
// Prints a value to a string.
|
||||
//
|
||||
// TODO(wan@google.com): remove PrintValue() when we move matchers and
|
||||
// EXPECT_THAT() from Google Mock to Google Test. At that time, we
|
||||
// can write EXPECT_THAT(x, Eq(y)) to compare two tuples x and y, as
|
||||
// EXPECT_THAT() and the matchers know how to print tuples.
|
||||
template <typename T>
|
||||
::std::string PrintValue(const T& value) {
|
||||
::std::stringstream stream;
|
||||
stream << value;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
#if GTEST_HAS_COMBINE
|
||||
|
||||
// These overloads allow printing tuples in our tests. We cannot
|
||||
// define an operator<< for tuples, as that definition needs to be in
|
||||
// the std namespace in order to be picked up by Google Test via
|
||||
// Argument-Dependent Lookup, yet defining anything in the std
|
||||
// namespace in non-STL code is undefined behavior.
|
||||
|
||||
template <typename T1, typename T2>
|
||||
::std::string PrintValue(const tuple<T1, T2>& value) {
|
||||
::std::stringstream stream;
|
||||
stream << "(" << get<0>(value) << ", " << get<1>(value) << ")";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
::std::string PrintValue(const tuple<T1, T2, T3>& value) {
|
||||
::std::stringstream stream;
|
||||
stream << "(" << get<0>(value) << ", " << get<1>(value)
|
||||
<< ", "<< get<2>(value) << ")";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||
::std::string PrintValue(
|
||||
const tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& value) {
|
||||
::std::stringstream stream;
|
||||
stream << "(" << get<0>(value) << ", " << get<1>(value)
|
||||
<< ", "<< get<2>(value) << ", " << get<3>(value)
|
||||
<< ", "<< get<4>(value) << ", " << get<5>(value)
|
||||
<< ", "<< get<6>(value) << ", " << get<7>(value)
|
||||
<< ", "<< get<8>(value) << ", " << get<9>(value) << ")";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_COMBINE
|
||||
|
||||
// Verifies that a sequence generated by the generator and accessed
|
||||
// via the iterator object matches the expected one using Google Test
|
||||
// assertions.
|
||||
@@ -80,15 +133,19 @@ void VerifyGenerator(const ParamGenerator<T>& generator,
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
ASSERT_FALSE(it == generator.end())
|
||||
<< "At element " << i << " when accessing via an iterator "
|
||||
<< "created with the copy constructor." << std::endl;
|
||||
EXPECT_EQ(expected_values[i], *it)
|
||||
<< "At element " << i << " when accessing via an iterator "
|
||||
<< "created with the copy constructor." << std::endl;
|
||||
<< "created with the copy constructor.\n";
|
||||
// We cannot use EXPECT_EQ() here as the values may be tuples,
|
||||
// which don't support <<.
|
||||
EXPECT_TRUE(expected_values[i] == *it)
|
||||
<< "where i is " << i
|
||||
<< ", expected_values[i] is " << PrintValue(expected_values[i])
|
||||
<< ", *it is " << PrintValue(*it)
|
||||
<< ", and 'it' is an iterator created with the copy constructor.\n";
|
||||
it++;
|
||||
}
|
||||
EXPECT_TRUE(it == generator.end())
|
||||
<< "At the presumed end of sequence when accessing via an iterator "
|
||||
<< "created with the copy constructor." << std::endl;
|
||||
<< "created with the copy constructor.\n";
|
||||
|
||||
// Test the iterator assignment. The following lines verify that
|
||||
// the sequence accessed via an iterator initialized via the
|
||||
@@ -98,15 +155,17 @@ void VerifyGenerator(const ParamGenerator<T>& generator,
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
ASSERT_FALSE(it == generator.end())
|
||||
<< "At element " << i << " when accessing via an iterator "
|
||||
<< "created with the assignment operator." << std::endl;
|
||||
EXPECT_EQ(expected_values[i], *it)
|
||||
<< "At element " << i << " when accessing via an iterator "
|
||||
<< "created with the assignment operator." << std::endl;
|
||||
<< "created with the assignment operator.\n";
|
||||
EXPECT_TRUE(expected_values[i] == *it)
|
||||
<< "where i is " << i
|
||||
<< ", expected_values[i] is " << PrintValue(expected_values[i])
|
||||
<< ", *it is " << PrintValue(*it)
|
||||
<< ", and 'it' is an iterator created with the copy constructor.\n";
|
||||
it++;
|
||||
}
|
||||
EXPECT_TRUE(it == generator.end())
|
||||
<< "At the presumed end of sequence when accessing via an iterator "
|
||||
<< "created with the assignment operator." << std::endl;
|
||||
<< "created with the assignment operator.\n";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -205,7 +264,7 @@ TEST(RangeTest, IntRangeWithCustomStepOverUpperBound) {
|
||||
// copy constructor, operator=(), operator+(), and operator<().
|
||||
class DogAdder {
|
||||
public:
|
||||
explicit DogAdder(const char* value) : value_(value) {}
|
||||
explicit DogAdder(const char* a_value) : value_(a_value) {}
|
||||
DogAdder(const DogAdder& other) : value_(other.value_.c_str()) {}
|
||||
|
||||
DogAdder operator=(const DogAdder& other) {
|
||||
@@ -243,7 +302,7 @@ TEST(RangeTest, WorksWithACustomType) {
|
||||
|
||||
class IntWrapper {
|
||||
public:
|
||||
explicit IntWrapper(int value) : value_(value) {}
|
||||
explicit IntWrapper(int a_value) : value_(a_value) {}
|
||||
IntWrapper(const IntWrapper& other) : value_(other.value_) {}
|
||||
|
||||
IntWrapper operator=(const IntWrapper& other) {
|
||||
@@ -400,33 +459,6 @@ TEST(BoolTest, BoolWorks) {
|
||||
|
||||
#if GTEST_HAS_COMBINE
|
||||
|
||||
template <typename T1, typename T2>
|
||||
::std::ostream& operator<<(::std::ostream& stream, const tuple<T1, T2>& value) {
|
||||
stream << "(" << get<0>(value) << ", " << get<1>(value) << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
::std::ostream& operator<<(::std::ostream& stream,
|
||||
const tuple<T1, T2, T3>& value) {
|
||||
stream << "(" << get<0>(value) << ", " << get<1>(value)
|
||||
<< ", "<< get<2>(value) << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||
::std::ostream& operator<<(
|
||||
::std::ostream& stream,
|
||||
const tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& value) {
|
||||
stream << "(" << get<0>(value) << ", " << get<1>(value)
|
||||
<< ", "<< get<2>(value) << ", " << get<3>(value)
|
||||
<< ", "<< get<4>(value) << ", " << get<5>(value)
|
||||
<< ", "<< get<6>(value) << ", " << get<7>(value)
|
||||
<< ", "<< get<8>(value) << ", " << get<9>(value) << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
// Tests that Combine() with two parameters generates the expected sequence.
|
||||
TEST(CombineTest, CombineWithTwoParameters) {
|
||||
const char* foo = "foo";
|
||||
@@ -660,13 +692,15 @@ INSTANTIATE_TEST_CASE_P(TestExpansionModule, TestGenerationTest,
|
||||
ValuesIn(test_generation_params));
|
||||
|
||||
// This test verifies that the element sequence (third parameter of
|
||||
// INSTANTIATE_TEST_CASE_P) is evaluated in RUN_ALL_TESTS and not at the call
|
||||
// site of INSTANTIATE_TEST_CASE_P.
|
||||
// For that, we declare param_value_ to be a static member of
|
||||
// GeneratorEvaluationTest and initialize it to 0. We set it to 1 in main(),
|
||||
// just before invocation of RUN_ALL_TESTS. If the sequence is evaluated
|
||||
// before that moment, INSTANTIATE_TEST_CASE_P will create a test with
|
||||
// parameter 0, and the test body will fail the assertion.
|
||||
// INSTANTIATE_TEST_CASE_P) is evaluated in InitGoogleTest() and neither at
|
||||
// the call site of INSTANTIATE_TEST_CASE_P nor in RUN_ALL_TESTS(). For
|
||||
// that, we declare param_value_ to be a static member of
|
||||
// GeneratorEvaluationTest and initialize it to 0. We set it to 1 in
|
||||
// main(), just before invocation of InitGoogleTest(). After calling
|
||||
// InitGoogleTest(), we set the value to 2. If the sequence is evaluated
|
||||
// before or after InitGoogleTest, INSTANTIATE_TEST_CASE_P will create a
|
||||
// test with parameter other than 1, and the test body will fail the
|
||||
// assertion.
|
||||
class GeneratorEvaluationTest : public TestWithParam<int> {
|
||||
public:
|
||||
static int param_value() { return param_value_; }
|
||||
@@ -783,10 +817,19 @@ int main(int argc, char **argv) {
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
// Used in TestGenerationTest test case.
|
||||
AddGlobalTestEnvironment(TestGenerationTest::Environment::Instance());
|
||||
// Used in GeneratorEvaluationTest test case.
|
||||
// Used in GeneratorEvaluationTest test case. Tests that the updated value
|
||||
// will be picked up for instantiating tests in GeneratorEvaluationTest.
|
||||
GeneratorEvaluationTest::set_param_value(1);
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
// Used in GeneratorEvaluationTest test case. Tests that value updated
|
||||
// here will NOT be used for instantiating tests in
|
||||
// GeneratorEvaluationTest.
|
||||
GeneratorEvaluationTest::set_param_value(2);
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
+331
-12
@@ -33,11 +33,14 @@
|
||||
|
||||
#include <gtest/internal/gtest-port.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if GTEST_OS_MAC
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#endif // GTEST_OS_MAC
|
||||
|
||||
#include <utility> // For std::pair and std::make_pair.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gtest/gtest-spi.h>
|
||||
|
||||
@@ -50,9 +53,20 @@
|
||||
#include "src/gtest-internal-inl.h"
|
||||
#undef GTEST_IMPLEMENTATION_
|
||||
|
||||
using std::make_pair;
|
||||
using std::pair;
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Tests that the element_type typedef is available in scoped_ptr and refers
|
||||
// to the parameter type.
|
||||
TEST(ScopedPtrTest, DefinesElementType) {
|
||||
StaticAssertTypeEq<int, ::testing::internal::scoped_ptr<int>::element_type>();
|
||||
}
|
||||
|
||||
// TODO(vladl@google.com): Implement THE REST of scoped_ptr tests.
|
||||
|
||||
TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) {
|
||||
if (AlwaysFalse())
|
||||
GTEST_CHECK_(false) << "This should never be executed; "
|
||||
@@ -84,7 +98,7 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
|
||||
|
||||
#if GTEST_OS_MAC
|
||||
void* ThreadFunc(void* data) {
|
||||
pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>(data);
|
||||
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data);
|
||||
pthread_mutex_lock(mutex);
|
||||
pthread_mutex_unlock(mutex);
|
||||
return NULL;
|
||||
@@ -119,10 +133,7 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
||||
if (GetThreadCount() == 1)
|
||||
break;
|
||||
|
||||
timespec time;
|
||||
time.tv_sec = 0;
|
||||
time.tv_nsec = 100L * 1000 * 1000; // .1 seconds.
|
||||
nanosleep(&time, NULL);
|
||||
SleepMilliseconds(100);
|
||||
}
|
||||
EXPECT_EQ(1U, GetThreadCount());
|
||||
pthread_mutex_destroy(&mutex);
|
||||
@@ -161,15 +172,15 @@ TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
|
||||
|
||||
#if GTEST_USES_POSIX_RE
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST
|
||||
|
||||
template <typename Str>
|
||||
class RETest : public ::testing::Test {};
|
||||
|
||||
// Defines StringTypes as the list of all string types that class RE
|
||||
// supports.
|
||||
typedef testing::Types<
|
||||
#if GTEST_HAS_STD_STRING
|
||||
::std::string,
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
#if GTEST_HAS_GLOBAL_STRING
|
||||
::string,
|
||||
#endif // GTEST_HAS_GLOBAL_STRING
|
||||
@@ -223,6 +234,8 @@ TYPED_TEST(RETest, PartialMatchWorks) {
|
||||
EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re));
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST
|
||||
|
||||
#elif GTEST_USES_SIMPLE_RE
|
||||
|
||||
TEST(IsInSetTest, NulCharIsNotInAnySet) {
|
||||
@@ -689,11 +702,317 @@ TEST(RETest, PartialMatchWorks) {
|
||||
|
||||
#endif // GTEST_USES_POSIX_RE
|
||||
|
||||
TEST(CaptureStderrTest, CapturesStdErr) {
|
||||
CaptureStderr();
|
||||
fprintf(stderr, "abc");
|
||||
ASSERT_STREQ("abc", GetCapturedStderr().c_str());
|
||||
#if !GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
TEST(CaptureTest, CapturesStdout) {
|
||||
CaptureStdout();
|
||||
fprintf(stdout, "abc");
|
||||
EXPECT_STREQ("abc", GetCapturedStdout().c_str());
|
||||
|
||||
CaptureStdout();
|
||||
fprintf(stdout, "def%cghi", '\0');
|
||||
EXPECT_EQ(::std::string("def\0ghi", 7), ::std::string(GetCapturedStdout()));
|
||||
}
|
||||
|
||||
TEST(CaptureTest, CapturesStderr) {
|
||||
CaptureStderr();
|
||||
fprintf(stderr, "jkl");
|
||||
EXPECT_STREQ("jkl", GetCapturedStderr().c_str());
|
||||
|
||||
CaptureStderr();
|
||||
fprintf(stderr, "jkl%cmno", '\0');
|
||||
EXPECT_EQ(::std::string("jkl\0mno", 7), ::std::string(GetCapturedStderr()));
|
||||
}
|
||||
|
||||
// Tests that stdout and stderr capture don't interfere with each other.
|
||||
TEST(CaptureTest, CapturesStdoutAndStderr) {
|
||||
CaptureStdout();
|
||||
CaptureStderr();
|
||||
fprintf(stdout, "pqr");
|
||||
fprintf(stderr, "stu");
|
||||
EXPECT_STREQ("pqr", GetCapturedStdout().c_str());
|
||||
EXPECT_STREQ("stu", GetCapturedStderr().c_str());
|
||||
}
|
||||
|
||||
TEST(CaptureDeathTest, CannotReenterStdoutCapture) {
|
||||
CaptureStdout();
|
||||
EXPECT_DEATH_IF_SUPPORTED(CaptureStdout();,
|
||||
"Only one stdout capturer can exist at a time");
|
||||
GetCapturedStdout();
|
||||
|
||||
// We cannot test stderr capturing using death tests as they use it
|
||||
// themselves.
|
||||
}
|
||||
|
||||
#endif // !GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
TEST(ThreadLocalTest, DefaultConstructorInitializesToDefaultValues) {
|
||||
ThreadLocal<int> t1;
|
||||
EXPECT_EQ(0, t1.get());
|
||||
|
||||
ThreadLocal<void*> t2;
|
||||
EXPECT_TRUE(t2.get() == NULL);
|
||||
}
|
||||
|
||||
TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) {
|
||||
ThreadLocal<int> t1(123);
|
||||
EXPECT_EQ(123, t1.get());
|
||||
|
||||
int i = 0;
|
||||
ThreadLocal<int*> t2(&i);
|
||||
EXPECT_EQ(&i, t2.get());
|
||||
}
|
||||
|
||||
class NoDefaultContructor {
|
||||
public:
|
||||
explicit NoDefaultContructor(const char*) {}
|
||||
NoDefaultContructor(const NoDefaultContructor&) {}
|
||||
};
|
||||
|
||||
TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) {
|
||||
ThreadLocal<NoDefaultContructor> bar(NoDefaultContructor("foo"));
|
||||
bar.pointer();
|
||||
}
|
||||
|
||||
TEST(ThreadLocalTest, GetAndPointerReturnSameValue) {
|
||||
ThreadLocal<String> thread_local;
|
||||
|
||||
EXPECT_EQ(thread_local.pointer(), &(thread_local.get()));
|
||||
|
||||
// Verifies the condition still holds after calling set.
|
||||
thread_local.set("foo");
|
||||
EXPECT_EQ(thread_local.pointer(), &(thread_local.get()));
|
||||
}
|
||||
|
||||
TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) {
|
||||
ThreadLocal<String> thread_local;
|
||||
const ThreadLocal<String>& const_thread_local = thread_local;
|
||||
|
||||
EXPECT_EQ(thread_local.pointer(), const_thread_local.pointer());
|
||||
|
||||
thread_local.set("foo");
|
||||
EXPECT_EQ(thread_local.pointer(), const_thread_local.pointer());
|
||||
}
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
|
||||
void AddTwo(int* param) { *param += 2; }
|
||||
|
||||
TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) {
|
||||
int i = 40;
|
||||
ThreadWithParam<int*> thread(&AddTwo, &i, NULL);
|
||||
thread.Join();
|
||||
EXPECT_EQ(42, i);
|
||||
}
|
||||
|
||||
TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
|
||||
// AssertHeld() is flaky only in the presence of multiple threads accessing
|
||||
// the lock. In this case, the test is robust.
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
Mutex m;
|
||||
{ MutexLock lock(&m); }
|
||||
m.AssertHeld();
|
||||
},
|
||||
"thread .*hold");
|
||||
}
|
||||
|
||||
TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
|
||||
Mutex m;
|
||||
MutexLock lock(&m);
|
||||
m.AssertHeld();
|
||||
}
|
||||
|
||||
class AtomicCounterWithMutex {
|
||||
public:
|
||||
explicit AtomicCounterWithMutex(Mutex* mutex) :
|
||||
value_(0), mutex_(mutex), random_(42) {}
|
||||
|
||||
void Increment() {
|
||||
MutexLock lock(mutex_);
|
||||
int temp = value_;
|
||||
{
|
||||
// Locking a mutex puts up a memory barrier, preventing reads and
|
||||
// writes to value_ rearranged when observed from other threads.
|
||||
//
|
||||
// We cannot use Mutex and MutexLock here or rely on their memory
|
||||
// barrier functionality as we are testing them here.
|
||||
pthread_mutex_t memory_barrier_mutex;
|
||||
GTEST_CHECK_POSIX_SUCCESS_(
|
||||
pthread_mutex_init(&memory_barrier_mutex, NULL));
|
||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
|
||||
|
||||
SleepMilliseconds(random_.Generate(30));
|
||||
|
||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
|
||||
}
|
||||
value_ = temp + 1;
|
||||
}
|
||||
int value() const { return value_; }
|
||||
|
||||
private:
|
||||
volatile int value_;
|
||||
Mutex* const mutex_; // Protects value_.
|
||||
Random random_;
|
||||
};
|
||||
|
||||
void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
|
||||
for (int i = 0; i < param.second; ++i)
|
||||
param.first->Increment();
|
||||
}
|
||||
|
||||
// Tests that the mutex only lets one thread at a time to lock it.
|
||||
TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
|
||||
Mutex mutex;
|
||||
AtomicCounterWithMutex locked_counter(&mutex);
|
||||
|
||||
typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
|
||||
const int kCycleCount = 20;
|
||||
const int kThreadCount = 7;
|
||||
scoped_ptr<ThreadType> counting_threads[kThreadCount];
|
||||
Notification threads_can_start;
|
||||
// Creates and runs kThreadCount threads that increment locked_counter
|
||||
// kCycleCount times each.
|
||||
for (int i = 0; i < kThreadCount; ++i) {
|
||||
counting_threads[i].reset(new ThreadType(&CountingThreadFunc,
|
||||
make_pair(&locked_counter,
|
||||
kCycleCount),
|
||||
&threads_can_start));
|
||||
}
|
||||
threads_can_start.Notify();
|
||||
for (int i = 0; i < kThreadCount; ++i)
|
||||
counting_threads[i]->Join();
|
||||
|
||||
// If the mutex lets more than one thread to increment the counter at a
|
||||
// time, they are likely to encounter a race condition and have some
|
||||
// increments overwritten, resulting in the lower then expected counter
|
||||
// value.
|
||||
EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void RunFromThread(void (func)(T), T param) {
|
||||
ThreadWithParam<T> thread(func, param, NULL);
|
||||
thread.Join();
|
||||
}
|
||||
|
||||
void RetrieveThreadLocalValue(pair<ThreadLocal<String>*, String*> param) {
|
||||
*param.second = param.first->get();
|
||||
}
|
||||
|
||||
TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) {
|
||||
ThreadLocal<String> thread_local("foo");
|
||||
EXPECT_STREQ("foo", thread_local.get().c_str());
|
||||
|
||||
thread_local.set("bar");
|
||||
EXPECT_STREQ("bar", thread_local.get().c_str());
|
||||
|
||||
String result;
|
||||
RunFromThread(&RetrieveThreadLocalValue, make_pair(&thread_local, &result));
|
||||
EXPECT_STREQ("foo", result.c_str());
|
||||
}
|
||||
|
||||
// DestructorTracker keeps track of whether its instances have been
|
||||
// destroyed.
|
||||
static std::vector<bool> g_destroyed;
|
||||
|
||||
class DestructorTracker {
|
||||
public:
|
||||
DestructorTracker() : index_(GetNewIndex()) {}
|
||||
DestructorTracker(const DestructorTracker& /* rhs */)
|
||||
: index_(GetNewIndex()) {}
|
||||
~DestructorTracker() {
|
||||
// We never access g_destroyed concurrently, so we don't need to
|
||||
// protect the write operation under a mutex.
|
||||
g_destroyed[index_] = true;
|
||||
}
|
||||
|
||||
private:
|
||||
static int GetNewIndex() {
|
||||
g_destroyed.push_back(false);
|
||||
return g_destroyed.size() - 1;
|
||||
}
|
||||
const int index_;
|
||||
};
|
||||
|
||||
typedef ThreadLocal<DestructorTracker>* ThreadParam;
|
||||
|
||||
void CallThreadLocalGet(ThreadParam thread_local) {
|
||||
thread_local->get();
|
||||
}
|
||||
|
||||
// Tests that when a ThreadLocal object dies in a thread, it destroys
|
||||
// the managed object for that thread.
|
||||
TEST(ThreadLocalTest, DestroysManagedObjectForOwnThreadWhenDying) {
|
||||
g_destroyed.clear();
|
||||
|
||||
{
|
||||
// The next line default constructs a DestructorTracker object as
|
||||
// the default value of objects managed by thread_local.
|
||||
ThreadLocal<DestructorTracker> thread_local;
|
||||
ASSERT_EQ(1U, g_destroyed.size());
|
||||
ASSERT_FALSE(g_destroyed[0]);
|
||||
|
||||
// This creates another DestructorTracker object for the main thread.
|
||||
thread_local.get();
|
||||
ASSERT_EQ(2U, g_destroyed.size());
|
||||
ASSERT_FALSE(g_destroyed[0]);
|
||||
ASSERT_FALSE(g_destroyed[1]);
|
||||
}
|
||||
|
||||
// Now thread_local has died. It should have destroyed both the
|
||||
// default value shared by all threads and the value for the main
|
||||
// thread.
|
||||
ASSERT_EQ(2U, g_destroyed.size());
|
||||
EXPECT_TRUE(g_destroyed[0]);
|
||||
EXPECT_TRUE(g_destroyed[1]);
|
||||
|
||||
g_destroyed.clear();
|
||||
}
|
||||
|
||||
// Tests that when a thread exits, the thread-local object for that
|
||||
// thread is destroyed.
|
||||
TEST(ThreadLocalTest, DestroysManagedObjectAtThreadExit) {
|
||||
g_destroyed.clear();
|
||||
|
||||
{
|
||||
// The next line default constructs a DestructorTracker object as
|
||||
// the default value of objects managed by thread_local.
|
||||
ThreadLocal<DestructorTracker> thread_local;
|
||||
ASSERT_EQ(1U, g_destroyed.size());
|
||||
ASSERT_FALSE(g_destroyed[0]);
|
||||
|
||||
// This creates another DestructorTracker object in the new thread.
|
||||
ThreadWithParam<ThreadParam> thread(
|
||||
&CallThreadLocalGet, &thread_local, NULL);
|
||||
thread.Join();
|
||||
|
||||
// Now the new thread has exited. The per-thread object for it
|
||||
// should have been destroyed.
|
||||
ASSERT_EQ(2U, g_destroyed.size());
|
||||
ASSERT_FALSE(g_destroyed[0]);
|
||||
ASSERT_TRUE(g_destroyed[1]);
|
||||
}
|
||||
|
||||
// Now thread_local has died. The default value should have been
|
||||
// destroyed too.
|
||||
ASSERT_EQ(2U, g_destroyed.size());
|
||||
EXPECT_TRUE(g_destroyed[0]);
|
||||
EXPECT_TRUE(g_destroyed[1]);
|
||||
|
||||
g_destroyed.clear();
|
||||
}
|
||||
|
||||
TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) {
|
||||
ThreadLocal<String> thread_local;
|
||||
thread_local.set("Foo");
|
||||
EXPECT_STREQ("Foo", thread_local.get().c_str());
|
||||
|
||||
String result;
|
||||
RunFromThread(&RetrieveThreadLocalValue, make_pair(&thread_local, &result));
|
||||
EXPECT_TRUE(result.c_str() == NULL);
|
||||
}
|
||||
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using testing::Message;
|
||||
using testing::Test;
|
||||
using testing::TestPartResult;
|
||||
using testing::TestPartResultArray;
|
||||
@@ -53,6 +54,54 @@ class TestPartResultTest : public Test {
|
||||
TestPartResult r1_, r2_, r3_;
|
||||
};
|
||||
|
||||
|
||||
TEST_F(TestPartResultTest, ConstructorWorks) {
|
||||
Message message;
|
||||
message << "something is terribly wrong";
|
||||
message << static_cast<const char*>(testing::internal::kStackTraceMarker);
|
||||
message << "some unimportant stack trace";
|
||||
|
||||
const TestPartResult result(TestPartResult::kNonFatalFailure,
|
||||
"some_file.cc",
|
||||
42,
|
||||
message.GetString().c_str());
|
||||
|
||||
EXPECT_EQ(TestPartResult::kNonFatalFailure, result.type());
|
||||
EXPECT_STREQ("some_file.cc", result.file_name());
|
||||
EXPECT_EQ(42, result.line_number());
|
||||
EXPECT_STREQ(message.GetString().c_str(), result.message());
|
||||
EXPECT_STREQ("something is terribly wrong", result.summary());
|
||||
}
|
||||
|
||||
TEST_F(TestPartResultTest, ResultAccessorsWork) {
|
||||
const TestPartResult success(TestPartResult::kSuccess,
|
||||
"file.cc",
|
||||
42,
|
||||
"message");
|
||||
EXPECT_TRUE(success.passed());
|
||||
EXPECT_FALSE(success.failed());
|
||||
EXPECT_FALSE(success.nonfatally_failed());
|
||||
EXPECT_FALSE(success.fatally_failed());
|
||||
|
||||
const TestPartResult nonfatal_failure(TestPartResult::kNonFatalFailure,
|
||||
"file.cc",
|
||||
42,
|
||||
"message");
|
||||
EXPECT_FALSE(nonfatal_failure.passed());
|
||||
EXPECT_TRUE(nonfatal_failure.failed());
|
||||
EXPECT_TRUE(nonfatal_failure.nonfatally_failed());
|
||||
EXPECT_FALSE(nonfatal_failure.fatally_failed());
|
||||
|
||||
const TestPartResult fatal_failure(TestPartResult::kFatalFailure,
|
||||
"file.cc",
|
||||
42,
|
||||
"message");
|
||||
EXPECT_FALSE(fatal_failure.passed());
|
||||
EXPECT_TRUE(fatal_failure.failed());
|
||||
EXPECT_FALSE(fatal_failure.nonfatally_failed());
|
||||
EXPECT_TRUE(fatal_failure.fatally_failed());
|
||||
}
|
||||
|
||||
// Tests TestPartResult::type().
|
||||
TEST_F(TestPartResultTest, type) {
|
||||
EXPECT_EQ(TestPartResult::kSuccess, r1_.type());
|
||||
|
||||
@@ -135,12 +135,44 @@ TEST(ReferenceFieldTest, IsAliasOfReferencedVariable) {
|
||||
<< "Changing a reference field should update the underlying variable.";
|
||||
}
|
||||
|
||||
// Tests tuple's default constructor.
|
||||
TEST(TupleConstructorTest, DefaultConstructor) {
|
||||
// We are just testing that the following compiles.
|
||||
// Tests that tuple's default constructor default initializes each field.
|
||||
// This test needs to compile without generating warnings.
|
||||
TEST(TupleConstructorTest, DefaultConstructorDefaultInitializesEachField) {
|
||||
// The TR1 report requires that tuple's default constructor default
|
||||
// initializes each field, even if it's a primitive type. If the
|
||||
// implementation forgets to do this, this test will catch it by
|
||||
// generating warnings about using uninitialized variables (assuming
|
||||
// a decent compiler).
|
||||
|
||||
tuple<> empty;
|
||||
tuple<int> one_field;
|
||||
tuple<double, char, bool*> three_fields;
|
||||
|
||||
tuple<int> a1, b1;
|
||||
b1 = a1;
|
||||
EXPECT_EQ(0, get<0>(b1));
|
||||
|
||||
tuple<int, double> a2, b2;
|
||||
b2 = a2;
|
||||
EXPECT_EQ(0, get<0>(b2));
|
||||
EXPECT_EQ(0.0, get<1>(b2));
|
||||
|
||||
tuple<double, char, bool*> a3, b3;
|
||||
b3 = a3;
|
||||
EXPECT_EQ(0.0, get<0>(b3));
|
||||
EXPECT_EQ('\0', get<1>(b3));
|
||||
EXPECT_TRUE(get<2>(b3) == NULL);
|
||||
|
||||
tuple<int, int, int, int, int, int, int, int, int, int> a10, b10;
|
||||
b10 = a10;
|
||||
EXPECT_EQ(0, get<0>(b10));
|
||||
EXPECT_EQ(0, get<1>(b10));
|
||||
EXPECT_EQ(0, get<2>(b10));
|
||||
EXPECT_EQ(0, get<3>(b10));
|
||||
EXPECT_EQ(0, get<4>(b10));
|
||||
EXPECT_EQ(0, get<5>(b10));
|
||||
EXPECT_EQ(0, get<6>(b10));
|
||||
EXPECT_EQ(0, get<7>(b10));
|
||||
EXPECT_EQ(0, get<8>(b10));
|
||||
EXPECT_EQ(0, get<9>(b10));
|
||||
}
|
||||
|
||||
// Tests constructing a tuple from its fields.
|
||||
|
||||
@@ -349,12 +349,12 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, NumericTest, NumericTypes);
|
||||
|
||||
#if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
|
||||
|
||||
// Google Test doesn't support type-parameterized tests on some platforms
|
||||
// and compilers, such as MSVC 7.1. If we use conditional compilation to
|
||||
// compile out all code referring to the gtest_main library, MSVC linker
|
||||
// will not link that library at all and consequently complain about
|
||||
// missing entry point defined in that library (fatal error LNK1561:
|
||||
// entry point must be defined). This dummy test keeps gtest_main linked in.
|
||||
// Google Test may not support type-parameterized tests with some
|
||||
// compilers. If we use conditional compilation to compile out all
|
||||
// code referring to the gtest_main library, MSVC linker will not link
|
||||
// that library at all and consequently complain about missing entry
|
||||
// point defined in that library (fatal error LNK1561: entry point
|
||||
// must be defined). This dummy test keeps gtest_main linked in.
|
||||
TEST(DummyTest, TypedTestsAreNotSupportedOnThisPlatform) {}
|
||||
|
||||
#endif // #if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
|
||||
|
||||
@@ -45,3 +45,4 @@
|
||||
#include "test/gtest-typed-test2_test.cc"
|
||||
#include "test/gtest_unittest.cc"
|
||||
#include "test/production.cc"
|
||||
#include "src/gtest_main.cc"
|
||||
|
||||
@@ -69,21 +69,24 @@ EXE_PATH = gtest_test_utils.GetTestExecutablePath(
|
||||
# Utilities.
|
||||
|
||||
|
||||
environ = os.environ.copy()
|
||||
|
||||
|
||||
def SetEnvVar(env_var, value):
|
||||
"""Sets an environment variable to a given value; unsets it when the
|
||||
given value is None.
|
||||
"""
|
||||
|
||||
if value is not None:
|
||||
os.environ[env_var] = value
|
||||
elif env_var in os.environ:
|
||||
del os.environ[env_var]
|
||||
environ[env_var] = value
|
||||
elif env_var in environ:
|
||||
del environ[env_var]
|
||||
|
||||
|
||||
def Run(command):
|
||||
"""Runs a command; returns 1 if it was killed by a signal, or 0 otherwise."""
|
||||
|
||||
p = gtest_test_utils.Subprocess(command)
|
||||
p = gtest_test_utils.Subprocess(command, env=environ)
|
||||
if p.terminated_by_signal:
|
||||
return 1
|
||||
else:
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
@@ -52,6 +53,14 @@ TEST(Foo, Bar) {
|
||||
EXPECT_EQ(2, 3);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_SEH && !GTEST_OS_WINDOWS_MOBILE
|
||||
// On Windows Mobile global exception handlers are not supported.
|
||||
LONG WINAPI ExitWithExceptionCode(
|
||||
struct _EXCEPTION_POINTERS* exception_pointers) {
|
||||
exit(exception_pointers->ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
@@ -59,7 +68,18 @@ int main(int argc, char **argv) {
|
||||
// Suppresses display of the Windows error dialog upon encountering
|
||||
// a general protection fault (segment violation).
|
||||
SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS);
|
||||
|
||||
#if !GTEST_OS_WINDOWS_MOBILE
|
||||
// The default unhandled exception filter does not always exit
|
||||
// with the exception code as exit code - for example it exits with
|
||||
// 0 for EXCEPTION_ACCESS_VIOLATION and 1 for EXCEPTION_BREAKPOINT
|
||||
// if the application is compiled in debug mode. Thus we use our own
|
||||
// filter which always exits with the exception code for unhandled
|
||||
// exceptions.
|
||||
SetUnhandledExceptionFilter(ExitWithExceptionCode);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
|
||||
@@ -37,11 +37,14 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
bool ShouldUseColor(bool stdout_is_tty);
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
// Indicates that this translation unit is part of Google Test's
|
||||
// implementation. It must come before gtest-internal-inl.h is
|
||||
// included, or there will be a compiler error. This trick is to
|
||||
// prevent a user from accidentally including gtest-internal-inl.h in
|
||||
// his code.
|
||||
#define GTEST_IMPLEMENTATION_ 1
|
||||
#include "src/gtest-internal-inl.h"
|
||||
#undef GTEST_IMPLEMENTATION_
|
||||
|
||||
using testing::internal::ShouldUseColor;
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
|
||||
|
||||
COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_env_var_test_')
|
||||
|
||||
environ = os.environ.copy()
|
||||
|
||||
|
||||
def AssertEq(expected, actual):
|
||||
if expected != actual:
|
||||
@@ -54,9 +56,9 @@ def SetEnvVar(env_var, value):
|
||||
"""Sets the env variable to 'value'; unsets it when 'value' is None."""
|
||||
|
||||
if value is not None:
|
||||
os.environ[env_var] = value
|
||||
elif env_var in os.environ:
|
||||
del os.environ[env_var]
|
||||
environ[env_var] = value
|
||||
elif env_var in environ:
|
||||
del environ[env_var]
|
||||
|
||||
|
||||
def GetFlag(flag):
|
||||
@@ -65,7 +67,7 @@ def GetFlag(flag):
|
||||
args = [COMMAND]
|
||||
if flag is not None:
|
||||
args += [flag]
|
||||
return gtest_test_utils.Subprocess(args).output
|
||||
return gtest_test_utils.Subprocess(args, env=environ).output
|
||||
|
||||
|
||||
def TestFlag(flag, test_val, default_val):
|
||||
|
||||
+112
-73
@@ -45,11 +45,42 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
|
||||
import os
|
||||
import re
|
||||
import sets
|
||||
import sys
|
||||
|
||||
import gtest_test_utils
|
||||
|
||||
# Constants.
|
||||
|
||||
IS_WINDOWS = os.name == 'nt'
|
||||
# Checks if this platform can pass empty environment variables to child
|
||||
# processes. We set an env variable to an empty string and invoke a python
|
||||
# script in a subprocess to print whether the variable is STILL in
|
||||
# os.environ. We then use 'eval' to parse the child's output so that an
|
||||
# exception is thrown if the input is anything other than 'True' nor 'False'.
|
||||
os.environ['EMPTY_VAR'] = ''
|
||||
child = gtest_test_utils.Subprocess(
|
||||
[sys.executable, '-c', 'import os; print \'EMPTY_VAR\' in os.environ'])
|
||||
CAN_PASS_EMPTY_ENV = eval(child.output)
|
||||
|
||||
|
||||
# Check if this platform can unset environment variables in child processes.
|
||||
# We set an env variable to a non-empty string, unset it, and invoke
|
||||
# a python script in a subprocess to print whether the variable
|
||||
# is NO LONGER in os.environ.
|
||||
# We use 'eval' to parse the child's output so that an exception
|
||||
# is thrown if the input is neither 'True' nor 'False'.
|
||||
os.environ['UNSET_VAR'] = 'X'
|
||||
del os.environ['UNSET_VAR']
|
||||
child = gtest_test_utils.Subprocess(
|
||||
[sys.executable, '-c', 'import os; print \'UNSET_VAR\' not in os.environ'])
|
||||
CAN_UNSET_ENV = eval(child.output)
|
||||
|
||||
|
||||
# Checks if we should test with an empty filter. This doesn't
|
||||
# make sense on platforms that cannot pass empty env variables (Win32)
|
||||
# and on platforms that cannot unset variables (since we cannot tell
|
||||
# the difference between "" and NULL -- Borland and Solaris < 5.10)
|
||||
CAN_TEST_EMPTY_FILTER = (CAN_PASS_EMPTY_ENV and CAN_UNSET_ENV)
|
||||
|
||||
|
||||
# The environment variable for specifying the test filters.
|
||||
FILTER_ENV_VAR = 'GTEST_FILTER'
|
||||
@@ -77,6 +108,14 @@ TEST_CASE_REGEX = re.compile(r'^\[\-+\] \d+ tests? from (\w+(/\w+)?)')
|
||||
# Regex for parsing test names from Google Test's output.
|
||||
TEST_REGEX = re.compile(r'^\[\s*RUN\s*\].*\.(\w+(/\w+)?)')
|
||||
|
||||
# The command line flag to tell Google Test to output the list of tests it
|
||||
# will run.
|
||||
LIST_TESTS_FLAG = '--gtest_list_tests'
|
||||
|
||||
# Indicates whether Google Test supports death tests.
|
||||
SUPPORTS_DEATH_TESTS = 'HasDeathTest' in gtest_test_utils.Subprocess(
|
||||
[COMMAND, LIST_TESTS_FLAG]).output
|
||||
|
||||
# Full names of all tests in gtest_filter_unittests_.
|
||||
PARAM_TESTS = [
|
||||
'SeqP/ParamTest.TestX/0',
|
||||
@@ -98,6 +137,14 @@ DISABLED_TESTS = [
|
||||
'DISABLED_FoobarbazTest.TestA',
|
||||
]
|
||||
|
||||
if SUPPORTS_DEATH_TESTS:
|
||||
DEATH_TESTS = [
|
||||
'HasDeathTest.Test1',
|
||||
'HasDeathTest.Test2',
|
||||
]
|
||||
else:
|
||||
DEATH_TESTS = []
|
||||
|
||||
# All the non-disabled tests.
|
||||
ACTIVE_TESTS = [
|
||||
'FooTest.Abc',
|
||||
@@ -110,35 +157,35 @@ ACTIVE_TESTS = [
|
||||
'BazTest.TestOne',
|
||||
'BazTest.TestA',
|
||||
'BazTest.TestB',
|
||||
|
||||
'HasDeathTest.Test1',
|
||||
'HasDeathTest.Test2',
|
||||
] + PARAM_TESTS
|
||||
] + DEATH_TESTS + PARAM_TESTS
|
||||
|
||||
param_tests_present = None
|
||||
|
||||
# Utilities.
|
||||
|
||||
environ = os.environ.copy()
|
||||
|
||||
|
||||
def SetEnvVar(env_var, value):
|
||||
"""Sets the env variable to 'value'; unsets it when 'value' is None."""
|
||||
|
||||
if value is not None:
|
||||
os.environ[env_var] = value
|
||||
elif env_var in os.environ:
|
||||
del os.environ[env_var]
|
||||
environ[env_var] = value
|
||||
elif env_var in environ:
|
||||
del environ[env_var]
|
||||
|
||||
|
||||
def RunAndReturnOutput(args = None):
|
||||
"""Runs the test program and returns its output."""
|
||||
|
||||
return gtest_test_utils.Subprocess([COMMAND] + (args or [])).output
|
||||
return gtest_test_utils.Subprocess([COMMAND] + (args or []),
|
||||
env=environ).output
|
||||
|
||||
|
||||
def RunAndExtractTestList(args = None):
|
||||
"""Runs the test program and returns its exit code and a list of tests run."""
|
||||
|
||||
p = gtest_test_utils.Subprocess([COMMAND] + (args or []))
|
||||
p = gtest_test_utils.Subprocess([COMMAND] + (args or []), env=environ)
|
||||
tests_run = []
|
||||
test_case = ''
|
||||
test = ''
|
||||
@@ -157,15 +204,12 @@ def RunAndExtractTestList(args = None):
|
||||
def InvokeWithModifiedEnv(extra_env, function, *args, **kwargs):
|
||||
"""Runs the given function and arguments in a modified environment."""
|
||||
try:
|
||||
original_env = os.environ.copy()
|
||||
os.environ.update(extra_env)
|
||||
original_env = environ.copy()
|
||||
environ.update(extra_env)
|
||||
return function(*args, **kwargs)
|
||||
finally:
|
||||
for key in extra_env.iterkeys():
|
||||
if key in original_env:
|
||||
os.environ[key] = original_env[key]
|
||||
else:
|
||||
del os.environ[key]
|
||||
environ.clear()
|
||||
environ.update(original_env)
|
||||
|
||||
|
||||
def RunWithSharding(total_shards, shard_index, command):
|
||||
@@ -179,7 +223,7 @@ def RunWithSharding(total_shards, shard_index, command):
|
||||
|
||||
|
||||
class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
"""Tests GTEST_FILTER env variable or --gtest_filter flag to filter tests."""
|
||||
"""Tests the env variable or the command line flag to filter tests."""
|
||||
|
||||
# Utilities.
|
||||
|
||||
@@ -211,26 +255,26 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
return tests_to_run
|
||||
|
||||
def RunAndVerify(self, gtest_filter, tests_to_run):
|
||||
"""Checks that the binary runs correct set of tests for the given filter."""
|
||||
"""Checks that the binary runs correct set of tests for a given filter."""
|
||||
|
||||
tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
|
||||
|
||||
# First, tests using GTEST_FILTER.
|
||||
# First, tests using the environment variable.
|
||||
|
||||
# Windows removes empty variables from the environment when passing it
|
||||
# to a new process. This means it is impossible to pass an empty filter
|
||||
# into a process using the GTEST_FILTER environment variable. However,
|
||||
# we can still test the case when the variable is not supplied (i.e.,
|
||||
# gtest_filter is None).
|
||||
# to a new process. This means it is impossible to pass an empty filter
|
||||
# into a process using the environment variable. However, we can still
|
||||
# test the case when the variable is not supplied (i.e., gtest_filter is
|
||||
# None).
|
||||
# pylint: disable-msg=C6403
|
||||
if not IS_WINDOWS or gtest_filter != '':
|
||||
if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
|
||||
SetEnvVar(FILTER_ENV_VAR, gtest_filter)
|
||||
tests_run = RunAndExtractTestList()[0]
|
||||
SetEnvVar(FILTER_ENV_VAR, None)
|
||||
self.AssertSetEqual(tests_run, tests_to_run)
|
||||
# pylint: enable-msg=C6403
|
||||
|
||||
# Next, tests using --gtest_filter.
|
||||
# Next, tests using the command line flag.
|
||||
|
||||
if gtest_filter is None:
|
||||
args = []
|
||||
@@ -260,12 +304,12 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
|
||||
|
||||
# Windows removes empty variables from the environment when passing it
|
||||
# to a new process. This means it is impossible to pass an empty filter
|
||||
# into a process using the GTEST_FILTER environment variable. However,
|
||||
# we can still test the case when the variable is not supplied (i.e.,
|
||||
# gtest_filter is None).
|
||||
# to a new process. This means it is impossible to pass an empty filter
|
||||
# into a process using the environment variable. However, we can still
|
||||
# test the case when the variable is not supplied (i.e., gtest_filter is
|
||||
# None).
|
||||
# pylint: disable-msg=C6403
|
||||
if not IS_WINDOWS or gtest_filter != '':
|
||||
if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
|
||||
SetEnvVar(FILTER_ENV_VAR, gtest_filter)
|
||||
partition = []
|
||||
for i in range(0, total_shards):
|
||||
@@ -404,10 +448,7 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
|
||||
'BazTest.TestOne',
|
||||
'BazTest.TestA',
|
||||
'BazTest.TestB',
|
||||
|
||||
'HasDeathTest.Test1',
|
||||
'HasDeathTest.Test2', ] + PARAM_TESTS)
|
||||
'BazTest.TestB', ] + DEATH_TESTS + PARAM_TESTS)
|
||||
|
||||
def testWildcardInTestName(self):
|
||||
"""Tests using wildcard in the test name."""
|
||||
@@ -468,7 +509,7 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
])
|
||||
|
||||
def testNegativeFilters(self):
|
||||
self.RunAndVerify('*-HasDeathTest.Test1', [
|
||||
self.RunAndVerify('*-BazTest.TestOne', [
|
||||
'FooTest.Abc',
|
||||
'FooTest.Xyz',
|
||||
|
||||
@@ -476,24 +517,17 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
'BarTest.TestTwo',
|
||||
'BarTest.TestThree',
|
||||
|
||||
'BazTest.TestOne',
|
||||
'BazTest.TestA',
|
||||
'BazTest.TestB',
|
||||
] + DEATH_TESTS + PARAM_TESTS)
|
||||
|
||||
'HasDeathTest.Test2',
|
||||
] + PARAM_TESTS)
|
||||
|
||||
self.RunAndVerify('*-FooTest.Abc:HasDeathTest.*', [
|
||||
self.RunAndVerify('*-FooTest.Abc:BazTest.*', [
|
||||
'FooTest.Xyz',
|
||||
|
||||
'BarTest.TestOne',
|
||||
'BarTest.TestTwo',
|
||||
'BarTest.TestThree',
|
||||
|
||||
'BazTest.TestOne',
|
||||
'BazTest.TestA',
|
||||
'BazTest.TestB',
|
||||
] + PARAM_TESTS)
|
||||
] + DEATH_TESTS + PARAM_TESTS)
|
||||
|
||||
self.RunAndVerify('BarTest.*-BarTest.TestOne', [
|
||||
'BarTest.TestTwo',
|
||||
@@ -501,15 +535,11 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
])
|
||||
|
||||
# Tests without leading '*'.
|
||||
self.RunAndVerify('-FooTest.Abc:FooTest.Xyz:HasDeathTest.*', [
|
||||
self.RunAndVerify('-FooTest.Abc:FooTest.Xyz:BazTest.*', [
|
||||
'BarTest.TestOne',
|
||||
'BarTest.TestTwo',
|
||||
'BarTest.TestThree',
|
||||
|
||||
'BazTest.TestOne',
|
||||
'BazTest.TestA',
|
||||
'BazTest.TestB',
|
||||
] + PARAM_TESTS)
|
||||
] + DEATH_TESTS + PARAM_TESTS)
|
||||
|
||||
# Value parameterized tests.
|
||||
self.RunAndVerify('*/*', PARAM_TESTS)
|
||||
@@ -555,7 +585,7 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
os.remove(shard_status_file)
|
||||
|
||||
def testShardStatusFileIsCreatedWithListTests(self):
|
||||
"""Tests that the shard file is created with --gtest_list_tests."""
|
||||
"""Tests that the shard file is created with the "list_tests" flag."""
|
||||
|
||||
shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
|
||||
'shard_status_file2')
|
||||
@@ -563,32 +593,41 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
|
||||
extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
|
||||
try:
|
||||
InvokeWithModifiedEnv(extra_env,
|
||||
RunAndReturnOutput,
|
||||
['--gtest_list_tests'])
|
||||
output = InvokeWithModifiedEnv(extra_env,
|
||||
RunAndReturnOutput,
|
||||
[LIST_TESTS_FLAG])
|
||||
finally:
|
||||
# This assertion ensures that Google Test enumerated the tests as
|
||||
# opposed to running them.
|
||||
self.assert_('[==========]' not in output,
|
||||
'Unexpected output during test enumeration.\n'
|
||||
'Please ensure that LIST_TESTS_FLAG is assigned the\n'
|
||||
'correct flag value for listing Google Test tests.')
|
||||
|
||||
self.assert_(os.path.exists(shard_status_file))
|
||||
os.remove(shard_status_file)
|
||||
|
||||
def testShardingWorksWithDeathTests(self):
|
||||
"""Tests integration with death tests and sharding."""
|
||||
gtest_filter = 'HasDeathTest.*:SeqP/*'
|
||||
expected_tests = [
|
||||
'HasDeathTest.Test1',
|
||||
'HasDeathTest.Test2',
|
||||
if SUPPORTS_DEATH_TESTS:
|
||||
def testShardingWorksWithDeathTests(self):
|
||||
"""Tests integration with death tests and sharding."""
|
||||
|
||||
'SeqP/ParamTest.TestX/0',
|
||||
'SeqP/ParamTest.TestX/1',
|
||||
'SeqP/ParamTest.TestY/0',
|
||||
'SeqP/ParamTest.TestY/1',
|
||||
]
|
||||
gtest_filter = 'HasDeathTest.*:SeqP/*'
|
||||
expected_tests = [
|
||||
'HasDeathTest.Test1',
|
||||
'HasDeathTest.Test2',
|
||||
|
||||
for flag in ['--gtest_death_test_style=threadsafe',
|
||||
'--gtest_death_test_style=fast']:
|
||||
self.RunAndVerifyWithSharding(gtest_filter, 3, expected_tests,
|
||||
check_exit_0=True, args=[flag])
|
||||
self.RunAndVerifyWithSharding(gtest_filter, 5, expected_tests,
|
||||
check_exit_0=True, args=[flag])
|
||||
'SeqP/ParamTest.TestX/0',
|
||||
'SeqP/ParamTest.TestX/1',
|
||||
'SeqP/ParamTest.TestY/0',
|
||||
'SeqP/ParamTest.TestY/1',
|
||||
]
|
||||
|
||||
for flag in ['--gtest_death_test_style=threadsafe',
|
||||
'--gtest_death_test_style=fast']:
|
||||
self.RunAndVerifyWithSharding(gtest_filter, 3, expected_tests,
|
||||
check_exit_0=True, args=[flag])
|
||||
self.RunAndVerifyWithSharding(gtest_filter, 5, expected_tests,
|
||||
check_exit_0=True, args=[flag])
|
||||
|
||||
if __name__ == '__main__':
|
||||
gtest_test_utils.Main()
|
||||
|
||||
+49
-6
@@ -50,6 +50,15 @@ PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_help_test_')
|
||||
FLAG_PREFIX = '--gtest_'
|
||||
CATCH_EXCEPTIONS_FLAG = FLAG_PREFIX + 'catch_exceptions'
|
||||
DEATH_TEST_STYLE_FLAG = FLAG_PREFIX + 'death_test_style'
|
||||
UNKNOWN_FLAG = FLAG_PREFIX + 'unknown_flag_for_testing'
|
||||
LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
|
||||
INCORRECT_FLAG_VARIANTS = [re.sub('^--', '-', LIST_TESTS_FLAG),
|
||||
re.sub('^--', '/', LIST_TESTS_FLAG),
|
||||
re.sub('_', '-', LIST_TESTS_FLAG)]
|
||||
INTERNAL_FLAG_FOR_TESTING = FLAG_PREFIX + 'internal_flag_for_testing'
|
||||
|
||||
SUPPORTS_DEATH_TESTS = "DeathTest" in gtest_test_utils.Subprocess(
|
||||
[PROGRAM_PATH, LIST_TESTS_FLAG]).output
|
||||
|
||||
# The help message must match this regex.
|
||||
HELP_REGEX = re.compile(
|
||||
@@ -88,18 +97,41 @@ class GTestHelpTest(gtest_test_utils.TestCase):
|
||||
"""Tests the --help flag and its equivalent forms."""
|
||||
|
||||
def TestHelpFlag(self, flag):
|
||||
"""Verifies that the right message is printed and the tests are
|
||||
skipped when the given flag is specified."""
|
||||
"""Verifies correct behavior when help flag is specified.
|
||||
|
||||
The right message must be printed and the tests must
|
||||
skipped when the given flag is specified.
|
||||
|
||||
Args:
|
||||
flag: A flag to pass to the binary or None.
|
||||
"""
|
||||
|
||||
exit_code, output = RunWithFlag(flag)
|
||||
self.assertEquals(0, exit_code)
|
||||
self.assert_(HELP_REGEX.search(output), output)
|
||||
if IS_WINDOWS:
|
||||
self.assert_(CATCH_EXCEPTIONS_FLAG in output, output)
|
||||
self.assert_(DEATH_TEST_STYLE_FLAG not in output, output)
|
||||
else:
|
||||
self.assert_(CATCH_EXCEPTIONS_FLAG not in output, output)
|
||||
|
||||
if SUPPORTS_DEATH_TESTS and not IS_WINDOWS:
|
||||
self.assert_(DEATH_TEST_STYLE_FLAG in output, output)
|
||||
else:
|
||||
self.assert_(DEATH_TEST_STYLE_FLAG not in output, output)
|
||||
|
||||
def TestNonHelpFlag(self, flag):
|
||||
"""Verifies correct behavior when no help flag is specified.
|
||||
|
||||
Verifies that when no help flag is specified, the tests are run
|
||||
and the help message is not printed.
|
||||
|
||||
Args:
|
||||
flag: A flag to pass to the binary or None.
|
||||
"""
|
||||
|
||||
exit_code, output = RunWithFlag(flag)
|
||||
self.assert_(exit_code != 0)
|
||||
self.assert_(not HELP_REGEX.search(output), output)
|
||||
|
||||
def testPrintsHelpWithFullFlag(self):
|
||||
self.TestHelpFlag('--help')
|
||||
@@ -113,13 +145,24 @@ class GTestHelpTest(gtest_test_utils.TestCase):
|
||||
def testPrintsHelpWithWindowsStyleQuestionFlag(self):
|
||||
self.TestHelpFlag('/?')
|
||||
|
||||
def testPrintsHelpWithUnrecognizedGoogleTestFlag(self):
|
||||
self.TestHelpFlag(UNKNOWN_FLAG)
|
||||
|
||||
def testPrintsHelpWithIncorrectFlagStyle(self):
|
||||
for incorrect_flag in INCORRECT_FLAG_VARIANTS:
|
||||
self.TestHelpFlag(incorrect_flag)
|
||||
|
||||
def testRunsTestsWithoutHelpFlag(self):
|
||||
"""Verifies that when no help flag is specified, the tests are run
|
||||
and the help message is not printed."""
|
||||
|
||||
exit_code, output = RunWithFlag(None)
|
||||
self.assert_(exit_code != 0)
|
||||
self.assert_(not HELP_REGEX.search(output), output)
|
||||
self.TestNonHelpFlag(None)
|
||||
|
||||
def testRunsTestsWithGtestInternalFlag(self):
|
||||
"""Verifies that the tests are run and no help message is printed when
|
||||
a flag starting with Google Test prefix and 'internal_' is supplied."""
|
||||
|
||||
self.TestNonHelpFlag(INTERNAL_FLAG_FOR_TESTING)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -40,3 +40,7 @@
|
||||
TEST(HelpFlagTest, ShouldNotBeRun) {
|
||||
ASSERT_TRUE(false) << "Tests shouldn't be run when --help is specified.";
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
TEST(DeathTest, UsedByPythonScriptToDetectSupportForDeathTestsInThisBinary) {}
|
||||
#endif
|
||||
|
||||
+53
-33
@@ -48,6 +48,7 @@ import gtest_test_utils
|
||||
|
||||
# The flag for generating the golden file
|
||||
GENGOLDEN_FLAG = '--gengolden'
|
||||
CATCH_EXCEPTIONS_ENV_VAR_NAME = 'GTEST_CATCH_EXCEPTIONS'
|
||||
|
||||
IS_WINDOWS = os.name == 'nt'
|
||||
|
||||
@@ -123,18 +124,32 @@ def RemoveTime(output):
|
||||
return re.sub(r'\(\d+ ms', '(? ms', output)
|
||||
|
||||
|
||||
def RemoveTypeInfoDetails(test_output):
|
||||
"""Removes compiler-specific type info from Google Test program's output.
|
||||
|
||||
Args:
|
||||
test_output: the output of a Google Test program.
|
||||
|
||||
Returns:
|
||||
output with type information normalized to canonical form.
|
||||
"""
|
||||
|
||||
# some compilers output the name of type 'unsigned int' as 'unsigned'
|
||||
return re.sub(r'unsigned int', 'unsigned', test_output)
|
||||
|
||||
|
||||
def RemoveTestCounts(output):
|
||||
"""Removes test counts from a Google Test program's output."""
|
||||
|
||||
output = re.sub(r'\d+ tests, listed below',
|
||||
output = re.sub(r'\d+ tests?, listed below',
|
||||
'? tests, listed below', output)
|
||||
output = re.sub(r'\d+ FAILED TESTS',
|
||||
'? FAILED TESTS', output)
|
||||
output = re.sub(r'\d+ tests from \d+ test cases',
|
||||
output = re.sub(r'\d+ tests? from \d+ test cases?',
|
||||
'? tests from ? test cases', output)
|
||||
output = re.sub(r'\d+ tests from ([a-zA-Z_])',
|
||||
output = re.sub(r'\d+ tests? from ([a-zA-Z_])',
|
||||
r'? tests from \1', output)
|
||||
return re.sub(r'\d+ tests\.', '? tests.', output)
|
||||
return re.sub(r'\d+ tests?\.', '? tests.', output)
|
||||
|
||||
|
||||
def RemoveMatchingTests(test_output, pattern):
|
||||
@@ -184,16 +199,9 @@ def GetShellCommandOutput(env_cmd):
|
||||
|
||||
# Spawns cmd in a sub-process, and gets its standard I/O file objects.
|
||||
# Set and save the environment properly.
|
||||
old_env_vars = dict(os.environ)
|
||||
os.environ.update(env_cmd[0])
|
||||
p = gtest_test_utils.Subprocess(env_cmd[1])
|
||||
|
||||
# Changes made by os.environ.clear are not inheritable by child processes
|
||||
# until Python 2.6. To produce inheritable changes we have to delete
|
||||
# environment items with the del statement.
|
||||
for key in os.environ.keys():
|
||||
del os.environ[key]
|
||||
os.environ.update(old_env_vars)
|
||||
environ = os.environ.copy()
|
||||
environ.update(env_cmd[0])
|
||||
p = gtest_test_utils.Subprocess(env_cmd[1], env=environ)
|
||||
|
||||
return p.output
|
||||
|
||||
@@ -209,8 +217,10 @@ def GetCommandOutput(env_cmd):
|
||||
"""
|
||||
|
||||
# Disables exception pop-ups on Windows.
|
||||
os.environ['GTEST_CATCH_EXCEPTIONS'] = '1'
|
||||
return NormalizeOutput(GetShellCommandOutput(env_cmd))
|
||||
environ, cmdline = env_cmd
|
||||
environ = dict(environ) # Ensures we are modifying a copy.
|
||||
environ[CATCH_EXCEPTIONS_ENV_VAR_NAME] = '1'
|
||||
return NormalizeOutput(GetShellCommandOutput((environ, cmdline)))
|
||||
|
||||
|
||||
def GetOutputOfAllCommands():
|
||||
@@ -228,7 +238,9 @@ SUPPORTS_TYPED_TESTS = 'TypedTest' in test_list
|
||||
SUPPORTS_THREADS = 'ExpectFailureWithThreadsTest' in test_list
|
||||
SUPPORTS_STACK_TRACES = False
|
||||
|
||||
CAN_GENERATE_GOLDEN_FILE = SUPPORTS_DEATH_TESTS and SUPPORTS_TYPED_TESTS
|
||||
CAN_GENERATE_GOLDEN_FILE = (SUPPORTS_DEATH_TESTS and
|
||||
SUPPORTS_TYPED_TESTS and
|
||||
SUPPORTS_THREADS)
|
||||
|
||||
|
||||
class GTestOutputTest(gtest_test_utils.TestCase):
|
||||
@@ -237,6 +249,8 @@ class GTestOutputTest(gtest_test_utils.TestCase):
|
||||
test_output = RemoveMatchingTests(test_output, 'DeathTest')
|
||||
if not SUPPORTS_TYPED_TESTS:
|
||||
test_output = RemoveMatchingTests(test_output, 'TypedTest')
|
||||
test_output = RemoveMatchingTests(test_output, 'TypedDeathTest')
|
||||
test_output = RemoveMatchingTests(test_output, 'TypeParamDeathTest')
|
||||
if not SUPPORTS_THREADS:
|
||||
test_output = RemoveMatchingTests(test_output,
|
||||
'ExpectFailureWithThreadsTest')
|
||||
@@ -262,24 +276,30 @@ class GTestOutputTest(gtest_test_utils.TestCase):
|
||||
|
||||
# We want the test to pass regardless of certain features being
|
||||
# supported or not.
|
||||
|
||||
# We still have to remove type name specifics in all cases.
|
||||
normalized_actual = RemoveTypeInfoDetails(output)
|
||||
normalized_golden = RemoveTypeInfoDetails(golden)
|
||||
|
||||
if CAN_GENERATE_GOLDEN_FILE:
|
||||
self.assert_(golden == output)
|
||||
self.assertEqual(normalized_golden, normalized_actual)
|
||||
else:
|
||||
normalized_actual = RemoveTestCounts(output)
|
||||
normalized_golden = RemoveTestCounts(self.RemoveUnsupportedTests(golden))
|
||||
normalized_actual = RemoveTestCounts(normalized_actual)
|
||||
normalized_golden = RemoveTestCounts(self.RemoveUnsupportedTests(
|
||||
normalized_golden))
|
||||
|
||||
# This code is very handy when debugging test differences so I left it
|
||||
# here, commented.
|
||||
# open(os.path.join(
|
||||
# gtest_test_utils.GetSourceDir(),
|
||||
# '_gtest_output_test_normalized_actual.txt'), 'wb').write(
|
||||
# normalized_actual)
|
||||
# open(os.path.join(
|
||||
# gtest_test_utils.GetSourceDir(),
|
||||
# '_gtest_output_test_normalized_golden.txt'), 'wb').write(
|
||||
# normalized_golden)
|
||||
# This code is very handy when debugging golden file differences:
|
||||
if os.getenv('DEBUG_GTEST_OUTPUT_TEST'):
|
||||
open(os.path.join(
|
||||
gtest_test_utils.GetSourceDir(),
|
||||
'_gtest_output_test_normalized_actual.txt'), 'wb').write(
|
||||
normalized_actual)
|
||||
open(os.path.join(
|
||||
gtest_test_utils.GetSourceDir(),
|
||||
'_gtest_output_test_normalized_golden.txt'), 'wb').write(
|
||||
normalized_golden)
|
||||
|
||||
self.assert_(normalized_golden == normalized_actual)
|
||||
self.assertEqual(normalized_golden, normalized_actual)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -298,8 +318,8 @@ that does not support all the required features (death tests""")
|
||||
"""\nand typed tests). Please check that you are using VC++ 8.0 SP1
|
||||
or higher as your compiler.""")
|
||||
else:
|
||||
message += """\nand typed tests). Please generate the golden file
|
||||
using a binary built with those features enabled."""
|
||||
message += """\ntyped tests, and threads). Please generate the
|
||||
golden file using a binary built with those features enabled."""
|
||||
|
||||
sys.stderr.write(message)
|
||||
sys.exit(1)
|
||||
|
||||
+144
-18
@@ -46,15 +46,17 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if GTEST_HAS_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif // GTEST_HAS_PTHREAD
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
using testing::ScopedFakeTestPartResultReporter;
|
||||
using testing::TestPartResultArray;
|
||||
|
||||
using testing::internal::Notification;
|
||||
using testing::internal::ThreadWithParam;
|
||||
#endif
|
||||
|
||||
namespace posix = ::testing::internal::posix;
|
||||
using testing::internal::String;
|
||||
using testing::internal::scoped_ptr;
|
||||
|
||||
// Tests catching fatal failures.
|
||||
|
||||
@@ -214,6 +216,83 @@ TEST(SCOPED_TRACETest, CanBeRepeated) {
|
||||
<< "trace point A, B, and D.";
|
||||
}
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
// Tests that SCOPED_TRACE()s can be used concurrently from multiple
|
||||
// threads. Namely, an assertion should be affected by
|
||||
// SCOPED_TRACE()s in its own thread only.
|
||||
|
||||
// Here's the sequence of actions that happen in the test:
|
||||
//
|
||||
// Thread A (main) | Thread B (spawned)
|
||||
// ===============================|================================
|
||||
// spawns thread B |
|
||||
// -------------------------------+--------------------------------
|
||||
// waits for n1 | SCOPED_TRACE("Trace B");
|
||||
// | generates failure #1
|
||||
// | notifies n1
|
||||
// -------------------------------+--------------------------------
|
||||
// SCOPED_TRACE("Trace A"); | waits for n2
|
||||
// generates failure #2 |
|
||||
// notifies n2 |
|
||||
// -------------------------------|--------------------------------
|
||||
// waits for n3 | generates failure #3
|
||||
// | trace B dies
|
||||
// | generates failure #4
|
||||
// | notifies n3
|
||||
// -------------------------------|--------------------------------
|
||||
// generates failure #5 | finishes
|
||||
// trace A dies |
|
||||
// generates failure #6 |
|
||||
// -------------------------------|--------------------------------
|
||||
// waits for thread B to finish |
|
||||
|
||||
struct CheckPoints {
|
||||
Notification n1;
|
||||
Notification n2;
|
||||
Notification n3;
|
||||
};
|
||||
|
||||
static void ThreadWithScopedTrace(CheckPoints* check_points) {
|
||||
{
|
||||
SCOPED_TRACE("Trace B");
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #1 (in thread B, only trace B alive).";
|
||||
check_points->n1.Notify();
|
||||
check_points->n2.WaitForNotification();
|
||||
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #3 (in thread B, trace A & B both alive).";
|
||||
} // Trace B dies here.
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #4 (in thread B, only trace A alive).";
|
||||
check_points->n3.Notify();
|
||||
}
|
||||
|
||||
TEST(SCOPED_TRACETest, WorksConcurrently) {
|
||||
printf("(expecting 6 failures)\n");
|
||||
|
||||
CheckPoints check_points;
|
||||
ThreadWithParam<CheckPoints*> thread(&ThreadWithScopedTrace,
|
||||
&check_points,
|
||||
NULL);
|
||||
check_points.n1.WaitForNotification();
|
||||
|
||||
{
|
||||
SCOPED_TRACE("Trace A");
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #2 (in thread A, trace A & B both alive).";
|
||||
check_points.n2.Notify();
|
||||
check_points.n3.WaitForNotification();
|
||||
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #5 (in thread A, only trace A alive).";
|
||||
} // Trace A dies here.
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #6 (in thread A, no trace alive).";
|
||||
thread.Join();
|
||||
}
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
TEST(DisabledTestsWarningTest,
|
||||
DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning) {
|
||||
// This test body is intentionally empty. Its sole purpose is for
|
||||
@@ -479,6 +558,63 @@ TEST_F(ExceptionInTearDownTest, ExceptionInTearDown) {
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
|
||||
// A unary function that may die.
|
||||
void DieIf(bool should_die) {
|
||||
GTEST_CHECK_(!should_die) << " - death inside DieIf().";
|
||||
}
|
||||
|
||||
// Tests running death tests in a multi-threaded context.
|
||||
|
||||
// Used for coordination between the main and the spawn thread.
|
||||
struct SpawnThreadNotifications {
|
||||
SpawnThreadNotifications() {}
|
||||
|
||||
Notification spawn_thread_started;
|
||||
Notification spawn_thread_ok_to_terminate;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(SpawnThreadNotifications);
|
||||
};
|
||||
|
||||
// The function to be executed in the thread spawn by the
|
||||
// MultipleThreads test (below).
|
||||
static void ThreadRoutine(SpawnThreadNotifications* notifications) {
|
||||
// Signals the main thread that this thread has started.
|
||||
notifications->spawn_thread_started.Notify();
|
||||
|
||||
// Waits for permission to finish from the main thread.
|
||||
notifications->spawn_thread_ok_to_terminate.WaitForNotification();
|
||||
}
|
||||
|
||||
// This is a death-test test, but it's not named with a DeathTest
|
||||
// suffix. It starts threads which might interfere with later
|
||||
// death tests, so it must run after all other death tests.
|
||||
class DeathTestAndMultiThreadsTest : public testing::Test {
|
||||
protected:
|
||||
// Starts a thread and waits for it to begin.
|
||||
virtual void SetUp() {
|
||||
thread_.reset(new ThreadWithParam<SpawnThreadNotifications*>(
|
||||
&ThreadRoutine, ¬ifications_, NULL));
|
||||
notifications_.spawn_thread_started.WaitForNotification();
|
||||
}
|
||||
// Tells the thread to finish, and reaps it.
|
||||
// Depending on the version of the thread library in use,
|
||||
// a manager thread might still be left running that will interfere
|
||||
// with later death tests. This is unfortunate, but this class
|
||||
// cleans up after itself as best it can.
|
||||
virtual void TearDown() {
|
||||
notifications_.spawn_thread_ok_to_terminate.Notify();
|
||||
}
|
||||
|
||||
private:
|
||||
SpawnThreadNotifications notifications_;
|
||||
scoped_ptr<ThreadWithParam<SpawnThreadNotifications*> > thread_;
|
||||
};
|
||||
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
// The MixedUpTestCaseTest test case verifies that Google Test will fail a
|
||||
// test if it uses a different fixture class than what other tests in
|
||||
// the same test case use. It deliberately contains two fixture
|
||||
@@ -849,23 +985,13 @@ TEST_F(ExpectFailureTest, ExpectNonFatalFailure) {
|
||||
"failure.");
|
||||
}
|
||||
|
||||
#if GTEST_IS_THREADSAFE && GTEST_HAS_PTHREAD
|
||||
#if GTEST_IS_THREADSAFE
|
||||
|
||||
class ExpectFailureWithThreadsTest : public ExpectFailureTest {
|
||||
protected:
|
||||
static void AddFailureInOtherThread(FailureMode failure) {
|
||||
pthread_t tid;
|
||||
pthread_create(&tid,
|
||||
NULL,
|
||||
ExpectFailureWithThreadsTest::FailureThread,
|
||||
&failure);
|
||||
pthread_join(tid, NULL);
|
||||
}
|
||||
private:
|
||||
static void* FailureThread(void* attr) {
|
||||
FailureMode* failure = static_cast<FailureMode*>(attr);
|
||||
AddFailure(*failure);
|
||||
return NULL;
|
||||
ThreadWithParam<FailureMode> thread(&AddFailure, failure, NULL);
|
||||
thread.Join();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -901,7 +1027,7 @@ TEST_F(ScopedFakeTestPartResultReporterTest, InterceptOnlyCurrentThread) {
|
||||
EXPECT_EQ(0, results.size()) << "This shouldn't fail.";
|
||||
}
|
||||
|
||||
#endif // GTEST_IS_THREADSAFE && GTEST_HAS_PTHREAD
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
TEST_F(ExpectFailureTest, ExpectFatalFailureOnAllThreads) {
|
||||
// Expected fatal failure, but succeeds.
|
||||
|
||||
@@ -7,7 +7,7 @@ Expected: true
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Value of: 3
|
||||
Expected: 2
|
||||
[0;32m[==========] [mRunning 56 tests from 23 test cases.
|
||||
[0;32m[==========] [mRunning 60 tests from 25 test cases.
|
||||
[0;32m[----------] [mGlobal test environment set-up.
|
||||
FooEnvironment::SetUp() called.
|
||||
BarEnvironment::SetUp() called.
|
||||
@@ -65,7 +65,7 @@ i == 3
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Expected: (3) >= (a[i]), actual: 3 vs 6
|
||||
[0;31m[ FAILED ] [mLoggingTest.InterleavingLoggingAndAssertions
|
||||
[0;32m[----------] [m5 tests from SCOPED_TRACETest
|
||||
[0;32m[----------] [m6 tests from SCOPED_TRACETest
|
||||
[0;32m[ RUN ] [mSCOPED_TRACETest.ObeysScopes
|
||||
(expected to fail)
|
||||
gtest_output_test_.cc:#: Failure
|
||||
@@ -148,6 +148,35 @@ gtest_output_test_.cc:#: D
|
||||
gtest_output_test_.cc:#: B
|
||||
gtest_output_test_.cc:#: A
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.CanBeRepeated
|
||||
[0;32m[ RUN ] [mSCOPED_TRACETest.WorksConcurrently
|
||||
(expecting 6 failures)
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #1 (in thread B, only trace B alive).
|
||||
Google Test trace:
|
||||
gtest_output_test_.cc:#: Trace B
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #2 (in thread A, trace A & B both alive).
|
||||
Google Test trace:
|
||||
gtest_output_test_.cc:#: Trace A
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #3 (in thread B, trace A & B both alive).
|
||||
Google Test trace:
|
||||
gtest_output_test_.cc:#: Trace B
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #4 (in thread B, only trace A alive).
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #5 (in thread A, only trace A alive).
|
||||
Google Test trace:
|
||||
gtest_output_test_.cc:#: Trace A
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #6 (in thread A, no trace alive).
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.WorksConcurrently
|
||||
[0;32m[----------] [m1 test from NonFatalFailureInFixtureConstructorTest
|
||||
[0;32m[ RUN ] [mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
|
||||
(expecting 5 failures)
|
||||
@@ -506,6 +535,35 @@ Failed
|
||||
Expected non-fatal failure.
|
||||
|
||||
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
|
||||
[0;32m[----------] [m2 tests from ExpectFailureWithThreadsTest
|
||||
[0;32m[ RUN ] [mExpectFailureWithThreadsTest.ExpectFatalFailure
|
||||
(expecting 2 failures)
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected fatal failure.
|
||||
gtest.cc:#: Failure
|
||||
Expected: 1 fatal failure
|
||||
Actual: 0 failures
|
||||
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectFatalFailure
|
||||
[0;32m[ RUN ] [mExpectFailureWithThreadsTest.ExpectNonFatalFailure
|
||||
(expecting 2 failures)
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected non-fatal failure.
|
||||
gtest.cc:#: Failure
|
||||
Expected: 1 non-fatal failure
|
||||
Actual: 0 failures
|
||||
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectNonFatalFailure
|
||||
[0;32m[----------] [m1 test from ScopedFakeTestPartResultReporterTest
|
||||
[0;32m[ RUN ] [mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
|
||||
(expecting 2 failures)
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected fatal failure.
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected non-fatal failure.
|
||||
[0;31m[ FAILED ] [mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
|
||||
[0;32m[----------] [mGlobal test environment tear-down
|
||||
BarEnvironment::TearDown() called.
|
||||
gtest_output_test_.cc:#: Failure
|
||||
@@ -515,9 +573,9 @@ FooEnvironment::TearDown() called.
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected fatal failure.
|
||||
[0;32m[==========] [m56 tests from 23 test cases ran.
|
||||
[0;32m[==========] [m60 tests from 25 test cases ran.
|
||||
[0;32m[ PASSED ] [m21 tests.
|
||||
[0;31m[ FAILED ] [m35 tests, listed below:
|
||||
[0;31m[ FAILED ] [m39 tests, listed below:
|
||||
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInSubroutine
|
||||
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInNestedSubroutine
|
||||
[0;31m[ FAILED ] [mFatalFailureTest.NonfatalFailureInSubroutine
|
||||
@@ -527,6 +585,7 @@ Expected fatal failure.
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.WorksInSubroutine
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.CanBeNested
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.CanBeRepeated
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.WorksConcurrently
|
||||
[0;31m[ FAILED ] [mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
|
||||
[0;31m[ FAILED ] [mFatalFailureInFixtureConstructorTest.FailureInConstructor
|
||||
[0;31m[ FAILED ] [mNonFatalFailureInSetUpTest.FailureInSetUp
|
||||
@@ -553,8 +612,11 @@ Expected fatal failure.
|
||||
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailure
|
||||
[0;31m[ FAILED ] [mExpectFailureTest.ExpectFatalFailureOnAllThreads
|
||||
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
|
||||
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectFatalFailure
|
||||
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectNonFatalFailure
|
||||
[0;31m[ FAILED ] [mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
|
||||
|
||||
35 FAILED TESTS
|
||||
39 FAILED TESTS
|
||||
[0;33m YOU HAVE 1 DISABLED TEST
|
||||
|
||||
[mNote: Google Test filter = FatalFailureTest.*:LoggingTest.*
|
||||
|
||||
@@ -78,16 +78,10 @@ def RandomSeedFlag(n):
|
||||
def RunAndReturnOutput(extra_env, args):
|
||||
"""Runs the test program and returns its output."""
|
||||
|
||||
try:
|
||||
original_env = os.environ.copy()
|
||||
os.environ.update(extra_env)
|
||||
return gtest_test_utils.Subprocess([COMMAND] + args).output
|
||||
finally:
|
||||
for key in extra_env.iterkeys():
|
||||
if key in original_env:
|
||||
os.environ[key] = original_env[key]
|
||||
else:
|
||||
del os.environ[key]
|
||||
environ_copy = os.environ.copy()
|
||||
environ_copy.update(extra_env)
|
||||
|
||||
return gtest_test_utils.Subprocess([COMMAND] + args, env=environ_copy).output
|
||||
|
||||
|
||||
def GetTestsForAllIterations(extra_env, args):
|
||||
|
||||
+128
-22
@@ -32,9 +32,11 @@
|
||||
// Tests that SCOPED_TRACE() and various Google Test assertions can be
|
||||
// used in a large number of threads concurrently.
|
||||
|
||||
#include <iostream>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
// We must define this macro in order to #include
|
||||
// gtest-internal-inl.h. This is how Google Test prevents a user from
|
||||
// accidentally depending on its internal implementation.
|
||||
@@ -42,12 +44,20 @@
|
||||
#include "src/gtest-internal-inl.h"
|
||||
#undef GTEST_IMPLEMENTATION_
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
|
||||
namespace testing {
|
||||
namespace {
|
||||
|
||||
using internal::Notification;
|
||||
using internal::String;
|
||||
using internal::TestPropertyKeyIs;
|
||||
using internal::Vector;
|
||||
using internal::ThreadWithParam;
|
||||
using internal::scoped_ptr;
|
||||
|
||||
// In order to run tests in this file, for platforms where Google Test is
|
||||
// thread safe, implement ThreadWithParam. See the description of its API
|
||||
// in gtest-port.h, where it is defined for already supported platforms.
|
||||
|
||||
// How many threads to create?
|
||||
const int kThreadCount = 50;
|
||||
@@ -64,12 +74,13 @@ String IdToString(int id) {
|
||||
return id_message.GetString();
|
||||
}
|
||||
|
||||
void ExpectKeyAndValueWereRecordedForId(const Vector<TestProperty>& properties,
|
||||
int id,
|
||||
const char* suffix) {
|
||||
void ExpectKeyAndValueWereRecordedForId(
|
||||
const std::vector<TestProperty>& properties,
|
||||
int id, const char* suffix) {
|
||||
TestPropertyKeyIs matches_key(IdToKey(id, suffix).c_str());
|
||||
const TestProperty* property = properties.FindIf(matches_key);
|
||||
ASSERT_TRUE(property != NULL)
|
||||
const std::vector<TestProperty>::const_iterator property =
|
||||
std::find_if(properties.begin(), properties.end(), matches_key);
|
||||
ASSERT_TRUE(property != properties.end())
|
||||
<< "expecting " << suffix << " value for id " << id;
|
||||
EXPECT_STREQ(IdToString(id).c_str(), property->value());
|
||||
}
|
||||
@@ -77,7 +88,7 @@ void ExpectKeyAndValueWereRecordedForId(const Vector<TestProperty>& properties,
|
||||
// Calls a large number of Google Test assertions, where exactly one of them
|
||||
// will fail.
|
||||
void ManyAsserts(int id) {
|
||||
::std::cout << "Thread #" << id << " running...\n";
|
||||
GTEST_LOG_(INFO) << "Thread #" << id << " running...";
|
||||
|
||||
SCOPED_TRACE(Message() << "Thread #" << id);
|
||||
|
||||
@@ -104,41 +115,121 @@ void ManyAsserts(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
void CheckTestFailureCount(int expected_failures) {
|
||||
const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
|
||||
const TestResult* const result = info->result();
|
||||
GTEST_CHECK_(expected_failures == result->total_part_count())
|
||||
<< "Logged " << result->total_part_count() << " failures "
|
||||
<< " vs. " << expected_failures << " expected";
|
||||
}
|
||||
|
||||
// Tests using SCOPED_TRACE() and Google Test assertions in many threads
|
||||
// concurrently.
|
||||
TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
|
||||
// TODO(wan): when Google Test is made thread-safe, run
|
||||
// ManyAsserts() in many threads here.
|
||||
{
|
||||
scoped_ptr<ThreadWithParam<int> > threads[kThreadCount];
|
||||
Notification threads_can_start;
|
||||
for (int i = 0; i != kThreadCount; i++)
|
||||
threads[i].reset(new ThreadWithParam<int>(&ManyAsserts,
|
||||
i,
|
||||
&threads_can_start));
|
||||
|
||||
threads_can_start.Notify();
|
||||
|
||||
// Blocks until all the threads are done.
|
||||
for (int i = 0; i != kThreadCount; i++)
|
||||
threads[i]->Join();
|
||||
}
|
||||
|
||||
// Ensures that kThreadCount*kThreadCount failures have been reported.
|
||||
const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
|
||||
const TestResult* const result = info->result();
|
||||
|
||||
std::vector<TestProperty> properties;
|
||||
// We have no access to the TestResult's list of properties but we can
|
||||
// copy them one by one.
|
||||
for (int i = 0; i < result->test_property_count(); ++i)
|
||||
properties.push_back(result->GetTestProperty(i));
|
||||
|
||||
EXPECT_EQ(kThreadCount * 2 + 1, result->test_property_count())
|
||||
<< "String and int values recorded on each thread, "
|
||||
<< "as well as one shared_key";
|
||||
for (int i = 0; i < kThreadCount; ++i) {
|
||||
ExpectKeyAndValueWereRecordedForId(properties, i, "string");
|
||||
ExpectKeyAndValueWereRecordedForId(properties, i, "int");
|
||||
}
|
||||
CheckTestFailureCount(kThreadCount*kThreadCount);
|
||||
}
|
||||
|
||||
void FailingThread(bool is_fatal) {
|
||||
if (is_fatal)
|
||||
FAIL() << "Fatal failure in some other thread. "
|
||||
<< "(This failure is expected.)";
|
||||
else
|
||||
ADD_FAILURE() << "Non-fatal failure in some other thread. "
|
||||
<< "(This failure is expected.)";
|
||||
}
|
||||
|
||||
void GenerateFatalFailureInAnotherThread(bool is_fatal) {
|
||||
ThreadWithParam<bool> thread(&FailingThread, is_fatal, NULL);
|
||||
thread.Join();
|
||||
}
|
||||
|
||||
TEST(NoFatalFailureTest, ExpectNoFatalFailureIgnoresFailuresInOtherThreads) {
|
||||
// TODO(mheule@google.com): Test this works correctly when Google
|
||||
// Test is made thread-safe.
|
||||
EXPECT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
|
||||
// We should only have one failure (the one from
|
||||
// GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
|
||||
// should succeed.
|
||||
CheckTestFailureCount(1);
|
||||
}
|
||||
|
||||
void AssertNoFatalFailureIgnoresFailuresInOtherThreads() {
|
||||
ASSERT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
|
||||
}
|
||||
TEST(NoFatalFailureTest, AssertNoFatalFailureIgnoresFailuresInOtherThreads) {
|
||||
// TODO(mheule@google.com): Test this works correctly when Google
|
||||
// Test is made thread-safe.
|
||||
// Using a subroutine, to make sure, that the test continues.
|
||||
AssertNoFatalFailureIgnoresFailuresInOtherThreads();
|
||||
// We should only have one failure (the one from
|
||||
// GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
|
||||
// should succeed.
|
||||
CheckTestFailureCount(1);
|
||||
}
|
||||
|
||||
TEST(FatalFailureTest, ExpectFatalFailureIgnoresFailuresInOtherThreads) {
|
||||
// TODO(mheule@google.com): Test this works correctly when Google
|
||||
// Test is made thread-safe.
|
||||
// This statement should fail, since the current thread doesn't generate a
|
||||
// fatal failure, only another one does.
|
||||
EXPECT_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true), "expected");
|
||||
CheckTestFailureCount(2);
|
||||
}
|
||||
|
||||
TEST(FatalFailureOnAllThreadsTest, ExpectFatalFailureOnAllThreads) {
|
||||
// TODO(wan@google.com): Test this works correctly when Google Test
|
||||
// is made thread-safe.
|
||||
// This statement should succeed, because failures in all threads are
|
||||
// considered.
|
||||
EXPECT_FATAL_FAILURE_ON_ALL_THREADS(
|
||||
GenerateFatalFailureInAnotherThread(true), "expected");
|
||||
CheckTestFailureCount(0);
|
||||
// We need to add a failure, because main() checks that there are failures.
|
||||
// But when only this test is run, we shouldn't have any failures.
|
||||
ADD_FAILURE() << "This is an expected non-fatal failure.";
|
||||
}
|
||||
|
||||
TEST(NonFatalFailureTest, ExpectNonFatalFailureIgnoresFailuresInOtherThreads) {
|
||||
// TODO(mheule@google.com): Test this works correctly when Google
|
||||
// Test is made thread-safe.
|
||||
// This statement should fail, since the current thread doesn't generate a
|
||||
// fatal failure, only another one does.
|
||||
EXPECT_NONFATAL_FAILURE(GenerateFatalFailureInAnotherThread(false),
|
||||
"expected");
|
||||
CheckTestFailureCount(2);
|
||||
}
|
||||
|
||||
TEST(NonFatalFailureOnAllThreadsTest, ExpectNonFatalFailureOnAllThreads) {
|
||||
// TODO(wan@google.com): Test this works correctly when Google Test
|
||||
// is made thread-safe.
|
||||
// This statement should succeed, because failures in all threads are
|
||||
// considered.
|
||||
EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
|
||||
GenerateFatalFailureInAnotherThread(false), "expected");
|
||||
CheckTestFailureCount(0);
|
||||
// We need to add a failure, because main() checks that there are failures,
|
||||
// But when only this test is run, we shouldn't have any failures.
|
||||
ADD_FAILURE() << "This is an expected non-fatal failure.";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -147,5 +238,20 @@ TEST(NonFatalFailureOnAllThreadsTest, ExpectNonFatalFailureOnAllThreads) {
|
||||
int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
const int result = RUN_ALL_TESTS(); // Expected to fail.
|
||||
GTEST_CHECK_(result == 1) << "RUN_ALL_TESTS() did not fail as expected";
|
||||
|
||||
printf("\nPASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
TEST(StressTest,
|
||||
DISABLED_ThreadSafetyTestsAreSkippedWhenGoogleTestIsNotThreadSafe) {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
+52
-13
@@ -51,6 +51,7 @@ except:
|
||||
_SUBPROCESS_MODULE_AVAILABLE = False
|
||||
# pylint: enable-msg=C6204
|
||||
|
||||
GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
|
||||
|
||||
IS_WINDOWS = os.name == 'nt'
|
||||
IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
|
||||
@@ -137,7 +138,7 @@ def GetTempDir():
|
||||
return _temp_dir
|
||||
|
||||
|
||||
def GetTestExecutablePath(executable_name):
|
||||
def GetTestExecutablePath(executable_name, build_dir=None):
|
||||
"""Returns the absolute path of the test binary given its name.
|
||||
|
||||
The function will print a message and abort the program if the resulting file
|
||||
@@ -145,12 +146,15 @@ def GetTestExecutablePath(executable_name):
|
||||
|
||||
Args:
|
||||
executable_name: name of the test binary that the test script runs.
|
||||
build_dir: directory where to look for executables, by default
|
||||
the result of GetBuildDir().
|
||||
|
||||
Returns:
|
||||
The absolute path of the test binary.
|
||||
"""
|
||||
|
||||
path = os.path.abspath(os.path.join(GetBuildDir(), executable_name))
|
||||
path = os.path.abspath(os.path.join(build_dir or GetBuildDir(),
|
||||
executable_name))
|
||||
if (IS_WINDOWS or IS_CYGWIN) and not path.endswith('.exe'):
|
||||
path += '.exe'
|
||||
|
||||
@@ -190,23 +194,28 @@ def GetExitStatus(exit_code):
|
||||
|
||||
|
||||
class Subprocess:
|
||||
def __init__(self, command, working_dir=None, capture_stderr=True):
|
||||
def __init__(self, command, working_dir=None, capture_stderr=True, env=None):
|
||||
"""Changes into a specified directory, if provided, and executes a command.
|
||||
Restores the old directory afterwards. Execution results are returned
|
||||
via the following attributes:
|
||||
terminated_by_sygnal True iff the child process has been terminated
|
||||
by a signal.
|
||||
signal Sygnal that terminated the child process.
|
||||
exited True iff the child process exited normally.
|
||||
exit_code The code with which the child proces exited.
|
||||
output Child process's stdout and stderr output
|
||||
combined in a string.
|
||||
|
||||
Restores the old directory afterwards.
|
||||
|
||||
Args:
|
||||
command: The command to run, in the form of sys.argv.
|
||||
working_dir: The directory to change into.
|
||||
capture_stderr: Determines whether to capture stderr in the output member
|
||||
or to discard it.
|
||||
env: Dictionary with environment to pass to the subprocess.
|
||||
|
||||
Returns:
|
||||
An object that represents outcome of the executed process. It has the
|
||||
following attributes:
|
||||
terminated_by_signal True iff the child process has been terminated
|
||||
by a signal.
|
||||
signal Sygnal that terminated the child process.
|
||||
exited True iff the child process exited normally.
|
||||
exit_code The code with which the child process exited.
|
||||
output Child process's stdout and stderr output
|
||||
combined in a string.
|
||||
"""
|
||||
|
||||
# The subprocess module is the preferrable way of running programs
|
||||
@@ -224,13 +233,30 @@ class Subprocess:
|
||||
|
||||
p = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE, stderr=stderr,
|
||||
cwd=working_dir, universal_newlines=True)
|
||||
cwd=working_dir, universal_newlines=True, env=env)
|
||||
# communicate returns a tuple with the file obect for the child's
|
||||
# output.
|
||||
self.output = p.communicate()[0]
|
||||
self._return_code = p.returncode
|
||||
else:
|
||||
old_dir = os.getcwd()
|
||||
|
||||
def _ReplaceEnvDict(dest, src):
|
||||
# Changes made by os.environ.clear are not inheritable by child
|
||||
# processes until Python 2.6. To produce inheritable changes we have
|
||||
# to delete environment items with the del statement.
|
||||
for key in dest:
|
||||
del dest[key]
|
||||
dest.update(src)
|
||||
|
||||
# When 'env' is not None, backup the environment variables and replace
|
||||
# them with the passed 'env'. When 'env' is None, we simply use the
|
||||
# current 'os.environ' for compatibility with the subprocess.Popen
|
||||
# semantics used above.
|
||||
if env is not None:
|
||||
old_environ = os.environ.copy()
|
||||
_ReplaceEnvDict(os.environ, env)
|
||||
|
||||
try:
|
||||
if working_dir is not None:
|
||||
os.chdir(working_dir)
|
||||
@@ -243,6 +269,12 @@ class Subprocess:
|
||||
ret_code = p.wait()
|
||||
finally:
|
||||
os.chdir(old_dir)
|
||||
|
||||
# Restore the old environment variables
|
||||
# if they were replaced.
|
||||
if env is not None:
|
||||
_ReplaceEnvDict(os.environ, old_environ)
|
||||
|
||||
# Converts ret_code to match the semantics of
|
||||
# subprocess.Popen.returncode.
|
||||
if os.WIFSIGNALED(ret_code):
|
||||
@@ -267,4 +299,11 @@ def Main():
|
||||
# unittest.main(). Otherwise the latter will be confused by the
|
||||
# --gtest_* flags.
|
||||
_ParseAndStripGTestFlags(sys.argv)
|
||||
# The tested binaries should not be writing XML output files unless the
|
||||
# script explicitly instructs them to.
|
||||
# TODO(vladl@google.com): Move this into Subprocess when we implement
|
||||
# passing environment into it as a parameter.
|
||||
if GTEST_OUTPUT_VAR_NAME in os.environ:
|
||||
del os.environ[GTEST_OUTPUT_VAR_NAME]
|
||||
|
||||
_test_module.main()
|
||||
|
||||
+469
-598
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -48,7 +48,7 @@ class PrivateCode {
|
||||
|
||||
int x() const { return x_; }
|
||||
private:
|
||||
void set_x(int x) { x_ = x; }
|
||||
void set_x(int an_x) { x_ = an_x; }
|
||||
int x_;
|
||||
};
|
||||
|
||||
|
||||
Executable
+466
@@ -0,0 +1,466 @@
|
||||
# Copyright 2008 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.
|
||||
|
||||
"""Provides facilities for running SCons-built Google Test/Mock tests."""
|
||||
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import re
|
||||
import sets
|
||||
import sys
|
||||
|
||||
try:
|
||||
# subrocess module is a preferable way to invoke subprocesses but it may
|
||||
# not be available on MacOS X 10.4.
|
||||
# Suppresses the 'Import not at the top of the file' lint complaint.
|
||||
# pylint: disable-msg=C6204
|
||||
import subprocess
|
||||
except ImportError:
|
||||
subprocess = None
|
||||
|
||||
HELP_MSG = """Runs the specified tests for %(proj)s.
|
||||
|
||||
SYNOPSIS
|
||||
run_tests.py [OPTION]... [BUILD_DIR]... [TEST]...
|
||||
|
||||
DESCRIPTION
|
||||
Runs the specified tests (either binary or Python), and prints a
|
||||
summary of the results. BUILD_DIRS will be used to search for the
|
||||
binaries. If no TESTs are specified, all binary tests found in
|
||||
BUILD_DIRs and all Python tests found in the directory test/ (in the
|
||||
%(proj)s root) are run.
|
||||
|
||||
TEST is a name of either a binary or a Python test. A binary test is
|
||||
an executable file named *_test or *_unittest (with the .exe
|
||||
extension on Windows) A Python test is a script named *_test.py or
|
||||
*_unittest.py.
|
||||
|
||||
OPTIONS
|
||||
-h, --help
|
||||
Print this help message.
|
||||
-c CONFIGURATIONS
|
||||
Specify build directories via build configurations.
|
||||
CONFIGURATIONS is either a comma-separated list of build
|
||||
configurations or 'all'. Each configuration is equivalent to
|
||||
adding 'scons/build/<configuration>/%(proj)s/scons' to BUILD_DIRs.
|
||||
Specifying -c=all is equivalent to providing all directories
|
||||
listed in KNOWN BUILD DIRECTORIES section below.
|
||||
-a
|
||||
Equivalent to -c=all
|
||||
-b
|
||||
Equivalent to -c=all with the exception that the script will not
|
||||
fail if some of the KNOWN BUILD DIRECTORIES do not exists; the
|
||||
script will simply not run the tests there. 'b' stands for
|
||||
'built directories'.
|
||||
|
||||
RETURN VALUE
|
||||
Returns 0 if all tests are successful; otherwise returns 1.
|
||||
|
||||
EXAMPLES
|
||||
run_tests.py
|
||||
Runs all tests for the default build configuration.
|
||||
run_tests.py -a
|
||||
Runs all tests with binaries in KNOWN BUILD DIRECTORIES.
|
||||
run_tests.py -b
|
||||
Runs all tests in KNOWN BUILD DIRECTORIES that have been
|
||||
built.
|
||||
run_tests.py foo/
|
||||
Runs all tests in the foo/ directory and all Python tests in
|
||||
the directory test. The Python tests are instructed to look
|
||||
for binaries in foo/.
|
||||
run_tests.py bar_test.exe test/baz_test.exe foo/ bar/
|
||||
Runs foo/bar_test.exe, bar/bar_test.exe, foo/baz_test.exe, and
|
||||
bar/baz_test.exe.
|
||||
run_tests.py foo bar test/foo_test.py
|
||||
Runs test/foo_test.py twice instructing it to look for its
|
||||
test binaries in the directories foo and bar,
|
||||
correspondingly.
|
||||
|
||||
KNOWN BUILD DIRECTORIES
|
||||
run_tests.py knows about directories where the SCons build script
|
||||
deposits its products. These are the directories where run_tests.py
|
||||
will be looking for its binaries. Currently, %(proj)s's SConstruct file
|
||||
defines them as follows (the default build directory is the first one
|
||||
listed in each group):
|
||||
On Windows:
|
||||
<%(proj)s root>/scons/build/win-dbg8/%(proj)s/scons/
|
||||
<%(proj)s root>/scons/build/win-opt8/%(proj)s/scons/
|
||||
On Mac:
|
||||
<%(proj)s root>/scons/build/mac-dbg/%(proj)s/scons/
|
||||
<%(proj)s root>/scons/build/mac-opt/%(proj)s/scons/
|
||||
On other platforms:
|
||||
<%(proj)s root>/scons/build/dbg/%(proj)s/scons/
|
||||
<%(proj)s root>/scons/build/opt/%(proj)s/scons/"""
|
||||
|
||||
IS_WINDOWS = os.name == 'nt'
|
||||
IS_MAC = os.name == 'posix' and os.uname()[0] == 'Darwin'
|
||||
IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
|
||||
|
||||
# Definition of CONFIGS must match that of the build directory names in the
|
||||
# SConstruct script. The first list item is the default build configuration.
|
||||
if IS_WINDOWS:
|
||||
CONFIGS = ('win-dbg8', 'win-opt8')
|
||||
elif IS_MAC:
|
||||
CONFIGS = ('mac-dbg', 'mac-opt')
|
||||
else:
|
||||
CONFIGS = ('dbg', 'opt')
|
||||
|
||||
if IS_WINDOWS or IS_CYGWIN:
|
||||
PYTHON_TEST_REGEX = re.compile(r'_(unit)?test\.py$', re.IGNORECASE)
|
||||
BINARY_TEST_REGEX = re.compile(r'_(unit)?test(\.exe)?$', re.IGNORECASE)
|
||||
BINARY_TEST_SEARCH_REGEX = re.compile(r'_(unit)?test\.exe$', re.IGNORECASE)
|
||||
else:
|
||||
PYTHON_TEST_REGEX = re.compile(r'_(unit)?test\.py$')
|
||||
BINARY_TEST_REGEX = re.compile(r'_(unit)?test$')
|
||||
BINARY_TEST_SEARCH_REGEX = BINARY_TEST_REGEX
|
||||
|
||||
|
||||
def _GetGtestBuildDir(injected_os, script_dir, config):
|
||||
"""Calculates path to the Google Test SCons build directory."""
|
||||
|
||||
return injected_os.path.normpath(injected_os.path.join(script_dir,
|
||||
'scons/build',
|
||||
config,
|
||||
'gtest/scons'))
|
||||
|
||||
|
||||
def _GetConfigFromBuildDir(build_dir):
|
||||
"""Extracts the configuration name from the build directory."""
|
||||
|
||||
# We don't want to depend on build_dir containing the correct path
|
||||
# separators.
|
||||
m = re.match(r'.*[\\/]([^\\/]+)[\\/][^\\/]+[\\/]scons[\\/]?$', build_dir)
|
||||
if m:
|
||||
return m.group(1)
|
||||
else:
|
||||
print >>sys.stderr, ('%s is an invalid build directory that does not '
|
||||
'correspond to any configuration.' % (build_dir,))
|
||||
return ''
|
||||
|
||||
|
||||
# All paths in this script are either absolute or relative to the current
|
||||
# working directory, unless otherwise specified.
|
||||
class TestRunner(object):
|
||||
"""Provides facilities for running Python and binary tests for Google Test."""
|
||||
|
||||
def __init__(self,
|
||||
script_dir,
|
||||
build_dir_var_name='GTEST_BUILD_DIR',
|
||||
injected_os=os,
|
||||
injected_subprocess=subprocess,
|
||||
injected_build_dir_finder=_GetGtestBuildDir):
|
||||
"""Initializes a TestRunner instance.
|
||||
|
||||
Args:
|
||||
script_dir: File path to the calling script.
|
||||
build_dir_var_name: Name of the env variable used to pass the
|
||||
the build directory path to the invoked
|
||||
tests.
|
||||
injected_os: standard os module or a mock/stub for
|
||||
testing.
|
||||
injected_subprocess: standard subprocess module or a mock/stub
|
||||
for testing
|
||||
injected_build_dir_finder: function that determines the path to
|
||||
the build directory.
|
||||
"""
|
||||
|
||||
self.os = injected_os
|
||||
self.subprocess = injected_subprocess
|
||||
self.build_dir_finder = injected_build_dir_finder
|
||||
self.build_dir_var_name = build_dir_var_name
|
||||
self.script_dir = script_dir
|
||||
|
||||
def _GetBuildDirForConfig(self, config):
|
||||
"""Returns the build directory for a given configuration."""
|
||||
|
||||
return self.build_dir_finder(self.os, self.script_dir, config)
|
||||
|
||||
def _Run(self, args):
|
||||
"""Runs the executable with given args (args[0] is the executable name).
|
||||
|
||||
Args:
|
||||
args: Command line arguments for the process.
|
||||
|
||||
Returns:
|
||||
Process's exit code if it exits normally, or -signal if the process is
|
||||
killed by a signal.
|
||||
"""
|
||||
|
||||
if self.subprocess:
|
||||
return self.subprocess.Popen(args).wait()
|
||||
else:
|
||||
return self.os.spawnv(self.os.P_WAIT, args[0], args)
|
||||
|
||||
def _RunBinaryTest(self, test):
|
||||
"""Runs the binary test given its path.
|
||||
|
||||
Args:
|
||||
test: Path to the test binary.
|
||||
|
||||
Returns:
|
||||
Process's exit code if it exits normally, or -signal if the process is
|
||||
killed by a signal.
|
||||
"""
|
||||
|
||||
return self._Run([test])
|
||||
|
||||
def _RunPythonTest(self, test, build_dir):
|
||||
"""Runs the Python test script with the specified build directory.
|
||||
|
||||
Args:
|
||||
test: Path to the test's Python script.
|
||||
build_dir: Path to the directory where the test binary is to be found.
|
||||
|
||||
Returns:
|
||||
Process's exit code if it exits normally, or -signal if the process is
|
||||
killed by a signal.
|
||||
"""
|
||||
|
||||
old_build_dir = self.os.environ.get(self.build_dir_var_name)
|
||||
|
||||
try:
|
||||
self.os.environ[self.build_dir_var_name] = build_dir
|
||||
|
||||
# If this script is run on a Windows machine that has no association
|
||||
# between the .py extension and a python interpreter, simply passing
|
||||
# the script name into subprocess.Popen/os.spawn will not work.
|
||||
print 'Running %s . . .' % (test,)
|
||||
return self._Run([sys.executable, test])
|
||||
|
||||
finally:
|
||||
if old_build_dir is None:
|
||||
del self.os.environ[self.build_dir_var_name]
|
||||
else:
|
||||
self.os.environ[self.build_dir_var_name] = old_build_dir
|
||||
|
||||
def _FindFilesByRegex(self, directory, regex):
|
||||
"""Returns files in a directory whose names match a regular expression.
|
||||
|
||||
Args:
|
||||
directory: Path to the directory to search for files.
|
||||
regex: Regular expression to filter file names.
|
||||
|
||||
Returns:
|
||||
The list of the paths to the files in the directory.
|
||||
"""
|
||||
|
||||
return [self.os.path.join(directory, file_name)
|
||||
for file_name in self.os.listdir(directory)
|
||||
if re.search(regex, file_name)]
|
||||
|
||||
# TODO(vladl@google.com): Implement parsing of scons/SConscript to run all
|
||||
# tests defined there when no tests are specified.
|
||||
# TODO(vladl@google.com): Update the docstring after the code is changed to
|
||||
# try to test all builds defined in scons/SConscript.
|
||||
def GetTestsToRun(self,
|
||||
args,
|
||||
named_configurations,
|
||||
built_configurations,
|
||||
available_configurations=CONFIGS,
|
||||
python_tests_to_skip=None):
|
||||
"""Determines what tests should be run.
|
||||
|
||||
Args:
|
||||
args: The list of non-option arguments from the command line.
|
||||
named_configurations: The list of configurations specified via -c or -a.
|
||||
built_configurations: True if -b has been specified.
|
||||
available_configurations: a list of configurations available on the
|
||||
current platform, injectable for testing.
|
||||
python_tests_to_skip: a collection of (configuration, python test name)s
|
||||
that need to be skipped.
|
||||
|
||||
Returns:
|
||||
A tuple with 2 elements: the list of Python tests to run and the list of
|
||||
binary tests to run.
|
||||
"""
|
||||
|
||||
if named_configurations == 'all':
|
||||
named_configurations = ','.join(available_configurations)
|
||||
|
||||
normalized_args = [self.os.path.normpath(arg) for arg in args]
|
||||
|
||||
# A final list of build directories which will be searched for the test
|
||||
# binaries. First, add directories specified directly on the command
|
||||
# line.
|
||||
build_dirs = filter(self.os.path.isdir, normalized_args)
|
||||
|
||||
# Adds build directories specified via their build configurations using
|
||||
# the -c or -a options.
|
||||
if named_configurations:
|
||||
build_dirs += [self._GetBuildDirForConfig(config)
|
||||
for config in named_configurations.split(',')]
|
||||
|
||||
# Adds KNOWN BUILD DIRECTORIES if -b is specified.
|
||||
if built_configurations:
|
||||
build_dirs += [self._GetBuildDirForConfig(config)
|
||||
for config in available_configurations
|
||||
if self.os.path.isdir(self._GetBuildDirForConfig(config))]
|
||||
|
||||
# If no directories were specified either via -a, -b, -c, or directly, use
|
||||
# the default configuration.
|
||||
elif not build_dirs:
|
||||
build_dirs = [self._GetBuildDirForConfig(available_configurations[0])]
|
||||
|
||||
# Makes sure there are no duplications.
|
||||
build_dirs = sets.Set(build_dirs)
|
||||
|
||||
errors_found = False
|
||||
listed_python_tests = [] # All Python tests listed on the command line.
|
||||
listed_binary_tests = [] # All binary tests listed on the command line.
|
||||
|
||||
test_dir = self.os.path.normpath(self.os.path.join(self.script_dir, 'test'))
|
||||
|
||||
# Sifts through non-directory arguments fishing for any Python or binary
|
||||
# tests and detecting errors.
|
||||
for argument in sets.Set(normalized_args) - build_dirs:
|
||||
if re.search(PYTHON_TEST_REGEX, argument):
|
||||
python_path = self.os.path.join(test_dir,
|
||||
self.os.path.basename(argument))
|
||||
if self.os.path.isfile(python_path):
|
||||
listed_python_tests.append(python_path)
|
||||
else:
|
||||
sys.stderr.write('Unable to find Python test %s' % argument)
|
||||
errors_found = True
|
||||
elif re.search(BINARY_TEST_REGEX, argument):
|
||||
# This script also accepts binary test names prefixed with test/ for
|
||||
# the convenience of typing them (can use path completions in the
|
||||
# shell). Strips test/ prefix from the binary test names.
|
||||
listed_binary_tests.append(self.os.path.basename(argument))
|
||||
else:
|
||||
sys.stderr.write('%s is neither test nor build directory' % argument)
|
||||
errors_found = True
|
||||
|
||||
if errors_found:
|
||||
return None
|
||||
|
||||
user_has_listed_tests = listed_python_tests or listed_binary_tests
|
||||
|
||||
if user_has_listed_tests:
|
||||
selected_python_tests = listed_python_tests
|
||||
else:
|
||||
selected_python_tests = self._FindFilesByRegex(test_dir,
|
||||
PYTHON_TEST_REGEX)
|
||||
|
||||
# TODO(vladl@google.com): skip unbuilt Python tests when -b is specified.
|
||||
python_test_pairs = []
|
||||
for directory in build_dirs:
|
||||
for test in selected_python_tests:
|
||||
config = _GetConfigFromBuildDir(directory)
|
||||
file_name = os.path.basename(test)
|
||||
if python_tests_to_skip and (config, file_name) in python_tests_to_skip:
|
||||
print ('NOTE: %s is skipped for configuration %s, as it does not '
|
||||
'work there.' % (file_name, config))
|
||||
else:
|
||||
python_test_pairs.append((directory, test))
|
||||
|
||||
binary_test_pairs = []
|
||||
for directory in build_dirs:
|
||||
if user_has_listed_tests:
|
||||
binary_test_pairs.extend(
|
||||
[(directory, self.os.path.join(directory, test))
|
||||
for test in listed_binary_tests])
|
||||
else:
|
||||
tests = self._FindFilesByRegex(directory, BINARY_TEST_SEARCH_REGEX)
|
||||
binary_test_pairs.extend([(directory, test) for test in tests])
|
||||
|
||||
return (python_test_pairs, binary_test_pairs)
|
||||
|
||||
def RunTests(self, python_tests, binary_tests):
|
||||
"""Runs Python and binary tests and reports results to the standard output.
|
||||
|
||||
Args:
|
||||
python_tests: List of Python tests to run in the form of tuples
|
||||
(build directory, Python test script).
|
||||
binary_tests: List of binary tests to run in the form of tuples
|
||||
(build directory, binary file).
|
||||
|
||||
Returns:
|
||||
The exit code the program should pass into sys.exit().
|
||||
"""
|
||||
|
||||
if python_tests or binary_tests:
|
||||
results = []
|
||||
for directory, test in python_tests:
|
||||
results.append((directory,
|
||||
test,
|
||||
self._RunPythonTest(test, directory) == 0))
|
||||
for directory, test in binary_tests:
|
||||
results.append((directory,
|
||||
self.os.path.basename(test),
|
||||
self._RunBinaryTest(test) == 0))
|
||||
|
||||
failed = [(directory, test)
|
||||
for (directory, test, success) in results
|
||||
if not success]
|
||||
print
|
||||
print '%d tests run.' % len(results)
|
||||
if failed:
|
||||
print 'The following %d tests failed:' % len(failed)
|
||||
for (directory, test) in failed:
|
||||
print '%s in %s' % (test, directory)
|
||||
return 1
|
||||
else:
|
||||
print 'All tests passed!'
|
||||
else: # No tests defined
|
||||
print 'Nothing to test - no tests specified!'
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def ParseArgs(project_name, argv=None, help_callback=None):
|
||||
"""Parses the options run_tests.py uses."""
|
||||
|
||||
# Suppresses lint warning on unused arguments. These arguments are
|
||||
# required by optparse, even though they are unused.
|
||||
# pylint: disable-msg=W0613
|
||||
def PrintHelp(option, opt, value, parser):
|
||||
print HELP_MSG % {'proj': project_name}
|
||||
sys.exit(1)
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-c',
|
||||
action='store',
|
||||
dest='configurations',
|
||||
default=None)
|
||||
parser.add_option('-a',
|
||||
action='store_const',
|
||||
dest='configurations',
|
||||
default=None,
|
||||
const='all')
|
||||
parser.add_option('-b',
|
||||
action='store_const',
|
||||
dest='built_configurations',
|
||||
default=False,
|
||||
const=True)
|
||||
# Replaces the built-in help with ours.
|
||||
parser.remove_option('-h')
|
||||
parser.add_option('-h', '--help',
|
||||
action='callback',
|
||||
callback=help_callback or PrintHelp)
|
||||
return parser.parse_args(argv)
|
||||
@@ -28,29 +28,27 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Tests for run_tests.py test runner script."""
|
||||
"""Tests for run_tests_util.py test runner script."""
|
||||
|
||||
__author__ = 'vladl@google.com (Vlad Losev)'
|
||||
|
||||
import os
|
||||
import re
|
||||
import sets
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), os.pardir))
|
||||
import run_tests
|
||||
import run_tests_util
|
||||
|
||||
|
||||
GTEST_DBG_DIR = 'scons/build/dbg/scons'
|
||||
GTEST_OPT_DIR = 'scons/build/opt/scons'
|
||||
GTEST_OTHER_DIR = 'scons/build/other/scons'
|
||||
GTEST_DBG_DIR = 'scons/build/dbg/gtest/scons'
|
||||
GTEST_OPT_DIR = 'scons/build/opt/gtest/scons'
|
||||
GTEST_OTHER_DIR = 'scons/build/other/gtest/scons'
|
||||
|
||||
|
||||
def AddExeExtension(path):
|
||||
"""Appends .exe to the path on Windows or Cygwin."""
|
||||
|
||||
if run_tests.IS_WINDOWS or run_tests.IS_CYGWIN:
|
||||
if run_tests_util.IS_WINDOWS or run_tests_util.IS_CYGWIN:
|
||||
return path + '.exe'
|
||||
else:
|
||||
return path
|
||||
@@ -109,6 +107,8 @@ class FakePath(object):
|
||||
|
||||
return tree
|
||||
|
||||
# Silences pylint warning about using standard names.
|
||||
# pylint: disable-msg=C6409
|
||||
def normpath(self, path):
|
||||
return os.path.normpath(path)
|
||||
|
||||
@@ -141,6 +141,7 @@ class FakeOs(object):
|
||||
# Some methods/attributes are delegated to the real os module.
|
||||
self.environ = os.environ
|
||||
|
||||
# pylint: disable-msg=C6409
|
||||
def listdir(self, path):
|
||||
assert self.path.isdir(path)
|
||||
return self.path.PathElement(path).iterkeys()
|
||||
@@ -169,7 +170,7 @@ class GetTestsToRunTest(unittest.TestCase):
|
||||
# On Windows and Cygwin, the test file names have the .exe extension, but
|
||||
# they can be invoked either by name or by name+extension. Our test must
|
||||
# accommodate both situations.
|
||||
if run_tests.IS_WINDOWS or run_tests.IS_CYGWIN:
|
||||
if run_tests_util.IS_WINDOWS or run_tests_util.IS_CYGWIN:
|
||||
executable = re.sub(r'\.exe$', '', executable)
|
||||
return (directory, executable)
|
||||
|
||||
@@ -187,14 +188,14 @@ class GetTestsToRunTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.fake_os = FakeOs(FakePath(
|
||||
current_dir=os.path.abspath(os.path.dirname(run_tests.__file__)),
|
||||
current_dir=os.path.abspath(os.path.dirname(run_tests_util.__file__)),
|
||||
known_paths=[AddExeExtension(GTEST_DBG_DIR + '/gtest_unittest'),
|
||||
AddExeExtension(GTEST_OPT_DIR + '/gtest_unittest'),
|
||||
'test/gtest_color_test.py']))
|
||||
self.fake_configurations = ['dbg', 'opt']
|
||||
self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
|
||||
injected_subprocess=None,
|
||||
injected_script_dir='.')
|
||||
self.test_runner = run_tests_util.TestRunner(script_dir='.',
|
||||
injected_os=self.fake_os,
|
||||
injected_subprocess=None)
|
||||
|
||||
def testBinaryTestsOnly(self):
|
||||
"""Exercises GetTestsToRun with parameters designating binary tests only."""
|
||||
@@ -419,12 +420,12 @@ class GetTestsToRunTest(unittest.TestCase):
|
||||
"""Verifies that GetTestsToRun ignores non-test files in the filesystem."""
|
||||
|
||||
self.fake_os = FakeOs(FakePath(
|
||||
current_dir=os.path.abspath(os.path.dirname(run_tests.__file__)),
|
||||
current_dir=os.path.abspath(os.path.dirname(run_tests_util.__file__)),
|
||||
known_paths=[AddExeExtension(GTEST_DBG_DIR + '/gtest_nontest'),
|
||||
'test/']))
|
||||
self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
|
||||
injected_subprocess=None,
|
||||
injected_script_dir='.')
|
||||
self.test_runner = run_tests_util.TestRunner(script_dir='.',
|
||||
injected_os=self.fake_os,
|
||||
injected_subprocess=None)
|
||||
self.AssertResultsEqual(
|
||||
self.test_runner.GetTestsToRun(
|
||||
[],
|
||||
@@ -446,9 +447,9 @@ class GetTestsToRunTest(unittest.TestCase):
|
||||
AddExeExtension('/d/' + GTEST_OPT_DIR + '/gtest_unittest'),
|
||||
'/d/test/gtest_color_test.py']))
|
||||
self.fake_configurations = ['dbg', 'opt']
|
||||
self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
|
||||
injected_subprocess=None,
|
||||
injected_script_dir='/d/')
|
||||
self.test_runner = run_tests_util.TestRunner(script_dir='/d/',
|
||||
injected_os=self.fake_os,
|
||||
injected_subprocess=None)
|
||||
# A binary test.
|
||||
self.AssertResultsEqual(
|
||||
self.test_runner.GetTestsToRun(
|
||||
@@ -468,7 +469,6 @@ class GetTestsToRunTest(unittest.TestCase):
|
||||
available_configurations=self.fake_configurations),
|
||||
([('/d/' + GTEST_DBG_DIR, '/d/test/gtest_color_test.py')], []))
|
||||
|
||||
|
||||
def testNonTestBinary(self):
|
||||
"""Exercises GetTestsToRun with a non-test parameter."""
|
||||
|
||||
@@ -489,16 +489,17 @@ class GetTestsToRunTest(unittest.TestCase):
|
||||
False,
|
||||
available_configurations=self.fake_configurations))
|
||||
|
||||
if run_tests.IS_WINDOWS or run_tests.IS_CYGWIN:
|
||||
if run_tests_util.IS_WINDOWS or run_tests_util.IS_CYGWIN:
|
||||
|
||||
def testDoesNotPickNonExeFilesOnWindows(self):
|
||||
"""Verifies that GetTestsToRun does not find _test files on Windows."""
|
||||
|
||||
self.fake_os = FakeOs(FakePath(
|
||||
current_dir=os.path.abspath(os.path.dirname(run_tests.__file__)),
|
||||
current_dir=os.path.abspath(os.path.dirname(run_tests_util.__file__)),
|
||||
known_paths=['/d/' + GTEST_DBG_DIR + '/gtest_test', 'test/']))
|
||||
self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
|
||||
injected_subprocess=None,
|
||||
injected_script_dir='.')
|
||||
self.test_runner = run_tests_util.TestRunner(script_dir='.',
|
||||
injected_os=self.fake_os,
|
||||
injected_subprocess=None)
|
||||
self.AssertResultsEqual(
|
||||
self.test_runner.GetTestsToRun(
|
||||
[],
|
||||
@@ -525,14 +526,16 @@ class RunTestsTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.fake_os = FakeOs(FakePath(
|
||||
current_dir=os.path.abspath(os.path.dirname(run_tests.__file__)),
|
||||
current_dir=os.path.abspath(os.path.dirname(run_tests_util.__file__)),
|
||||
known_paths=[
|
||||
AddExeExtension(GTEST_DBG_DIR + '/gtest_unittest'),
|
||||
AddExeExtension(GTEST_OPT_DIR + '/gtest_unittest'),
|
||||
'test/gtest_color_test.py']))
|
||||
self.fake_configurations = ['dbg', 'opt']
|
||||
self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
|
||||
injected_subprocess=None)
|
||||
self.test_runner = run_tests_util.TestRunner(
|
||||
script_dir=os.path.dirname(__file__) or '.',
|
||||
injected_os=self.fake_os,
|
||||
injected_subprocess=None)
|
||||
self.num_spawn_calls = 0 # A number of calls to spawn.
|
||||
|
||||
def testRunPythonTestSuccess(self):
|
||||
@@ -610,5 +613,64 @@ class RunTestsTest(unittest.TestCase):
|
||||
self.assertEqual(self.num_spawn_calls, 2)
|
||||
|
||||
|
||||
class ParseArgsTest(unittest.TestCase):
|
||||
"""Exercises ParseArgs."""
|
||||
|
||||
def testNoOptions(self):
|
||||
options, args = run_tests_util.ParseArgs('gtest', argv=['script.py'])
|
||||
self.assertEqual(args, ['script.py'])
|
||||
self.assert_(options.configurations is None)
|
||||
self.assertFalse(options.built_configurations)
|
||||
|
||||
def testOptionC(self):
|
||||
options, args = run_tests_util.ParseArgs(
|
||||
'gtest', argv=['script.py', '-c', 'dbg'])
|
||||
self.assertEqual(args, ['script.py'])
|
||||
self.assertEqual(options.configurations, 'dbg')
|
||||
self.assertFalse(options.built_configurations)
|
||||
|
||||
def testOptionA(self):
|
||||
options, args = run_tests_util.ParseArgs('gtest', argv=['script.py', '-a'])
|
||||
self.assertEqual(args, ['script.py'])
|
||||
self.assertEqual(options.configurations, 'all')
|
||||
self.assertFalse(options.built_configurations)
|
||||
|
||||
def testOptionB(self):
|
||||
options, args = run_tests_util.ParseArgs('gtest', argv=['script.py', '-b'])
|
||||
self.assertEqual(args, ['script.py'])
|
||||
self.assert_(options.configurations is None)
|
||||
self.assertTrue(options.built_configurations)
|
||||
|
||||
def testOptionCAndOptionB(self):
|
||||
options, args = run_tests_util.ParseArgs(
|
||||
'gtest', argv=['script.py', '-c', 'dbg', '-b'])
|
||||
self.assertEqual(args, ['script.py'])
|
||||
self.assertEqual(options.configurations, 'dbg')
|
||||
self.assertTrue(options.built_configurations)
|
||||
|
||||
def testOptionH(self):
|
||||
help_called = [False]
|
||||
|
||||
# Suppresses lint warning on unused arguments. These arguments are
|
||||
# required by optparse, even though they are unused.
|
||||
# pylint: disable-msg=W0613
|
||||
def VerifyHelp(option, opt, value, parser):
|
||||
help_called[0] = True
|
||||
|
||||
# Verifies that -h causes the help callback to be called.
|
||||
help_called[0] = False
|
||||
_, args = run_tests_util.ParseArgs(
|
||||
'gtest', argv=['script.py', '-h'], help_callback=VerifyHelp)
|
||||
self.assertEqual(args, ['script.py'])
|
||||
self.assertTrue(help_called[0])
|
||||
|
||||
# Verifies that --help causes the help callback to be called.
|
||||
help_called[0] = False
|
||||
_, args = run_tests_util.ParseArgs(
|
||||
'gtest', argv=['script.py', '--help'], help_callback=VerifyHelp)
|
||||
self.assertEqual(args, ['script.py'])
|
||||
self.assertTrue(help_called[0])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -17,7 +17,7 @@ ZERO_LINK = NO
|
||||
PREBINDING = NO
|
||||
|
||||
// Strictest warning policy
|
||||
WARNING_CFLAGS = -Wall -Werror -Wendif-labels -Wnewline-eof -Wno-sign-compare
|
||||
WARNING_CFLAGS = -Wall -Werror -Wendif-labels -Wnewline-eof -Wno-sign-compare -Wshadow
|
||||
|
||||
// Work around Xcode bugs by using external strip. See:
|
||||
// http://lists.apple.com/archives/Xcode-users/2006/Feb/msg00050.html
|
||||
|
||||
@@ -6,13 +6,40 @@
|
||||
objectVersion = 42;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
4024D162113D7D2400C7059E /* Test */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = 4024D169113D7D4600C7059E /* Build configuration list for PBXAggregateTarget "Test" */;
|
||||
buildPhases = (
|
||||
4024D161113D7D2400C7059E /* ShellScript */,
|
||||
);
|
||||
dependencies = (
|
||||
4024D166113D7D3100C7059E /* PBXTargetDependency */,
|
||||
);
|
||||
name = Test;
|
||||
productName = TestAndBuild;
|
||||
};
|
||||
4024D1E9113D83FF00C7059E /* TestAndBuild */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = 4024D1F0113D842B00C7059E /* Build configuration list for PBXAggregateTarget "TestAndBuild" */;
|
||||
buildPhases = (
|
||||
);
|
||||
dependencies = (
|
||||
4024D1ED113D840900C7059E /* PBXTargetDependency */,
|
||||
4024D1EF113D840D00C7059E /* PBXTargetDependency */,
|
||||
);
|
||||
name = TestAndBuild;
|
||||
productName = TestAndBuild;
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
3B7EB1250E5AEE3500C7F239 /* widget.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B7EB1230E5AEE3500C7F239 /* widget.cc */; };
|
||||
3B7EB1260E5AEE3500C7F239 /* widget.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B7EB1240E5AEE3500C7F239 /* widget.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3B7EB1280E5AEE4600C7F239 /* widget_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B7EB1270E5AEE4600C7F239 /* widget_test.cc */; };
|
||||
3B7EB1480E5AF3B400C7F239 /* Widget.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D07F2C80486CC7A007CD1D0 /* Widget.framework */; };
|
||||
408BEC281046D72200DEF522 /* gtest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 408BEC271046D72200DEF522 /* gtest.framework */; };
|
||||
408BEC431046D7B300DEF522 /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 408BEC421046D7B300DEF522 /* libgtest_main.a */; };
|
||||
4024D188113D7D7800C7059E /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4024D185113D7D5500C7059E /* libgtest.a */; };
|
||||
4024D189113D7D7A00C7059E /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4024D183113D7D5500C7059E /* libgtest_main.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -23,6 +50,27 @@
|
||||
remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
|
||||
remoteInfo = gTestExample;
|
||||
};
|
||||
4024D165113D7D3100C7059E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 3B07BDE90E3F3F9E00647869;
|
||||
remoteInfo = WidgetFrameworkTest;
|
||||
};
|
||||
4024D1EC113D840900C7059E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
|
||||
remoteInfo = WidgetFramework;
|
||||
};
|
||||
4024D1EE113D840D00C7059E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 4024D162113D7D2400C7059E;
|
||||
remoteInfo = Test;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -30,8 +78,9 @@
|
||||
3B7EB1230E5AEE3500C7F239 /* widget.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = widget.cc; sourceTree = "<group>"; };
|
||||
3B7EB1240E5AEE3500C7F239 /* widget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = widget.h; sourceTree = "<group>"; };
|
||||
3B7EB1270E5AEE4600C7F239 /* widget_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = widget_test.cc; sourceTree = "<group>"; };
|
||||
408BEC271046D72200DEF522 /* gtest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = gtest.framework; path = /Library/Frameworks/gtest.framework; sourceTree = "<absolute>"; };
|
||||
408BEC421046D7B300DEF522 /* libgtest_main.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgtest_main.a; path = /Library/Frameworks/gtest.framework/Versions/A/Resources/libgtest_main.a; sourceTree = "<absolute>"; };
|
||||
4024D183113D7D5500C7059E /* libgtest_main.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgtest_main.a; path = /usr/local/lib/libgtest_main.a; sourceTree = "<absolute>"; };
|
||||
4024D185113D7D5500C7059E /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgtest.a; path = /usr/local/lib/libgtest.a; sourceTree = "<absolute>"; };
|
||||
4024D1E2113D838200C7059E /* runtests.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = runtests.sh; sourceTree = "<group>"; };
|
||||
8D07F2C70486CC7A007CD1D0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
8D07F2C80486CC7A007CD1D0 /* Widget.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Widget.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -41,9 +90,9 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4024D189113D7D7A00C7059E /* libgtest_main.a in Frameworks */,
|
||||
4024D188113D7D7800C7059E /* libgtest.a in Frameworks */,
|
||||
3B7EB1480E5AF3B400C7F239 /* Widget.framework in Frameworks */,
|
||||
408BEC281046D72200DEF522 /* gtest.framework in Frameworks */,
|
||||
408BEC431046D7B300DEF522 /* libgtest_main.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -69,6 +118,7 @@
|
||||
0867D691FE84028FC02AAC07 /* gTestExample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4024D1E1113D836C00C7059E /* Scripts */,
|
||||
08FB77ACFE841707C02AAC07 /* Source */,
|
||||
089C1665FE841158C02AAC07 /* Resources */,
|
||||
3B07BE350E4094E400647869 /* Test */,
|
||||
@@ -81,8 +131,8 @@
|
||||
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
408BEC421046D7B300DEF522 /* libgtest_main.a */,
|
||||
408BEC271046D72200DEF522 /* gtest.framework */,
|
||||
4024D183113D7D5500C7059E /* libgtest_main.a */,
|
||||
4024D185113D7D5500C7059E /* libgtest.a */,
|
||||
);
|
||||
name = "External Frameworks and Libraries";
|
||||
sourceTree = "<group>";
|
||||
@@ -112,6 +162,14 @@
|
||||
name = Test;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4024D1E1113D836C00C7059E /* Scripts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4024D1E2113D838200C7059E /* runtests.sh */,
|
||||
);
|
||||
name = Scripts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@@ -178,6 +236,8 @@
|
||||
targets = (
|
||||
8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */,
|
||||
3B07BDE90E3F3F9E00647869 /* WidgetFrameworkTest */,
|
||||
4024D162113D7D2400C7059E /* Test */,
|
||||
4024D1E9113D83FF00C7059E /* TestAndBuild */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -202,6 +262,22 @@
|
||||
};
|
||||
/* End PBXRezBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
4024D161113D7D2400C7059E /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/bash $SRCROOT/runtests.sh $BUILT_PRODUCTS_DIR/WidgetFrameworkTest\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
3B07BDE70E3F3F9E00647869 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
@@ -227,6 +303,21 @@
|
||||
target = 8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */;
|
||||
targetProxy = 3B07BDF00E3F3FAE00647869 /* PBXContainerItemProxy */;
|
||||
};
|
||||
4024D166113D7D3100C7059E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 3B07BDE90E3F3F9E00647869 /* WidgetFrameworkTest */;
|
||||
targetProxy = 4024D165113D7D3100C7059E /* PBXContainerItemProxy */;
|
||||
};
|
||||
4024D1ED113D840900C7059E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */;
|
||||
targetProxy = 4024D1EC113D840900C7059E /* PBXContainerItemProxy */;
|
||||
};
|
||||
4024D1EF113D840D00C7059E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 4024D162113D7D2400C7059E /* Test */;
|
||||
targetProxy = 4024D1EE113D840D00C7059E /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
@@ -244,6 +335,34 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
4024D163113D7D2400C7059E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = TestAndBuild;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4024D164113D7D2400C7059E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = TestAndBuild;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
4024D1EA113D83FF00C7059E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = TestAndBuild;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4024D1EB113D83FF00C7059E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = TestAndBuild;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
4FADC24308B4156D00ABE55E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -296,6 +415,24 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
4024D169113D7D4600C7059E /* Build configuration list for PBXAggregateTarget "Test" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4024D163113D7D2400C7059E /* Debug */,
|
||||
4024D164113D7D2400C7059E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
4024D1F0113D842B00C7059E /* Build configuration list for PBXAggregateTarget "TestAndBuild" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4024D1EA113D83FF00C7059E /* Debug */,
|
||||
4024D1EB113D83FF00C7059E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "WidgetFramework" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# -*- Python -*-
|
||||
# Copyright 2008 Google Inc. All Rights Reserved.
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2008, 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
|
||||
@@ -26,36 +28,35 @@
|
||||
# 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: joi@google.com (Joi Sigurdsson)
|
||||
# Author: vladl@google.com (Vlad Losev)
|
||||
#
|
||||
# Base build file for Google Test Tests.
|
||||
#
|
||||
# Usage:
|
||||
# cd to the directory with this file, then
|
||||
# ./scons.py [OPTIONS]
|
||||
#
|
||||
# where frequently used command-line options include:
|
||||
# -h print usage help.
|
||||
# BUILD=all build all build types.
|
||||
# BUILD=win-opt build the given build type.
|
||||
|
||||
EnsurePythonVersion(2, 3)
|
||||
# Executes the samples and tests for the Google Test Framework.
|
||||
|
||||
sconstruct_helper = SConscript('SConstruct.common')
|
||||
# Help the dynamic linker find the path to the libraries.
|
||||
export DYLD_FRAMEWORK_PATH=$BUILT_PRODUCTS_DIR
|
||||
export DYLD_LIBRARY_PATH=$BUILT_PRODUCTS_DIR
|
||||
|
||||
sconstruct_helper.Initialize(build_root_path='..',
|
||||
support_multiple_win_builds=False)
|
||||
# Create some executables.
|
||||
test_executables=$@
|
||||
|
||||
win_base = sconstruct_helper.MakeWinBaseEnvironment()
|
||||
# Now execute each one in turn keeping track of how many succeeded and failed.
|
||||
succeeded=0
|
||||
failed=0
|
||||
failed_list=()
|
||||
for test in ${test_executables[*]}; do
|
||||
"$test"
|
||||
result=$?
|
||||
if [ $result -eq 0 ]; then
|
||||
succeeded=$(( $succeeded + 1 ))
|
||||
else
|
||||
failed=$(( failed + 1 ))
|
||||
failed_list="$failed_list $test"
|
||||
fi
|
||||
done
|
||||
|
||||
if win_base.get('MSVS_VERSION', None) == '7.1':
|
||||
sconstruct_helper.AllowVc71StlWithoutExceptions(win_base)
|
||||
|
||||
sconstruct_helper.MakeWinDebugEnvironment(win_base, 'win-dbg')
|
||||
sconstruct_helper.MakeWinOptimizedEnvironment(win_base, 'win-opt')
|
||||
|
||||
sconstruct_helper.ConfigureGccEnvironments()
|
||||
|
||||
sconstruct_helper.BuildSelectedEnvironments()
|
||||
# Report the successes and failures to the console.
|
||||
echo "Tests complete with $succeeded successes and $failed failures."
|
||||
if [ $failed -ne 0 ]; then
|
||||
echo "The following tests failed:"
|
||||
echo $failed_list
|
||||
fi
|
||||
exit $failed
|
||||
@@ -27,7 +27,7 @@
|
||||
// (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: preston.jackson@gmail.com (Preston Jackson)
|
||||
// Author: preston.a.jackson@gmail.com (Preston Jackson)
|
||||
//
|
||||
// Google Test - FrameworkSample
|
||||
// widget.cc
|
||||
@@ -42,7 +42,7 @@ Widget::Widget(int number, const std::string& name)
|
||||
name_(name) {}
|
||||
|
||||
Widget::~Widget() {}
|
||||
|
||||
|
||||
float Widget::GetFloatValue() const {
|
||||
return number_;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ float Widget::GetFloatValue() const {
|
||||
int Widget::GetIntValue() const {
|
||||
return static_cast<int>(number_);
|
||||
}
|
||||
|
||||
|
||||
std::string Widget::GetStringValue() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
// (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: preston.jackson@gmail.com (Preston Jackson)
|
||||
// Author: preston.a.jackson@gmail.com (Preston Jackson)
|
||||
//
|
||||
// Google Test - FrameworkSample
|
||||
// widget.h
|
||||
@@ -43,15 +43,15 @@ class Widget {
|
||||
public:
|
||||
Widget(int number, const std::string& name);
|
||||
~Widget();
|
||||
|
||||
|
||||
// Public accessors to number data
|
||||
float GetFloatValue() const;
|
||||
int GetIntValue() const;
|
||||
|
||||
|
||||
// Public accessors to the string data
|
||||
std::string GetStringValue() const;
|
||||
void GetCharPtrValue(char* buffer, size_t max_size) const;
|
||||
|
||||
|
||||
private:
|
||||
// Data members
|
||||
float number_;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
// (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: preston.jackson@gmail.com (Preston Jackson)
|
||||
// Author: preston.a.jackson@gmail.com (Preston Jackson)
|
||||
//
|
||||
// Google Test - FrameworkSample
|
||||
// widget_test.cc
|
||||
@@ -58,7 +58,7 @@ TEST(WidgetInitializerTest, TestConversion) {
|
||||
char buffer[max_size];
|
||||
widget.GetCharPtrValue(buffer, max_size);
|
||||
EXPECT_STREQ("name", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the Google Test main that is linked into the framework. It does something
|
||||
// like this:
|
||||
|
||||
@@ -1,4 +1,33 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2008, 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.
|
||||
|
||||
# Executes the samples and tests for the Google Test Framework.
|
||||
|
||||
|
||||
@@ -1,4 +1,33 @@
|
||||
#/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2008, 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.
|
||||
|
||||
"""A script to prepare version informtion for use the gtest Info.plist file.
|
||||
|
||||
@@ -13,7 +42,7 @@
|
||||
1. The AC_INIT macro will be contained within the first 1024 characters
|
||||
of configure.ac
|
||||
2. The version string will be 3 integers separated by periods and will be
|
||||
surrounded by squre brackets, "[" and "]" (e.g. [1.0.1]). The first
|
||||
surrounded by squre brackets, "[" and "]" (e.g. [1.0.1]). The first
|
||||
segment represents the major version, the second represents the minor
|
||||
version and the third represents the fix version.
|
||||
3. No ")" character exists between the opening "(" and closing ")" of
|
||||
@@ -25,7 +54,7 @@ import re
|
||||
|
||||
# Read the command line argument (the output directory for Version.h)
|
||||
if (len(sys.argv) < 3):
|
||||
print "Usage: /usr/bin/python versiongenerate.py input_dir output_dir"
|
||||
print "Usage: versiongenerate.py input_dir output_dir"
|
||||
sys.exit(1)
|
||||
else:
|
||||
input_dir = sys.argv[1]
|
||||
|
||||
Reference in New Issue
Block a user