зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset ee89101cd0e4 (bug 1743993) for xpcshel failures on test_httpssvc_retry_with_ech.js UPGRADE_NSS_RELEASE
This commit is contained in:
Родитель
210b2e543f
Коммит
e74a8e2d1d
|
@ -9,7 +9,7 @@ system_lib_option("--with-system-nss", help="Use system NSS")
|
|||
imply_option("--with-system-nspr", True, when="--with-system-nss")
|
||||
|
||||
nss_pkg = pkg_check_modules(
|
||||
"NSS", "nss >= 3.74", when="--with-system-nss", config=False
|
||||
"NSS", "nss >= 3.73", when="--with-system-nss", config=False
|
||||
)
|
||||
|
||||
set_config("MOZ_SYSTEM_NSS", True, when="--with-system-nss")
|
||||
|
|
|
@ -1 +1 @@
|
|||
d41c0fcdcf85
|
||||
7d4f221b1fff
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
1 function with some indirect sub-type change:
|
||||
|
||||
[C]'function SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc*, SSLExtensionType, PRBool*)' at sslreveal.c:72:1 has some indirect sub-type changes:
|
||||
parameter 2 of type 'typedef SSLExtensionType' has sub-type changes:
|
||||
underlying type 'enum __anonymous_enum__' at sslt.h:525:1 changed:
|
||||
type size hasn't changed
|
||||
1 enumerator deletion:
|
||||
'__anonymous_enum__::ssl_tls13_ech_is_inner_xtn' value '55817'
|
||||
|
||||
1 enumerator change:
|
||||
'__anonymous_enum__::ssl_tls13_encrypted_client_hello_xtn' from value '65034' to '65037' at sslt.h:525:1
|
||||
|
||||
|
||||
|
|
@ -1 +1 @@
|
|||
NSS_3_73_BRANCH
|
||||
NSS_3_72_BRANCH
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
release-1.10.0
|
||||
703bd9caab50b139428cea1aaff9974ebee5742e
|
||||
release-1.11.0
|
||||
e2239ee6043f73722e7aa812a459f54a28552929
|
||||
|
|
|
@ -53,7 +53,7 @@ else()
|
|||
cmake_policy(SET CMP0048 NEW)
|
||||
project(gtest VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C)
|
||||
endif()
|
||||
cmake_minimum_required(VERSION 2.6.4)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
if (POLICY CMP0063) # Visibility
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
@ -92,10 +92,13 @@ include(cmake/internal_utils.cmake)
|
|||
|
||||
config_compiler_and_linker() # Defined in internal_utils.cmake.
|
||||
|
||||
# Needed to set the namespace for both the export targets and the
|
||||
# alias libraries
|
||||
set(cmake_package_name GTest CACHE INTERNAL "")
|
||||
|
||||
# Create the CMake package file descriptors.
|
||||
if (INSTALL_GTEST)
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(cmake_package_name GTest)
|
||||
set(targets_export_name ${cmake_package_name}Targets CACHE INTERNAL "")
|
||||
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated" CACHE INTERNAL "")
|
||||
set(cmake_files_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${cmake_package_name}")
|
||||
|
@ -126,7 +129,9 @@ include_directories(${gtest_build_include_dirs})
|
|||
# are used for other targets, to ensure that gtest can be compiled by a user
|
||||
# aggressive about warnings.
|
||||
cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
|
||||
set_target_properties(gtest PROPERTIES VERSION ${GOOGLETEST_VERSION})
|
||||
cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
|
||||
set_target_properties(gtest_main PROPERTIES VERSION ${GOOGLETEST_VERSION})
|
||||
# If the CMake version supports it, attach header directory information
|
||||
# to the targets for when we are part of a parent build (ie being pulled
|
||||
# in via add_subdirectory() rather than being a standalone build).
|
||||
|
@ -182,20 +187,6 @@ if (gtest_build_tests)
|
|||
# 'make test' or ctest.
|
||||
enable_testing()
|
||||
|
||||
if (WIN32)
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/RunTest.ps1"
|
||||
CONTENT
|
||||
"$project_bin = \"${CMAKE_BINARY_DIR}/bin/$<CONFIG>\"
|
||||
$env:Path = \"$project_bin;$env:Path\"
|
||||
& $args")
|
||||
elseif (MINGW OR CYGWIN)
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/RunTest.ps1"
|
||||
CONTENT
|
||||
"$project_bin = (cygpath --windows ${CMAKE_BINARY_DIR}/bin)
|
||||
$env:Path = \"$project_bin;$env:Path\"
|
||||
& $args")
|
||||
endif()
|
||||
|
||||
############################################################
|
||||
# C++ tests built with standard compiler flags.
|
||||
|
||||
|
@ -266,6 +257,7 @@ $env:Path = \"$project_bin;$env:Path\"
|
|||
cxx_executable(googletest-break-on-failure-unittest_ test gtest)
|
||||
py_test(googletest-break-on-failure-unittest)
|
||||
|
||||
py_test(gtest_skip_check_output_test)
|
||||
py_test(gtest_skip_environment_check_output_test)
|
||||
|
||||
# Visual Studio .NET 2003 does not support STL with exceptions disabled.
|
||||
|
@ -317,6 +309,9 @@ $env:Path = \"$project_bin;$env:Path\"
|
|||
cxx_executable(googletest-uninitialized-test_ test gtest)
|
||||
py_test(googletest-uninitialized-test)
|
||||
|
||||
cxx_executable(gtest_list_output_unittest_ test gtest)
|
||||
py_test(gtest_list_output_unittest)
|
||||
|
||||
cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
|
||||
cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
|
||||
py_test(gtest_xml_outfiles_test)
|
||||
|
|
|
@ -5,33 +5,59 @@
|
|||
|
||||
Ajay Joshi <jaj@google.com>
|
||||
Balázs Dán <balazs.dan@gmail.com>
|
||||
Benoit Sigoure <tsuna@google.com>
|
||||
Bharat Mediratta <bharat@menalto.com>
|
||||
Bogdan Piloca <boo@google.com>
|
||||
Chandler Carruth <chandlerc@google.com>
|
||||
Chris Prince <cprince@google.com>
|
||||
Chris Taylor <taylorc@google.com>
|
||||
Dan Egnor <egnor@google.com>
|
||||
Dave MacLachlan <dmaclach@gmail.com>
|
||||
David Anderson <danderson@google.com>
|
||||
Dean Sturtevant
|
||||
Eric Roman <eroman@chromium.org>
|
||||
Gene Volovich <gv@cite.com>
|
||||
Hady Zalek <hady.zalek@gmail.com>
|
||||
Hal Burch <gmock@hburch.com>
|
||||
Jeffrey Yasskin <jyasskin@google.com>
|
||||
Jim Keller <jimkeller@google.com>
|
||||
Joe Walnes <joe@truemesh.com>
|
||||
Jon Wray <jwray@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>
|
||||
Kostya Serebryany <kcc@google.com>
|
||||
Krystian Kuzniarek <krystian.kuzniarek@gmail.com>
|
||||
Lev Makhlis
|
||||
Manuel Klimek <klimek@google.com>
|
||||
Mario Tanev <radix@google.com>
|
||||
Mark Paskin
|
||||
Markus Heule <markus.heule@gmail.com>
|
||||
Matthew Simmons <simmonmt@acm.org>
|
||||
Mika Raento <mikie@iki.fi>
|
||||
Mike Bland <mbland@google.com>
|
||||
Miklós Fazekas <mfazekas@szemafor.com>
|
||||
Neal Norwitz <nnorwitz@gmail.com>
|
||||
Nermin Ozkiranartli <nermin@google.com>
|
||||
Owen Carlsen <ocarlsen@google.com>
|
||||
Paneendra Ba <paneendra@google.com>
|
||||
Pasi Valminen <pasi.valminen@gmail.com>
|
||||
Patrick Hanna <phanna@google.com>
|
||||
Patrick Riley <pfr@google.com>
|
||||
Paul Menage <menage@google.com>
|
||||
Peter Kaminski <piotrk@google.com>
|
||||
Piotr Kaminski <piotrk@google.com>
|
||||
Preston Jackson <preston.a.jackson@gmail.com>
|
||||
Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
|
||||
Russ Cox <rsc@google.com>
|
||||
Russ Rufer <russ@pentad.com>
|
||||
Sean Mcafee <eefacm@gmail.com>
|
||||
Sigurður Ásgeirsson <siggi@google.com>
|
||||
Sverre Sundsdal <sundsdal@gmail.com>
|
||||
Takeshi Yoshino <tyoshino@google.com>
|
||||
Tracy Bialik <tracy@pentad.com>
|
||||
Vadim Berman <vadimb@google.com>
|
||||
Vlad Losev <vladl@google.com>
|
||||
Wolfgang Klier <wklier@google.com>
|
||||
Zhanyong Wan <wan@google.com>
|
||||
|
|
|
@ -2,39 +2,51 @@
|
|||
|
||||
#### Setup
|
||||
|
||||
To build Google Test and your tests that use it, you need to tell your build
|
||||
To build GoogleTest 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.
|
||||
|
||||
### Build with CMake
|
||||
|
||||
Google Test comes with a CMake build script (
|
||||
[CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt))
|
||||
GoogleTest comes with a CMake build script
|
||||
([CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt))
|
||||
that can be used on a wide range of platforms ("C" stands for cross-platform.).
|
||||
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. You can either build Google Test as a
|
||||
the compiler environment of your choice. You can either build GoogleTest as a
|
||||
standalone project or it can be incorporated into an existing CMake build for
|
||||
another project.
|
||||
|
||||
#### Standalone CMake Project
|
||||
|
||||
When building Google Test as a standalone project, 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
|
||||
When building GoogleTest as a standalone project, the typical workflow starts
|
||||
with
|
||||
|
||||
cmake -Dgtest_build_samples=ON ${GTEST_DIR}
|
||||
```
|
||||
git clone https://github.com/google/googletest.git -b release-1.10.0
|
||||
cd googletest # Main directory of the cloned repository.
|
||||
mkdir build # Create a directory to hold the build output.
|
||||
cd build
|
||||
cmake .. # Generate native build scripts for GoogleTest.
|
||||
```
|
||||
|
||||
The above command also includes GoogleMock by default. And so, if you want to
|
||||
build only GoogleTest, you should replace the last command with
|
||||
|
||||
```
|
||||
cmake .. -DBUILD_GMOCK=OFF
|
||||
```
|
||||
|
||||
If you are on a \*nix system, you should now see a Makefile in the current
|
||||
directory. Just type 'make' to build gtest.
|
||||
directory. Just type `make` to build GoogleTest. And then you can simply install
|
||||
GoogleTest if you are a system administrator.
|
||||
|
||||
```
|
||||
make
|
||||
sudo make install # Install in /usr/local/ by default
|
||||
```
|
||||
|
||||
If you use Windows and have Visual Studio installed, a `gtest.sln` file and
|
||||
several `.vcproj` files will be created. You can then build them using Visual
|
||||
|
@ -44,13 +56,19 @@ On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated.
|
|||
|
||||
#### Incorporating Into An Existing CMake Project
|
||||
|
||||
If you want to use gtest in a project which already uses CMake, then a more
|
||||
robust and flexible approach is to build gtest as part of that project directly.
|
||||
This is done by making the GoogleTest source code available to the main build
|
||||
and adding it using CMake's `add_subdirectory()` command. This has the
|
||||
significant advantage that the same compiler and linker settings are used
|
||||
between gtest and the rest of your project, so issues associated with using
|
||||
incompatible libraries (eg debug/release), etc. are avoided. This is
|
||||
If you want to use GoogleTest in a project which already uses CMake, the easiest
|
||||
way is to get installed libraries and headers.
|
||||
|
||||
* Import GoogleTest by using `find_package` (or `pkg_check_modules`). For
|
||||
example, if `find_package(GTest CONFIG REQUIRED)` succeeds, you can use the
|
||||
libraries as `GTest::gtest`, `GTest::gmock`.
|
||||
|
||||
And a more robust and flexible approach is to build GoogleTest as part of that
|
||||
project directly. This is done by making the GoogleTest source code available to
|
||||
the main build and adding it using CMake's `add_subdirectory()` command. This
|
||||
has the significant advantage that the same compiler and linker settings are
|
||||
used between GoogleTest and the rest of your project, so issues associated with
|
||||
using incompatible libraries (eg debug/release), etc. are avoided. This is
|
||||
particularly useful on Windows. Making GoogleTest's source code available to the
|
||||
main build can be done a few different ways:
|
||||
|
||||
|
@ -64,68 +82,23 @@ main build can be done a few different ways:
|
|||
possible or appropriate. Git submodules, for example, have their own set of
|
||||
advantages and drawbacks.
|
||||
* Use CMake to download GoogleTest as part of the build's configure step. This
|
||||
is just a little more complex, but doesn't have the limitations of the other
|
||||
methods.
|
||||
approach doesn't have the limitations of the other methods.
|
||||
|
||||
The last of the above methods is implemented with a small piece of CMake code in
|
||||
a separate file (e.g. `CMakeLists.txt.in`) which is copied to the build area and
|
||||
then invoked as a sub-build _during the CMake stage_. That directory is then
|
||||
pulled into the main build with `add_subdirectory()`. For example:
|
||||
The last of the above methods is implemented with a small piece of CMake code
|
||||
that downloads and pulls the GoogleTest code into the main build.
|
||||
|
||||
New file `CMakeLists.txt.in`:
|
||||
Just add to your `CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
project(googletest-download NONE)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG master
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
# Specify the commit you depend on and update it regularly.
|
||||
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
|
||||
)
|
||||
```
|
||||
|
||||
Existing build's `CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
# Download and unpack googletest at configure time
|
||||
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
|
||||
if(result)
|
||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
|
||||
if(result)
|
||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
# Prevent overriding the parent project's compiler/linker
|
||||
# settings on Windows
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Add googletest directly to our build. This defines
|
||||
# the gtest and gtest_main targets.
|
||||
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
|
||||
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
|
||||
EXCLUDE_FROM_ALL)
|
||||
|
||||
# The gtest/gtest_main targets carry header search path
|
||||
# dependencies automatically when using CMake 2.8.11 or
|
||||
# later. Otherwise we have to add them here ourselves.
|
||||
if (CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
include_directories("${gtest_SOURCE_DIR}/include")
|
||||
endif()
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# Now simply link against gtest or gtest_main as needed. Eg
|
||||
add_executable(example example.cpp)
|
||||
|
@ -133,20 +106,18 @@ target_link_libraries(example gtest_main)
|
|||
add_test(NAME example_test COMMAND example)
|
||||
```
|
||||
|
||||
Note that this approach requires CMake 2.8.2 or later due to its use of the
|
||||
`ExternalProject_Add()` command. The above technique is discussed in more detail
|
||||
in [this separate article](http://crascit.com/2015/07/25/cmake-gtest/) which
|
||||
also contains a link to a fully generalized implementation of the technique.
|
||||
Note that this approach requires CMake 3.14 or later due to its use of the
|
||||
`FetchContent_MakeAvailable()` command.
|
||||
|
||||
##### Visual Studio Dynamic vs Static Runtimes
|
||||
|
||||
By default, new Visual Studio projects link the C runtimes dynamically but
|
||||
Google Test links them statically. This will generate an error that looks
|
||||
GoogleTest links them statically. This will generate an error that looks
|
||||
something like the following: gtest.lib(gtest-all.obj) : error LNK2038: mismatch
|
||||
detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value
|
||||
'MDd_DynamicDebug' in main.obj
|
||||
|
||||
Google Test already has a CMake option for this: `gtest_force_shared_crt`
|
||||
GoogleTest already has a CMake option for this: `gtest_force_shared_crt`
|
||||
|
||||
Enabling this option will make gtest link the runtimes dynamically too, and
|
||||
match the project in which it is included.
|
||||
|
@ -154,17 +125,17 @@ match the project in which it is included.
|
|||
#### C++ Standard Version
|
||||
|
||||
An environment that supports C++11 is required in order to successfully build
|
||||
Google Test. One way to ensure this is to specify the standard in the top-level
|
||||
GoogleTest. One way to ensure this is to specify the standard in the top-level
|
||||
project, for example by using the `set(CMAKE_CXX_STANDARD 11)` command. If this
|
||||
is not feasible, for example in a C project using Google Test for validation,
|
||||
is not feasible, for example in a C project using GoogleTest for validation,
|
||||
then it can be specified by adding it to the options for cmake via the
|
||||
`DCMAKE_CXX_FLAGS` option.
|
||||
|
||||
### Tweaking Google Test
|
||||
### Tweaking GoogleTest
|
||||
|
||||
Google Test can be used in diverse environments. The default configuration may
|
||||
GoogleTest 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
|
||||
you can easily tweak GoogleTest 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.
|
||||
|
||||
|
@ -173,12 +144,12 @@ We list the most frequently used macros below. For a complete list, see file
|
|||
|
||||
### Multi-threaded Tests
|
||||
|
||||
Google Test is thread-safe where the pthread library is available. After
|
||||
GoogleTest 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
|
||||
If GoogleTest doesn't correctly detect whether pthread is available in your
|
||||
environment, you can force it with
|
||||
|
||||
-DGTEST_HAS_PTHREAD=1
|
||||
|
@ -187,16 +158,16 @@ or
|
|||
|
||||
-DGTEST_HAS_PTHREAD=0
|
||||
|
||||
When Google Test uses pthread, you may need to add flags to your compiler and/or
|
||||
When GoogleTest 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.
|
||||
CMake 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
|
||||
GoogleTest is compact, so most users can build and link it as a static library
|
||||
for the simplicity. You can choose to use GoogleTest as a shared library (known
|
||||
as a DLL on Windows) if you prefer.
|
||||
|
||||
To compile *gtest* as a shared library, add
|
||||
|
@ -216,22 +187,22 @@ Note: while the above steps aren't technically necessary today when using some
|
|||
compilers (e.g. GCC), they may become necessary in the future, if we decide to
|
||||
improve the speed of loading the library (see
|
||||
<http://gcc.gnu.org/wiki/Visibility> for details). Therefore you are recommended
|
||||
to always add the above flags when using Google Test as a shared library.
|
||||
Otherwise a future release of Google Test may break your build script.
|
||||
to always add the above flags when using GoogleTest as a shared library.
|
||||
Otherwise a future release of GoogleTest may break your build script.
|
||||
|
||||
### 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
|
||||
GoogleTest macro clashes with another library, you can force GoogleTest to
|
||||
rename its macro to avoid the conflict.
|
||||
|
||||
Specifically, if both Google Test and some other code define macro FOO, you can
|
||||
Specifically, if both GoogleTest 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 the compiler flags to tell GoogleTest 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
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
prefix=${pcfiledir}/../..
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: gtest
|
||||
Description: GoogleTest (without main() function)
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/google/googletest
|
||||
Libs: -L${libdir} -lgtest @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
prefix=${pcfiledir}/../..
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: gtest_main
|
||||
Description: GoogleTest (with main() function)
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/google/googletest
|
||||
Requires: gtest
|
||||
Requires: gtest = @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lgtest_main @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@
|
||||
|
|
|
@ -72,7 +72,7 @@ macro(config_compiler_and_linker)
|
|||
if (MSVC)
|
||||
# Newlines inside flags variables break CMake's NMake generator.
|
||||
# TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
|
||||
set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J -Zi")
|
||||
set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J")
|
||||
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")
|
||||
|
@ -81,6 +81,8 @@ macro(config_compiler_and_linker)
|
|||
# Suppress "unreachable code" warning
|
||||
# http://stackoverflow.com/questions/3232669 explains the issue.
|
||||
set(cxx_base_flags "${cxx_base_flags} -wd4702")
|
||||
# Ensure MSVC treats source files as UTF-8 encoded.
|
||||
set(cxx_base_flags "${cxx_base_flags} -utf-8")
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(cxx_base_flags "-Wall -Wshadow -Werror -Wconversion")
|
||||
set(cxx_exception_flags "-fexceptions")
|
||||
|
@ -148,6 +150,7 @@ 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})
|
||||
add_library(${cmake_package_name}::${name} ALIAS ${name})
|
||||
set_target_properties(${name}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "${cxx_flags}")
|
||||
|
@ -188,6 +191,10 @@ function(cxx_library_with_type name type cxx_flags)
|
|||
endif()
|
||||
target_link_libraries(${name} PUBLIC ${threads_spec})
|
||||
endif()
|
||||
|
||||
if (NOT "${CMAKE_VERSION}" VERSION_LESS "3.8")
|
||||
target_compile_features(${name} PUBLIC cxx_std_11)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
########################################################################
|
||||
|
@ -240,7 +247,13 @@ function(cxx_executable name dir libs)
|
|||
endfunction()
|
||||
|
||||
# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
|
||||
find_package(PythonInterp)
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "3.12.0")
|
||||
find_package(PythonInterp)
|
||||
else()
|
||||
find_package(Python COMPONENTS Interpreter)
|
||||
set(PYTHONINTERP_FOUND ${Python_Interpreter_FOUND})
|
||||
set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})
|
||||
endif()
|
||||
|
||||
# cxx_test_with_flags(name cxx_flags libs srcs...)
|
||||
#
|
||||
|
@ -248,13 +261,7 @@ find_package(PythonInterp)
|
|||
# from the given source files with the given compiler flags.
|
||||
function(cxx_test_with_flags name cxx_flags libs)
|
||||
cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
|
||||
if (WIN32 OR MINGW)
|
||||
add_test(NAME ${name}
|
||||
COMMAND "powershell" "-Command" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/RunTest.ps1" "$<TARGET_FILE:${name}>")
|
||||
else()
|
||||
add_test(NAME ${name}
|
||||
COMMAND "$<TARGET_FILE:${name}>")
|
||||
endif()
|
||||
add_test(NAME ${name} COMMAND "$<TARGET_FILE:${name}>")
|
||||
endfunction()
|
||||
|
||||
# cxx_test(name libs srcs...)
|
||||
|
@ -278,45 +285,24 @@ function(py_test name)
|
|||
# Multi-configuration build generators as for Visual Studio save
|
||||
# output in a subdirectory of CMAKE_CURRENT_BINARY_DIR (Debug,
|
||||
# Release etc.), so we have to provide it here.
|
||||
if (WIN32 OR MINGW)
|
||||
add_test(NAME ${name}
|
||||
COMMAND powershell -Command ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/RunTest.ps1
|
||||
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
add_test(NAME ${name}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG> ${ARGN})
|
||||
else()
|
||||
add_test(NAME ${name}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG> ${ARGN})
|
||||
endif()
|
||||
else (CMAKE_CONFIGURATION_TYPES)
|
||||
# Single-configuration build generators like Makefile generators
|
||||
# don't have subdirs below CMAKE_CURRENT_BINARY_DIR.
|
||||
if (WIN32 OR MINGW)
|
||||
add_test(NAME ${name}
|
||||
COMMAND powershell -Command ${CMAKE_CURRENT_BINARY_DIR}/RunTest.ps1
|
||||
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR} ${ARGN})
|
||||
else()
|
||||
add_test(NAME ${name}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR} ${ARGN})
|
||||
endif()
|
||||
add_test(NAME ${name}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR} ${ARGN})
|
||||
endif (CMAKE_CONFIGURATION_TYPES)
|
||||
else()
|
||||
# ${CMAKE_CURRENT_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.
|
||||
if (WIN32 OR MINGW)
|
||||
add_test(NAME ${name}
|
||||
COMMAND powershell -Command ${CMAKE_CURRENT_BINARY_DIR}/RunTest.ps1
|
||||
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE} ${ARGN})
|
||||
else()
|
||||
add_test(NAME ${name}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE} ${ARGN})
|
||||
endif()
|
||||
add_test(NAME ${name}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE} ${ARGN})
|
||||
endif()
|
||||
endif(PYTHONINTERP_FOUND)
|
||||
endfunction()
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
## Using GoogleTest from various build systems
|
||||
|
||||
GoogleTest comes with pkg-config files that can be used to determine all
|
||||
necessary flags for compiling and linking to GoogleTest (and GoogleMock).
|
||||
Pkg-config is a standardised plain-text format containing
|
||||
|
||||
* the includedir (-I) path
|
||||
* necessary macro (-D) definitions
|
||||
* further required flags (-pthread)
|
||||
* the library (-L) path
|
||||
* the library (-l) to link to
|
||||
|
||||
All current build systems support pkg-config in one way or another. For all
|
||||
examples here we assume you want to compile the sample
|
||||
`samples/sample3_unittest.cc`.
|
||||
|
||||
### CMake
|
||||
|
||||
Using `pkg-config` in CMake is fairly easy:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
project(my_gtest_pkgconfig VERSION 0.0.1 LANGUAGES CXX)
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_search_module(GTEST REQUIRED gtest_main)
|
||||
|
||||
add_executable(testapp samples/sample3_unittest.cc)
|
||||
target_link_libraries(testapp ${GTEST_LDFLAGS})
|
||||
target_compile_options(testapp PUBLIC ${GTEST_CFLAGS})
|
||||
|
||||
include(CTest)
|
||||
add_test(first_and_only_test testapp)
|
||||
```
|
||||
|
||||
It is generally recommended that you use `target_compile_options` + `_CFLAGS`
|
||||
over `target_include_directories` + `_INCLUDE_DIRS` as the former includes not
|
||||
just -I flags (GoogleTest might require a macro indicating to internal headers
|
||||
that all libraries have been compiled with threading enabled. In addition,
|
||||
GoogleTest might also require `-pthread` in the compiling step, and as such
|
||||
splitting the pkg-config `Cflags` variable into include dirs and macros for
|
||||
`target_compile_definitions()` might still miss this). The same recommendation
|
||||
goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which happens
|
||||
to discard `-L` flags and `-pthread`.
|
||||
|
||||
### Autotools
|
||||
|
||||
Finding GoogleTest in Autoconf and using it from Automake is also fairly easy:
|
||||
|
||||
In your `configure.ac`:
|
||||
|
||||
```
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([my_gtest_pkgconfig], [0.0.1])
|
||||
AC_CONFIG_SRCDIR([samples/sample3_unittest.cc])
|
||||
AC_PROG_CXX
|
||||
|
||||
PKG_CHECK_MODULES([GTEST], [gtest_main])
|
||||
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
```
|
||||
|
||||
and in your `Makefile.am`:
|
||||
|
||||
```
|
||||
check_PROGRAMS = testapp
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
testapp_SOURCES = samples/sample3_unittest.cc
|
||||
testapp_CXXFLAGS = $(GTEST_CFLAGS)
|
||||
testapp_LDADD = $(GTEST_LIBS)
|
||||
```
|
||||
|
||||
### Meson
|
||||
|
||||
Meson natively uses pkgconfig to query dependencies:
|
||||
|
||||
```
|
||||
project('my_gtest_pkgconfig', 'cpp', version : '0.0.1')
|
||||
|
||||
gtest_dep = dependency('gtest_main')
|
||||
|
||||
testapp = executable(
|
||||
'testapp',
|
||||
files(['samples/sample3_unittest.cc']),
|
||||
dependencies : gtest_dep,
|
||||
install : false)
|
||||
|
||||
test('first_and_only_test', testapp)
|
||||
```
|
||||
|
||||
### Plain Makefiles
|
||||
|
||||
Since `pkg-config` is a small Unix command-line utility, it can be used in
|
||||
handwritten `Makefile`s too:
|
||||
|
||||
```makefile
|
||||
GTEST_CFLAGS = `pkg-config --cflags gtest_main`
|
||||
GTEST_LIBS = `pkg-config --libs gtest_main`
|
||||
|
||||
.PHONY: tests all
|
||||
|
||||
tests: all
|
||||
./testapp
|
||||
|
||||
all: testapp
|
||||
|
||||
testapp: testapp.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $< -o $@ $(GTEST_LIBS)
|
||||
|
||||
testapp.o: samples/sample3_unittest.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -c -o $@ $(GTEST_CFLAGS)
|
||||
```
|
||||
|
||||
### Help! pkg-config can't find GoogleTest!
|
||||
|
||||
Let's say you have a `CMakeLists.txt` along the lines of the one in this
|
||||
tutorial and you try to run `cmake`. It is very possible that you get a failure
|
||||
along the lines of:
|
||||
|
||||
```
|
||||
-- Checking for one of the modules 'gtest_main'
|
||||
CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message):
|
||||
None of the required 'gtest_main' found
|
||||
```
|
||||
|
||||
These failures are common if you installed GoogleTest yourself and have not
|
||||
sourced it from a distro or other package manager. If so, you need to tell
|
||||
pkg-config where it can find the `.pc` files containing the information. Say you
|
||||
installed GoogleTest to `/usr/local`, then it might be that the `.pc` files are
|
||||
installed under `/usr/local/lib64/pkgconfig`. If you set
|
||||
|
||||
```
|
||||
export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
|
||||
```
|
||||
|
||||
pkg-config will also try to look in `PKG_CONFIG_PATH` to find `gtest_main.pc`.
|
|
@ -0,0 +1,4 @@
|
|||
# Content Moved
|
||||
|
||||
We are working on updates to the GoogleTest documentation, which has moved to
|
||||
the top-level [docs](../../docs) directory.
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,753 +0,0 @@
|
|||
# Googletest FAQ
|
||||
|
||||
<!-- GOOGLETEST_CM0014 DO NOT DELETE -->
|
||||
|
||||
## Why should test suite names and test names not contain underscore?
|
||||
|
||||
Underscore (`_`) is special, as C++ reserves the following to be used by the
|
||||
compiler and the standard library:
|
||||
|
||||
1. any identifier that starts with an `_` followed by an upper-case letter, and
|
||||
2. any identifier that contains two consecutive underscores (i.e. `__`)
|
||||
*anywhere* in its name.
|
||||
|
||||
User code is *prohibited* from using such identifiers.
|
||||
|
||||
Now let's look at what this means for `TEST` and `TEST_F`.
|
||||
|
||||
Currently `TEST(TestSuiteName, TestName)` generates a class named
|
||||
`TestSuiteName_TestName_Test`. What happens if `TestSuiteName` or `TestName`
|
||||
contains `_`?
|
||||
|
||||
1. If `TestSuiteName` starts with an `_` followed by an upper-case letter (say,
|
||||
`_Foo`), we end up with `_Foo_TestName_Test`, which is reserved and thus
|
||||
invalid.
|
||||
2. If `TestSuiteName` ends with an `_` (say, `Foo_`), we get
|
||||
`Foo__TestName_Test`, which is invalid.
|
||||
3. If `TestName` starts with an `_` (say, `_Bar`), we get
|
||||
`TestSuiteName__Bar_Test`, which is invalid.
|
||||
4. If `TestName` ends with an `_` (say, `Bar_`), we get
|
||||
`TestSuiteName_Bar__Test`, which is invalid.
|
||||
|
||||
So clearly `TestSuiteName` and `TestName` cannot start or end with `_`
|
||||
(Actually, `TestSuiteName` can start with `_` -- as long as the `_` isn't
|
||||
followed by an upper-case letter. But that's getting complicated. So for
|
||||
simplicity we just say that it cannot start with `_`.).
|
||||
|
||||
It may seem fine for `TestSuiteName` and `TestName` to contain `_` in the
|
||||
middle. However, consider this:
|
||||
|
||||
```c++
|
||||
TEST(Time, Flies_Like_An_Arrow) { ... }
|
||||
TEST(Time_Flies, Like_An_Arrow) { ... }
|
||||
```
|
||||
|
||||
Now, the two `TEST`s will both generate the same class
|
||||
(`Time_Flies_Like_An_Arrow_Test`). That's not good.
|
||||
|
||||
So for simplicity, we just ask the users to avoid `_` in `TestSuiteName` and
|
||||
`TestName`. The rule is more constraining than necessary, but it's simple and
|
||||
easy to remember. It also gives googletest some wiggle room in case its
|
||||
implementation needs to change in the future.
|
||||
|
||||
If you violate the rule, there may not be immediate consequences, but your test
|
||||
may (just may) break with a new compiler (or a new version of the compiler you
|
||||
are using) or with a new version of googletest. Therefore it's best to follow
|
||||
the rule.
|
||||
|
||||
## Why does googletest support `EXPECT_EQ(NULL, ptr)` and `ASSERT_EQ(NULL, ptr)` but not `EXPECT_NE(NULL, ptr)` and `ASSERT_NE(NULL, ptr)`?
|
||||
|
||||
First of all you can use `EXPECT_NE(nullptr, ptr)` and `ASSERT_NE(nullptr,
|
||||
ptr)`. This is the preferred syntax in the style guide because nullptr does not
|
||||
have the type problems that NULL does. Which is why NULL does not work.
|
||||
|
||||
Due to some peculiarity of C++, it requires some non-trivial template meta
|
||||
programming tricks to support using `NULL` as an argument of the `EXPECT_XX()`
|
||||
and `ASSERT_XX()` macros. Therefore we only do it where it's most needed
|
||||
(otherwise we make the implementation of googletest harder to maintain and more
|
||||
error-prone than necessary).
|
||||
|
||||
The `EXPECT_EQ()` macro takes the *expected* value as its first argument and the
|
||||
*actual* value as the second. It's reasonable that someone wants to write
|
||||
`EXPECT_EQ(NULL, some_expression)`, and this indeed was requested several times.
|
||||
Therefore we implemented it.
|
||||
|
||||
The need for `EXPECT_NE(NULL, ptr)` isn't nearly as strong. When the assertion
|
||||
fails, you already know that `ptr` must be `NULL`, so it doesn't add any
|
||||
information to print `ptr` in this case. That means `EXPECT_TRUE(ptr != NULL)`
|
||||
works just as well.
|
||||
|
||||
If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'll have to
|
||||
support `EXPECT_NE(ptr, NULL)` as well, as unlike `EXPECT_EQ`, we don't have a
|
||||
convention on the order of the two arguments for `EXPECT_NE`. This means using
|
||||
the template meta programming tricks twice in the implementation, making it even
|
||||
harder to understand and maintain. We believe the benefit doesn't justify the
|
||||
cost.
|
||||
|
||||
Finally, with the growth of the gMock matcher library, we are encouraging people
|
||||
to use the unified `EXPECT_THAT(value, matcher)` syntax more often in tests. One
|
||||
significant advantage of the matcher approach is that matchers can be easily
|
||||
combined to form new matchers, while the `EXPECT_NE`, etc, macros cannot be
|
||||
easily combined. Therefore we want to invest more in the matchers than in the
|
||||
`EXPECT_XX()` macros.
|
||||
|
||||
## I need to test that different implementations of an interface satisfy some common requirements. Should I use typed tests or value-parameterized tests?
|
||||
|
||||
For testing various implementations of the same interface, either typed tests or
|
||||
value-parameterized tests can get it done. It's really up to you the user to
|
||||
decide which is more convenient for you, depending on your particular case. Some
|
||||
rough guidelines:
|
||||
|
||||
* Typed tests can be easier to write if instances of the different
|
||||
implementations can be created the same way, modulo the type. For example,
|
||||
if all these implementations have a public default constructor (such that
|
||||
you can write `new TypeParam`), or if their factory functions have the same
|
||||
form (e.g. `CreateInstance<TypeParam>()`).
|
||||
* Value-parameterized tests can be easier to write if you need different code
|
||||
patterns to create different implementations' instances, e.g. `new Foo` vs
|
||||
`new Bar(5)`. To accommodate for the differences, you can write factory
|
||||
function wrappers and pass these function pointers to the tests as their
|
||||
parameters.
|
||||
* When a typed test fails, the default output includes the name of the type,
|
||||
which can help you quickly identify which implementation is wrong.
|
||||
Value-parameterized tests only show the number of the failed iteration by
|
||||
default. You will need to define a function that returns the iteration name
|
||||
and pass it as the third parameter to INSTANTIATE_TEST_SUITE_P to have more
|
||||
useful output.
|
||||
* When using typed tests, you need to make sure you are testing against the
|
||||
interface type, not the concrete types (in other words, you want to make
|
||||
sure `implicit_cast<MyInterface*>(my_concrete_impl)` works, not just that
|
||||
`my_concrete_impl` works). It's less likely to make mistakes in this area
|
||||
when using value-parameterized tests.
|
||||
|
||||
I hope I didn't confuse you more. :-) If you don't mind, I'd suggest you to give
|
||||
both approaches a try. Practice is a much better way to grasp the subtle
|
||||
differences between the two tools. Once you have some concrete experience, you
|
||||
can much more easily decide which one to use the next time.
|
||||
|
||||
## I got some run-time errors about invalid proto descriptors when using `ProtocolMessageEquals`. Help!
|
||||
|
||||
**Note:** `ProtocolMessageEquals` and `ProtocolMessageEquiv` are *deprecated*
|
||||
now. Please use `EqualsProto`, etc instead.
|
||||
|
||||
`ProtocolMessageEquals` and `ProtocolMessageEquiv` were redefined recently and
|
||||
are now less tolerant of invalid protocol buffer definitions. In particular, if
|
||||
you have a `foo.proto` that doesn't fully qualify the type of a protocol message
|
||||
it references (e.g. `message<Bar>` where it should be `message<blah.Bar>`), you
|
||||
will now get run-time errors like:
|
||||
|
||||
```
|
||||
... descriptor.cc:...] Invalid proto descriptor for file "path/to/foo.proto":
|
||||
... descriptor.cc:...] blah.MyMessage.my_field: ".Bar" is not defined.
|
||||
```
|
||||
|
||||
If you see this, your `.proto` file is broken and needs to be fixed by making
|
||||
the types fully qualified. The new definition of `ProtocolMessageEquals` and
|
||||
`ProtocolMessageEquiv` just happen to reveal your bug.
|
||||
|
||||
## My death test modifies some state, but the change seems lost after the death test finishes. Why?
|
||||
|
||||
Death tests (`EXPECT_DEATH`, etc) are executed in a sub-process s.t. the
|
||||
expected crash won't kill the test program (i.e. the parent process). As a
|
||||
result, any in-memory side effects they incur are observable in their respective
|
||||
sub-processes, but not in the parent process. You can think of them as running
|
||||
in a parallel universe, more or less.
|
||||
|
||||
In particular, if you use mocking and the death test statement invokes some mock
|
||||
methods, the parent process will think the calls have never occurred. Therefore,
|
||||
you may want to move your `EXPECT_CALL` statements inside the `EXPECT_DEATH`
|
||||
macro.
|
||||
|
||||
## EXPECT_EQ(htonl(blah), blah_blah) generates weird compiler errors in opt mode. Is this a googletest bug?
|
||||
|
||||
Actually, the bug is in `htonl()`.
|
||||
|
||||
According to `'man htonl'`, `htonl()` is a *function*, which means it's valid to
|
||||
use `htonl` as a function pointer. However, in opt mode `htonl()` is defined as
|
||||
a *macro*, which breaks this usage.
|
||||
|
||||
Worse, the macro definition of `htonl()` uses a `gcc` extension and is *not*
|
||||
standard C++. That hacky implementation has some ad hoc limitations. In
|
||||
particular, it prevents you from writing `Foo<sizeof(htonl(x))>()`, where `Foo`
|
||||
is a template that has an integral argument.
|
||||
|
||||
The implementation of `EXPECT_EQ(a, b)` uses `sizeof(... a ...)` inside a
|
||||
template argument, and thus doesn't compile in opt mode when `a` contains a call
|
||||
to `htonl()`. It is difficult to make `EXPECT_EQ` bypass the `htonl()` bug, as
|
||||
the solution must work with different compilers on various platforms.
|
||||
|
||||
`htonl()` has some other problems as described in `//util/endian/endian.h`,
|
||||
which defines `ghtonl()` to replace it. `ghtonl()` does the same thing `htonl()`
|
||||
does, only without its problems. We suggest you to use `ghtonl()` instead of
|
||||
`htonl()`, both in your tests and production code.
|
||||
|
||||
`//util/endian/endian.h` also defines `ghtons()`, which solves similar problems
|
||||
in `htons()`.
|
||||
|
||||
Don't forget to add `//util/endian` to the list of dependencies in the `BUILD`
|
||||
file wherever `ghtonl()` and `ghtons()` are used. The library consists of a
|
||||
single header file and will not bloat your binary.
|
||||
|
||||
## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong?
|
||||
|
||||
If your class has a static data member:
|
||||
|
||||
```c++
|
||||
// foo.h
|
||||
class Foo {
|
||||
...
|
||||
static const int kBar = 100;
|
||||
};
|
||||
```
|
||||
|
||||
You also need to define it *outside* of the class body in `foo.cc`:
|
||||
|
||||
```c++
|
||||
const int Foo::kBar; // No initializer here.
|
||||
```
|
||||
|
||||
Otherwise your code is **invalid C++**, and may break in unexpected ways. In
|
||||
particular, using it in googletest comparison assertions (`EXPECT_EQ`, etc) will
|
||||
generate an "undefined reference" linker error. The fact that "it used to work"
|
||||
doesn't mean it's valid. It just means that you were lucky. :-)
|
||||
|
||||
## Can I derive a test fixture from another?
|
||||
|
||||
Yes.
|
||||
|
||||
Each test fixture has a corresponding and same named test suite. This means only
|
||||
one test suite can use a particular fixture. Sometimes, however, multiple test
|
||||
cases may want to use the same or slightly different fixtures. For example, you
|
||||
may want to make sure that all of a GUI library's test suites don't leak
|
||||
important system resources like fonts and brushes.
|
||||
|
||||
In googletest, you share a fixture among test suites by putting the shared logic
|
||||
in a base test fixture, then deriving from that base a separate fixture for each
|
||||
test suite that wants to use this common logic. You then use `TEST_F()` to write
|
||||
tests using each derived fixture.
|
||||
|
||||
Typically, your code looks like this:
|
||||
|
||||
```c++
|
||||
// Defines a base test fixture.
|
||||
class BaseTest : public ::testing::Test {
|
||||
protected:
|
||||
...
|
||||
};
|
||||
|
||||
// Derives a fixture FooTest from BaseTest.
|
||||
class FooTest : public BaseTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
BaseTest::SetUp(); // Sets up the base fixture first.
|
||||
... additional set-up work ...
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
... clean-up work for FooTest ...
|
||||
BaseTest::TearDown(); // Remember to tear down the base fixture
|
||||
// after cleaning up FooTest!
|
||||
}
|
||||
|
||||
... functions and variables for FooTest ...
|
||||
};
|
||||
|
||||
// Tests that use the fixture FooTest.
|
||||
TEST_F(FooTest, Bar) { ... }
|
||||
TEST_F(FooTest, Baz) { ... }
|
||||
|
||||
... additional fixtures derived from BaseTest ...
|
||||
```
|
||||
|
||||
If necessary, you can continue to derive test fixtures from a derived fixture.
|
||||
googletest has no limit on how deep the hierarchy can be.
|
||||
|
||||
For a complete example using derived test fixtures, see
|
||||
[sample5_unittest.cc](../samples/sample5_unittest.cc).
|
||||
|
||||
## My compiler complains "void value not ignored as it ought to be." What does this mean?
|
||||
|
||||
You're probably using an `ASSERT_*()` in a function that doesn't return `void`.
|
||||
`ASSERT_*()` can only be used in `void` functions, due to exceptions being
|
||||
disabled by our build system. Please see more details
|
||||
[here](advanced.md#assertion-placement).
|
||||
|
||||
## My death test hangs (or seg-faults). How do I fix it?
|
||||
|
||||
In googletest, death tests are run in a child process and the way they work is
|
||||
delicate. To write death tests you really need to understand how they work.
|
||||
Please make sure you have read [this](advanced.md#how-it-works).
|
||||
|
||||
In particular, death tests don't like having multiple threads in the parent
|
||||
process. So the first thing you can try is to eliminate creating threads outside
|
||||
of `EXPECT_DEATH()`. For example, you may want to use mocks or fake objects
|
||||
instead of real ones in your tests.
|
||||
|
||||
Sometimes this is impossible as some library you must use may be creating
|
||||
threads before `main()` is even reached. In this case, you can try to minimize
|
||||
the chance of conflicts by either moving as many activities as possible inside
|
||||
`EXPECT_DEATH()` (in the extreme case, you want to move everything inside), or
|
||||
leaving as few things as possible in it. Also, you can try to set the death test
|
||||
style to `"threadsafe"`, which is safer but slower, and see if it helps.
|
||||
|
||||
If you go with thread-safe death tests, remember that they rerun the test
|
||||
program from the beginning in the child process. Therefore make sure your
|
||||
program can run side-by-side with itself and is deterministic.
|
||||
|
||||
In the end, this boils down to good concurrent programming. You have to make
|
||||
sure that there is no race conditions or dead locks in your program. No silver
|
||||
bullet - sorry!
|
||||
|
||||
## Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()? {#CtorVsSetUp}
|
||||
|
||||
The first thing to remember is that googletest does **not** reuse the same test
|
||||
fixture object across multiple tests. For each `TEST_F`, googletest will create
|
||||
a **fresh** test fixture object, immediately call `SetUp()`, run the test body,
|
||||
call `TearDown()`, and then delete the test fixture object.
|
||||
|
||||
When you need to write per-test set-up and tear-down logic, you have the choice
|
||||
between using the test fixture constructor/destructor or `SetUp()/TearDown()`.
|
||||
The former is usually preferred, as it has the following benefits:
|
||||
|
||||
* By initializing a member variable in the constructor, we have the option to
|
||||
make it `const`, which helps prevent accidental changes to its value and
|
||||
makes the tests more obviously correct.
|
||||
* In case we need to subclass the test fixture class, the subclass'
|
||||
constructor is guaranteed to call the base class' constructor *first*, and
|
||||
the subclass' destructor is guaranteed to call the base class' destructor
|
||||
*afterward*. With `SetUp()/TearDown()`, a subclass may make the mistake of
|
||||
forgetting to call the base class' `SetUp()/TearDown()` or call them at the
|
||||
wrong time.
|
||||
|
||||
You may still want to use `SetUp()/TearDown()` in the following cases:
|
||||
|
||||
* C++ does not allow virtual function calls in constructors and destructors.
|
||||
You can call a method declared as virtual, but it will not use dynamic
|
||||
dispatch, it will use the definition from the class the constructor of which
|
||||
is currently executing. This is because calling a virtual method before the
|
||||
derived class constructor has a chance to run is very dangerous - the
|
||||
virtual method might operate on uninitialized data. Therefore, if you need
|
||||
to call a method that will be overridden in a derived class, you have to use
|
||||
`SetUp()/TearDown()`.
|
||||
* In the body of a constructor (or destructor), it's not possible to use the
|
||||
`ASSERT_xx` macros. Therefore, if the set-up operation could cause a fatal
|
||||
test failure that should prevent the test from running, it's necessary to
|
||||
use `abort` <!-- GOOGLETEST_CM0015 DO NOT DELETE --> and abort the whole test executable,
|
||||
or to use `SetUp()` instead of a constructor.
|
||||
* If the tear-down operation could throw an exception, you must use
|
||||
`TearDown()` as opposed to the destructor, as throwing in a destructor leads
|
||||
to undefined behavior and usually will kill your program right away. Note
|
||||
that many standard libraries (like STL) may throw when exceptions are
|
||||
enabled in the compiler. Therefore you should prefer `TearDown()` if you
|
||||
want to write portable tests that work with or without exceptions.
|
||||
* The googletest team is considering making the assertion macros throw on
|
||||
platforms where exceptions are enabled (e.g. Windows, Mac OS, and Linux
|
||||
client-side), which will eliminate the need for the user to propagate
|
||||
failures from a subroutine to its caller. Therefore, you shouldn't use
|
||||
googletest assertions in a destructor if your code could run on such a
|
||||
platform.
|
||||
|
||||
## The compiler complains "no matching function to call" when I use ASSERT_PRED*. How do I fix it?
|
||||
|
||||
If the predicate function you use in `ASSERT_PRED*` or `EXPECT_PRED*` is
|
||||
overloaded or a template, the compiler will have trouble figuring out which
|
||||
overloaded version it should use. `ASSERT_PRED_FORMAT*` and
|
||||
`EXPECT_PRED_FORMAT*` don't have this problem.
|
||||
|
||||
If you see this error, you might want to switch to
|
||||
`(ASSERT|EXPECT)_PRED_FORMAT*`, which will also give you a better failure
|
||||
message. If, however, that is not an option, you can resolve the problem by
|
||||
explicitly telling the compiler which version to pick.
|
||||
|
||||
For example, suppose you have
|
||||
|
||||
```c++
|
||||
bool IsPositive(int n) {
|
||||
return n > 0;
|
||||
}
|
||||
|
||||
bool IsPositive(double x) {
|
||||
return x > 0;
|
||||
}
|
||||
```
|
||||
|
||||
you will get a compiler error if you write
|
||||
|
||||
```c++
|
||||
EXPECT_PRED1(IsPositive, 5);
|
||||
```
|
||||
|
||||
However, this will work:
|
||||
|
||||
```c++
|
||||
EXPECT_PRED1(static_cast<bool (*)(int)>(IsPositive), 5);
|
||||
```
|
||||
|
||||
(The stuff inside the angled brackets for the `static_cast` operator is the type
|
||||
of the function pointer for the `int`-version of `IsPositive()`.)
|
||||
|
||||
As another example, when you have a template function
|
||||
|
||||
```c++
|
||||
template <typename T>
|
||||
bool IsNegative(T x) {
|
||||
return x < 0;
|
||||
}
|
||||
```
|
||||
|
||||
you can use it in a predicate assertion like this:
|
||||
|
||||
```c++
|
||||
ASSERT_PRED1(IsNegative<int>, -5);
|
||||
```
|
||||
|
||||
Things are more interesting if your template has more than one parameters. The
|
||||
following won't compile:
|
||||
|
||||
```c++
|
||||
ASSERT_PRED2(GreaterThan<int, int>, 5, 0);
|
||||
```
|
||||
|
||||
as the C++ pre-processor thinks you are giving `ASSERT_PRED2` 4 arguments, which
|
||||
is one more than expected. The workaround is to wrap the predicate function in
|
||||
parentheses:
|
||||
|
||||
```c++
|
||||
ASSERT_PRED2((GreaterThan<int, int>), 5, 0);
|
||||
```
|
||||
|
||||
## My compiler complains about "ignoring return value" when I call RUN_ALL_TESTS(). Why?
|
||||
|
||||
Some people had been ignoring the return value of `RUN_ALL_TESTS()`. That is,
|
||||
instead of
|
||||
|
||||
```c++
|
||||
return RUN_ALL_TESTS();
|
||||
```
|
||||
|
||||
they write
|
||||
|
||||
```c++
|
||||
RUN_ALL_TESTS();
|
||||
```
|
||||
|
||||
This is **wrong and dangerous**. The testing services needs to see the return
|
||||
value of `RUN_ALL_TESTS()` in order to determine if a test has passed. If your
|
||||
`main()` function ignores it, your test will be considered successful even if it
|
||||
has a googletest assertion failure. Very bad.
|
||||
|
||||
We have decided to fix this (thanks to Michael Chastain for the idea). Now, your
|
||||
code will no longer be able to ignore `RUN_ALL_TESTS()` when compiled with
|
||||
`gcc`. If you do so, you'll get a compiler error.
|
||||
|
||||
If you see the compiler complaining about you ignoring the return value of
|
||||
`RUN_ALL_TESTS()`, the fix is simple: just make sure its value is used as the
|
||||
return value of `main()`.
|
||||
|
||||
But how could we introduce a change that breaks existing tests? Well, in this
|
||||
case, the code was already broken in the first place, so we didn't break it. :-)
|
||||
|
||||
## My compiler complains that a constructor (or destructor) cannot return a value. What's going on?
|
||||
|
||||
Due to a peculiarity of C++, in order to support the syntax for streaming
|
||||
messages to an `ASSERT_*`, e.g.
|
||||
|
||||
```c++
|
||||
ASSERT_EQ(1, Foo()) << "blah blah" << foo;
|
||||
```
|
||||
|
||||
we had to give up using `ASSERT*` and `FAIL*` (but not `EXPECT*` and
|
||||
`ADD_FAILURE*`) in constructors and destructors. The workaround is to move the
|
||||
content of your constructor/destructor to a private void member function, or
|
||||
switch to `EXPECT_*()` if that works. This
|
||||
[section](advanced.md#assertion-placement) in the user's guide explains it.
|
||||
|
||||
## My SetUp() function is not called. Why?
|
||||
|
||||
C++ is case-sensitive. Did you spell it as `Setup()`?
|
||||
|
||||
Similarly, sometimes people spell `SetUpTestSuite()` as `SetupTestSuite()` and
|
||||
wonder why it's never called.
|
||||
|
||||
|
||||
## I have several test suites which share the same test fixture logic, do I have to define a new test fixture class for each of them? This seems pretty tedious.
|
||||
|
||||
You don't have to. Instead of
|
||||
|
||||
```c++
|
||||
class FooTest : public BaseTest {};
|
||||
|
||||
TEST_F(FooTest, Abc) { ... }
|
||||
TEST_F(FooTest, Def) { ... }
|
||||
|
||||
class BarTest : public BaseTest {};
|
||||
|
||||
TEST_F(BarTest, Abc) { ... }
|
||||
TEST_F(BarTest, Def) { ... }
|
||||
```
|
||||
|
||||
you can simply `typedef` the test fixtures:
|
||||
|
||||
```c++
|
||||
typedef BaseTest FooTest;
|
||||
|
||||
TEST_F(FooTest, Abc) { ... }
|
||||
TEST_F(FooTest, Def) { ... }
|
||||
|
||||
typedef BaseTest BarTest;
|
||||
|
||||
TEST_F(BarTest, Abc) { ... }
|
||||
TEST_F(BarTest, Def) { ... }
|
||||
```
|
||||
|
||||
## googletest output is buried in a whole bunch of LOG messages. What do I do?
|
||||
|
||||
The googletest output is meant to be a concise and human-friendly report. If
|
||||
your test generates textual output itself, it will mix with the googletest
|
||||
output, making it hard to read. However, there is an easy solution to this
|
||||
problem.
|
||||
|
||||
Since `LOG` messages go to stderr, we decided to let googletest output go to
|
||||
stdout. This way, you can easily separate the two using redirection. For
|
||||
example:
|
||||
|
||||
```shell
|
||||
$ ./my_test > gtest_output.txt
|
||||
```
|
||||
|
||||
## Why should I prefer test fixtures over global variables?
|
||||
|
||||
There are several good reasons:
|
||||
|
||||
1. It's likely your test needs to change the states of its global variables.
|
||||
This makes it difficult to keep side effects from escaping one test and
|
||||
contaminating others, making debugging difficult. By using fixtures, each
|
||||
test has a fresh set of variables that's different (but with the same
|
||||
names). Thus, tests are kept independent of each other.
|
||||
2. Global variables pollute the global namespace.
|
||||
3. Test fixtures can be reused via subclassing, which cannot be done easily
|
||||
with global variables. This is useful if many test suites have something in
|
||||
common.
|
||||
|
||||
## What can the statement argument in ASSERT_DEATH() be?
|
||||
|
||||
`ASSERT_DEATH(*statement*, *regex*)` (or any death assertion macro) can be used
|
||||
wherever `*statement*` is valid. So basically `*statement*` can be any C++
|
||||
statement that makes sense in the current context. In particular, it can
|
||||
reference global and/or local variables, and can be:
|
||||
|
||||
* a simple function call (often the case),
|
||||
* a complex expression, or
|
||||
* a compound statement.
|
||||
|
||||
Some examples are shown here:
|
||||
|
||||
```c++
|
||||
// A death test can be a simple function call.
|
||||
TEST(MyDeathTest, FunctionCall) {
|
||||
ASSERT_DEATH(Xyz(5), "Xyz failed");
|
||||
}
|
||||
|
||||
// Or a complex expression that references variables and functions.
|
||||
TEST(MyDeathTest, ComplexExpression) {
|
||||
const bool c = Condition();
|
||||
ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
|
||||
"(Func1|Method) failed");
|
||||
}
|
||||
|
||||
// Death assertions can be used any where in a function. In
|
||||
// particular, they can be inside a loop.
|
||||
TEST(MyDeathTest, InsideLoop) {
|
||||
// Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
|
||||
::testing::Message() << "where i is " << i);
|
||||
}
|
||||
}
|
||||
|
||||
// A death assertion can contain a compound statement.
|
||||
TEST(MyDeathTest, CompoundStatement) {
|
||||
// Verifies that at lease one of Bar(0), Bar(1), ..., and
|
||||
// Bar(4) dies.
|
||||
ASSERT_DEATH({
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Bar(i);
|
||||
}
|
||||
},
|
||||
"Bar has \\d+ errors");
|
||||
}
|
||||
```
|
||||
|
||||
gtest-death-test_test.cc contains more examples if you are interested.
|
||||
|
||||
## I have a fixture class `FooTest`, but `TEST_F(FooTest, Bar)` gives me error ``"no matching function for call to `FooTest::FooTest()'"``. Why?
|
||||
|
||||
Googletest needs to be able to create objects of your test fixture class, so it
|
||||
must have a default constructor. Normally the compiler will define one for you.
|
||||
However, there are cases where you have to define your own:
|
||||
|
||||
* If you explicitly declare a non-default constructor for class `FooTest`
|
||||
(`DISALLOW_EVIL_CONSTRUCTORS()` does this), then you need to define a
|
||||
default constructor, even if it would be empty.
|
||||
* If `FooTest` has a const non-static data member, then you have to define the
|
||||
default constructor *and* initialize the const member in the initializer
|
||||
list of the constructor. (Early versions of `gcc` doesn't force you to
|
||||
initialize the const member. It's a bug that has been fixed in `gcc 4`.)
|
||||
|
||||
## Why does ASSERT_DEATH complain about previous threads that were already joined?
|
||||
|
||||
With the Linux pthread library, there is no turning back once you cross the line
|
||||
from single thread to multiple threads. The first time you create a thread, a
|
||||
manager thread is created in addition, so you get 3, not 2, threads. Later when
|
||||
the thread you create joins the main thread, the thread count decrements by 1,
|
||||
but the manager thread will never be killed, so you still have 2 threads, which
|
||||
means you cannot safely run a death test.
|
||||
|
||||
The new NPTL thread library doesn't suffer from this problem, as it doesn't
|
||||
create a manager thread. However, if you don't control which machine your test
|
||||
runs on, you shouldn't depend on this.
|
||||
|
||||
## Why does googletest require the entire test suite, instead of individual tests, to be named *DeathTest when it uses ASSERT_DEATH?
|
||||
|
||||
googletest does not interleave tests from different test suites. That is, it
|
||||
runs all tests in one test suite first, and then runs all tests in the next test
|
||||
suite, and so on. googletest does this because it needs to set up a test suite
|
||||
before the first test in it is run, and tear it down afterwords. Splitting up
|
||||
the test case would require multiple set-up and tear-down processes, which is
|
||||
inefficient and makes the semantics unclean.
|
||||
|
||||
If we were to determine the order of tests based on test name instead of test
|
||||
case name, then we would have a problem with the following situation:
|
||||
|
||||
```c++
|
||||
TEST_F(FooTest, AbcDeathTest) { ... }
|
||||
TEST_F(FooTest, Uvw) { ... }
|
||||
|
||||
TEST_F(BarTest, DefDeathTest) { ... }
|
||||
TEST_F(BarTest, Xyz) { ... }
|
||||
```
|
||||
|
||||
Since `FooTest.AbcDeathTest` needs to run before `BarTest.Xyz`, and we don't
|
||||
interleave tests from different test suites, we need to run all tests in the
|
||||
`FooTest` case before running any test in the `BarTest` case. This contradicts
|
||||
with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`.
|
||||
|
||||
## But I don't like calling my entire test suite \*DeathTest when it contains both death tests and non-death tests. What do I do?
|
||||
|
||||
You don't have to, but if you like, you may split up the test suite into
|
||||
`FooTest` and `FooDeathTest`, where the names make it clear that they are
|
||||
related:
|
||||
|
||||
```c++
|
||||
class FooTest : public ::testing::Test { ... };
|
||||
|
||||
TEST_F(FooTest, Abc) { ... }
|
||||
TEST_F(FooTest, Def) { ... }
|
||||
|
||||
using FooDeathTest = FooTest;
|
||||
|
||||
TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
|
||||
TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
|
||||
```
|
||||
|
||||
## googletest prints the LOG messages in a death test's child process only when the test fails. How can I see the LOG messages when the death test succeeds?
|
||||
|
||||
Printing the LOG messages generated by the statement inside `EXPECT_DEATH()`
|
||||
makes it harder to search for real problems in the parent's log. Therefore,
|
||||
googletest only prints them when the death test has failed.
|
||||
|
||||
If you really need to see such LOG messages, a workaround is to temporarily
|
||||
break the death test (e.g. by changing the regex pattern it is expected to
|
||||
match). Admittedly, this is a hack. We'll consider a more permanent solution
|
||||
after the fork-and-exec-style death tests are implemented.
|
||||
|
||||
## The compiler complains about "no match for 'operator<<'" when I use an assertion. What gives?
|
||||
|
||||
If you use a user-defined type `FooType` in an assertion, you must make sure
|
||||
there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function
|
||||
defined such that we can print a value of `FooType`.
|
||||
|
||||
In addition, if `FooType` is declared in a name space, the `<<` operator also
|
||||
needs to be defined in the *same* name space. See https://abseil.io/tips/49 for details.
|
||||
|
||||
## How do I suppress the memory leak messages on Windows?
|
||||
|
||||
Since the statically initialized googletest singleton requires allocations on
|
||||
the heap, the Visual C++ memory leak detector will report memory leaks at the
|
||||
end of the program run. The easiest way to avoid this is to use the
|
||||
`_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any
|
||||
statically initialized heap objects. See MSDN for more details and additional
|
||||
heap check/debug routines.
|
||||
|
||||
## How can my code detect if it is running in a test?
|
||||
|
||||
If you write code that sniffs whether it's running in a test and does different
|
||||
things accordingly, you are leaking test-only logic into production code and
|
||||
there is no easy way to ensure that the test-only code paths aren't run by
|
||||
mistake in production. Such cleverness also leads to
|
||||
[Heisenbugs](https://en.wikipedia.org/wiki/Heisenbug). Therefore we strongly
|
||||
advise against the practice, and googletest doesn't provide a way to do it.
|
||||
|
||||
In general, the recommended way to cause the code to behave differently under
|
||||
test is [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection). You can inject
|
||||
different functionality from the test and from the production code. Since your
|
||||
production code doesn't link in the for-test logic at all (the
|
||||
[`testonly`](https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly) attribute for BUILD targets helps to ensure
|
||||
that), there is no danger in accidentally running it.
|
||||
|
||||
However, if you *really*, *really*, *really* have no choice, and if you follow
|
||||
the rule of ending your test program names with `_test`, you can use the
|
||||
*horrible* hack of sniffing your executable name (`argv[0]` in `main()`) to know
|
||||
whether the code is under test.
|
||||
|
||||
## How do I temporarily disable a test?
|
||||
|
||||
If you have a broken test that you cannot fix right away, you can add the
|
||||
DISABLED_ prefix to its name. This will exclude it from execution. This is
|
||||
better than commenting out the code or using #if 0, as disabled tests are still
|
||||
compiled (and thus won't rot).
|
||||
|
||||
To include disabled tests in test execution, just invoke the test program with
|
||||
the --gtest_also_run_disabled_tests flag.
|
||||
|
||||
## Is it OK if I have two separate `TEST(Foo, Bar)` test methods defined in different namespaces?
|
||||
|
||||
Yes.
|
||||
|
||||
The rule is **all test methods in the same test suite must use the same fixture
|
||||
class.** This means that the following is **allowed** because both tests use the
|
||||
same fixture class (`::testing::Test`).
|
||||
|
||||
```c++
|
||||
namespace foo {
|
||||
TEST(CoolTest, DoSomething) {
|
||||
SUCCEED();
|
||||
}
|
||||
} // namespace foo
|
||||
|
||||
namespace bar {
|
||||
TEST(CoolTest, DoSomething) {
|
||||
SUCCEED();
|
||||
}
|
||||
} // namespace bar
|
||||
```
|
||||
|
||||
However, the following code is **not allowed** and will produce a runtime error
|
||||
from googletest because the test methods are using different test fixture
|
||||
classes with the same test suite name.
|
||||
|
||||
```c++
|
||||
namespace foo {
|
||||
class CoolTest : public ::testing::Test {}; // Fixture foo::CoolTest
|
||||
TEST_F(CoolTest, DoSomething) {
|
||||
SUCCEED();
|
||||
}
|
||||
} // namespace foo
|
||||
|
||||
namespace bar {
|
||||
class CoolTest : public ::testing::Test {}; // Fixture: bar::CoolTest
|
||||
TEST_F(CoolTest, DoSomething) {
|
||||
SUCCEED();
|
||||
}
|
||||
} // namespace bar
|
||||
```
|
|
@ -1,567 +0,0 @@
|
|||
# Googletest Primer
|
||||
|
||||
## Introduction: Why googletest?
|
||||
|
||||
*googletest* helps you write better C++ tests.
|
||||
|
||||
googletest is a testing framework developed by the Testing Technology team with
|
||||
Google's specific requirements and constraints in mind. Whether you work on
|
||||
Linux, Windows, or a Mac, if you write C++ code, googletest can help you. And it
|
||||
supports *any* kind of tests, not just unit tests.
|
||||
|
||||
So what makes a good test, and how does googletest fit in? We believe:
|
||||
|
||||
1. Tests should be *independent* and *repeatable*. It's a pain to debug a test
|
||||
that succeeds or fails as a result of other tests. googletest isolates the
|
||||
tests by running each of them on a different object. When a test fails,
|
||||
googletest allows you to run it in isolation for quick debugging.
|
||||
2. Tests should be well *organized* and reflect the structure of the tested
|
||||
code. googletest groups related tests into test suites that can share data
|
||||
and subroutines. This common pattern is easy to recognize and makes tests
|
||||
easy to maintain. Such consistency is especially helpful when people switch
|
||||
projects and start to work on a new code base.
|
||||
3. Tests should be *portable* and *reusable*. Google has a lot of code that is
|
||||
platform-neutral; its tests should also be platform-neutral. googletest
|
||||
works on different OSes, with different compilers, with or without
|
||||
exceptions, so googletest tests can work with a variety of configurations.
|
||||
4. When tests fail, they should provide as much *information* about the problem
|
||||
as possible. googletest doesn't stop at the first test failure. Instead, it
|
||||
only stops the current test and continues with the next. You can also set up
|
||||
tests that report non-fatal failures after which the current test continues.
|
||||
Thus, you can detect and fix multiple bugs in a single run-edit-compile
|
||||
cycle.
|
||||
5. The testing framework should liberate test writers from housekeeping chores
|
||||
and let them focus on the test *content*. googletest automatically keeps
|
||||
track of all tests defined, and doesn't require the user to enumerate them
|
||||
in order to run them.
|
||||
6. Tests should be *fast*. With googletest, you can reuse shared resources
|
||||
across tests and pay for the set-up/tear-down only once, without making
|
||||
tests depend on each other.
|
||||
|
||||
Since googletest is based on the popular xUnit architecture, you'll feel right
|
||||
at home if you've used JUnit or PyUnit before. If not, it will take you about 10
|
||||
minutes to learn the basics and get started. So let's go!
|
||||
|
||||
## Beware of the nomenclature
|
||||
|
||||
_Note:_ There might be some confusion arising from different definitions of the
|
||||
terms _Test_, _Test Case_ and _Test Suite_, so beware of misunderstanding these.
|
||||
|
||||
Historically, googletest started to use the term _Test Case_ for grouping
|
||||
related tests, whereas current publications, including International Software
|
||||
Testing Qualifications Board ([ISTQB](http://www.istqb.org/)) materials and
|
||||
various textbooks on software quality, use the term
|
||||
_[Test Suite][istqb test suite]_ for this.
|
||||
|
||||
The related term _Test_, as it is used in googletest, corresponds to the term
|
||||
_[Test Case][istqb test case]_ of ISTQB and others.
|
||||
|
||||
The term _Test_ is commonly of broad enough sense, including ISTQB's definition
|
||||
of _Test Case_, so it's not much of a problem here. But the term _Test Case_ as
|
||||
was used in Google Test is of contradictory sense and thus confusing.
|
||||
|
||||
googletest recently started replacing the term _Test Case_ with _Test Suite_.
|
||||
The preferred API is *TestSuite*. The older TestCase API is being slowly
|
||||
deprecated and refactored away.
|
||||
|
||||
So please be aware of the different definitions of the terms:
|
||||
|
||||
<!-- mdformat off(github rendering does not support multiline tables) -->
|
||||
|
||||
Meaning | googletest Term | [ISTQB](http://www.istqb.org/) Term
|
||||
:----------------------------------------------------------------------------------- | :---------------------- | :----------------------------------
|
||||
Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case]
|
||||
|
||||
<!-- mdformat on -->
|
||||
|
||||
[istqb test case]: http://glossary.istqb.org/en/search/test%20case
|
||||
[istqb test suite]: http://glossary.istqb.org/en/search/test%20suite
|
||||
|
||||
## Basic Concepts
|
||||
|
||||
When using googletest, you start by writing *assertions*, which are statements
|
||||
that check whether a condition is true. An assertion's result can be *success*,
|
||||
*nonfatal failure*, or *fatal failure*. If a fatal failure occurs, it aborts the
|
||||
current function; otherwise the program continues normally.
|
||||
|
||||
*Tests* use assertions to verify the tested code's behavior. If a test crashes
|
||||
or has a failed assertion, then it *fails*; otherwise it *succeeds*.
|
||||
|
||||
A *test suite* contains one or many tests. You should group your tests into test
|
||||
suites that reflect the structure of the tested code. When multiple tests in a
|
||||
test suite need to share common objects and subroutines, you can put them into a
|
||||
*test fixture* class.
|
||||
|
||||
A *test program* can contain multiple test suites.
|
||||
|
||||
We'll now explain how to write a test program, starting at the individual
|
||||
assertion level and building up to tests and test suites.
|
||||
|
||||
## Assertions
|
||||
|
||||
googletest assertions are macros that resemble function calls. You test a class
|
||||
or function by making assertions about its behavior. When an assertion fails,
|
||||
googletest prints the assertion's source file and line number location, along
|
||||
with a failure message. You may also supply a custom failure message which will
|
||||
be appended to googletest's message.
|
||||
|
||||
The assertions come in pairs that test the same thing but have different effects
|
||||
on the current function. `ASSERT_*` versions generate fatal failures when they
|
||||
fail, and **abort the current function**. `EXPECT_*` versions generate nonfatal
|
||||
failures, which don't abort the current function. Usually `EXPECT_*` are
|
||||
preferred, as they allow more than one failure to be reported in a test.
|
||||
However, you should use `ASSERT_*` if it doesn't make sense to continue when the
|
||||
assertion in question fails.
|
||||
|
||||
Since a failed `ASSERT_*` returns from the current function immediately,
|
||||
possibly skipping clean-up code that comes after it, it may cause a space leak.
|
||||
Depending on the nature of the leak, it may or may not be worth fixing - so keep
|
||||
this in mind if you get a heap checker error in addition to assertion errors.
|
||||
|
||||
To provide a custom failure message, simply stream it into the macro using the
|
||||
`<<` operator or a sequence of such operators. An example:
|
||||
|
||||
```c++
|
||||
ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
|
||||
|
||||
for (int i = 0; i < x.size(); ++i) {
|
||||
EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
|
||||
}
|
||||
```
|
||||
|
||||
Anything that can be streamed to an `ostream` can be streamed to an assertion
|
||||
macro--in particular, C strings and `string` objects. If a wide string
|
||||
(`wchar_t*`, `TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is
|
||||
streamed to an assertion, it will be translated to UTF-8 when printed.
|
||||
|
||||
### Basic Assertions
|
||||
|
||||
These assertions do basic true/false condition testing.
|
||||
|
||||
Fatal assertion | Nonfatal assertion | Verifies
|
||||
-------------------------- | -------------------------- | --------------------
|
||||
`ASSERT_TRUE(condition);` | `EXPECT_TRUE(condition);` | `condition` is true
|
||||
`ASSERT_FALSE(condition);` | `EXPECT_FALSE(condition);` | `condition` is false
|
||||
|
||||
Remember, when they fail, `ASSERT_*` yields a fatal failure and returns from the
|
||||
current function, while `EXPECT_*` yields a nonfatal failure, allowing the
|
||||
function to continue running. In either case, an assertion failure means its
|
||||
containing test fails.
|
||||
|
||||
**Availability**: Linux, Windows, Mac.
|
||||
|
||||
### Binary Comparison
|
||||
|
||||
This section describes assertions that compare two values.
|
||||
|
||||
Fatal assertion | Nonfatal assertion | Verifies
|
||||
------------------------ | ------------------------ | --------------
|
||||
`ASSERT_EQ(val1, val2);` | `EXPECT_EQ(val1, val2);` | `val1 == val2`
|
||||
`ASSERT_NE(val1, val2);` | `EXPECT_NE(val1, val2);` | `val1 != val2`
|
||||
`ASSERT_LT(val1, val2);` | `EXPECT_LT(val1, val2);` | `val1 < val2`
|
||||
`ASSERT_LE(val1, val2);` | `EXPECT_LE(val1, val2);` | `val1 <= val2`
|
||||
`ASSERT_GT(val1, val2);` | `EXPECT_GT(val1, val2);` | `val1 > val2`
|
||||
`ASSERT_GE(val1, val2);` | `EXPECT_GE(val1, val2);` | `val1 >= val2`
|
||||
|
||||
Value arguments must be comparable by the assertion's comparison operator or
|
||||
you'll get a compiler error. We used to require the arguments to support the
|
||||
`<<` operator for streaming to an `ostream`, but this is no longer necessary. If
|
||||
`<<` is supported, it will be called to print the arguments when the assertion
|
||||
fails; otherwise googletest will attempt to print them in the best way it can.
|
||||
For more details and how to customize the printing of the arguments, see the
|
||||
[documentation](../../googlemock/docs/cook_book.md#teaching-gmock-how-to-print-your-values).
|
||||
|
||||
These assertions can work with a user-defined type, but only if you define the
|
||||
corresponding comparison operator (e.g., `==` or `<`). Since this is discouraged
|
||||
by the Google
|
||||
[C++ Style Guide](https://google.github.io/styleguide/cppguide.html#Operator_Overloading),
|
||||
you may need to use `ASSERT_TRUE()` or `EXPECT_TRUE()` to assert the equality of
|
||||
two objects of a user-defined type.
|
||||
|
||||
However, when possible, `ASSERT_EQ(actual, expected)` is preferred to
|
||||
`ASSERT_TRUE(actual == expected)`, since it tells you `actual` and `expected`'s
|
||||
values on failure.
|
||||
|
||||
Arguments are always evaluated exactly once. Therefore, it's OK for the
|
||||
arguments to have side effects. However, as with any ordinary C/C++ function,
|
||||
the arguments' evaluation order is undefined (i.e., the compiler is free to
|
||||
choose any order), and your code should not depend on any particular argument
|
||||
evaluation order.
|
||||
|
||||
`ASSERT_EQ()` does pointer equality on pointers. If used on two C strings, it
|
||||
tests if they are in the same memory location, not if they have the same value.
|
||||
Therefore, if you want to compare C strings (e.g. `const char*`) by value, use
|
||||
`ASSERT_STREQ()`, which will be described later on. In particular, to assert
|
||||
that a C string is `NULL`, use `ASSERT_STREQ(c_string, NULL)`. Consider using
|
||||
`ASSERT_EQ(c_string, nullptr)` if c++11 is supported. To compare two `string`
|
||||
objects, you should use `ASSERT_EQ`.
|
||||
|
||||
When doing pointer comparisons use `*_EQ(ptr, nullptr)` and `*_NE(ptr, nullptr)`
|
||||
instead of `*_EQ(ptr, NULL)` and `*_NE(ptr, NULL)`. This is because `nullptr` is
|
||||
typed, while `NULL` is not. See the [FAQ](faq.md) for more details.
|
||||
|
||||
If you're working with floating point numbers, you may want to use the floating
|
||||
point variations of some of these macros in order to avoid problems caused by
|
||||
rounding. See [Advanced googletest Topics](advanced.md) for details.
|
||||
|
||||
Macros in this section work with both narrow and wide string objects (`string`
|
||||
and `wstring`).
|
||||
|
||||
**Availability**: Linux, Windows, Mac.
|
||||
|
||||
**Historical note**: Before February 2016 `*_EQ` had a convention of calling it
|
||||
as `ASSERT_EQ(expected, actual)`, so lots of existing code uses this order. Now
|
||||
`*_EQ` treats both parameters in the same way.
|
||||
|
||||
### String Comparison
|
||||
|
||||
The assertions in this group compare two **C strings**. If you want to compare
|
||||
two `string` objects, use `EXPECT_EQ`, `EXPECT_NE`, and etc instead.
|
||||
|
||||
<!-- mdformat off(github rendering does not support multiline tables) -->
|
||||
|
||||
| Fatal assertion | Nonfatal assertion | Verifies |
|
||||
| -------------------------- | ------------------------------ | -------------------------------------------------------- |
|
||||
| `ASSERT_STREQ(str1,str2);` | `EXPECT_STREQ(str1,str2);` | the two C strings have the same content |
|
||||
| `ASSERT_STRNE(str1,str2);` | `EXPECT_STRNE(str1,str2);` | the two C strings have different contents |
|
||||
| `ASSERT_STRCASEEQ(str1,str2);` | `EXPECT_STRCASEEQ(str1,str2);` | the two C strings have the same content, ignoring case |
|
||||
| `ASSERT_STRCASENE(str1,str2);` | `EXPECT_STRCASENE(str1,str2);` | the two C strings have different contents, ignoring case |
|
||||
|
||||
<!-- mdformat on-->
|
||||
|
||||
Note that "CASE" in an assertion name means that case is ignored. A `NULL`
|
||||
pointer and an empty string are considered *different*.
|
||||
|
||||
`*STREQ*` and `*STRNE*` also accept wide C strings (`wchar_t*`). If a comparison
|
||||
of two wide strings fails, their values will be printed as UTF-8 narrow strings.
|
||||
|
||||
**Availability**: Linux, Windows, Mac.
|
||||
|
||||
**See also**: For more string comparison tricks (substring, prefix, suffix, and
|
||||
regular expression matching, for example), see [this](advanced.md) in the
|
||||
Advanced googletest Guide.
|
||||
|
||||
## Simple Tests
|
||||
|
||||
To create a test:
|
||||
|
||||
1. Use the `TEST()` macro to define and name a test function. These are
|
||||
ordinary C++ functions that don't return a value.
|
||||
2. In this function, along with any valid C++ statements you want to include,
|
||||
use the various googletest assertions to check values.
|
||||
3. The test's result is determined by the assertions; if any assertion in the
|
||||
test fails (either fatally or non-fatally), or if the test crashes, the
|
||||
entire test fails. Otherwise, it succeeds.
|
||||
|
||||
```c++
|
||||
TEST(TestSuiteName, TestName) {
|
||||
... test body ...
|
||||
}
|
||||
```
|
||||
|
||||
`TEST()` arguments go from general to specific. The *first* argument is the name
|
||||
of the test suite, and the *second* argument is the test's name within the test
|
||||
case. Both names must be valid C++ identifiers, and they should not contain
|
||||
any underscores (`_`). A test's *full name* consists of its containing test suite and
|
||||
its individual name. Tests from different test suites can have the same
|
||||
individual name.
|
||||
|
||||
For example, let's take a simple integer function:
|
||||
|
||||
```c++
|
||||
int Factorial(int n); // Returns the factorial of n
|
||||
```
|
||||
|
||||
A test suite for this function might look like:
|
||||
|
||||
```c++
|
||||
// Tests factorial of 0.
|
||||
TEST(FactorialTest, HandlesZeroInput) {
|
||||
EXPECT_EQ(Factorial(0), 1);
|
||||
}
|
||||
|
||||
// Tests factorial of positive numbers.
|
||||
TEST(FactorialTest, HandlesPositiveInput) {
|
||||
EXPECT_EQ(Factorial(1), 1);
|
||||
EXPECT_EQ(Factorial(2), 2);
|
||||
EXPECT_EQ(Factorial(3), 6);
|
||||
EXPECT_EQ(Factorial(8), 40320);
|
||||
}
|
||||
```
|
||||
|
||||
googletest groups the test results by test suites, so logically related tests
|
||||
should be in the same test suite; in other words, the first argument to their
|
||||
`TEST()` should be the same. In the above example, we have two tests,
|
||||
`HandlesZeroInput` and `HandlesPositiveInput`, that belong to the same test
|
||||
suite `FactorialTest`.
|
||||
|
||||
When naming your test suites and tests, you should follow the same convention as
|
||||
for
|
||||
[naming functions and classes](https://google.github.io/styleguide/cppguide.html#Function_Names).
|
||||
|
||||
**Availability**: Linux, Windows, Mac.
|
||||
|
||||
## Test Fixtures: Using the Same Data Configuration for Multiple Tests {#same-data-multiple-tests}
|
||||
|
||||
If you find yourself writing two or more tests that operate on similar data, you
|
||||
can use a *test fixture*. This allows you to reuse the same configuration of
|
||||
objects for several different tests.
|
||||
|
||||
To create a fixture:
|
||||
|
||||
1. Derive a class from `::testing::Test` . Start its body with `protected:`, as
|
||||
we'll want to access fixture members from sub-classes.
|
||||
2. Inside the class, declare any objects you plan to use.
|
||||
3. If necessary, write a default constructor or `SetUp()` function to prepare
|
||||
the objects for each test. A common mistake is to spell `SetUp()` as
|
||||
**`Setup()`** with a small `u` - Use `override` in C++11 to make sure you
|
||||
spelled it correctly.
|
||||
4. If necessary, write a destructor or `TearDown()` function to release any
|
||||
resources you allocated in `SetUp()` . To learn when you should use the
|
||||
constructor/destructor and when you should use `SetUp()/TearDown()`, read
|
||||
the [FAQ](faq.md#CtorVsSetUp).
|
||||
5. If needed, define subroutines for your tests to share.
|
||||
|
||||
When using a fixture, use `TEST_F()` instead of `TEST()` as it allows you to
|
||||
access objects and subroutines in the test fixture:
|
||||
|
||||
```c++
|
||||
TEST_F(TestFixtureName, TestName) {
|
||||
... test body ...
|
||||
}
|
||||
```
|
||||
|
||||
Like `TEST()`, the first argument is the test suite name, but for `TEST_F()`
|
||||
this must be the name of the test fixture class. You've probably guessed: `_F`
|
||||
is for fixture.
|
||||
|
||||
Unfortunately, the C++ macro system does not allow us to create a single macro
|
||||
that can handle both types of tests. Using the wrong macro causes a compiler
|
||||
error.
|
||||
|
||||
Also, you must first define a test fixture class before using it in a
|
||||
`TEST_F()`, or you'll get the compiler error "`virtual outside class
|
||||
declaration`".
|
||||
|
||||
For each test defined with `TEST_F()`, googletest will create a *fresh* test
|
||||
fixture at runtime, immediately initialize it via `SetUp()`, run the test,
|
||||
clean up by calling `TearDown()`, and then delete the test fixture. Note that
|
||||
different tests in the same test suite have different test fixture objects, and
|
||||
googletest always deletes a test fixture before it creates the next one.
|
||||
googletest does **not** reuse the same test fixture for multiple tests. Any
|
||||
changes one test makes to the fixture do not affect other tests.
|
||||
|
||||
As an example, let's write tests for a FIFO queue class named `Queue`, which has
|
||||
the following interface:
|
||||
|
||||
```c++
|
||||
template <typename E> // E is the element type.
|
||||
class Queue {
|
||||
public:
|
||||
Queue();
|
||||
void Enqueue(const E& element);
|
||||
E* Dequeue(); // Returns NULL if the queue is empty.
|
||||
size_t size() const;
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
First, define a fixture class. By convention, you should give it the name
|
||||
`FooTest` where `Foo` is the class being tested.
|
||||
|
||||
```c++
|
||||
class QueueTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
q1_.Enqueue(1);
|
||||
q2_.Enqueue(2);
|
||||
q2_.Enqueue(3);
|
||||
}
|
||||
|
||||
// void TearDown() override {}
|
||||
|
||||
Queue<int> q0_;
|
||||
Queue<int> q1_;
|
||||
Queue<int> q2_;
|
||||
};
|
||||
```
|
||||
|
||||
In this case, `TearDown()` is not needed since we don't have to clean up after
|
||||
each test, other than what's already done by the destructor.
|
||||
|
||||
Now we'll write tests using `TEST_F()` and this fixture.
|
||||
|
||||
```c++
|
||||
TEST_F(QueueTest, IsEmptyInitially) {
|
||||
EXPECT_EQ(q0_.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(QueueTest, DequeueWorks) {
|
||||
int* n = q0_.Dequeue();
|
||||
EXPECT_EQ(n, nullptr);
|
||||
|
||||
n = q1_.Dequeue();
|
||||
ASSERT_NE(n, nullptr);
|
||||
EXPECT_EQ(*n, 1);
|
||||
EXPECT_EQ(q1_.size(), 0);
|
||||
delete n;
|
||||
|
||||
n = q2_.Dequeue();
|
||||
ASSERT_NE(n, nullptr);
|
||||
EXPECT_EQ(*n, 2);
|
||||
EXPECT_EQ(q2_.size(), 1);
|
||||
delete n;
|
||||
}
|
||||
```
|
||||
|
||||
The above uses both `ASSERT_*` and `EXPECT_*` assertions. The rule of thumb is
|
||||
to use `EXPECT_*` when you want the test to continue to reveal more errors after
|
||||
the assertion failure, and use `ASSERT_*` when continuing after failure doesn't
|
||||
make sense. For example, the second assertion in the `Dequeue` test is
|
||||
`ASSERT_NE(nullptr, n)`, as we need to dereference the pointer `n` later, which
|
||||
would lead to a segfault when `n` is `NULL`.
|
||||
|
||||
When these tests run, the following happens:
|
||||
|
||||
1. googletest constructs a `QueueTest` object (let's call it `t1`).
|
||||
2. `t1.SetUp()` initializes `t1`.
|
||||
3. The first test (`IsEmptyInitially`) runs on `t1`.
|
||||
4. `t1.TearDown()` cleans up after the test finishes.
|
||||
5. `t1` is destructed.
|
||||
6. The above steps are repeated on another `QueueTest` object, this time
|
||||
running the `DequeueWorks` test.
|
||||
|
||||
**Availability**: Linux, Windows, Mac.
|
||||
|
||||
## Invoking the Tests
|
||||
|
||||
`TEST()` and `TEST_F()` implicitly register their tests with googletest. So,
|
||||
unlike with many other C++ testing frameworks, you don't have to re-list all
|
||||
your defined tests in order to run them.
|
||||
|
||||
After defining your tests, you can run them with `RUN_ALL_TESTS()`, which
|
||||
returns `0` if all the tests are successful, or `1` otherwise. Note that
|
||||
`RUN_ALL_TESTS()` runs *all tests* in your link unit--they can be from
|
||||
different test suites, or even different source files.
|
||||
|
||||
When invoked, the `RUN_ALL_TESTS()` macro:
|
||||
|
||||
* Saves the state of all googletest flags.
|
||||
|
||||
* Creates a test fixture object for the first test.
|
||||
|
||||
* Initializes it via `SetUp()`.
|
||||
|
||||
* Runs the test on the fixture object.
|
||||
|
||||
* Cleans up the fixture via `TearDown()`.
|
||||
|
||||
* Deletes the fixture.
|
||||
|
||||
* Restores the state of all googletest flags.
|
||||
|
||||
* Repeats the above steps for the next test, until all tests have run.
|
||||
|
||||
If a fatal failure happens the subsequent steps will be skipped.
|
||||
|
||||
> IMPORTANT: You must **not** ignore the return value of `RUN_ALL_TESTS()`, or
|
||||
> you will get a compiler error. The rationale for this design is that the
|
||||
> automated testing service determines whether a test has passed based on its
|
||||
> exit code, not on its stdout/stderr output; thus your `main()` function must
|
||||
> return the value of `RUN_ALL_TESTS()`.
|
||||
>
|
||||
> Also, you should call `RUN_ALL_TESTS()` only **once**. Calling it more than
|
||||
> once conflicts with some advanced googletest features (e.g., thread-safe
|
||||
> [death tests](advanced.md#death-tests)) and thus is not supported.
|
||||
|
||||
**Availability**: Linux, Windows, Mac.
|
||||
|
||||
## Writing the main() Function
|
||||
|
||||
Write your own main() function, which should return the value of
|
||||
`RUN_ALL_TESTS()`.
|
||||
|
||||
You can start from this boilerplate:
|
||||
|
||||
```c++
|
||||
#include "this/package/foo.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// The fixture for testing class Foo.
|
||||
class FooTest : public ::testing::Test {
|
||||
protected:
|
||||
// You can remove any or all of the following functions if its body
|
||||
// is empty.
|
||||
|
||||
FooTest() {
|
||||
// You can do set-up work for each test here.
|
||||
}
|
||||
|
||||
~FooTest() override {
|
||||
// You can do clean-up work that doesn't throw exceptions here.
|
||||
}
|
||||
|
||||
// If the constructor and destructor are not enough for setting up
|
||||
// and cleaning up each test, you can define the following methods:
|
||||
|
||||
void SetUp() override {
|
||||
// Code here will be called immediately after the constructor (right
|
||||
// before each test).
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Code here will be called immediately after each test (right
|
||||
// before the destructor).
|
||||
}
|
||||
|
||||
// Objects declared here can be used by all tests in the test suite for Foo.
|
||||
};
|
||||
|
||||
// Tests that the Foo::Bar() method does Abc.
|
||||
TEST_F(FooTest, MethodBarDoesAbc) {
|
||||
const std::string input_filepath = "this/package/testdata/myinputfile.dat";
|
||||
const std::string output_filepath = "this/package/testdata/myoutputfile.dat";
|
||||
Foo f;
|
||||
EXPECT_EQ(f.Bar(input_filepath, output_filepath), 0);
|
||||
}
|
||||
|
||||
// Tests that Foo does Xyz.
|
||||
TEST_F(FooTest, DoesXyz) {
|
||||
// Exercises the Xyz feature of Foo.
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
```
|
||||
|
||||
The `::testing::InitGoogleTest()` function parses the command line for
|
||||
googletest flags, and removes all recognized flags. This allows the user to
|
||||
control a test program's behavior via various flags, which we'll cover in
|
||||
the [AdvancedGuide](advanced.md). You **must** call this function before calling
|
||||
`RUN_ALL_TESTS()`, or the flags won't be properly initialized.
|
||||
|
||||
On Windows, `InitGoogleTest()` also works with wide strings, so it can be used
|
||||
in programs compiled in `UNICODE` mode as well.
|
||||
|
||||
But maybe you think that writing all those main() functions is too much work? We
|
||||
agree with you completely, and that's why Google Test provides a basic
|
||||
implementation of main(). If it fits your needs, then just link your test with
|
||||
gtest\_main library and you are good to go.
|
||||
|
||||
NOTE: `ParseGUnitFlags()` is deprecated in favor of `InitGoogleTest()`.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
* Google Test is designed to be thread-safe. The implementation is thread-safe
|
||||
on systems where the `pthreads` library is available. It is currently
|
||||
_unsafe_ to use Google Test assertions from two threads concurrently on
|
||||
other systems (e.g. Windows). In most tests this is not an issue as usually
|
||||
the assertions are done in the main thread. If you want to help, you can
|
||||
volunteer to implement the necessary synchronization primitives in
|
||||
`gtest-port.h` for your platform.
|
|
@ -1,190 +0,0 @@
|
|||
<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
|
||||
|
||||
# The Problem
|
||||
|
||||
Template and macro libraries often need to define many classes, functions, or
|
||||
macros that vary only (or almost only) in the number of arguments they take.
|
||||
It's a lot of repetitive, mechanical, and error-prone work.
|
||||
|
||||
Variadic templates and variadic macros can alleviate the problem. However, while
|
||||
both are being considered by the C++ committee, neither is in the standard yet
|
||||
or widely supported by compilers. Thus they are often not a good choice,
|
||||
especially when your code needs to be portable. And their capabilities are still
|
||||
limited.
|
||||
|
||||
As a result, authors of such libraries often have to write scripts to generate
|
||||
their implementation. However, our experience is that it's tedious to write such
|
||||
scripts, which tend to reflect the structure of the generated code poorly and
|
||||
are often hard to read and edit. For example, a small change needed in the
|
||||
generated code may require some non-intuitive, non-trivial changes in the
|
||||
script. This is especially painful when experimenting with the code.
|
||||
|
||||
# Our Solution
|
||||
|
||||
Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
|
||||
Programming, or Practical Utility for Meta Programming, whichever you prefer) is
|
||||
a simple meta-programming tool for C++. The idea is that a programmer writes a
|
||||
`foo.pump` file which contains C++ code plus meta code that manipulates the C++
|
||||
code. The meta code can handle iterations over a range, nested iterations, local
|
||||
meta variable definitions, simple arithmetic, and conditional expressions. You
|
||||
can view it as a small Domain-Specific Language. The meta language is designed
|
||||
to be non-intrusive (s.t. it won't confuse Emacs' C++ mode, for example) and
|
||||
concise, making Pump code intuitive and easy to maintain.
|
||||
|
||||
## Highlights
|
||||
|
||||
* The implementation is in a single Python script and thus ultra portable: no
|
||||
build or installation is needed and it works cross platforms.
|
||||
* Pump tries to be smart with respect to
|
||||
[Google's style guide](https://github.com/google/styleguide): it breaks long
|
||||
lines (easy to have when they are generated) at acceptable places to fit
|
||||
within 80 columns and indent the continuation lines correctly.
|
||||
* The format is human-readable and more concise than XML.
|
||||
* The format works relatively well with Emacs' C++ mode.
|
||||
|
||||
## Examples
|
||||
|
||||
The following Pump code (where meta keywords start with `$`, `[[` and `]]` are
|
||||
meta brackets, and `$$` starts a meta comment that ends with the line):
|
||||
|
||||
```
|
||||
$var n = 3 $$ Defines a meta variable n.
|
||||
$range i 0..n $$ Declares the range of meta iterator i (inclusive).
|
||||
$for i [[
|
||||
$$ Meta loop.
|
||||
// Foo$i does blah for $i-ary predicates.
|
||||
$range j 1..i
|
||||
template <size_t N $for j [[, typename A$j]]>
|
||||
class Foo$i {
|
||||
$if i == 0 [[
|
||||
blah a;
|
||||
]] $elif i <= 2 [[
|
||||
blah b;
|
||||
]] $else [[
|
||||
blah c;
|
||||
]]
|
||||
};
|
||||
|
||||
]]
|
||||
```
|
||||
|
||||
will be translated by the Pump compiler to:
|
||||
|
||||
```cpp
|
||||
// Foo0 does blah for 0-ary predicates.
|
||||
template <size_t N>
|
||||
class Foo0 {
|
||||
blah a;
|
||||
};
|
||||
|
||||
// Foo1 does blah for 1-ary predicates.
|
||||
template <size_t N, typename A1>
|
||||
class Foo1 {
|
||||
blah b;
|
||||
};
|
||||
|
||||
// Foo2 does blah for 2-ary predicates.
|
||||
template <size_t N, typename A1, typename A2>
|
||||
class Foo2 {
|
||||
blah b;
|
||||
};
|
||||
|
||||
// Foo3 does blah for 3-ary predicates.
|
||||
template <size_t N, typename A1, typename A2, typename A3>
|
||||
class Foo3 {
|
||||
blah c;
|
||||
};
|
||||
```
|
||||
|
||||
In another example,
|
||||
|
||||
```
|
||||
$range i 1..n
|
||||
Func($for i + [[a$i]]);
|
||||
$$ The text between i and [[ is the separator between iterations.
|
||||
```
|
||||
|
||||
will generate one of the following lines (without the comments), depending on
|
||||
the value of `n`:
|
||||
|
||||
```cpp
|
||||
Func(); // If n is 0.
|
||||
Func(a1); // If n is 1.
|
||||
Func(a1 + a2); // If n is 2.
|
||||
Func(a1 + a2 + a3); // If n is 3.
|
||||
// And so on...
|
||||
```
|
||||
|
||||
## Constructs
|
||||
|
||||
We support the following meta programming constructs:
|
||||
|
||||
| `$var id = exp` | Defines a named constant value. `$id` is |
|
||||
: : valid util the end of the current meta :
|
||||
: : lexical block. :
|
||||
| :------------------------------- | :--------------------------------------- |
|
||||
| `$range id exp..exp` | Sets the range of an iteration variable, |
|
||||
: : which can be reused in multiple loops :
|
||||
: : later. :
|
||||
| `$for id sep [[ code ]]` | Iteration. The range of `id` must have |
|
||||
: : been defined earlier. `$id` is valid in :
|
||||
: : `code`. :
|
||||
| `$($)` | Generates a single `$` character. |
|
||||
| `$id` | Value of the named constant or iteration |
|
||||
: : variable. :
|
||||
| `$(exp)` | Value of the expression. |
|
||||
| `$if exp [[ code ]] else_branch` | Conditional. |
|
||||
| `[[ code ]]` | Meta lexical block. |
|
||||
| `cpp_code` | Raw C++ code. |
|
||||
| `$$ comment` | Meta comment. |
|
||||
|
||||
**Note:** To give the user some freedom in formatting the Pump source code, Pump
|
||||
ignores a new-line character if it's right after `$for foo` or next to `[[` or
|
||||
`]]`. Without this rule you'll often be forced to write very long lines to get
|
||||
the desired output. Therefore sometimes you may need to insert an extra new-line
|
||||
in such places for a new-line to show up in your output.
|
||||
|
||||
## Grammar
|
||||
|
||||
```ebnf
|
||||
code ::= atomic_code*
|
||||
atomic_code ::= $var id = exp
|
||||
| $var id = [[ code ]]
|
||||
| $range id exp..exp
|
||||
| $for id sep [[ code ]]
|
||||
| $($)
|
||||
| $id
|
||||
| $(exp)
|
||||
| $if exp [[ code ]] else_branch
|
||||
| [[ code ]]
|
||||
| cpp_code
|
||||
sep ::= cpp_code | empty_string
|
||||
else_branch ::= $else [[ code ]]
|
||||
| $elif exp [[ code ]] else_branch
|
||||
| empty_string
|
||||
exp ::= simple_expression_in_Python_syntax
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py).
|
||||
It is still very unpolished and lacks automated tests, although it has been
|
||||
successfully used many times. If you find a chance to use it in your project,
|
||||
please let us know what you think! We also welcome help on improving Pump.
|
||||
|
||||
## Real Examples
|
||||
|
||||
You can find real-world applications of Pump in
|
||||
[Google Test](https://github.com/google/googletest/tree/master/googletest) and
|
||||
[Google Mock](https://github.com/google/googletest/tree/master/googlemock). The
|
||||
source file `foo.h.pump` generates `foo.h`.
|
||||
|
||||
## Tips
|
||||
|
||||
* If a meta variable is followed by a letter or digit, you can separate them
|
||||
using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper`
|
||||
generate `Foo1Helper` when `j` is 1.
|
||||
* To avoid extra-long Pump source lines, you can break a line anywhere you
|
||||
want by inserting `[[]]` followed by a new line. Since any new-line
|
||||
character next to `[[` or `]]` is ignored, the generated code won't contain
|
||||
this new line.
|
|
@ -1,22 +0,0 @@
|
|||
# Googletest Samples {#samples}
|
||||
|
||||
If you're like us, you'd like to look at
|
||||
[googletest samples.](https://github.com/google/googletest/tree/master/googletest/samples)
|
||||
The sample directory has a number of well-commented samples showing how to use a
|
||||
variety of googletest features.
|
||||
|
||||
* Sample #1 shows the basic steps of using googletest to test C++ functions.
|
||||
* Sample #2 shows a more complex unit test for a class with multiple member
|
||||
functions.
|
||||
* Sample #3 uses a test fixture.
|
||||
* Sample #4 teaches you how to use googletest and `googletest.h` together to
|
||||
get the best of both libraries.
|
||||
* Sample #5 puts shared testing logic in a base test fixture, and reuses it in
|
||||
derived fixtures.
|
||||
* Sample #6 demonstrates type-parameterized tests.
|
||||
* Sample #7 teaches the basics of value-parameterized tests.
|
||||
* Sample #8 shows using `Combine()` in value-parameterized tests.
|
||||
* Sample #9 shows use of the listener API to modify Google Test's console
|
||||
output and the use of its reflection API to inspect test results.
|
||||
* Sample #10 shows use of the listener API to implement a primitive memory
|
||||
leak checker.
|
|
@ -35,8 +35,8 @@
|
|||
// directly.
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
|
||||
#include "gtest/internal/gtest-death-test-internal.h"
|
||||
|
||||
|
@ -97,6 +97,10 @@ GTEST_API_ bool InDeathTestChild();
|
|||
//
|
||||
// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
|
||||
//
|
||||
// The final parameter to each of these macros is a matcher applied to any data
|
||||
// the sub-process wrote to stderr. For compatibility with existing tests, a
|
||||
// bare string is interpreted as a regular expression matcher.
|
||||
//
|
||||
// On the regular expressions used in death tests:
|
||||
//
|
||||
// GOOGLETEST_CM0005 DO NOT DELETE
|
||||
|
@ -162,27 +166,27 @@ GTEST_API_ bool InDeathTestChild();
|
|||
// directory in PATH.
|
||||
//
|
||||
|
||||
// Asserts that a given statement causes the program to exit, with an
|
||||
// integer exit status that satisfies predicate, and emitting error output
|
||||
// that matches regex.
|
||||
#define ASSERT_EXIT(statement, predicate, regex) \
|
||||
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
|
||||
// Asserts that a given `statement` causes the program to exit, with an
|
||||
// integer exit status that satisfies `predicate`, and emitting error output
|
||||
// that matches `matcher`.
|
||||
# define ASSERT_EXIT(statement, predicate, matcher) \
|
||||
GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_FATAL_FAILURE_)
|
||||
|
||||
// Like ASSERT_EXIT, but continues on to successive tests in the
|
||||
// Like `ASSERT_EXIT`, but continues on to successive tests in the
|
||||
// test suite, if any:
|
||||
#define EXPECT_EXIT(statement, predicate, regex) \
|
||||
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
|
||||
# define EXPECT_EXIT(statement, predicate, matcher) \
|
||||
GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_NONFATAL_FAILURE_)
|
||||
|
||||
// Asserts that a given statement causes the program to exit, either by
|
||||
// Asserts that a given `statement` causes the program to exit, either by
|
||||
// explicitly exiting with a nonzero exit code or being killed by a
|
||||
// signal, and emitting error output that matches regex.
|
||||
#define ASSERT_DEATH(statement, regex) \
|
||||
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
||||
// signal, and emitting error output that matches `matcher`.
|
||||
# define ASSERT_DEATH(statement, matcher) \
|
||||
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
|
||||
|
||||
// Like ASSERT_DEATH, but continues on to successive tests in the
|
||||
// Like `ASSERT_DEATH`, but continues on to successive tests in the
|
||||
// test suite, if any:
|
||||
#define EXPECT_DEATH(statement, regex) \
|
||||
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
||||
# define EXPECT_DEATH(statement, matcher) \
|
||||
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
|
||||
|
||||
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
||||
|
||||
|
@ -190,16 +194,14 @@ GTEST_API_ bool InDeathTestChild();
|
|||
class GTEST_API_ ExitedWithCode {
|
||||
public:
|
||||
explicit ExitedWithCode(int exit_code);
|
||||
ExitedWithCode(const ExitedWithCode&) = default;
|
||||
void operator=(const ExitedWithCode& other) = delete;
|
||||
bool operator()(int exit_status) const;
|
||||
|
||||
private:
|
||||
// No implementation - assignment is unsupported.
|
||||
void operator=(const ExitedWithCode& other);
|
||||
|
||||
const int exit_code_;
|
||||
};
|
||||
|
||||
#if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
// Tests that an exit code describes an exit due to termination by a
|
||||
// given signal.
|
||||
// GOOGLETEST_CM0006 DO NOT DELETE
|
||||
|
@ -207,11 +209,10 @@ class GTEST_API_ KilledBySignal {
|
|||
public:
|
||||
explicit KilledBySignal(int signum);
|
||||
bool operator()(int exit_status) const;
|
||||
|
||||
private:
|
||||
const int signum_;
|
||||
};
|
||||
#endif // !GTEST_OS_WINDOWS
|
||||
# endif // !GTEST_OS_WINDOWS
|
||||
|
||||
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
|
||||
// The death testing framework causes this to have interesting semantics,
|
||||
|
@ -256,21 +257,23 @@ class GTEST_API_ KilledBySignal {
|
|||
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
|
||||
// }, "death");
|
||||
//
|
||||
#ifdef NDEBUG
|
||||
# ifdef NDEBUG
|
||||
|
||||
#define EXPECT_DEBUG_DEATH(statement, regex) \
|
||||
# define EXPECT_DEBUG_DEATH(statement, regex) \
|
||||
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
||||
|
||||
#define ASSERT_DEBUG_DEATH(statement, regex) \
|
||||
# define ASSERT_DEBUG_DEATH(statement, regex) \
|
||||
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
#define EXPECT_DEBUG_DEATH(statement, regex) EXPECT_DEATH(statement, regex)
|
||||
# define EXPECT_DEBUG_DEATH(statement, regex) \
|
||||
EXPECT_DEATH(statement, regex)
|
||||
|
||||
#define ASSERT_DEBUG_DEATH(statement, regex) ASSERT_DEATH(statement, regex)
|
||||
# define ASSERT_DEBUG_DEATH(statement, regex) \
|
||||
ASSERT_DEATH(statement, regex)
|
||||
|
||||
#endif // NDEBUG for EXPECT_DEBUG_DEATH
|
||||
# endif // NDEBUG for EXPECT_DEBUG_DEATH
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
// This macro is used for implementing macros such as
|
||||
|
@ -308,17 +311,18 @@ class GTEST_API_ KilledBySignal {
|
|||
// statement unconditionally returns or throws. The Message constructor at
|
||||
// the end allows the syntax of streaming additional messages into the
|
||||
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
|
||||
#define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
GTEST_LOG_(WARNING) << "Death tests are not supported on this platform.\n" \
|
||||
<< "Statement '" #statement "' cannot be verified."; \
|
||||
} else if (::testing::internal::AlwaysFalse()) { \
|
||||
::testing::internal::RE::PartialMatch(".*", (regex)); \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
terminator; \
|
||||
} else \
|
||||
::testing::Message()
|
||||
# define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
GTEST_LOG_(WARNING) \
|
||||
<< "Death tests are not supported on this platform.\n" \
|
||||
<< "Statement '" #statement "' cannot be verified."; \
|
||||
} else if (::testing::internal::AlwaysFalse()) { \
|
||||
::testing::internal::RE::PartialMatch(".*", (regex)); \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
terminator; \
|
||||
} else \
|
||||
::testing::Message()
|
||||
|
||||
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
|
||||
// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
|
||||
|
@ -326,17 +330,17 @@ class GTEST_API_ KilledBySignal {
|
|||
// useful when you are combining death test assertions with normal test
|
||||
// assertions in one test.
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||
EXPECT_DEATH(statement, regex)
|
||||
#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||
ASSERT_DEATH(statement, regex)
|
||||
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||
EXPECT_DEATH(statement, regex)
|
||||
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||
ASSERT_DEATH(statement, regex)
|
||||
#else
|
||||
#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, )
|
||||
#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return )
|
||||
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, )
|
||||
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return)
|
||||
#endif
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
|
|
|
@ -32,13 +32,10 @@
|
|||
// This file implements just enough of the matcher interface to allow
|
||||
// EXPECT_DEATH and friends to accept a matcher argument.
|
||||
|
||||
// IWYU pragma: private, include "testing/base/public/gunit.h"
|
||||
// IWYU pragma: friend third_party/googletest/googlemock/.*
|
||||
// IWYU pragma: friend third_party/googletest/googletest/.*
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
@ -63,20 +60,16 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
|||
namespace testing {
|
||||
|
||||
// To implement a matcher Foo for type T, define:
|
||||
// 1. a class FooMatcherImpl that implements the
|
||||
// MatcherInterface<T> interface, and
|
||||
// 1. a class FooMatcherMatcher that implements the matcher interface:
|
||||
// using is_gtest_matcher = void;
|
||||
// bool MatchAndExplain(const T&, std::ostream*);
|
||||
// (MatchResultListener* can also be used instead of std::ostream*)
|
||||
// void DescribeTo(std::ostream*);
|
||||
// void DescribeNegationTo(std::ostream*);
|
||||
//
|
||||
// 2. a factory function that creates a Matcher<T> object from a
|
||||
// FooMatcherImpl*.
|
||||
//
|
||||
// The two-level delegation design makes it possible to allow a user
|
||||
// to write "v" instead of "Eq(v)" where a Matcher is expected, which
|
||||
// is impossible if we pass matchers by pointers. It also eases
|
||||
// ownership management as Matcher objects can now be copied like
|
||||
// plain values.
|
||||
// FooMatcherMatcher.
|
||||
|
||||
// MatchResultListener is an abstract class. Its << operator can be
|
||||
// used by a matcher to explain why a value matches or doesn't match.
|
||||
//
|
||||
class MatchResultListener {
|
||||
public:
|
||||
// Creates a listener object with the given underlying ostream. The
|
||||
|
@ -113,7 +106,7 @@ inline MatchResultListener::~MatchResultListener() {
|
|||
|
||||
// An instance of a subclass of this knows how to describe itself as a
|
||||
// matcher.
|
||||
class MatcherDescriberInterface {
|
||||
class GTEST_API_ MatcherDescriberInterface {
|
||||
public:
|
||||
virtual ~MatcherDescriberInterface() {}
|
||||
|
||||
|
@ -181,31 +174,6 @@ class MatcherInterface : public MatcherDescriberInterface {
|
|||
|
||||
namespace internal {
|
||||
|
||||
// Converts a MatcherInterface<T> to a MatcherInterface<const T&>.
|
||||
template <typename T>
|
||||
class MatcherInterfaceAdapter : public MatcherInterface<const T&> {
|
||||
public:
|
||||
explicit MatcherInterfaceAdapter(const MatcherInterface<T>* impl)
|
||||
: impl_(impl) {}
|
||||
~MatcherInterfaceAdapter() override { delete impl_; }
|
||||
|
||||
void DescribeTo(::std::ostream* os) const override { impl_->DescribeTo(os); }
|
||||
|
||||
void DescribeNegationTo(::std::ostream* os) const override {
|
||||
impl_->DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
bool MatchAndExplain(const T& x,
|
||||
MatchResultListener* listener) const override {
|
||||
return impl_->MatchAndExplain(x, listener);
|
||||
}
|
||||
|
||||
private:
|
||||
const MatcherInterface<T>* const impl_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter);
|
||||
};
|
||||
|
||||
struct AnyEq {
|
||||
template <typename A, typename B>
|
||||
bool operator()(const A& a, const B& b) const { return a == b; }
|
||||
|
@ -252,16 +220,35 @@ class StreamMatchResultListener : public MatchResultListener {
|
|||
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
|
||||
};
|
||||
|
||||
struct SharedPayloadBase {
|
||||
std::atomic<int> ref{1};
|
||||
void Ref() { ref.fetch_add(1, std::memory_order_relaxed); }
|
||||
bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SharedPayload : SharedPayloadBase {
|
||||
explicit SharedPayload(const T& v) : value(v) {}
|
||||
explicit SharedPayload(T&& v) : value(std::move(v)) {}
|
||||
|
||||
static void Destroy(SharedPayloadBase* shared) {
|
||||
delete static_cast<SharedPayload*>(shared);
|
||||
}
|
||||
|
||||
T value;
|
||||
};
|
||||
|
||||
// An internal class for implementing Matcher<T>, which will derive
|
||||
// from it. We put functionalities common to all Matcher<T>
|
||||
// specializations here to avoid code duplication.
|
||||
template <typename T>
|
||||
class MatcherBase {
|
||||
class MatcherBase : private MatcherDescriberInterface {
|
||||
public:
|
||||
// Returns true if and only if the matcher matches x; also explains the
|
||||
// match result to 'listener'.
|
||||
bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
|
||||
return impl_->MatchAndExplain(x, listener);
|
||||
GTEST_CHECK_(vtable_ != nullptr);
|
||||
return vtable_->match_and_explain(*this, x, listener);
|
||||
}
|
||||
|
||||
// Returns true if and only if this matcher matches x.
|
||||
|
@ -271,11 +258,15 @@ class MatcherBase {
|
|||
}
|
||||
|
||||
// Describes this matcher to an ostream.
|
||||
void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
|
||||
void DescribeTo(::std::ostream* os) const final {
|
||||
GTEST_CHECK_(vtable_ != nullptr);
|
||||
vtable_->describe(*this, os, false);
|
||||
}
|
||||
|
||||
// Describes the negation of this matcher to an ostream.
|
||||
void DescribeNegationTo(::std::ostream* os) const {
|
||||
impl_->DescribeNegationTo(os);
|
||||
void DescribeNegationTo(::std::ostream* os) const final {
|
||||
GTEST_CHECK_(vtable_ != nullptr);
|
||||
vtable_->describe(*this, os, true);
|
||||
}
|
||||
|
||||
// Explains why x matches, or doesn't match, the matcher.
|
||||
|
@ -288,31 +279,194 @@ class MatcherBase {
|
|||
// of the describer, which is only guaranteed to be alive when
|
||||
// this matcher object is alive.
|
||||
const MatcherDescriberInterface* GetDescriber() const {
|
||||
return impl_.get();
|
||||
if (vtable_ == nullptr) return nullptr;
|
||||
return vtable_->get_describer(*this);
|
||||
}
|
||||
|
||||
protected:
|
||||
MatcherBase() {}
|
||||
MatcherBase() : vtable_(nullptr) {}
|
||||
|
||||
// Constructs a matcher from its implementation.
|
||||
explicit MatcherBase(const MatcherInterface<const T&>* impl) : impl_(impl) {}
|
||||
|
||||
template <typename U>
|
||||
explicit MatcherBase(
|
||||
const MatcherInterface<U>* impl,
|
||||
typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
|
||||
nullptr)
|
||||
: impl_(new internal::MatcherInterfaceAdapter<U>(impl)) {}
|
||||
explicit MatcherBase(const MatcherInterface<U>* impl) {
|
||||
Init(impl);
|
||||
}
|
||||
|
||||
MatcherBase(const MatcherBase&) = default;
|
||||
MatcherBase& operator=(const MatcherBase&) = default;
|
||||
MatcherBase(MatcherBase&&) = default;
|
||||
MatcherBase& operator=(MatcherBase&&) = default;
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
MatcherBase(M&& m) { // NOLINT
|
||||
Init(std::forward<M>(m));
|
||||
}
|
||||
|
||||
virtual ~MatcherBase() {}
|
||||
MatcherBase(const MatcherBase& other)
|
||||
: vtable_(other.vtable_), buffer_(other.buffer_) {
|
||||
if (IsShared()) buffer_.shared->Ref();
|
||||
}
|
||||
|
||||
MatcherBase& operator=(const MatcherBase& other) {
|
||||
if (this == &other) return *this;
|
||||
Destroy();
|
||||
vtable_ = other.vtable_;
|
||||
buffer_ = other.buffer_;
|
||||
if (IsShared()) buffer_.shared->Ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
MatcherBase(MatcherBase&& other)
|
||||
: vtable_(other.vtable_), buffer_(other.buffer_) {
|
||||
other.vtable_ = nullptr;
|
||||
}
|
||||
|
||||
MatcherBase& operator=(MatcherBase&& other) {
|
||||
if (this == &other) return *this;
|
||||
Destroy();
|
||||
vtable_ = other.vtable_;
|
||||
buffer_ = other.buffer_;
|
||||
other.vtable_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MatcherBase() override { Destroy(); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<const MatcherInterface<const T&>> impl_;
|
||||
struct VTable {
|
||||
bool (*match_and_explain)(const MatcherBase&, const T&,
|
||||
MatchResultListener*);
|
||||
void (*describe)(const MatcherBase&, std::ostream*, bool negation);
|
||||
// Returns the captured object if it implements the interface, otherwise
|
||||
// returns the MatcherBase itself.
|
||||
const MatcherDescriberInterface* (*get_describer)(const MatcherBase&);
|
||||
// Called on shared instances when the reference count reaches 0.
|
||||
void (*shared_destroy)(SharedPayloadBase*);
|
||||
};
|
||||
|
||||
bool IsShared() const {
|
||||
return vtable_ != nullptr && vtable_->shared_destroy != nullptr;
|
||||
}
|
||||
|
||||
// If the implementation uses a listener, call that.
|
||||
template <typename P>
|
||||
static auto MatchAndExplainImpl(const MatcherBase& m, const T& value,
|
||||
MatchResultListener* listener)
|
||||
-> decltype(P::Get(m).MatchAndExplain(value, listener->stream())) {
|
||||
return P::Get(m).MatchAndExplain(value, listener->stream());
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
static auto MatchAndExplainImpl(const MatcherBase& m, const T& value,
|
||||
MatchResultListener* listener)
|
||||
-> decltype(P::Get(m).MatchAndExplain(value, listener)) {
|
||||
return P::Get(m).MatchAndExplain(value, listener);
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
static void DescribeImpl(const MatcherBase& m, std::ostream* os,
|
||||
bool negation) {
|
||||
if (negation) {
|
||||
P::Get(m).DescribeNegationTo(os);
|
||||
} else {
|
||||
P::Get(m).DescribeTo(os);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
static const MatcherDescriberInterface* GetDescriberImpl(
|
||||
const MatcherBase& m) {
|
||||
// If the impl is a MatcherDescriberInterface, then return it.
|
||||
// Otherwise use MatcherBase itself.
|
||||
// This allows us to implement the GetDescriber() function without support
|
||||
// from the impl, but some users really want to get their impl back when
|
||||
// they call GetDescriber().
|
||||
// We use std::get on a tuple as a workaround of not having `if constexpr`.
|
||||
return std::get<(
|
||||
std::is_convertible<decltype(&P::Get(m)),
|
||||
const MatcherDescriberInterface*>::value
|
||||
? 1
|
||||
: 0)>(std::make_tuple(&m, &P::Get(m)));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
const VTable* GetVTable() {
|
||||
static constexpr VTable kVTable = {&MatchAndExplainImpl<P>,
|
||||
&DescribeImpl<P>, &GetDescriberImpl<P>,
|
||||
P::shared_destroy};
|
||||
return &kVTable;
|
||||
}
|
||||
|
||||
union Buffer {
|
||||
// Add some types to give Buffer some common alignment/size use cases.
|
||||
void* ptr;
|
||||
double d;
|
||||
int64_t i;
|
||||
// And add one for the out-of-line cases.
|
||||
SharedPayloadBase* shared;
|
||||
};
|
||||
|
||||
void Destroy() {
|
||||
if (IsShared() && buffer_.shared->Unref()) {
|
||||
vtable_->shared_destroy(buffer_.shared);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
static constexpr bool IsInlined() {
|
||||
return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) &&
|
||||
std::is_trivially_copy_constructible<M>::value &&
|
||||
std::is_trivially_destructible<M>::value;
|
||||
}
|
||||
|
||||
template <typename M, bool = MatcherBase::IsInlined<M>()>
|
||||
struct ValuePolicy {
|
||||
static const M& Get(const MatcherBase& m) {
|
||||
// When inlined along with Init, need to be explicit to avoid violating
|
||||
// strict aliasing rules.
|
||||
const M *ptr = static_cast<const M*>(
|
||||
static_cast<const void*>(&m.buffer_));
|
||||
return *ptr;
|
||||
}
|
||||
static void Init(MatcherBase& m, M impl) {
|
||||
::new (static_cast<void*>(&m.buffer_)) M(impl);
|
||||
}
|
||||
static constexpr auto shared_destroy = nullptr;
|
||||
};
|
||||
|
||||
template <typename M>
|
||||
struct ValuePolicy<M, false> {
|
||||
using Shared = SharedPayload<M>;
|
||||
static const M& Get(const MatcherBase& m) {
|
||||
return static_cast<Shared*>(m.buffer_.shared)->value;
|
||||
}
|
||||
template <typename Arg>
|
||||
static void Init(MatcherBase& m, Arg&& arg) {
|
||||
m.buffer_.shared = new Shared(std::forward<Arg>(arg));
|
||||
}
|
||||
static constexpr auto shared_destroy = &Shared::Destroy;
|
||||
};
|
||||
|
||||
template <typename U, bool B>
|
||||
struct ValuePolicy<const MatcherInterface<U>*, B> {
|
||||
using M = const MatcherInterface<U>;
|
||||
using Shared = SharedPayload<std::unique_ptr<M>>;
|
||||
static const M& Get(const MatcherBase& m) {
|
||||
return *static_cast<Shared*>(m.buffer_.shared)->value;
|
||||
}
|
||||
static void Init(MatcherBase& m, M* impl) {
|
||||
m.buffer_.shared = new Shared(std::unique_ptr<M>(impl));
|
||||
}
|
||||
|
||||
static constexpr auto shared_destroy = &Shared::Destroy;
|
||||
};
|
||||
|
||||
template <typename M>
|
||||
void Init(M&& m) {
|
||||
using MM = typename std::decay<M>::type;
|
||||
using Policy = ValuePolicy<MM>;
|
||||
vtable_ = GetVTable<Policy>();
|
||||
Policy::Init(*this, std::forward<M>(m));
|
||||
}
|
||||
|
||||
const VTable* vtable_;
|
||||
Buffer buffer_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -340,6 +494,10 @@ class Matcher : public internal::MatcherBase<T> {
|
|||
nullptr)
|
||||
: internal::MatcherBase<T>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) : internal::MatcherBase<T>(std::forward<M>(m)) {} // NOLINT
|
||||
|
||||
// Implicit constructor here allows people to write
|
||||
// EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
|
||||
Matcher(T value); // NOLINT
|
||||
|
@ -357,6 +515,11 @@ class GTEST_API_ Matcher<const std::string&>
|
|||
explicit Matcher(const MatcherInterface<const std::string&>* impl)
|
||||
: internal::MatcherBase<const std::string&>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<const std::string&>(std::forward<M>(m)) {}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a std::string object.
|
||||
Matcher(const std::string& s); // NOLINT
|
||||
|
@ -376,6 +539,11 @@ class GTEST_API_ Matcher<std::string>
|
|||
explicit Matcher(const MatcherInterface<std::string>* impl)
|
||||
: internal::MatcherBase<std::string>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<std::string>(std::forward<M>(m)) {}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a string object.
|
||||
Matcher(const std::string& s); // NOLINT
|
||||
|
@ -384,18 +552,24 @@ class GTEST_API_ Matcher<std::string>
|
|||
Matcher(const char* s); // NOLINT
|
||||
};
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// The following two specializations allow the user to write str
|
||||
// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
|
||||
// matcher is expected.
|
||||
template <>
|
||||
class GTEST_API_ Matcher<const absl::string_view&>
|
||||
: public internal::MatcherBase<const absl::string_view&> {
|
||||
class GTEST_API_ Matcher<const internal::StringView&>
|
||||
: public internal::MatcherBase<const internal::StringView&> {
|
||||
public:
|
||||
Matcher() {}
|
||||
|
||||
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
|
||||
: internal::MatcherBase<const absl::string_view&>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
|
||||
: internal::MatcherBase<const internal::StringView&>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<const internal::StringView&>(std::forward<M>(m)) {
|
||||
}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a std::string object.
|
||||
|
@ -404,20 +578,25 @@ class GTEST_API_ Matcher<const absl::string_view&>
|
|||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||
Matcher(const char* s); // NOLINT
|
||||
|
||||
// Allows the user to pass absl::string_views directly.
|
||||
Matcher(absl::string_view s); // NOLINT
|
||||
// Allows the user to pass absl::string_views or std::string_views directly.
|
||||
Matcher(internal::StringView s); // NOLINT
|
||||
};
|
||||
|
||||
template <>
|
||||
class GTEST_API_ Matcher<absl::string_view>
|
||||
: public internal::MatcherBase<absl::string_view> {
|
||||
class GTEST_API_ Matcher<internal::StringView>
|
||||
: public internal::MatcherBase<internal::StringView> {
|
||||
public:
|
||||
Matcher() {}
|
||||
|
||||
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
|
||||
: internal::MatcherBase<absl::string_view>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<absl::string_view>* impl)
|
||||
: internal::MatcherBase<absl::string_view>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
|
||||
: internal::MatcherBase<internal::StringView>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<internal::StringView>* impl)
|
||||
: internal::MatcherBase<internal::StringView>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<internal::StringView>(std::forward<M>(m)) {}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a std::string object.
|
||||
|
@ -426,10 +605,10 @@ class GTEST_API_ Matcher<absl::string_view>
|
|||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||
Matcher(const char* s); // NOLINT
|
||||
|
||||
// Allows the user to pass absl::string_views directly.
|
||||
Matcher(absl::string_view s); // NOLINT
|
||||
// Allows the user to pass absl::string_views or std::string_views directly.
|
||||
Matcher(internal::StringView s); // NOLINT
|
||||
};
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Prints a matcher in a human-readable format.
|
||||
template <typename T>
|
||||
|
@ -474,13 +653,13 @@ class PolymorphicMatcher {
|
|||
public:
|
||||
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
|
||||
|
||||
virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); }
|
||||
void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); }
|
||||
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||
void DescribeNegationTo(::std::ostream* os) const override {
|
||||
impl_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
|
||||
bool MatchAndExplain(T x, MatchResultListener* listener) const override {
|
||||
return impl_.MatchAndExplain(x, listener);
|
||||
}
|
||||
|
||||
|
@ -529,37 +708,32 @@ template <typename D, typename Rhs, typename Op>
|
|||
class ComparisonBase {
|
||||
public:
|
||||
explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
|
||||
|
||||
using is_gtest_matcher = void;
|
||||
|
||||
template <typename Lhs>
|
||||
operator Matcher<Lhs>() const {
|
||||
return Matcher<Lhs>(new Impl<const Lhs&>(rhs_));
|
||||
bool MatchAndExplain(const Lhs& lhs, std::ostream*) const {
|
||||
return Op()(lhs, Unwrap(rhs_));
|
||||
}
|
||||
void DescribeTo(std::ostream* os) const {
|
||||
*os << D::Desc() << " ";
|
||||
UniversalPrint(Unwrap(rhs_), os);
|
||||
}
|
||||
void DescribeNegationTo(std::ostream* os) const {
|
||||
*os << D::NegatedDesc() << " ";
|
||||
UniversalPrint(Unwrap(rhs_), os);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
static const T& Unwrap(const T& v) { return v; }
|
||||
static const T& Unwrap(const T& v) {
|
||||
return v;
|
||||
}
|
||||
template <typename T>
|
||||
static const T& Unwrap(std::reference_wrapper<T> v) { return v; }
|
||||
static const T& Unwrap(std::reference_wrapper<T> v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Lhs, typename = Rhs>
|
||||
class Impl : public MatcherInterface<Lhs> {
|
||||
public:
|
||||
explicit Impl(const Rhs& rhs) : rhs_(rhs) {}
|
||||
bool MatchAndExplain(Lhs lhs,
|
||||
MatchResultListener* /* listener */) const override {
|
||||
return Op()(lhs, Unwrap(rhs_));
|
||||
}
|
||||
void DescribeTo(::std::ostream* os) const override {
|
||||
*os << D::Desc() << " ";
|
||||
UniversalPrint(Unwrap(rhs_), os);
|
||||
}
|
||||
void DescribeNegationTo(::std::ostream* os) const override {
|
||||
*os << D::NegatedDesc() << " ";
|
||||
UniversalPrint(Unwrap(rhs_), os);
|
||||
}
|
||||
|
||||
private:
|
||||
Rhs rhs_;
|
||||
};
|
||||
Rhs rhs_;
|
||||
};
|
||||
|
||||
|
@ -612,6 +786,10 @@ class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
|
|||
static const char* NegatedDesc() { return "isn't >="; }
|
||||
};
|
||||
|
||||
template <typename T, typename = typename std::enable_if<
|
||||
std::is_constructible<std::string, T>::value>::type>
|
||||
using StringLike = T;
|
||||
|
||||
// Implements polymorphic matchers MatchesRegex(regex) and
|
||||
// ContainsRegex(regex), which can be used as a Matcher<T> as long as
|
||||
// T can be converted to a string.
|
||||
|
@ -620,12 +798,12 @@ class MatchesRegexMatcher {
|
|||
MatchesRegexMatcher(const RE* regex, bool full_match)
|
||||
: regex_(regex), full_match_(full_match) {}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
bool MatchAndExplain(const absl::string_view& s,
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
bool MatchAndExplain(const internal::StringView& s,
|
||||
MatchResultListener* listener) const {
|
||||
return MatchAndExplain(std::string(s), listener);
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Accepts pointer types, particularly:
|
||||
// const char*
|
||||
|
@ -672,9 +850,10 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
|
|||
const internal::RE* regex) {
|
||||
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
|
||||
}
|
||||
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
|
||||
const std::string& regex) {
|
||||
return MatchesRegex(new internal::RE(regex));
|
||||
template <typename T = std::string>
|
||||
PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
|
||||
const internal::StringLike<T>& regex) {
|
||||
return MatchesRegex(new internal::RE(std::string(regex)));
|
||||
}
|
||||
|
||||
// Matches a string that contains regular expression 'regex'.
|
||||
|
@ -683,9 +862,10 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
|||
const internal::RE* regex) {
|
||||
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
|
||||
}
|
||||
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
||||
const std::string& regex) {
|
||||
return ContainsRegex(new internal::RE(regex));
|
||||
template <typename T = std::string>
|
||||
PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
||||
const internal::StringLike<T>& regex) {
|
||||
return ContainsRegex(new internal::RE(std::string(regex)));
|
||||
}
|
||||
|
||||
// Creates a polymorphic matcher that matches anything equal to x.
|
||||
|
@ -747,4 +927,4 @@ inline internal::NeMatcher<Rhs> Ne(Rhs x) {
|
|||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
|
|
|
@ -44,16 +44,17 @@
|
|||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4251 /* class A needs to have dll-interface to be used by clients of class B */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
// Ensures that there is at least one operator<< in the global namespace.
|
||||
// See Message& operator<<(...) below for why.
|
||||
|
@ -109,7 +110,7 @@ class GTEST_API_ Message {
|
|||
|
||||
// Streams a non-pointer value to this object.
|
||||
template <typename T>
|
||||
inline Message& operator<<(const T& val) {
|
||||
inline Message& operator <<(const T& val) {
|
||||
// Some libraries overload << for STL containers. These
|
||||
// overloads are defined in the global namespace instead of ::std.
|
||||
//
|
||||
|
@ -124,7 +125,7 @@ class GTEST_API_ Message {
|
|||
// from the global namespace. With this using declaration,
|
||||
// overloads of << defined in the global namespace and those
|
||||
// visible via Koenig lookup are both exposed in this function.
|
||||
using ::operator<<;
|
||||
using ::operator <<;
|
||||
*ss_ << val;
|
||||
return *this;
|
||||
}
|
||||
|
@ -143,7 +144,7 @@ class GTEST_API_ Message {
|
|||
// ensure consistent result across compilers, we always treat NULL
|
||||
// as "(null)".
|
||||
template <typename T>
|
||||
inline Message& operator<<(T* const& pointer) { // NOLINT
|
||||
inline Message& operator <<(T* const& pointer) { // NOLINT
|
||||
if (pointer == nullptr) {
|
||||
*ss_ << "(null)";
|
||||
} else {
|
||||
|
@ -158,23 +159,25 @@ class GTEST_API_ Message {
|
|||
// templatized version above. Without this definition, streaming
|
||||
// endl or other basic IO manipulators to Message will confuse the
|
||||
// compiler.
|
||||
Message& operator<<(BasicNarrowIoManip val) {
|
||||
Message& operator <<(BasicNarrowIoManip val) {
|
||||
*ss_ << val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Instead of 1/0, we want to see true/false for bool values.
|
||||
Message& operator<<(bool b) { return *this << (b ? "true" : "false"); }
|
||||
Message& operator <<(bool b) {
|
||||
return *this << (b ? "true" : "false");
|
||||
}
|
||||
|
||||
// These two overloads allow streaming a wide C string to a Message
|
||||
// using the UTF-8 encoding.
|
||||
Message& operator<<(const wchar_t* wide_c_str);
|
||||
Message& operator<<(wchar_t* wide_c_str);
|
||||
Message& operator <<(const wchar_t* wide_c_str);
|
||||
Message& operator <<(wchar_t* wide_c_str);
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
// Converts the given wide string to a narrow string using the UTF-8
|
||||
// encoding, and streams the result to this Message object.
|
||||
Message& operator<<(const ::std::wstring& wstr);
|
||||
Message& operator <<(const ::std::wstring& wstr);
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Gets the text streamed to this object so far as an std::string.
|
||||
|
@ -193,7 +196,7 @@ class GTEST_API_ Message {
|
|||
};
|
||||
|
||||
// Streams a Message to an ostream.
|
||||
inline std::ostream& operator<<(std::ostream& os, const Message& sb) {
|
||||
inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
|
||||
return os << sb.GetString();
|
||||
}
|
||||
|
||||
|
@ -213,4 +216,4 @@ std::string StreamableToString(const T& streamable) {
|
|||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
|
|
|
@ -30,11 +30,9 @@
|
|||
// Macros and functions for implementing parameterized tests
|
||||
// in Google C++ Testing and Mocking Framework (Google Test)
|
||||
//
|
||||
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||
//
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||
|
||||
// Value-parameterized tests allow you to test your code with different
|
||||
// parameters without writing multiple copies of the same test.
|
||||
|
@ -355,7 +353,9 @@ internal::ValueArray<T...> Values(T... v) {
|
|||
// }
|
||||
// INSTANTIATE_TEST_SUITE_P(BoolSequence, FlagDependentTest, Bool());
|
||||
//
|
||||
inline internal::ParamGenerator<bool> Bool() { return Values(false, true); }
|
||||
inline internal::ParamGenerator<bool> Bool() {
|
||||
return Values(false, true);
|
||||
}
|
||||
|
||||
// Combine() allows the user to combine two or more sequences to produce
|
||||
// values of a Cartesian product of those sequences' elements.
|
||||
|
@ -368,8 +368,6 @@ inline internal::ParamGenerator<bool> Bool() { return Values(false, true); }
|
|||
// std::tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
|
||||
// of elements from sequences produces by gen1, gen2, ..., genN.
|
||||
//
|
||||
// Combine can have up to 10 arguments.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// This will instantiate tests in test suite AnimalTest each one with
|
||||
|
@ -413,19 +411,20 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
|||
: public test_suite_name { \
|
||||
public: \
|
||||
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \
|
||||
virtual void TestBody(); \
|
||||
void TestBody() override; \
|
||||
\
|
||||
private: \
|
||||
static int AddToRegistry() { \
|
||||
::testing::UnitTest::GetInstance() \
|
||||
->parameterized_test_registry() \
|
||||
.GetTestSuitePatternHolder<test_suite_name>( \
|
||||
#test_suite_name, \
|
||||
GTEST_STRINGIFY_(test_suite_name), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)) \
|
||||
->AddTestPattern( \
|
||||
GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name), \
|
||||
new ::testing::internal::TestMetaFactory<GTEST_TEST_CLASS_NAME_( \
|
||||
test_suite_name, test_name)>()); \
|
||||
test_suite_name, test_name)>(), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)); \
|
||||
return 0; \
|
||||
} \
|
||||
static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
|
||||
|
@ -480,13 +479,21 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
|||
::testing::UnitTest::GetInstance() \
|
||||
->parameterized_test_registry() \
|
||||
.GetTestSuitePatternHolder<test_suite_name>( \
|
||||
#test_suite_name, \
|
||||
GTEST_STRINGIFY_(test_suite_name), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)) \
|
||||
->AddTestSuiteInstantiation( \
|
||||
#prefix, >est_##prefix##test_suite_name##_EvalGenerator_, \
|
||||
GTEST_STRINGIFY_(prefix), \
|
||||
>est_##prefix##test_suite_name##_EvalGenerator_, \
|
||||
>est_##prefix##test_suite_name##_EvalGenerateName_, \
|
||||
__FILE__, __LINE__)
|
||||
|
||||
|
||||
// Allow Marking a Parameterized test class as not needing to be instantiated.
|
||||
#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \
|
||||
namespace gtest_do_not_use_outside_namespace_scope {} \
|
||||
static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \
|
||||
GTEST_STRINGIFY_(T))
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
#define INSTANTIATE_TEST_CASE_P \
|
||||
|
@ -497,4 +504,4 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
|||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
// Google Test - The Google C++ Testing and Mocking Framework
|
||||
//
|
||||
// This file implements a universal value printer that can print a
|
||||
|
@ -96,10 +97,11 @@
|
|||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream> // NOLINT
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
@ -107,63 +109,124 @@
|
|||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "absl/types/variant.h"
|
||||
#endif // GTEST_HAS_ABSL
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Definitions in the 'internal' and 'internal2' name spaces are
|
||||
// subject to change without notice. DO NOT USE THEM IN USER CODE!
|
||||
namespace internal2 {
|
||||
// Definitions in the internal* namespaces are subject to change without notice.
|
||||
// DO NOT USE THEM IN USER CODE!
|
||||
namespace internal {
|
||||
|
||||
// Prints the given number of bytes in the given object to the given
|
||||
// ostream.
|
||||
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
|
||||
size_t count, ::std::ostream* os);
|
||||
template <typename T>
|
||||
void UniversalPrint(const T& value, ::std::ostream* os);
|
||||
|
||||
// For selecting which printer to use when a given type has neither <<
|
||||
// nor PrintTo().
|
||||
enum TypeKind {
|
||||
kProtobuf, // a protobuf type
|
||||
kConvertibleToInteger, // a type implicitly convertible to BiggestInt
|
||||
// (e.g. a named or unnamed enum type)
|
||||
#if GTEST_HAS_ABSL
|
||||
kConvertibleToStringView, // a type implicitly convertible to
|
||||
// absl::string_view
|
||||
#endif
|
||||
kOtherType // anything else
|
||||
};
|
||||
// Used to print an STL-style container when the user doesn't define
|
||||
// a PrintTo() for it.
|
||||
struct ContainerPrinter {
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<
|
||||
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
|
||||
!IsRecursiveContainer<T>::value>::type>
|
||||
static void PrintValue(const T& container, std::ostream* os) {
|
||||
const size_t kMaxCount = 32; // The maximum number of elements to print.
|
||||
*os << '{';
|
||||
size_t count = 0;
|
||||
for (auto&& elem : container) {
|
||||
if (count > 0) {
|
||||
*os << ',';
|
||||
if (count == kMaxCount) { // Enough has been printed.
|
||||
*os << " ...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
*os << ' ';
|
||||
// We cannot call PrintTo(elem, os) here as PrintTo() doesn't
|
||||
// handle `elem` being a native array.
|
||||
internal::UniversalPrint(elem, os);
|
||||
++count;
|
||||
}
|
||||
|
||||
// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
|
||||
// by the universal printer to print a value of type T when neither
|
||||
// operator<< nor PrintTo() is defined for T, where kTypeKind is the
|
||||
// "kind" of T as defined by enum TypeKind.
|
||||
template <typename T, TypeKind kTypeKind>
|
||||
class TypeWithoutFormatter {
|
||||
public:
|
||||
// This default version is called when kTypeKind is kOtherType.
|
||||
static void PrintValue(const T& value, ::std::ostream* os) {
|
||||
PrintBytesInObjectTo(
|
||||
static_cast<const unsigned char*>(
|
||||
reinterpret_cast<const void*>(std::addressof(value))),
|
||||
sizeof(value), os);
|
||||
if (count > 0) {
|
||||
*os << ' ';
|
||||
}
|
||||
*os << '}';
|
||||
}
|
||||
};
|
||||
|
||||
// We print a protobuf using its ShortDebugString() when the string
|
||||
// doesn't exceed this many characters; otherwise we print it using
|
||||
// DebugString() for better readability.
|
||||
const size_t kProtobufOneLinerMaxLength = 50;
|
||||
// Used to print a pointer that is neither a char pointer nor a member
|
||||
// pointer, when the user doesn't define PrintTo() for it. (A member
|
||||
// variable pointer or member function pointer doesn't really point to
|
||||
// a location in the address space. Their representation is
|
||||
// implementation-defined. Therefore they will be printed as raw
|
||||
// bytes.)
|
||||
struct FunctionPointerPrinter {
|
||||
template <typename T, typename = typename std::enable_if<
|
||||
std::is_function<T>::value>::type>
|
||||
static void PrintValue(T* p, ::std::ostream* os) {
|
||||
if (p == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
// T is a function type, so '*os << p' doesn't do what we want
|
||||
// (it just prints p as bool). We want to print p as a const
|
||||
// void*.
|
||||
*os << reinterpret_cast<const void*>(p);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TypeWithoutFormatter<T, kProtobuf> {
|
||||
public:
|
||||
struct PointerPrinter {
|
||||
template <typename T>
|
||||
static void PrintValue(T* p, ::std::ostream* os) {
|
||||
if (p == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
// T is not a function type. We just call << to print p,
|
||||
// relying on ADL to pick up user-defined << for their pointer
|
||||
// types, if any.
|
||||
*os << p;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace internal_stream_operator_without_lexical_name_lookup {
|
||||
|
||||
// The presence of an operator<< here will terminate lexical scope lookup
|
||||
// straight away (even though it cannot be a match because of its argument
|
||||
// types). Thus, the two operator<< calls in StreamPrinter will find only ADL
|
||||
// candidates.
|
||||
struct LookupBlocker {};
|
||||
void operator<<(LookupBlocker, LookupBlocker);
|
||||
|
||||
struct StreamPrinter {
|
||||
template <typename T,
|
||||
// Don't accept member pointers here. We'd print them via implicit
|
||||
// conversion to bool, which isn't useful.
|
||||
typename = typename std::enable_if<
|
||||
!std::is_member_pointer<T>::value>::type,
|
||||
// Only accept types for which we can find a streaming operator via
|
||||
// ADL (possibly involving implicit conversions).
|
||||
typename = decltype(std::declval<std::ostream&>()
|
||||
<< std::declval<const T&>())>
|
||||
static void PrintValue(const T& value, ::std::ostream* os) {
|
||||
// Call streaming operator found by ADL, possibly with implicit conversions
|
||||
// of the arguments.
|
||||
*os << value;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal_stream_operator_without_lexical_name_lookup
|
||||
|
||||
struct ProtobufPrinter {
|
||||
// We print a protobuf using its ShortDebugString() when the string
|
||||
// doesn't exceed this many characters; otherwise we print it using
|
||||
// DebugString() for better readability.
|
||||
static const size_t kProtobufOneLinerMaxLength = 50;
|
||||
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<
|
||||
internal::HasDebugStringAndShortDebugString<T>::value>::type>
|
||||
static void PrintValue(const T& value, ::std::ostream* os) {
|
||||
std::string pretty_str = value.ShortDebugString();
|
||||
if (pretty_str.length() > kProtobufOneLinerMaxLength) {
|
||||
|
@ -173,9 +236,7 @@ class TypeWithoutFormatter<T, kProtobuf> {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TypeWithoutFormatter<T, kConvertibleToInteger> {
|
||||
public:
|
||||
struct ConvertibleToIntegerPrinter {
|
||||
// Since T has no << operator or PrintTo() but can be implicitly
|
||||
// converted to BiggestInt, we print it as a BiggestInt.
|
||||
//
|
||||
|
@ -183,112 +244,74 @@ class TypeWithoutFormatter<T, kConvertibleToInteger> {
|
|||
// case printing it as an integer is the desired behavior. In case
|
||||
// T is not an enum, printing it as an integer is the best we can do
|
||||
// given that it has no user-defined printer.
|
||||
static void PrintValue(const T& value, ::std::ostream* os) {
|
||||
const internal::BiggestInt kBigInt = value;
|
||||
*os << kBigInt;
|
||||
static void PrintValue(internal::BiggestInt value, ::std::ostream* os) {
|
||||
*os << value;
|
||||
}
|
||||
};
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
template <typename T>
|
||||
class TypeWithoutFormatter<T, kConvertibleToStringView> {
|
||||
public:
|
||||
// Since T has neither operator<< nor PrintTo() but can be implicitly
|
||||
// converted to absl::string_view, we print it as a absl::string_view.
|
||||
//
|
||||
// Note: the implementation is further below, as it depends on
|
||||
// internal::PrintTo symbol which is defined later in the file.
|
||||
static void PrintValue(const T& value, ::std::ostream* os);
|
||||
struct ConvertibleToStringViewPrinter {
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
static void PrintValue(internal::StringView value, ::std::ostream* os) {
|
||||
internal::UniversalPrint(value, os);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
// Prints the given value to the given ostream. If the value is a
|
||||
// protocol message, its debug string is printed; if it's an enum or
|
||||
// of a type implicitly convertible to BiggestInt, it's printed as an
|
||||
// integer; otherwise the bytes in the value are printed. This is
|
||||
// what UniversalPrinter<T>::Print() does when it knows nothing about
|
||||
// type T and T has neither << operator nor PrintTo().
|
||||
//
|
||||
// A user can override this behavior for a class type Foo by defining
|
||||
// a << operator in the namespace where Foo is defined.
|
||||
//
|
||||
// We put this operator in namespace 'internal2' instead of 'internal'
|
||||
// to simplify the implementation, as much code in 'internal' needs to
|
||||
// use << in STL, which would conflict with our own << were it defined
|
||||
// in 'internal'.
|
||||
//
|
||||
// Note that this operator<< takes a generic std::basic_ostream<Char,
|
||||
// CharTraits> type instead of the more restricted std::ostream. If
|
||||
// we define it to take an std::ostream instead, we'll get an
|
||||
// "ambiguous overloads" compiler error when trying to print a type
|
||||
// Foo that supports streaming to std::basic_ostream<Char,
|
||||
// CharTraits>, as the compiler cannot tell whether
|
||||
// operator<<(std::ostream&, const T&) or
|
||||
// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
|
||||
// specific.
|
||||
template <typename Char, typename CharTraits, typename T>
|
||||
::std::basic_ostream<Char, CharTraits>& operator<<(
|
||||
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
|
||||
TypeWithoutFormatter<
|
||||
T, (internal::IsAProtocolMessage<T>::value
|
||||
? kProtobuf
|
||||
: std::is_convertible<const T&, internal::BiggestInt>::value
|
||||
? kConvertibleToInteger
|
||||
:
|
||||
#if GTEST_HAS_ABSL
|
||||
std::is_convertible<const T&, absl::string_view>::value
|
||||
? kConvertibleToStringView
|
||||
:
|
||||
#endif
|
||||
kOtherType)>::PrintValue(x, &os);
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace internal2
|
||||
} // namespace testing
|
||||
// Prints the given number of bytes in the given object to the given
|
||||
// ostream.
|
||||
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
|
||||
size_t count,
|
||||
::std::ostream* os);
|
||||
struct RawBytesPrinter {
|
||||
// SFINAE on `sizeof` to make sure we have a complete type.
|
||||
template <typename T, size_t = sizeof(T)>
|
||||
static void PrintValue(const T& value, ::std::ostream* os) {
|
||||
PrintBytesInObjectTo(
|
||||
static_cast<const unsigned char*>(
|
||||
// Load bearing cast to void* to support iOS
|
||||
reinterpret_cast<const void*>(std::addressof(value))),
|
||||
sizeof(value), os);
|
||||
}
|
||||
};
|
||||
|
||||
// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
|
||||
// magic needed for implementing UniversalPrinter won't work.
|
||||
namespace testing_internal {
|
||||
struct FallbackPrinter {
|
||||
template <typename T>
|
||||
static void PrintValue(const T&, ::std::ostream* os) {
|
||||
*os << "(incomplete type)";
|
||||
}
|
||||
};
|
||||
|
||||
// Used to print a value that is not an STL-style container when the
|
||||
// user doesn't define PrintTo() for it.
|
||||
// Try every printer in order and return the first one that works.
|
||||
template <typename T, typename E, typename Printer, typename... Printers>
|
||||
struct FindFirstPrinter : FindFirstPrinter<T, E, Printers...> {};
|
||||
|
||||
template <typename T, typename Printer, typename... Printers>
|
||||
struct FindFirstPrinter<
|
||||
T, decltype(Printer::PrintValue(std::declval<const T&>(), nullptr)),
|
||||
Printer, Printers...> {
|
||||
using type = Printer;
|
||||
};
|
||||
|
||||
// Select the best printer in the following order:
|
||||
// - Print containers (they have begin/end/etc).
|
||||
// - Print function pointers.
|
||||
// - Print object pointers.
|
||||
// - Use the stream operator, if available.
|
||||
// - Print protocol buffers.
|
||||
// - Print types convertible to BiggestInt.
|
||||
// - Print types convertible to StringView, if available.
|
||||
// - Fallback to printing the raw bytes of the object.
|
||||
template <typename T>
|
||||
void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
|
||||
// With the following statement, during unqualified name lookup,
|
||||
// testing::internal2::operator<< appears as if it was declared in
|
||||
// the nearest enclosing namespace that contains both
|
||||
// ::testing_internal and ::testing::internal2, i.e. the global
|
||||
// namespace. For more details, refer to the C++ Standard section
|
||||
// 7.3.4-1 [namespace.udir]. This allows us to fall back onto
|
||||
// testing::internal2::operator<< in case T doesn't come with a <<
|
||||
// operator.
|
||||
//
|
||||
// We cannot write 'using ::testing::internal2::operator<<;', which
|
||||
// gcc 3.3 fails to compile due to a compiler bug.
|
||||
using namespace ::testing::internal2; // NOLINT
|
||||
|
||||
// Assuming T is defined in namespace foo, in the next statement,
|
||||
// the compiler will consider all of:
|
||||
//
|
||||
// 1. foo::operator<< (thanks to Koenig look-up),
|
||||
// 2. ::operator<< (as the current namespace is enclosed in ::),
|
||||
// 3. testing::internal2::operator<< (thanks to the using statement above).
|
||||
//
|
||||
// The operator<< whose type matches T best will be picked.
|
||||
//
|
||||
// We deliberately allow #2 to be a candidate, as sometimes it's
|
||||
// impossible to define #1 (e.g. when foo is ::std, defining
|
||||
// anything in it is undefined behavior unless you are a compiler
|
||||
// vendor.).
|
||||
*os << value;
|
||||
void PrintWithFallback(const T& value, ::std::ostream* os) {
|
||||
using Printer = typename FindFirstPrinter<
|
||||
T, void, ContainerPrinter, FunctionPointerPrinter, PointerPrinter,
|
||||
internal_stream_operator_without_lexical_name_lookup::StreamPrinter,
|
||||
ProtobufPrinter, ConvertibleToIntegerPrinter,
|
||||
ConvertibleToStringViewPrinter, RawBytesPrinter, FallbackPrinter>::type;
|
||||
Printer::PrintValue(value, os);
|
||||
}
|
||||
|
||||
} // namespace testing_internal
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
|
||||
// value of type ToPrint that is an operand of a comparison assertion
|
||||
// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in
|
||||
|
@ -337,6 +360,14 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
|
|||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
|
||||
#ifdef __cpp_char8_t
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t);
|
||||
#endif
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char16_t);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char16_t);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char32_t);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char32_t);
|
||||
|
||||
#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
|
||||
|
||||
|
@ -344,16 +375,24 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
|
|||
// to point to a NUL-terminated string, and thus can print it as a string.
|
||||
|
||||
#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
|
||||
template <> \
|
||||
class FormatForComparison<CharType*, OtherStringType> { \
|
||||
public: \
|
||||
static ::std::string Format(CharType* value) { \
|
||||
return ::testing::PrintToString(value); \
|
||||
} \
|
||||
template <> \
|
||||
class FormatForComparison<CharType*, OtherStringType> { \
|
||||
public: \
|
||||
static ::std::string Format(CharType* value) { \
|
||||
return ::testing::PrintToString(value); \
|
||||
} \
|
||||
}
|
||||
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
|
||||
#ifdef __cpp_char8_t
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char8_t, ::std::u8string);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char8_t, ::std::u8string);
|
||||
#endif
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char16_t, ::std::u16string);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char16_t, ::std::u16string);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char32_t, ::std::u32string);
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char32_t, ::std::u32string);
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
|
||||
|
@ -371,8 +410,8 @@ GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
|
|||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
template <typename T1, typename T2>
|
||||
std::string FormatForComparisonFailureMessage(const T1& value,
|
||||
const T2& /* other_operand */) {
|
||||
std::string FormatForComparisonFailureMessage(
|
||||
const T1& value, const T2& /* other_operand */) {
|
||||
return FormatForComparison<T1, T2>::Format(value);
|
||||
}
|
||||
|
||||
|
@ -386,86 +425,6 @@ std::string FormatForComparisonFailureMessage(const T1& value,
|
|||
template <typename T>
|
||||
class UniversalPrinter;
|
||||
|
||||
template <typename T>
|
||||
void UniversalPrint(const T& value, ::std::ostream* os);
|
||||
|
||||
enum DefaultPrinterType {
|
||||
kPrintContainer,
|
||||
kPrintPointer,
|
||||
kPrintFunctionPointer,
|
||||
kPrintOther,
|
||||
};
|
||||
template <DefaultPrinterType type>
|
||||
struct WrapPrinterType {};
|
||||
|
||||
// Used to print an STL-style container when the user doesn't define
|
||||
// a PrintTo() for it.
|
||||
template <typename C>
|
||||
void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */,
|
||||
const C& container, ::std::ostream* os) {
|
||||
const size_t kMaxCount = 32; // The maximum number of elements to print.
|
||||
*os << '{';
|
||||
size_t count = 0;
|
||||
for (typename C::const_iterator it = container.begin(); it != container.end();
|
||||
++it, ++count) {
|
||||
if (count > 0) {
|
||||
*os << ',';
|
||||
if (count == kMaxCount) { // Enough has been printed.
|
||||
*os << " ...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
*os << ' ';
|
||||
// We cannot call PrintTo(*it, os) here as PrintTo() doesn't
|
||||
// handle *it being a native array.
|
||||
internal::UniversalPrint(*it, os);
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
*os << ' ';
|
||||
}
|
||||
*os << '}';
|
||||
}
|
||||
|
||||
// Used to print a pointer that is neither a char pointer nor a member
|
||||
// pointer, when the user doesn't define PrintTo() for it. (A member
|
||||
// variable pointer or member function pointer doesn't really point to
|
||||
// a location in the address space. Their representation is
|
||||
// implementation-defined. Therefore they will be printed as raw
|
||||
// bytes.)
|
||||
template <typename T>
|
||||
void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */, T* p,
|
||||
::std::ostream* os) {
|
||||
if (p == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
// T is not a function type. We just call << to print p,
|
||||
// relying on ADL to pick up user-defined << for their pointer
|
||||
// types, if any.
|
||||
*os << p;
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */, T* p,
|
||||
::std::ostream* os) {
|
||||
if (p == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
// T is a function type, so '*os << p' doesn't do what we want
|
||||
// (it just prints p as bool). We want to print p as a const
|
||||
// void*.
|
||||
*os << reinterpret_cast<const void*>(p);
|
||||
}
|
||||
}
|
||||
|
||||
// Used to print a non-container, non-pointer value when the user
|
||||
// doesn't define PrintTo() for it.
|
||||
template <typename T>
|
||||
void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */, const T& value,
|
||||
::std::ostream* os) {
|
||||
::testing_internal::DefaultPrintNonContainerTo(value, os);
|
||||
}
|
||||
|
||||
// Prints the given value using the << operator if it has one;
|
||||
// otherwise prints the bytes in it. This is what
|
||||
// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
|
||||
|
@ -479,36 +438,7 @@ void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */, const T& value,
|
|||
// wants).
|
||||
template <typename T>
|
||||
void PrintTo(const T& value, ::std::ostream* os) {
|
||||
// DefaultPrintTo() is overloaded. The type of its first argument
|
||||
// determines which version will be picked.
|
||||
//
|
||||
// Note that we check for container types here, prior to we check
|
||||
// for protocol message types in our operator<<. The rationale is:
|
||||
//
|
||||
// For protocol messages, we want to give people a chance to
|
||||
// override Google Mock's format by defining a PrintTo() or
|
||||
// operator<<. For STL containers, other formats can be
|
||||
// incompatible with Google Mock's format for the container
|
||||
// elements; therefore we check for container types here to ensure
|
||||
// that our format is used.
|
||||
//
|
||||
// Note that MSVC and clang-cl do allow an implicit conversion from
|
||||
// pointer-to-function to pointer-to-object, but clang-cl warns on it.
|
||||
// So don't use ImplicitlyConvertible if it can be helped since it will
|
||||
// cause this warning, and use a separate overload of DefaultPrintTo for
|
||||
// function pointers so that the `*os << p` in the object pointer overload
|
||||
// doesn't cause that warning either.
|
||||
DefaultPrintTo(
|
||||
WrapPrinterType <
|
||||
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
|
||||
!IsRecursiveContainer<T>::value
|
||||
? kPrintContainer
|
||||
: !std::is_pointer<T>::value
|
||||
? kPrintOther
|
||||
: std::is_function<typename std::remove_pointer<T>::type>::value
|
||||
? kPrintFunctionPointer
|
||||
: kPrintPointer > (),
|
||||
value, os);
|
||||
internal::PrintWithFallback(value, os);
|
||||
}
|
||||
|
||||
// The following list of PrintTo() overloads tells
|
||||
|
@ -539,6 +469,16 @@ inline void PrintTo(bool x, ::std::ostream* os) {
|
|||
// is implemented as an unsigned type.
|
||||
GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
|
||||
|
||||
GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os);
|
||||
inline void PrintTo(char16_t c, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<char32_t>(c), os);
|
||||
}
|
||||
#ifdef __cpp_char8_t
|
||||
inline void PrintTo(char8_t c, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<char32_t>(c), os);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Overloads for C strings.
|
||||
GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
|
||||
inline void PrintTo(char* s, ::std::ostream* os) {
|
||||
|
@ -559,6 +499,23 @@ inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
|
|||
inline void PrintTo(unsigned char* s, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<const void*>(s), os);
|
||||
}
|
||||
#ifdef __cpp_char8_t
|
||||
// Overloads for u8 strings.
|
||||
GTEST_API_ void PrintTo(const char8_t* s, ::std::ostream* os);
|
||||
inline void PrintTo(char8_t* s, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<const char8_t*>(s), os);
|
||||
}
|
||||
#endif
|
||||
// Overloads for u16 strings.
|
||||
GTEST_API_ void PrintTo(const char16_t* s, ::std::ostream* os);
|
||||
inline void PrintTo(char16_t* s, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<const char16_t*>(s), os);
|
||||
}
|
||||
// Overloads for u32 strings.
|
||||
GTEST_API_ void PrintTo(const char32_t* s, ::std::ostream* os);
|
||||
inline void PrintTo(char32_t* s, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<const char32_t*>(s), os);
|
||||
}
|
||||
|
||||
// MSVC can be configured to define wchar_t as a typedef of unsigned
|
||||
// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
|
||||
|
@ -588,25 +545,45 @@ void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
|
|||
}
|
||||
|
||||
// Overloads for ::std::string.
|
||||
GTEST_API_ void PrintStringTo(const ::std::string& s, ::std::ostream* os);
|
||||
GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
|
||||
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
|
||||
PrintStringTo(s, os);
|
||||
}
|
||||
|
||||
// Overloads for ::std::u8string
|
||||
#ifdef __cpp_char8_t
|
||||
GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os);
|
||||
inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) {
|
||||
PrintU8StringTo(s, os);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Overloads for ::std::u16string
|
||||
GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os);
|
||||
inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
|
||||
PrintU16StringTo(s, os);
|
||||
}
|
||||
|
||||
// Overloads for ::std::u32string
|
||||
GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os);
|
||||
inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
|
||||
PrintU32StringTo(s, os);
|
||||
}
|
||||
|
||||
// Overloads for ::std::wstring.
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
GTEST_API_ void PrintWideStringTo(const ::std::wstring& s, ::std::ostream* os);
|
||||
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
|
||||
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
||||
PrintWideStringTo(s, os);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
// Overload for absl::string_view.
|
||||
inline void PrintTo(absl::string_view sp, ::std::ostream* os) {
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Overload for internal::StringView.
|
||||
inline void PrintTo(internal::StringView sp, ::std::ostream* os) {
|
||||
PrintTo(::std::string(sp), os);
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
|
||||
|
||||
|
@ -615,6 +592,43 @@ void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) {
|
|||
UniversalPrinter<T&>::Print(ref.get(), os);
|
||||
}
|
||||
|
||||
inline const void* VoidifyPointer(const void* p) { return p; }
|
||||
inline const void* VoidifyPointer(volatile const void* p) {
|
||||
return const_cast<const void*>(p);
|
||||
}
|
||||
|
||||
template <typename T, typename Ptr>
|
||||
void PrintSmartPointer(const Ptr& ptr, std::ostream* os, char) {
|
||||
if (ptr == nullptr) {
|
||||
*os << "(nullptr)";
|
||||
} else {
|
||||
// We can't print the value. Just print the pointer..
|
||||
*os << "(" << (VoidifyPointer)(ptr.get()) << ")";
|
||||
}
|
||||
}
|
||||
template <typename T, typename Ptr,
|
||||
typename = typename std::enable_if<!std::is_void<T>::value &&
|
||||
!std::is_array<T>::value>::type>
|
||||
void PrintSmartPointer(const Ptr& ptr, std::ostream* os, int) {
|
||||
if (ptr == nullptr) {
|
||||
*os << "(nullptr)";
|
||||
} else {
|
||||
*os << "(ptr = " << (VoidifyPointer)(ptr.get()) << ", value = ";
|
||||
UniversalPrinter<T>::Print(*ptr, os);
|
||||
*os << ")";
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename D>
|
||||
void PrintTo(const std::unique_ptr<T, D>& ptr, std::ostream* os) {
|
||||
(PrintSmartPointer<T>)(ptr, os, 0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PrintTo(const std::shared_ptr<T>& ptr, std::ostream* os) {
|
||||
(PrintSmartPointer<T>)(ptr, os, 0);
|
||||
}
|
||||
|
||||
// Helper function for printing a tuple. T must be instantiated with
|
||||
// a tuple type.
|
||||
template <typename T>
|
||||
|
@ -680,14 +694,46 @@ class UniversalPrinter {
|
|||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
};
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
// Remove any const-qualifiers before passing a type to UniversalPrinter.
|
||||
template <typename T>
|
||||
class UniversalPrinter<const T> : public UniversalPrinter<T> {};
|
||||
|
||||
// Printer for absl::optional
|
||||
#if GTEST_INTERNAL_HAS_ANY
|
||||
|
||||
// Printer for std::any / absl::any
|
||||
|
||||
template <>
|
||||
class UniversalPrinter<Any> {
|
||||
public:
|
||||
static void Print(const Any& value, ::std::ostream* os) {
|
||||
if (value.has_value()) {
|
||||
*os << "value of type " << GetTypeName(value);
|
||||
} else {
|
||||
*os << "no value";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string GetTypeName(const Any& value) {
|
||||
#if GTEST_HAS_RTTI
|
||||
return internal::GetTypeName(value.type());
|
||||
#else
|
||||
static_cast<void>(value); // possibly unused
|
||||
return "<unknown_type>";
|
||||
#endif // GTEST_HAS_RTTI
|
||||
}
|
||||
};
|
||||
|
||||
#endif // GTEST_INTERNAL_HAS_ANY
|
||||
|
||||
#if GTEST_INTERNAL_HAS_OPTIONAL
|
||||
|
||||
// Printer for std::optional / absl::optional
|
||||
|
||||
template <typename T>
|
||||
class UniversalPrinter<::absl::optional<T>> {
|
||||
class UniversalPrinter<Optional<T>> {
|
||||
public:
|
||||
static void Print(const ::absl::optional<T>& value, ::std::ostream* os) {
|
||||
static void Print(const Optional<T>& value, ::std::ostream* os) {
|
||||
*os << '(';
|
||||
if (!value) {
|
||||
*os << "nullopt";
|
||||
|
@ -698,14 +744,22 @@ class UniversalPrinter<::absl::optional<T>> {
|
|||
}
|
||||
};
|
||||
|
||||
// Printer for absl::variant
|
||||
#endif // GTEST_INTERNAL_HAS_OPTIONAL
|
||||
|
||||
#if GTEST_INTERNAL_HAS_VARIANT
|
||||
|
||||
// Printer for std::variant / absl::variant
|
||||
|
||||
template <typename... T>
|
||||
class UniversalPrinter<::absl::variant<T...>> {
|
||||
class UniversalPrinter<Variant<T...>> {
|
||||
public:
|
||||
static void Print(const ::absl::variant<T...>& value, ::std::ostream* os) {
|
||||
static void Print(const Variant<T...>& value, ::std::ostream* os) {
|
||||
*os << '(';
|
||||
absl::visit(Visitor{os}, value);
|
||||
#if GTEST_HAS_ABSL
|
||||
absl::visit(Visitor{os, value.index()}, value);
|
||||
#else
|
||||
std::visit(Visitor{os, value.index()}, value);
|
||||
#endif // GTEST_HAS_ABSL
|
||||
*os << ')';
|
||||
}
|
||||
|
||||
|
@ -713,14 +767,16 @@ class UniversalPrinter<::absl::variant<T...>> {
|
|||
struct Visitor {
|
||||
template <typename U>
|
||||
void operator()(const U& u) const {
|
||||
*os << "'" << GetTypeName<U>() << "' with value ";
|
||||
*os << "'" << GetTypeName<U>() << "(index = " << index
|
||||
<< ")' with value ";
|
||||
UniversalPrint(u, os);
|
||||
}
|
||||
::std::ostream* os;
|
||||
std::size_t index;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_VARIANT
|
||||
|
||||
// UniversalPrintArray(begin, len, os) prints an array of 'len'
|
||||
// elements, starting at address 'begin'.
|
||||
|
@ -746,12 +802,26 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
|
|||
}
|
||||
}
|
||||
// This overload prints a (const) char array compactly.
|
||||
GTEST_API_ void UniversalPrintArray(const char* begin, size_t len,
|
||||
GTEST_API_ void UniversalPrintArray(
|
||||
const char* begin, size_t len, ::std::ostream* os);
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
// This overload prints a (const) char8_t array compactly.
|
||||
GTEST_API_ void UniversalPrintArray(const char8_t* begin, size_t len,
|
||||
::std::ostream* os);
|
||||
#endif
|
||||
|
||||
// This overload prints a (const) char16_t array compactly.
|
||||
GTEST_API_ void UniversalPrintArray(const char16_t* begin, size_t len,
|
||||
::std::ostream* os);
|
||||
|
||||
// This overload prints a (const) char32_t array compactly.
|
||||
GTEST_API_ void UniversalPrintArray(const char32_t* begin, size_t len,
|
||||
::std::ostream* os);
|
||||
|
||||
// This overload prints a (const) wchar_t array compactly.
|
||||
GTEST_API_ void UniversalPrintArray(const wchar_t* begin, size_t len,
|
||||
::std::ostream* os);
|
||||
GTEST_API_ void UniversalPrintArray(
|
||||
const wchar_t* begin, size_t len, ::std::ostream* os);
|
||||
|
||||
// Implements printing an array type T[N].
|
||||
template <typename T, size_t N>
|
||||
|
@ -821,12 +891,55 @@ class UniversalTersePrinter<const char*> {
|
|||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<char*> {
|
||||
class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {
|
||||
};
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
template <>
|
||||
class UniversalTersePrinter<const char8_t*> {
|
||||
public:
|
||||
static void Print(char* str, ::std::ostream* os) {
|
||||
UniversalTersePrinter<const char*>::Print(str, os);
|
||||
static void Print(const char8_t* str, ::std::ostream* os) {
|
||||
if (str == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
UniversalPrint(::std::u8string(str), os);
|
||||
}
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<char8_t*>
|
||||
: public UniversalTersePrinter<const char8_t*> {};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
class UniversalTersePrinter<const char16_t*> {
|
||||
public:
|
||||
static void Print(const char16_t* str, ::std::ostream* os) {
|
||||
if (str == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
UniversalPrint(::std::u16string(str), os);
|
||||
}
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<char16_t*>
|
||||
: public UniversalTersePrinter<const char16_t*> {};
|
||||
|
||||
template <>
|
||||
class UniversalTersePrinter<const char32_t*> {
|
||||
public:
|
||||
static void Print(const char32_t* str, ::std::ostream* os) {
|
||||
if (str == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
UniversalPrint(::std::u32string(str), os);
|
||||
}
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<char32_t*>
|
||||
: public UniversalTersePrinter<const char32_t*> {};
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
template <>
|
||||
|
@ -867,10 +980,10 @@ void UniversalPrint(const T& value, ::std::ostream* os) {
|
|||
UniversalPrinter<T1>::Print(value, os);
|
||||
}
|
||||
|
||||
typedef ::std::vector<::std::string> Strings;
|
||||
typedef ::std::vector< ::std::string> Strings;
|
||||
|
||||
// Tersely prints the first N fields of a tuple to a string vector,
|
||||
// one element for each field.
|
||||
// Tersely prints the first N fields of a tuple to a string vector,
|
||||
// one element for each field.
|
||||
template <typename Tuple>
|
||||
void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>,
|
||||
Strings*) {}
|
||||
|
@ -899,16 +1012,6 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
|||
|
||||
} // namespace internal
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
namespace internal2 {
|
||||
template <typename T>
|
||||
void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue(
|
||||
const T& value, ::std::ostream* os) {
|
||||
internal::PrintTo(absl::string_view(value), os);
|
||||
}
|
||||
} // namespace internal2
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
::std::string PrintToString(const T& value) {
|
||||
::std::stringstream ss;
|
||||
|
@ -923,4 +1026,4 @@ template <typename T>
|
|||
// declarations from this file.
|
||||
#include "gtest/internal/custom/gtest-printers.h"
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||
|
|
|
@ -33,13 +33,13 @@
|
|||
|
||||
// GOOGLETEST_CM0004 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4251 /* class A needs to have dll-interface to be used by clients of class B */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
namespace testing {
|
||||
|
||||
|
@ -104,7 +104,6 @@ class GTEST_API_ SingleFailureChecker {
|
|||
SingleFailureChecker(const TestPartResultArray* results,
|
||||
TestPartResult::Type type, const std::string& substr);
|
||||
~SingleFailureChecker();
|
||||
|
||||
private:
|
||||
const TestPartResultArray* const results_;
|
||||
const TestPartResult::Type type_;
|
||||
|
@ -142,39 +141,38 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
|||
// helper macro, due to some peculiarity in how the preprocessor
|
||||
// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
|
||||
// gtest_unittest.cc will fail to compile if we do that.
|
||||
#define EXPECT_FATAL_FAILURE(statement, substr) \
|
||||
do { \
|
||||
class GTestExpectFatalFailureHelper { \
|
||||
public: \
|
||||
static void Execute() { statement; } \
|
||||
}; \
|
||||
::testing::TestPartResultArray gtest_failures; \
|
||||
::testing::internal::SingleFailureChecker gtest_checker( \
|
||||
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr)); \
|
||||
{ \
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
|
||||
::testing::ScopedFakeTestPartResultReporter:: \
|
||||
INTERCEPT_ONLY_CURRENT_THREAD, \
|
||||
>est_failures); \
|
||||
GTestExpectFatalFailureHelper::Execute(); \
|
||||
} \
|
||||
#define EXPECT_FATAL_FAILURE(statement, substr) \
|
||||
do { \
|
||||
class GTestExpectFatalFailureHelper {\
|
||||
public:\
|
||||
static void Execute() { statement; }\
|
||||
};\
|
||||
::testing::TestPartResultArray gtest_failures;\
|
||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
||||
{\
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||
::testing::ScopedFakeTestPartResultReporter:: \
|
||||
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
||||
GTestExpectFatalFailureHelper::Execute();\
|
||||
}\
|
||||
} while (::testing::internal::AlwaysFalse())
|
||||
|
||||
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||
do { \
|
||||
class GTestExpectFatalFailureHelper { \
|
||||
public: \
|
||||
static void Execute() { statement; } \
|
||||
}; \
|
||||
::testing::TestPartResultArray gtest_failures; \
|
||||
::testing::internal::SingleFailureChecker gtest_checker( \
|
||||
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr)); \
|
||||
{ \
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
|
||||
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
||||
>est_failures); \
|
||||
GTestExpectFatalFailureHelper::Execute(); \
|
||||
} \
|
||||
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||
do { \
|
||||
class GTestExpectFatalFailureHelper {\
|
||||
public:\
|
||||
static void Execute() { statement; }\
|
||||
};\
|
||||
::testing::TestPartResultArray gtest_failures;\
|
||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
||||
{\
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||
::testing::ScopedFakeTestPartResultReporter:: \
|
||||
INTERCEPT_ALL_THREADS, >est_failures);\
|
||||
GTestExpectFatalFailureHelper::Execute();\
|
||||
}\
|
||||
} while (::testing::internal::AlwaysFalse())
|
||||
|
||||
// A macro for testing Google Test assertions or code that's expected to
|
||||
|
@ -209,37 +207,32 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
|||
// instead of
|
||||
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
||||
// to avoid an MSVC warning on unreachable code.
|
||||
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
|
||||
do { \
|
||||
::testing::TestPartResultArray gtest_failures; \
|
||||
::testing::internal::SingleFailureChecker gtest_checker( \
|
||||
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
|
||||
do {\
|
||||
::testing::TestPartResultArray gtest_failures;\
|
||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||
(substr)); \
|
||||
{ \
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
|
||||
::testing::ScopedFakeTestPartResultReporter:: \
|
||||
INTERCEPT_ONLY_CURRENT_THREAD, \
|
||||
>est_failures); \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
statement; \
|
||||
} \
|
||||
} \
|
||||
(substr));\
|
||||
{\
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||
::testing::ScopedFakeTestPartResultReporter:: \
|
||||
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
||||
if (::testing::internal::AlwaysTrue()) { statement; }\
|
||||
}\
|
||||
} while (::testing::internal::AlwaysFalse())
|
||||
|
||||
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||
do { \
|
||||
::testing::TestPartResultArray gtest_failures; \
|
||||
::testing::internal::SingleFailureChecker gtest_checker( \
|
||||
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||
(substr)); \
|
||||
{ \
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
|
||||
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||
do {\
|
||||
::testing::TestPartResultArray gtest_failures;\
|
||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||
(substr));\
|
||||
{\
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
||||
>est_failures); \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
statement; \
|
||||
} \
|
||||
} \
|
||||
>est_failures);\
|
||||
if (::testing::internal::AlwaysTrue()) { statement; }\
|
||||
}\
|
||||
} while (::testing::internal::AlwaysFalse())
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
|
|
|
@ -29,16 +29,16 @@
|
|||
//
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4251 /* class A needs to have dll-interface to be used by clients of class B */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
namespace testing {
|
||||
|
||||
|
@ -168,7 +168,6 @@ class GTEST_API_ HasNewFatalFailureHelper
|
|||
~HasNewFatalFailureHelper() override;
|
||||
void ReportTestPartResult(const TestPartResult& result) override;
|
||||
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
||||
|
||||
private:
|
||||
bool has_new_fatal_failure_;
|
||||
TestPartResultReporterInterface* original_reporter_;
|
||||
|
@ -182,4 +181,4 @@ class GTEST_API_ HasNewFatalFailureHelper
|
|||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
|
||||
// This header implements typed tests and type-parameterized tests.
|
||||
|
||||
|
@ -169,13 +169,12 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||
|
||||
#endif // 0
|
||||
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/internal/gtest-type-util.h"
|
||||
|
||||
// Implements typed tests.
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Expands to the name of the typedef for the type parameters of the
|
||||
|
@ -187,35 +186,39 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||
#define GTEST_NAME_GENERATOR_(TestSuiteName) \
|
||||
gtest_type_params_##TestSuiteName##_NameGenerator
|
||||
|
||||
#define TYPED_TEST_SUITE(CaseName, Types, ...) \
|
||||
typedef ::testing::internal::TypeList<Types>::type GTEST_TYPE_PARAMS_( \
|
||||
CaseName); \
|
||||
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
|
||||
#define TYPED_TEST_SUITE(CaseName, Types, ...) \
|
||||
typedef ::testing::internal::GenerateTypeList<Types>::type \
|
||||
GTEST_TYPE_PARAMS_(CaseName); \
|
||||
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
|
||||
GTEST_NAME_GENERATOR_(CaseName)
|
||||
|
||||
#define TYPED_TEST(CaseName, TestName) \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||
: public CaseName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
virtual void TestBody(); \
|
||||
}; \
|
||||
static bool gtest_##CaseName##_##TestName##_registered_ \
|
||||
GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest< \
|
||||
CaseName, ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_( \
|
||||
CaseName, TestName)>, \
|
||||
GTEST_TYPE_PARAMS_( \
|
||||
CaseName)>::Register("", \
|
||||
::testing::internal::CodeLocation( \
|
||||
__FILE__, __LINE__), \
|
||||
#CaseName, #TestName, 0, \
|
||||
::testing::internal::GenerateNames< \
|
||||
GTEST_NAME_GENERATOR_(CaseName), \
|
||||
GTEST_TYPE_PARAMS_(CaseName)>()); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
#define TYPED_TEST(CaseName, TestName) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
|
||||
"test-name must not be empty"); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||
: public CaseName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
static bool gtest_##CaseName##_##TestName##_registered_ \
|
||||
GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest< \
|
||||
CaseName, \
|
||||
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
TestName)>, \
|
||||
GTEST_TYPE_PARAMS_( \
|
||||
CaseName)>::Register("", \
|
||||
::testing::internal::CodeLocation( \
|
||||
__FILE__, __LINE__), \
|
||||
GTEST_STRINGIFY_(CaseName), \
|
||||
GTEST_STRINGIFY_(TestName), 0, \
|
||||
::testing::internal::GenerateNames< \
|
||||
GTEST_NAME_GENERATOR_(CaseName), \
|
||||
GTEST_TYPE_PARAMS_(CaseName)>()); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
TestName)<gtest_TypeParam_>::TestBody()
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
|
@ -225,12 +228,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||
TYPED_TEST_SUITE
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST
|
||||
|
||||
// Implements type-parameterized tests.
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Expands to the namespace name that the type-parameterized tests for
|
||||
|
@ -273,24 +272,26 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||
private: \
|
||||
typedef SuiteName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
virtual void TestBody(); \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
||||
__FILE__, __LINE__, #SuiteName, #TestName); \
|
||||
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_STRINGIFY_(TestName)); \
|
||||
} \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_SUITE_NAMESPACE_( \
|
||||
SuiteName)::TestName<gtest_TypeParam_>::TestBody()
|
||||
|
||||
#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
|
||||
} \
|
||||
static const char* const GTEST_REGISTERED_TEST_NAMES_( \
|
||||
SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
|
||||
__FILE__, __LINE__, #__VA_ARGS__)
|
||||
// Note: this won't work correctly if the trailing arguments are macros.
|
||||
#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
|
||||
} \
|
||||
static const char* const GTEST_REGISTERED_TEST_NAMES_( \
|
||||
SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
|
||||
GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
@ -301,18 +302,21 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
|
||||
"test-suit-prefix must not be empty"); \
|
||||
static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
::testing::internal::TypeParameterizedTestSuite< \
|
||||
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
|
||||
::testing::internal::TypeList<Types>::type>:: \
|
||||
Register(#Prefix, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>:: \
|
||||
Register(GTEST_STRINGIFY_(Prefix), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
||||
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), #SuiteName, \
|
||||
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
|
||||
GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
|
||||
::testing::internal::GenerateNames< \
|
||||
::testing::internal::NameGeneratorSelector< \
|
||||
__VA_ARGS__>::type, \
|
||||
::testing::internal::TypeList<Types>::type>())
|
||||
::testing::internal::GenerateTypeList<Types>::type>())
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
@ -322,6 +326,4 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||
INSTANTIATE_TYPED_TEST_SUITE_P
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
|
|
|
@ -49,8 +49,8 @@
|
|||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
|
@ -70,19 +70,20 @@
|
|||
#include "gtest/gtest-test-part.h"
|
||||
#include "gtest/gtest-typed-test.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4251 /* class A needs to have dll-interface to be used by clients of class B */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Silence C4100 (unreferenced formal parameter) and 4805
|
||||
// unsafe mix of type 'const int' and type 'const bool'
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4805)
|
||||
#pragma warning(disable : 4100)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4805)
|
||||
# pragma warning(disable:4100)
|
||||
#endif
|
||||
|
||||
|
||||
// Declares the flags.
|
||||
|
||||
// This flag temporary enables the disabled tests.
|
||||
|
@ -100,6 +101,10 @@ GTEST_DECLARE_bool_(catch_exceptions);
|
|||
// to let Google Test decide.
|
||||
GTEST_DECLARE_string_(color);
|
||||
|
||||
// This flag controls whether the test runner should continue execution past
|
||||
// first failure.
|
||||
GTEST_DECLARE_bool_(fail_fast);
|
||||
|
||||
// This flag sets up the filter to select by name using a glob pattern
|
||||
// the tests to run. If the filter is not given all tests are executed.
|
||||
GTEST_DECLARE_string_(filter);
|
||||
|
@ -116,6 +121,9 @@ GTEST_DECLARE_bool_(list_tests);
|
|||
// in addition to its normal textual output.
|
||||
GTEST_DECLARE_string_(output);
|
||||
|
||||
// This flags control whether Google Test prints only test failures.
|
||||
GTEST_DECLARE_bool_(brief);
|
||||
|
||||
// This flags control whether Google Test prints the elapsed time for each
|
||||
// test.
|
||||
GTEST_DECLARE_bool_(print_time);
|
||||
|
@ -176,6 +184,7 @@ class FuchsiaDeathTest;
|
|||
class UnitTestImpl* GetUnitTestImpl();
|
||||
void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
|
||||
const std::string& message);
|
||||
std::set<std::string>* GetIgnoredParameterizedTestSuites();
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
@ -277,7 +286,11 @@ class GTEST_API_ AssertionResult {
|
|||
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||
AssertionResult(const AssertionResult& other);
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1910
|
||||
// C4800 is a level 3 warning in Visual Studio 2015 and earlier.
|
||||
// This warning is not emitted in Visual Studio 2017.
|
||||
// This warning is off by default starting in Visual Studio 2019 but can be
|
||||
// enabled with command-line options.
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
|
||||
#endif
|
||||
|
||||
|
@ -297,7 +310,7 @@ class GTEST_API_ AssertionResult {
|
|||
= nullptr)
|
||||
: success_(success) {}
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1910
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
#endif
|
||||
|
||||
|
@ -324,8 +337,7 @@ class GTEST_API_ AssertionResult {
|
|||
const char* failure_message() const { return message(); }
|
||||
|
||||
// Streams a custom failure message into this object.
|
||||
template <typename T>
|
||||
AssertionResult& operator<<(const T& value) {
|
||||
template <typename T> AssertionResult& operator<<(const T& value) {
|
||||
AppendMessage(Message() << value);
|
||||
return *this;
|
||||
}
|
||||
|
@ -406,27 +418,24 @@ class GTEST_API_ Test {
|
|||
// The d'tor is virtual as we intend to inherit from Test.
|
||||
virtual ~Test();
|
||||
|
||||
// Sets up the stuff shared by all tests in this test case.
|
||||
// Sets up the stuff shared by all tests in this test suite.
|
||||
//
|
||||
// Google Test will call Foo::SetUpTestSuite() before running the first
|
||||
// test in test case Foo. Hence a sub-class can define its own
|
||||
// test in test suite Foo. Hence a sub-class can define its own
|
||||
// SetUpTestSuite() method to shadow the one defined in the super
|
||||
// class.
|
||||
// Failures that happen during SetUpTestSuite are logged but otherwise
|
||||
// ignored.
|
||||
static void SetUpTestSuite() {}
|
||||
|
||||
// Tears down the stuff shared by all tests in this test suite.
|
||||
//
|
||||
// Google Test will call Foo::TearDownTestSuite() after running the last
|
||||
// test in test case Foo. Hence a sub-class can define its own
|
||||
// test in test suite Foo. Hence a sub-class can define its own
|
||||
// TearDownTestSuite() method to shadow the one defined in the super
|
||||
// class.
|
||||
// Failures that happen during TearDownTestSuite are logged but otherwise
|
||||
// ignored.
|
||||
static void TearDownTestSuite() {}
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
// Legacy API is deprecated but still available. Use SetUpTestSuite and
|
||||
// TearDownTestSuite instead.
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
static void TearDownTestCase() {}
|
||||
static void SetUpTestCase() {}
|
||||
|
@ -527,17 +536,24 @@ class TestProperty {
|
|||
// C'tor. TestProperty does NOT have a default constructor.
|
||||
// Always use this constructor (with parameters) to create a
|
||||
// TestProperty object.
|
||||
TestProperty(const std::string& a_key, const std::string& a_value)
|
||||
: key_(a_key), value_(a_value) {}
|
||||
TestProperty(const std::string& a_key, const std::string& a_value) :
|
||||
key_(a_key), value_(a_value) {
|
||||
}
|
||||
|
||||
// Gets the user supplied key.
|
||||
const char* key() const { return key_.c_str(); }
|
||||
const char* key() const {
|
||||
return key_.c_str();
|
||||
}
|
||||
|
||||
// Gets the user supplied value.
|
||||
const char* value() const { return value_.c_str(); }
|
||||
const char* value() const {
|
||||
return value_.c_str();
|
||||
}
|
||||
|
||||
// Sets a new value, overriding the one supplied in the constructor.
|
||||
void SetValue(const std::string& new_value) { value_ = new_value; }
|
||||
void SetValue(const std::string& new_value) {
|
||||
value_ = new_value;
|
||||
}
|
||||
|
||||
private:
|
||||
// The key supplied by the user.
|
||||
|
@ -657,7 +673,7 @@ class GTEST_API_ TestResult {
|
|||
|
||||
// Protects mutable state of the property vector and of owned
|
||||
// properties, whose values may be updated.
|
||||
internal::Mutex test_properites_mutex_;
|
||||
internal::Mutex test_properties_mutex_;
|
||||
|
||||
// The vector of TestPartResults
|
||||
std::vector<TestPartResult> test_part_results_;
|
||||
|
@ -787,13 +803,16 @@ class GTEST_API_ TestInfo {
|
|||
// deletes it.
|
||||
void Run();
|
||||
|
||||
// Skip and records the test result for this object.
|
||||
void Skip();
|
||||
|
||||
static void ClearTestResult(TestInfo* test_info) {
|
||||
test_info->result_.Clear();
|
||||
}
|
||||
|
||||
// These fields are immutable properties of the test.
|
||||
const std::string test_suite_name_; // test suite name
|
||||
const std::string name_; // Test name
|
||||
const std::string test_suite_name_; // test suite name
|
||||
const std::string name_; // Test name
|
||||
// Name of the parameter type, or NULL if this is not a typed or a
|
||||
// type-parameterized test.
|
||||
const std::unique_ptr<const ::std::string> type_param_;
|
||||
|
@ -882,7 +901,9 @@ class GTEST_API_ TestSuite {
|
|||
bool Passed() const { return !Failed(); }
|
||||
|
||||
// Returns true if and only if the test suite failed.
|
||||
bool Failed() const { return failed_test_count() > 0; }
|
||||
bool Failed() const {
|
||||
return failed_test_count() > 0 || ad_hoc_test_result().Failed();
|
||||
}
|
||||
|
||||
// Returns the elapsed time, in milliseconds.
|
||||
TimeInMillis elapsed_time() const { return elapsed_time_; }
|
||||
|
@ -920,7 +941,7 @@ class GTEST_API_ TestSuite {
|
|||
|
||||
// Adds a TestInfo to this test suite. Will delete the TestInfo upon
|
||||
// destruction of the TestSuite object.
|
||||
void AddTestInfo(TestInfo* test_info);
|
||||
void AddTestInfo(TestInfo * test_info);
|
||||
|
||||
// Clears the results of all tests in this test suite.
|
||||
void ClearResult();
|
||||
|
@ -933,6 +954,9 @@ class GTEST_API_ TestSuite {
|
|||
// Runs every test in this TestSuite.
|
||||
void Run();
|
||||
|
||||
// Skips the execution of tests under this TestSuite
|
||||
void Skip();
|
||||
|
||||
// Runs SetUpTestSuite() for this TestSuite. This wrapper is needed
|
||||
// for catching exceptions thrown from SetUpTestSuite().
|
||||
void RunSetUpTestSuite() {
|
||||
|
@ -1045,7 +1069,6 @@ class Environment {
|
|||
|
||||
// Override this to define how to tear down the environment.
|
||||
virtual void TearDown() {}
|
||||
|
||||
private:
|
||||
// If you see an error about overriding the following function or
|
||||
// about it being private, you have mis-spelled SetUp() as Setup().
|
||||
|
@ -1089,7 +1112,7 @@ class TestEventListener {
|
|||
// Fired before the test suite starts.
|
||||
virtual void OnTestSuiteStart(const TestSuite& /*test_suite*/) {}
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
@ -1120,7 +1143,8 @@ class TestEventListener {
|
|||
virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
|
||||
|
||||
// Fired after each iteration of tests finishes.
|
||||
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) = 0;
|
||||
virtual void OnTestIterationEnd(const UnitTest& unit_test,
|
||||
int iteration) = 0;
|
||||
|
||||
// Fired after all test activities have ended.
|
||||
virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
|
||||
|
@ -1277,7 +1301,8 @@ class GTEST_API_ UnitTest {
|
|||
|
||||
// Returns the TestInfo object for the test that's currently running,
|
||||
// or NULL if no test is running.
|
||||
const TestInfo* current_test_info() const GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
const TestInfo* current_test_info() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
// Returns the random seed used at the start of the current test run.
|
||||
int random_seed() const;
|
||||
|
@ -1302,7 +1327,7 @@ class GTEST_API_ UnitTest {
|
|||
// that should run.
|
||||
int test_suite_to_run_count() const;
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
int successful_test_case_count() const;
|
||||
int failed_test_case_count() const;
|
||||
|
@ -1383,7 +1408,8 @@ class GTEST_API_ UnitTest {
|
|||
// eventually call this to report their results. The user code
|
||||
// should use the assertion macros instead of calling this directly.
|
||||
void AddTestPartResult(TestPartResult::Type result_type,
|
||||
const char* file_name, int line_number,
|
||||
const char* file_name,
|
||||
int line_number,
|
||||
const std::string& message,
|
||||
const std::string& os_stack_trace)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
@ -1411,9 +1437,11 @@ class GTEST_API_ UnitTest {
|
|||
friend class internal::StreamingListenerTest;
|
||||
friend class internal::UnitTestRecordPropertyTestHelper;
|
||||
friend Environment* AddGlobalTestEnvironment(Environment* env);
|
||||
friend std::set<std::string>* internal::GetIgnoredParameterizedTestSuites();
|
||||
friend internal::UnitTestImpl* internal::GetUnitTestImpl();
|
||||
friend void internal::ReportFailureInUnknownLocation(
|
||||
TestPartResult::Type result_type, const std::string& message);
|
||||
TestPartResult::Type result_type,
|
||||
const std::string& message);
|
||||
|
||||
// Creates an empty UnitTest.
|
||||
UnitTest();
|
||||
|
@ -1427,7 +1455,8 @@ class GTEST_API_ UnitTest {
|
|||
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
// Pops a trace from the per-thread Google Test trace stack.
|
||||
void PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
void PopGTestTrace()
|
||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
// Protects mutable state in *impl_. This is mutable as some const
|
||||
// methods need to lock it too.
|
||||
|
@ -1491,11 +1520,13 @@ namespace internal {
|
|||
// when calling EXPECT_* in a tight loop.
|
||||
template <typename T1, typename T2>
|
||||
AssertionResult CmpHelperEQFailure(const char* lhs_expression,
|
||||
const char* rhs_expression, const T1& lhs,
|
||||
const T2& rhs) {
|
||||
return EqFailure(lhs_expression, rhs_expression,
|
||||
const char* rhs_expression,
|
||||
const T1& lhs, const T2& rhs) {
|
||||
return EqFailure(lhs_expression,
|
||||
rhs_expression,
|
||||
FormatForComparisonFailureMessage(lhs, rhs),
|
||||
FormatForComparisonFailureMessage(rhs, lhs), false);
|
||||
FormatForComparisonFailureMessage(rhs, lhs),
|
||||
false);
|
||||
}
|
||||
|
||||
// This block of code defines operator==/!=
|
||||
|
@ -1508,7 +1539,8 @@ inline bool operator!=(faketype, faketype) { return false; }
|
|||
// The helper function for {ASSERT|EXPECT}_EQ.
|
||||
template <typename T1, typename T2>
|
||||
AssertionResult CmpHelperEQ(const char* lhs_expression,
|
||||
const char* rhs_expression, const T1& lhs,
|
||||
const char* rhs_expression,
|
||||
const T1& lhs,
|
||||
const T2& rhs) {
|
||||
if (lhs == rhs) {
|
||||
return AssertionSuccess();
|
||||
|
@ -1517,13 +1549,6 @@ AssertionResult CmpHelperEQ(const char* lhs_expression,
|
|||
return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs);
|
||||
}
|
||||
|
||||
// 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.
|
||||
GTEST_API_ AssertionResult CmpHelperEQ(const char* lhs_expression,
|
||||
const char* rhs_expression,
|
||||
BiggestInt lhs, BiggestInt rhs);
|
||||
|
||||
class EqHelper {
|
||||
public:
|
||||
// This templatized version is for the general case.
|
||||
|
@ -1546,7 +1571,8 @@ class EqHelper {
|
|||
// Even though its body looks the same as the above version, we
|
||||
// cannot merge the two, as it will make anonymous enums unhappy.
|
||||
static AssertionResult Compare(const char* lhs_expression,
|
||||
const char* rhs_expression, BiggestInt lhs,
|
||||
const char* rhs_expression,
|
||||
BiggestInt lhs,
|
||||
BiggestInt rhs) {
|
||||
return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
|
||||
}
|
||||
|
@ -1579,38 +1605,31 @@ AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2,
|
|||
// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste
|
||||
// of similar code.
|
||||
//
|
||||
// For each templatized helper function, we also define an overloaded
|
||||
// version for BiggestInt in order to reduce code bloat and allow
|
||||
// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
|
||||
// with gcc 4.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
|
||||
#define GTEST_IMPL_CMP_HELPER_(op_name, op) \
|
||||
template <typename T1, typename T2> \
|
||||
AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
|
||||
const T1& val1, const T2& val2) { \
|
||||
if (val1 op val2) { \
|
||||
return AssertionSuccess(); \
|
||||
} else { \
|
||||
return CmpHelperOpFailure(expr1, expr2, val1, val2, #op); \
|
||||
} \
|
||||
} \
|
||||
GTEST_API_ AssertionResult CmpHelper##op_name( \
|
||||
const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
|
||||
#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
|
||||
template <typename T1, typename T2>\
|
||||
AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
|
||||
const T1& val1, const T2& val2) {\
|
||||
if (val1 op val2) {\
|
||||
return AssertionSuccess();\
|
||||
} else {\
|
||||
return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\
|
||||
}\
|
||||
}
|
||||
|
||||
// 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_
|
||||
|
||||
|
@ -1619,42 +1638,49 @@ GTEST_IMPL_CMP_HELPER_(GT, >);
|
|||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1, const char* s2);
|
||||
const char* s1,
|
||||
const char* s2);
|
||||
|
||||
// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1, const char* s2);
|
||||
const char* s1,
|
||||
const char* s2);
|
||||
|
||||
// The helper function for {ASSERT|EXPECT}_STRNE.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1, const char* s2);
|
||||
const char* s1,
|
||||
const char* s2);
|
||||
|
||||
// The helper function for {ASSERT|EXPECT}_STRCASENE.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1, const char* s2);
|
||||
const char* s1,
|
||||
const char* s2);
|
||||
|
||||
|
||||
// Helper function for *_STREQ on wide strings.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const wchar_t* s1, const wchar_t* s2);
|
||||
const wchar_t* s1,
|
||||
const wchar_t* s2);
|
||||
|
||||
// Helper function for *_STRNE on wide strings.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const wchar_t* s1, const wchar_t* s2);
|
||||
const wchar_t* s1,
|
||||
const wchar_t* s2);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
@ -1666,40 +1692,32 @@ GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
|||
//
|
||||
// The {needle,haystack}_expr arguments are the stringified
|
||||
// expressions that generated the two real arguments.
|
||||
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const char* needle,
|
||||
const char* haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const wchar_t* needle,
|
||||
const wchar_t* haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const char* needle,
|
||||
const char* haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const wchar_t* needle,
|
||||
const wchar_t* haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const ::std::string& needle,
|
||||
const ::std::string& haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const ::std::string& needle,
|
||||
const ::std::string& haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const char* needle, const char* haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const wchar_t* needle, const wchar_t* haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const char* needle, const char* haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const wchar_t* needle, const wchar_t* haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::string& needle, const ::std::string& haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::string& needle, const ::std::string& haystack);
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const ::std::wstring& needle,
|
||||
const ::std::wstring& haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const ::std::wstring& needle,
|
||||
const ::std::wstring& haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(
|
||||
const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::wstring& needle, const ::std::wstring& haystack);
|
||||
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
|
||||
|
||||
namespace internal {
|
||||
|
@ -1714,7 +1732,8 @@ namespace internal {
|
|||
template <typename RawType>
|
||||
AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
|
||||
const char* rhs_expression,
|
||||
RawType lhs_value, RawType rhs_value) {
|
||||
RawType lhs_value,
|
||||
RawType rhs_value) {
|
||||
const FloatingPoint<RawType> lhs(lhs_value), rhs(rhs_value);
|
||||
|
||||
if (lhs.AlmostEquals(rhs)) {
|
||||
|
@ -1729,8 +1748,10 @@ AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
|
|||
rhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
|
||||
<< rhs_value;
|
||||
|
||||
return EqFailure(lhs_expression, rhs_expression,
|
||||
StringStreamToString(&lhs_ss), StringStreamToString(&rhs_ss),
|
||||
return EqFailure(lhs_expression,
|
||||
rhs_expression,
|
||||
StringStreamToString(&lhs_ss),
|
||||
StringStreamToString(&rhs_ss),
|
||||
false);
|
||||
}
|
||||
|
||||
|
@ -1740,7 +1761,8 @@ AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
|
|||
GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
|
||||
const char* expr2,
|
||||
const char* abs_error_expr,
|
||||
double val1, double val2,
|
||||
double val1,
|
||||
double val2,
|
||||
double abs_error);
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
|
@ -1748,7 +1770,9 @@ GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
|
|||
class GTEST_API_ AssertHelper {
|
||||
public:
|
||||
// Constructor.
|
||||
AssertHelper(TestPartResult::Type type, const char* file, int line,
|
||||
AssertHelper(TestPartResult::Type type,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* message);
|
||||
~AssertHelper();
|
||||
|
||||
|
@ -1762,9 +1786,11 @@ class GTEST_API_ AssertHelper {
|
|||
// re-using stack space even for temporary variables, so every EXPECT_EQ
|
||||
// reserves stack space for another AssertHelper.
|
||||
struct AssertHelperData {
|
||||
AssertHelperData(TestPartResult::Type t, const char* srcfile, int line_num,
|
||||
AssertHelperData(TestPartResult::Type t,
|
||||
const char* srcfile,
|
||||
int line_num,
|
||||
const char* msg)
|
||||
: type(t), file(srcfile), line(line_num), message(msg) {}
|
||||
: type(t), file(srcfile), line(line_num), message(msg) { }
|
||||
|
||||
TestPartResult::Type const type;
|
||||
const char* const file;
|
||||
|
@ -1780,12 +1806,6 @@ class GTEST_API_ AssertHelper {
|
|||
GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
|
||||
};
|
||||
|
||||
enum GTestColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW };
|
||||
|
||||
GTEST_API_ GTEST_ATTRIBUTE_PRINTF_(2, 3) void ColoredPrintf(GTestColor color,
|
||||
const char* fmt,
|
||||
...);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// The pure interface class that all value-parameterized tests inherit from.
|
||||
|
@ -1840,14 +1860,15 @@ class WithParamInterface {
|
|||
private:
|
||||
// Sets parameter value. The caller is responsible for making sure the value
|
||||
// remains alive and unchanged throughout the current test.
|
||||
static void SetParam(const ParamType* parameter) { parameter_ = parameter; }
|
||||
static void SetParam(const ParamType* parameter) {
|
||||
parameter_ = parameter;
|
||||
}
|
||||
|
||||
// Static value used for accessing parameter during a test lifetime.
|
||||
static const ParamType* parameter_;
|
||||
|
||||
// TestClass must be a subclass of WithParamInterface<T> and Test.
|
||||
template <class TestClass>
|
||||
friend class internal::ParameterizedTestFactory;
|
||||
template <class TestClass> friend class internal::ParameterizedTestFactory;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -1857,14 +1878,15 @@ const T* WithParamInterface<T>::parameter_ = nullptr;
|
|||
// WithParamInterface, and can just inherit from ::testing::TestWithParam.
|
||||
|
||||
template <typename T>
|
||||
class TestWithParam : public Test, public WithParamInterface<T> {};
|
||||
class TestWithParam : public Test, public WithParamInterface<T> {
|
||||
};
|
||||
|
||||
// Macros for indicating success/failure in test code.
|
||||
|
||||
// Skips test in runtime.
|
||||
// Skipping test aborts current function.
|
||||
// Skipped tests are neither successful nor failed.
|
||||
#define GTEST_SKIP() GTEST_SKIP_("Skipped")
|
||||
#define GTEST_SKIP() GTEST_SKIP_("")
|
||||
|
||||
// ADD_FAILURE unconditionally adds a failure to the current test.
|
||||
// SUCCEED generates a success - it doesn't automatically make the
|
||||
|
@ -1888,7 +1910,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
|||
|
||||
// Generates a nonfatal failure at the given source file location with
|
||||
// a generic message.
|
||||
#define ADD_FAILURE_AT(file, line) \
|
||||
#define ADD_FAILURE_AT(file, line) \
|
||||
GTEST_MESSAGE_AT_(file, line, "Failed", \
|
||||
::testing::TestPartResult::kNonFatalFailure)
|
||||
|
||||
|
@ -1903,7 +1925,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
|||
// 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()
|
||||
# define FAIL() GTEST_FAIL()
|
||||
#endif
|
||||
|
||||
// Generates a success with a generic message.
|
||||
|
@ -1912,7 +1934,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
|||
// 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()
|
||||
# define SUCCEED() GTEST_SUCCEED()
|
||||
#endif
|
||||
|
||||
// Macros for testing exceptions.
|
||||
|
@ -1940,18 +1962,38 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
|||
// 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) \
|
||||
#define GTEST_EXPECT_TRUE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
|
||||
GTEST_NONFATAL_FAILURE_)
|
||||
#define EXPECT_FALSE(condition) \
|
||||
#define GTEST_EXPECT_FALSE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
||||
GTEST_NONFATAL_FAILURE_)
|
||||
#define ASSERT_TRUE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, GTEST_FATAL_FAILURE_)
|
||||
#define ASSERT_FALSE(condition) \
|
||||
#define GTEST_ASSERT_TRUE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
|
||||
GTEST_FATAL_FAILURE_)
|
||||
#define GTEST_ASSERT_FALSE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
||||
GTEST_FATAL_FAILURE_)
|
||||
|
||||
// Define these macros to 1 to omit the definition of the corresponding
|
||||
// EXPECT or ASSERT, which clashes with some users' own code.
|
||||
|
||||
#if !GTEST_DONT_DEFINE_EXPECT_TRUE
|
||||
#define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition)
|
||||
#endif
|
||||
|
||||
#if !GTEST_DONT_DEFINE_EXPECT_FALSE
|
||||
#define EXPECT_FALSE(condition) GTEST_EXPECT_FALSE(condition)
|
||||
#endif
|
||||
|
||||
#if !GTEST_DONT_DEFINE_ASSERT_TRUE
|
||||
#define ASSERT_TRUE(condition) GTEST_ASSERT_TRUE(condition)
|
||||
#endif
|
||||
|
||||
#if !GTEST_DONT_DEFINE_ASSERT_FALSE
|
||||
#define ASSERT_FALSE(condition) GTEST_ASSERT_FALSE(condition)
|
||||
#endif
|
||||
|
||||
// Macros for testing equalities and inequalities.
|
||||
//
|
||||
// * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2
|
||||
|
@ -2028,27 +2070,27 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
|||
// ASSERT_XY(), which clashes with some users' own code.
|
||||
|
||||
#if !GTEST_DONT_DEFINE_ASSERT_EQ
|
||||
#define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
|
||||
# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
|
||||
#endif
|
||||
|
||||
#if !GTEST_DONT_DEFINE_ASSERT_NE
|
||||
#define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
|
||||
# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
|
||||
#endif
|
||||
|
||||
#if !GTEST_DONT_DEFINE_ASSERT_LE
|
||||
#define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
|
||||
# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
|
||||
#endif
|
||||
|
||||
#if !GTEST_DONT_DEFINE_ASSERT_LT
|
||||
#define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
|
||||
# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
|
||||
#endif
|
||||
|
||||
#if !GTEST_DONT_DEFINE_ASSERT_GE
|
||||
#define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
|
||||
# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
|
||||
#endif
|
||||
|
||||
#if !GTEST_DONT_DEFINE_ASSERT_GT
|
||||
#define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
|
||||
# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
|
||||
#endif
|
||||
|
||||
// C-string Comparisons. All tests treat NULL and any non-NULL string
|
||||
|
@ -2073,7 +2115,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
|||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
|
||||
#define EXPECT_STRCASEEQ(s1, s2) \
|
||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
|
||||
#define EXPECT_STRCASENE(s1, s2) \
|
||||
#define EXPECT_STRCASENE(s1, s2)\
|
||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
|
||||
|
||||
#define ASSERT_STREQ(s1, s2) \
|
||||
|
@ -2082,7 +2124,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
|||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
|
||||
#define ASSERT_STRCASEEQ(s1, s2) \
|
||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
|
||||
#define ASSERT_STRCASENE(s1, s2) \
|
||||
#define ASSERT_STRCASENE(s1, s2)\
|
||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
|
||||
|
||||
// Macros for comparing floating-point numbers.
|
||||
|
@ -2099,29 +2141,29 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
|||
// FloatingPoint template class in gtest-internal.h if you are
|
||||
// interested in the implementation details.
|
||||
|
||||
#define EXPECT_FLOAT_EQ(val1, val2) \
|
||||
#define EXPECT_FLOAT_EQ(val1, val2)\
|
||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
|
||||
val1, val2)
|
||||
|
||||
#define EXPECT_DOUBLE_EQ(val1, val2) \
|
||||
#define EXPECT_DOUBLE_EQ(val1, val2)\
|
||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
|
||||
val1, val2)
|
||||
|
||||
#define ASSERT_FLOAT_EQ(val1, val2) \
|
||||
#define ASSERT_FLOAT_EQ(val1, val2)\
|
||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
|
||||
val1, val2)
|
||||
|
||||
#define ASSERT_DOUBLE_EQ(val1, val2) \
|
||||
#define ASSERT_DOUBLE_EQ(val1, val2)\
|
||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
|
||||
val1, val2)
|
||||
|
||||
#define EXPECT_NEAR(val1, val2, abs_error) \
|
||||
EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, val1, val2, \
|
||||
abs_error)
|
||||
#define EXPECT_NEAR(val1, val2, abs_error)\
|
||||
EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
|
||||
val1, val2, abs_error)
|
||||
|
||||
#define ASSERT_NEAR(val1, val2, abs_error) \
|
||||
ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, val1, val2, \
|
||||
abs_error)
|
||||
#define ASSERT_NEAR(val1, val2, abs_error)\
|
||||
ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
|
||||
val1, val2, abs_error)
|
||||
|
||||
// These predicate format functions work on floating-point values, and
|
||||
// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
|
||||
|
@ -2135,6 +2177,7 @@ GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
|
|||
GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
||||
double val1, double val2);
|
||||
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
|
||||
// Macros that test for HRESULT failure and success, these are only useful
|
||||
|
@ -2146,17 +2189,17 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
|||
// expected result and the actual result with both a human-readable
|
||||
// string representation of the error, if available, as well as the
|
||||
// hex result code.
|
||||
#define EXPECT_HRESULT_SUCCEEDED(expr) \
|
||||
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
|
||||
# define EXPECT_HRESULT_SUCCEEDED(expr) \
|
||||
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
|
||||
|
||||
#define ASSERT_HRESULT_SUCCEEDED(expr) \
|
||||
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
|
||||
# define ASSERT_HRESULT_SUCCEEDED(expr) \
|
||||
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
|
||||
|
||||
#define EXPECT_HRESULT_FAILED(expr) \
|
||||
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
|
||||
# define EXPECT_HRESULT_FAILED(expr) \
|
||||
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
|
||||
|
||||
#define ASSERT_HRESULT_FAILED(expr) \
|
||||
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
|
||||
# define ASSERT_HRESULT_FAILED(expr) \
|
||||
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
|
@ -2171,9 +2214,9 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
|||
// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
|
||||
//
|
||||
#define ASSERT_NO_FATAL_FAILURE(statement) \
|
||||
GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
|
||||
GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
|
||||
#define EXPECT_NO_FATAL_FAILURE(statement) \
|
||||
GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
|
||||
GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
|
||||
|
||||
// Causes a trace (including the given source file path and line number,
|
||||
// and the given message) to be included in every test failure message generated
|
||||
|
@ -2235,9 +2278,9 @@ class GTEST_API_ ScopedTrace {
|
|||
// Assuming that each thread maintains its own stack of traces.
|
||||
// Therefore, a SCOPED_TRACE() would (correctly) only affect the
|
||||
// assertions in its own thread.
|
||||
#define SCOPED_TRACE(message) \
|
||||
::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)( \
|
||||
__FILE__, __LINE__, (message))
|
||||
#define SCOPED_TRACE(message) \
|
||||
::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
|
||||
__FILE__, __LINE__, (message))
|
||||
|
||||
// Compile-time assertion for type equality.
|
||||
// StaticAssertTypeEq<type1, type2>() compiles if and only if type1 and type2
|
||||
|
@ -2271,8 +2314,7 @@ class GTEST_API_ ScopedTrace {
|
|||
// to cause a compiler error.
|
||||
template <typename T1, typename T2>
|
||||
constexpr bool StaticAssertTypeEq() noexcept {
|
||||
static_assert(std::is_same<T1, T2>::value,
|
||||
"type1 and type2 are not the same type");
|
||||
static_assert(std::is_same<T1, T2>::value, "T1 and T2 are not the same type");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2338,16 +2380,18 @@ constexpr bool StaticAssertTypeEq() noexcept {
|
|||
// }
|
||||
//
|
||||
// GOOGLETEST_CM0011 DO NOT DELETE
|
||||
#define TEST_F(test_fixture, test_name) \
|
||||
#if !GTEST_DONT_DEFINE_TEST
|
||||
#define TEST_F(test_fixture, test_name)\
|
||||
GTEST_TEST_(test_fixture, test_name, test_fixture, \
|
||||
::testing::internal::GetTypeId<test_fixture>())
|
||||
#endif // !GTEST_DONT_DEFINE_TEST
|
||||
|
||||
// Returns a path to temporary directory.
|
||||
// Tries to determine an appropriate directory for the platform.
|
||||
GTEST_API_ std::string TempDir();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// Dynamically registers a test with the framework.
|
||||
|
@ -2442,8 +2486,10 @@ TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
|
|||
// namespace and has an all-caps name.
|
||||
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
|
||||
|
||||
inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }
|
||||
inline int RUN_ALL_TESTS() {
|
||||
return ::testing::UnitTest::GetInstance()->Run();
|
||||
}
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_H_
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
// Implements a family of generic predicate assertion macros.
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
@ -72,18 +72,22 @@ namespace testing {
|
|||
// GTEST_ASSERT_ is the basic statement to which all of the assertions
|
||||
// in this file reduce. Don't use this in your code.
|
||||
|
||||
#define GTEST_ASSERT_(expression, on_failure) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
#define GTEST_ASSERT_(expression, on_failure) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (const ::testing::AssertionResult gtest_ar = (expression)) \
|
||||
; \
|
||||
else \
|
||||
; \
|
||||
else \
|
||||
on_failure(gtest_ar.failure_message())
|
||||
|
||||
|
||||
// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
||||
// this in your code.
|
||||
template <typename Pred, typename T1>
|
||||
AssertionResult AssertPred1Helper(const char* pred_text, const char* e1,
|
||||
Pred pred, const T1& v1) {
|
||||
template <typename Pred,
|
||||
typename T1>
|
||||
AssertionResult AssertPred1Helper(const char* pred_text,
|
||||
const char* e1,
|
||||
Pred pred,
|
||||
const T1& v1) {
|
||||
if (pred(v1)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure()
|
||||
|
@ -94,27 +98,40 @@ AssertionResult AssertPred1Helper(const char* pred_text, const char* e1,
|
|||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
||||
// Don't use this in your code.
|
||||
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure) \
|
||||
GTEST_ASSERT_(pred_format(#v1, v1), on_failure)
|
||||
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
|
||||
GTEST_ASSERT_(pred_format(#v1, v1), \
|
||||
on_failure)
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
||||
// this in your code.
|
||||
#define GTEST_PRED1_(pred, v1, on_failure) \
|
||||
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, #v1, pred, v1), on_failure)
|
||||
#define GTEST_PRED1_(pred, v1, on_failure)\
|
||||
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
|
||||
#v1, \
|
||||
pred, \
|
||||
v1), on_failure)
|
||||
|
||||
// Unary predicate assertion macros.
|
||||
#define EXPECT_PRED_FORMAT1(pred_format, v1) \
|
||||
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
|
||||
#define EXPECT_PRED1(pred, v1) GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
|
||||
#define EXPECT_PRED1(pred, v1) \
|
||||
GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
|
||||
#define ASSERT_PRED_FORMAT1(pred_format, v1) \
|
||||
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
|
||||
#define ASSERT_PRED1(pred, v1) GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
|
||||
#define ASSERT_PRED1(pred, v1) \
|
||||
GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
|
||||
|
||||
|
||||
|
||||
// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
||||
// this in your code.
|
||||
template <typename Pred, typename T1, typename T2>
|
||||
AssertionResult AssertPred2Helper(const char* pred_text, const char* e1,
|
||||
const char* e2, Pred pred, const T1& v1,
|
||||
template <typename Pred,
|
||||
typename T1,
|
||||
typename T2>
|
||||
AssertionResult AssertPred2Helper(const char* pred_text,
|
||||
const char* e1,
|
||||
const char* e2,
|
||||
Pred pred,
|
||||
const T1& v1,
|
||||
const T2& v2) {
|
||||
if (pred(v1, v2)) return AssertionSuccess();
|
||||
|
||||
|
@ -128,14 +145,19 @@ AssertionResult AssertPred2Helper(const char* pred_text, const char* e1,
|
|||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
||||
// Don't use this in your code.
|
||||
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure) \
|
||||
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), on_failure)
|
||||
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
|
||||
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
|
||||
on_failure)
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
||||
// this in your code.
|
||||
#define GTEST_PRED2_(pred, v1, v2, on_failure) \
|
||||
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, #v1, #v2, pred, v1, v2), \
|
||||
on_failure)
|
||||
#define GTEST_PRED2_(pred, v1, v2, on_failure)\
|
||||
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
|
||||
#v1, \
|
||||
#v2, \
|
||||
pred, \
|
||||
v1, \
|
||||
v2), on_failure)
|
||||
|
||||
// Binary predicate assertion macros.
|
||||
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
|
||||
|
@ -147,12 +169,22 @@ AssertionResult AssertPred2Helper(const char* pred_text, const char* e1,
|
|||
#define ASSERT_PRED2(pred, v1, v2) \
|
||||
GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
|
||||
|
||||
|
||||
|
||||
// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
||||
// this in your code.
|
||||
template <typename Pred, typename T1, typename T2, typename T3>
|
||||
AssertionResult AssertPred3Helper(const char* pred_text, const char* e1,
|
||||
const char* e2, const char* e3, Pred pred,
|
||||
const T1& v1, const T2& v2, const T3& v3) {
|
||||
template <typename Pred,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3>
|
||||
AssertionResult AssertPred3Helper(const char* pred_text,
|
||||
const char* e1,
|
||||
const char* e2,
|
||||
const char* e3,
|
||||
Pred pred,
|
||||
const T1& v1,
|
||||
const T2& v2,
|
||||
const T3& v3) {
|
||||
if (pred(v1, v2, v3)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure()
|
||||
|
@ -166,15 +198,21 @@ AssertionResult AssertPred3Helper(const char* pred_text, const char* e1,
|
|||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
||||
// Don't use this in your code.
|
||||
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure) \
|
||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), on_failure)
|
||||
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
|
||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
|
||||
on_failure)
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
||||
// this in your code.
|
||||
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure) \
|
||||
GTEST_ASSERT_( \
|
||||
::testing::AssertPred3Helper(#pred, #v1, #v2, #v3, pred, v1, v2, v3), \
|
||||
on_failure)
|
||||
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
|
||||
GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
|
||||
#v1, \
|
||||
#v2, \
|
||||
#v3, \
|
||||
pred, \
|
||||
v1, \
|
||||
v2, \
|
||||
v3), on_failure)
|
||||
|
||||
// Ternary predicate assertion macros.
|
||||
#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
||||
|
@ -186,13 +224,25 @@ AssertionResult AssertPred3Helper(const char* pred_text, const char* e1,
|
|||
#define ASSERT_PRED3(pred, v1, v2, v3) \
|
||||
GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
||||
|
||||
|
||||
|
||||
// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
||||
// this in your code.
|
||||
template <typename Pred, typename T1, typename T2, typename T3, typename T4>
|
||||
AssertionResult AssertPred4Helper(const char* pred_text, const char* e1,
|
||||
const char* e2, const char* e3,
|
||||
const char* e4, Pred pred, const T1& v1,
|
||||
const T2& v2, const T3& v3, const T4& v4) {
|
||||
template <typename Pred,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4>
|
||||
AssertionResult AssertPred4Helper(const char* pred_text,
|
||||
const char* e1,
|
||||
const char* e2,
|
||||
const char* e3,
|
||||
const char* e4,
|
||||
Pred pred,
|
||||
const T1& v1,
|
||||
const T2& v2,
|
||||
const T3& v3,
|
||||
const T4& v4) {
|
||||
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure()
|
||||
|
@ -207,15 +257,23 @@ AssertionResult AssertPred4Helper(const char* pred_text, const char* e1,
|
|||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
||||
// Don't use this in your code.
|
||||
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure) \
|
||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), on_failure)
|
||||
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
|
||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
|
||||
on_failure)
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
||||
// this in your code.
|
||||
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure) \
|
||||
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, #v1, #v2, #v3, #v4, pred, \
|
||||
v1, v2, v3, v4), \
|
||||
on_failure)
|
||||
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
|
||||
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
|
||||
#v1, \
|
||||
#v2, \
|
||||
#v3, \
|
||||
#v4, \
|
||||
pred, \
|
||||
v1, \
|
||||
v2, \
|
||||
v3, \
|
||||
v4), on_failure)
|
||||
|
||||
// 4-ary predicate assertion macros.
|
||||
#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
||||
|
@ -227,15 +285,28 @@ AssertionResult AssertPred4Helper(const char* pred_text, const char* e1,
|
|||
#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
|
||||
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
||||
|
||||
|
||||
|
||||
// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
||||
// this in your code.
|
||||
template <typename Pred, typename T1, typename T2, typename T3, typename T4,
|
||||
template <typename Pred,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5>
|
||||
AssertionResult AssertPred5Helper(const char* pred_text, const char* e1,
|
||||
const char* e2, const char* e3,
|
||||
const char* e4, const char* e5, Pred pred,
|
||||
const T1& v1, const T2& v2, const T3& v3,
|
||||
const T4& v4, const T5& v5) {
|
||||
AssertionResult AssertPred5Helper(const char* pred_text,
|
||||
const char* e1,
|
||||
const char* e2,
|
||||
const char* e3,
|
||||
const char* e4,
|
||||
const char* e5,
|
||||
Pred pred,
|
||||
const T1& v1,
|
||||
const T2& v2,
|
||||
const T3& v3,
|
||||
const T4& v4,
|
||||
const T5& v5) {
|
||||
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure()
|
||||
|
@ -251,16 +322,25 @@ AssertionResult AssertPred5Helper(const char* pred_text, const char* e1,
|
|||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
||||
// Don't use this in your code.
|
||||
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure) \
|
||||
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
|
||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
|
||||
on_failure)
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
||||
// this in your code.
|
||||
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure) \
|
||||
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, #v1, #v2, #v3, #v4, #v5, \
|
||||
pred, v1, v2, v3, v4, v5), \
|
||||
on_failure)
|
||||
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
|
||||
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
|
||||
#v1, \
|
||||
#v2, \
|
||||
#v3, \
|
||||
#v4, \
|
||||
#v5, \
|
||||
pred, \
|
||||
v1, \
|
||||
v2, \
|
||||
v3, \
|
||||
v4, \
|
||||
v5), on_failure)
|
||||
|
||||
// 5-ary predicate assertion macros.
|
||||
#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
||||
|
@ -272,6 +352,8 @@ AssertionResult AssertPred5Helper(const char* pred_text, const char* e1,
|
|||
#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
|
||||
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
||||
|
||||
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
// Google C++ Testing and Mocking Framework definitions useful in production code.
|
||||
// GOOGLETEST_CM0003 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
|
||||
// When you need to test the private or protected members of a class,
|
||||
// use the FRIEND_TEST macro to declare your tests as friends of the
|
||||
|
@ -58,4 +58,4 @@
|
|||
#define FRIEND_TEST(test_case_name, test_name)\
|
||||
friend class test_case_name##_##test_name##_Test
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
//
|
||||
// ** Custom implementation starts here **
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
//
|
||||
// ** Custom implementation starts here **
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
//
|
||||
// ** Custom implementation starts here **
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
// death tests. They are subject to change without notice.
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
|
||||
#include "gtest/gtest-matchers.h"
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
|
@ -54,8 +54,8 @@ const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
|
|||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4251 /* class A needs to have dll-interface to be used by clients of class B */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
// DeathTest is a class that hides much of the complexity of the
|
||||
// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
|
||||
|
@ -83,14 +83,13 @@ class GTEST_API_ DeathTest {
|
|||
static bool Create(const char* statement, Matcher<const std::string&> matcher,
|
||||
const char* file, int line, DeathTest** test);
|
||||
DeathTest();
|
||||
virtual ~DeathTest() {}
|
||||
virtual ~DeathTest() { }
|
||||
|
||||
// A helper class that aborts a death test when it's deleted.
|
||||
class ReturnSentinel {
|
||||
public:
|
||||
explicit ReturnSentinel(DeathTest* test) : test_(test) {}
|
||||
explicit ReturnSentinel(DeathTest* test) : test_(test) { }
|
||||
~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
|
||||
|
||||
private:
|
||||
DeathTest* const test_;
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
|
||||
|
@ -146,7 +145,7 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
|||
// Factory interface for death tests. May be mocked out for testing.
|
||||
class DeathTestFactory {
|
||||
public:
|
||||
virtual ~DeathTestFactory() {}
|
||||
virtual ~DeathTestFactory() { }
|
||||
virtual bool Create(const char* statement,
|
||||
Matcher<const std::string&> matcher, const char* file,
|
||||
int line, DeathTest** test) = 0;
|
||||
|
@ -187,28 +186,28 @@ inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
|||
|
||||
// Traps C++ exceptions escaping statement and reports them as test
|
||||
// failures. Note that trapping SEH exceptions is not implemented here.
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
#define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
||||
try { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} catch (const ::std::exception& gtest_exception) { \
|
||||
fprintf( \
|
||||
stderr, \
|
||||
"\n%s: Caught std::exception-derived exception escaping the " \
|
||||
"death test statement. Exception message: %s\n", \
|
||||
# if GTEST_HAS_EXCEPTIONS
|
||||
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
||||
try { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} catch (const ::std::exception& gtest_exception) { \
|
||||
fprintf(\
|
||||
stderr, \
|
||||
"\n%s: Caught std::exception-derived exception escaping the " \
|
||||
"death test statement. Exception message: %s\n", \
|
||||
::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
|
||||
gtest_exception.what()); \
|
||||
fflush(stderr); \
|
||||
gtest_exception.what()); \
|
||||
fflush(stderr); \
|
||||
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
|
||||
} catch (...) { \
|
||||
} catch (...) { \
|
||||
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
|
||||
}
|
||||
|
||||
#else
|
||||
#define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
||||
# else
|
||||
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
||||
|
||||
#endif
|
||||
# endif
|
||||
|
||||
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
||||
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
||||
|
@ -266,12 +265,16 @@ inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
|||
// RUN_ALL_TESTS was called.
|
||||
class InternalRunDeathTestFlag {
|
||||
public:
|
||||
InternalRunDeathTestFlag(const std::string& a_file, int a_line, int an_index,
|
||||
InternalRunDeathTestFlag(const std::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) {}
|
||||
: file_(a_file), line_(a_line), index_(an_index),
|
||||
write_fd_(a_write_fd) {}
|
||||
|
||||
~InternalRunDeathTestFlag() {
|
||||
if (write_fd_ >= 0) posix::Close(write_fd_);
|
||||
if (write_fd_ >= 0)
|
||||
posix::Close(write_fd_);
|
||||
}
|
||||
|
||||
const std::string& file() const { return file_; }
|
||||
|
@ -298,4 +301,4 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
|
|||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
|
|
|
@ -37,13 +37,13 @@
|
|||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4251 /* class A needs to have dll-interface to be used by clients of class B */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
@ -61,8 +61,8 @@ namespace internal {
|
|||
|
||||
class GTEST_API_ FilePath {
|
||||
public:
|
||||
FilePath() : pathname_("") {}
|
||||
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {}
|
||||
FilePath() : pathname_("") { }
|
||||
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
|
||||
|
||||
explicit FilePath(const std::string& pathname) : pathname_(pathname) {
|
||||
Normalize();
|
||||
|
@ -73,7 +73,9 @@ class GTEST_API_ FilePath {
|
|||
return *this;
|
||||
}
|
||||
|
||||
void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; }
|
||||
void Set(const FilePath& rhs) {
|
||||
pathname_ = rhs.pathname_;
|
||||
}
|
||||
|
||||
const std::string& string() const { return pathname_; }
|
||||
const char* c_str() const { return pathname_.c_str(); }
|
||||
|
@ -86,7 +88,8 @@ class GTEST_API_ FilePath {
|
|||
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||
// On Windows platform, uses \ as the separator rather than /.
|
||||
static FilePath MakeFileName(const FilePath& directory,
|
||||
const FilePath& base_name, int number,
|
||||
const FilePath& base_name,
|
||||
int number,
|
||||
const char* extension);
|
||||
|
||||
// Given directory = "dir", relative_path = "test.xml",
|
||||
|
@ -192,7 +195,7 @@ class GTEST_API_ FilePath {
|
|||
|
||||
void Normalize();
|
||||
|
||||
// Returns a pointer to the last occurence of a valid path separator in
|
||||
// Returns a pointer to the last occurrence 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;
|
||||
|
@ -205,4 +208,4 @@ class GTEST_API_ FilePath {
|
|||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
|
|
|
@ -34,25 +34,26 @@
|
|||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
#if GTEST_OS_LINUX
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
# include <stdlib.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
# include <unistd.h>
|
||||
#endif // GTEST_OS_LINUX
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
#include <stdexcept>
|
||||
# include <stdexcept>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
|
@ -75,34 +76,43 @@
|
|||
// the current line number. For more details, see
|
||||
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
|
||||
#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
|
||||
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo##bar
|
||||
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
|
||||
|
||||
// Stringifies its argument.
|
||||
#define GTEST_STRINGIFY_(name) #name
|
||||
// Work around a bug in visual studio which doesn't accept code like this:
|
||||
//
|
||||
// #define GTEST_STRINGIFY_(name) #name
|
||||
// #define MACRO(a, b, c) ... GTEST_STRINGIFY_(a) ...
|
||||
// MACRO(, x, y)
|
||||
//
|
||||
// Complaining about the argument to GTEST_STRINGIFY_ being empty.
|
||||
// This is allowed by the spec.
|
||||
#define GTEST_STRINGIFY_HELPER_(name, ...) #name
|
||||
#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, )
|
||||
|
||||
namespace proto2 {
|
||||
class Message;
|
||||
class MessageLite;
|
||||
}
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Forward declarations.
|
||||
|
||||
class AssertionResult; // Result of an assertion.
|
||||
class Message; // Represents a failure message.
|
||||
class Test; // Represents a test.
|
||||
class TestInfo; // Information about a test.
|
||||
class TestPartResult; // Result of a test part.
|
||||
class UnitTest; // A collection of test suites.
|
||||
class AssertionResult; // Result of an assertion.
|
||||
class Message; // Represents a failure message.
|
||||
class Test; // Represents a test.
|
||||
class TestInfo; // Information about a test.
|
||||
class TestPartResult; // Result of a test part.
|
||||
class UnitTest; // A collection of test suites.
|
||||
|
||||
template <typename T>
|
||||
::std::string PrintToString(const T& value);
|
||||
|
||||
namespace internal {
|
||||
|
||||
struct TraceInfo; // Information about a trace point.
|
||||
class TestInfoImpl; // Opaque implementation of TestInfo
|
||||
class UnitTestImpl; // Opaque implementation of UnitTest
|
||||
struct TraceInfo; // Information about a trace point.
|
||||
class TestInfoImpl; // Opaque implementation of TestInfo
|
||||
class UnitTestImpl; // Opaque implementation of UnitTest
|
||||
|
||||
// The text used in failure messages to indicate the start of the
|
||||
// stack trace.
|
||||
|
@ -111,7 +121,6 @@ GTEST_API_ extern const char kStackTraceMarker[];
|
|||
// An IgnoredValue object can be implicitly constructed from ANY value.
|
||||
class IgnoredValue {
|
||||
struct Sink {};
|
||||
|
||||
public:
|
||||
// This constructor template allows any value to be implicitly
|
||||
// converted to IgnoredValue. The object has no data member and
|
||||
|
@ -127,13 +136,13 @@ class IgnoredValue {
|
|||
};
|
||||
|
||||
// Appends the user-supplied message to the Google-Test-generated message.
|
||||
GTEST_API_ std::string AppendUserMessage(const std::string& gtest_msg,
|
||||
const Message& user_msg);
|
||||
GTEST_API_ std::string AppendUserMessage(
|
||||
const std::string& gtest_msg, const Message& user_msg);
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4275 /* an exported class was derived from a class that was not exported */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4275 \
|
||||
/* an exported class was derived from a class that was not exported */)
|
||||
|
||||
// This exception is thrown by (and only by) a failed Google Test
|
||||
// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
|
||||
|
@ -203,8 +212,10 @@ GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
|
|||
|
||||
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
|
||||
GTEST_API_ std::string GetBoolAssertionFailureMessage(
|
||||
const AssertionResult& assertion_result, const char* expression_text,
|
||||
const char* actual_predicate_value, const char* expected_predicate_value);
|
||||
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
|
||||
|
@ -245,11 +256,11 @@ class FloatingPoint {
|
|||
// Constants.
|
||||
|
||||
// # of bits in a number.
|
||||
static const size_t kBitCount = 8 * sizeof(RawType);
|
||||
static const size_t kBitCount = 8*sizeof(RawType);
|
||||
|
||||
// # of fraction bits in a number.
|
||||
static const size_t kFractionBitCount =
|
||||
std::numeric_limits<RawType>::digits - 1;
|
||||
std::numeric_limits<RawType>::digits - 1;
|
||||
|
||||
// # of exponent bits in a number.
|
||||
static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
|
||||
|
@ -258,8 +269,8 @@ class FloatingPoint {
|
|||
static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
|
||||
|
||||
// The mask for the fraction bits.
|
||||
static const Bits kFractionBitMask = ~static_cast<Bits>(0) >>
|
||||
(kExponentBitCount + 1);
|
||||
static const Bits kFractionBitMask =
|
||||
~static_cast<Bits>(0) >> (kExponentBitCount + 1);
|
||||
|
||||
// The mask for the exponent bits.
|
||||
static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
|
||||
|
@ -276,7 +287,7 @@ class FloatingPoint {
|
|||
//
|
||||
// See the following article for more details on ULP:
|
||||
// http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
||||
static const size_t kMaxUlps = 4;
|
||||
static const uint32_t kMaxUlps = 4;
|
||||
|
||||
// Constructs a FloatingPoint from a raw floating-point number.
|
||||
//
|
||||
|
@ -298,7 +309,9 @@ class FloatingPoint {
|
|||
}
|
||||
|
||||
// Returns the floating-point number that represent positive infinity.
|
||||
static RawType Infinity() { return ReinterpretBits(kExponentBitMask); }
|
||||
static RawType Infinity() {
|
||||
return ReinterpretBits(kExponentBitMask);
|
||||
}
|
||||
|
||||
// Returns the maximum representable finite floating-point number.
|
||||
static RawType Max();
|
||||
|
@ -306,7 +319,7 @@ class FloatingPoint {
|
|||
// Non-static methods
|
||||
|
||||
// Returns the bits that represents this number.
|
||||
const Bits& bits() const { return u_.bits_; }
|
||||
const Bits &bits() const { return u_.bits_; }
|
||||
|
||||
// Returns the exponent bits of this number.
|
||||
Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
|
||||
|
@ -335,8 +348,8 @@ class FloatingPoint {
|
|||
// a NAN must return false.
|
||||
if (is_nan() || rhs.is_nan()) return false;
|
||||
|
||||
return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <=
|
||||
kMaxUlps;
|
||||
return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
|
||||
<= kMaxUlps;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -361,7 +374,7 @@ class FloatingPoint {
|
|||
//
|
||||
// Read http://en.wikipedia.org/wiki/Signed_number_representations
|
||||
// for more details on signed number representations.
|
||||
static Bits SignAndMagnitudeToBiased(const Bits& sam) {
|
||||
static Bits SignAndMagnitudeToBiased(const Bits &sam) {
|
||||
if (kSignBitMask & sam) {
|
||||
// sam represents a negative number.
|
||||
return ~sam + 1;
|
||||
|
@ -373,8 +386,8 @@ class FloatingPoint {
|
|||
|
||||
// Given two numbers in the sign-and-magnitude representation,
|
||||
// returns the distance between them as an unsigned number.
|
||||
static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits& sam1,
|
||||
const Bits& sam2) {
|
||||
static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
|
||||
const Bits &sam2) {
|
||||
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
|
||||
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
|
||||
return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
|
||||
|
@ -386,13 +399,9 @@ class FloatingPoint {
|
|||
// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
|
||||
// macro defined by <windows.h>.
|
||||
template <>
|
||||
inline float FloatingPoint<float>::Max() {
|
||||
return FLT_MAX;
|
||||
}
|
||||
inline float FloatingPoint<float>::Max() { return FLT_MAX; }
|
||||
template <>
|
||||
inline double FloatingPoint<double>::Max() {
|
||||
return DBL_MAX;
|
||||
}
|
||||
inline double FloatingPoint<double>::Max() { return DBL_MAX; }
|
||||
|
||||
// Typedefs the instances of the FloatingPoint template class that we
|
||||
// care to use.
|
||||
|
@ -511,6 +520,7 @@ struct SuiteApiResolver : T {
|
|||
|
||||
static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename,
|
||||
int line_num) {
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
SetUpTearDownSuiteFuncType test_case_fp =
|
||||
GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase);
|
||||
SetUpTearDownSuiteFuncType test_suite_fp =
|
||||
|
@ -522,10 +532,16 @@ struct SuiteApiResolver : T {
|
|||
<< filename << ":" << line_num;
|
||||
|
||||
return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
|
||||
#else
|
||||
(void)(filename);
|
||||
(void)(line_num);
|
||||
return &T::SetUpTestSuite;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename,
|
||||
int line_num) {
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
SetUpTearDownSuiteFuncType test_case_fp =
|
||||
GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase);
|
||||
SetUpTearDownSuiteFuncType test_suite_fp =
|
||||
|
@ -537,6 +553,11 @@ struct SuiteApiResolver : T {
|
|||
<< filename << ":" << line_num;
|
||||
|
||||
return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
|
||||
#else
|
||||
(void)(filename);
|
||||
(void)(line_num);
|
||||
return &T::TearDownTestSuite;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -545,11 +566,11 @@ struct SuiteApiResolver : T {
|
|||
//
|
||||
// Arguments:
|
||||
//
|
||||
// test_suite_name: name of the test suite
|
||||
// test_suite_name: name of the test suite
|
||||
// name: name of the test
|
||||
// type_param the name of the test's type parameter, or NULL if
|
||||
// type_param: the name of the test's type parameter, or NULL if
|
||||
// this is not a typed or a type-parameterized test.
|
||||
// value_param text representation of the test's value parameter,
|
||||
// value_param: text representation of the test's value parameter,
|
||||
// or NULL if this is not a type-parameterized test.
|
||||
// code_location: code location where the test is defined
|
||||
// fixture_class_id: ID of the test fixture class
|
||||
|
@ -569,10 +590,8 @@ GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
|
|||
// and returns false. None of pstr, *pstr, and prefix can be NULL.
|
||||
GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4251 /* class A needs to have dll-interface to be used by clients of class B */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
// State of the definition of a type-parameterized test suite.
|
||||
class GTEST_API_ TypedTestSuitePState {
|
||||
|
@ -610,7 +629,8 @@ class GTEST_API_ TypedTestSuitePState {
|
|||
// Verifies that registered_tests match the test names in
|
||||
// defined_test_names_; returns registered_tests if successful, or
|
||||
// aborts the program otherwise.
|
||||
const char* VerifyRegisteredTestNames(const char* file, int line,
|
||||
const char* VerifyRegisteredTestNames(const char* test_suite_name,
|
||||
const char* file, int line,
|
||||
const char* registered_tests);
|
||||
|
||||
private:
|
||||
|
@ -634,8 +654,7 @@ inline const char* SkipComma(const char* str) {
|
|||
if (comma == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
while (IsSpace(*(++comma))) {
|
||||
}
|
||||
while (IsSpace(*(++comma))) {}
|
||||
return comma;
|
||||
}
|
||||
|
||||
|
@ -649,7 +668,7 @@ inline std::string GetPrefixUntilComma(const char* str) {
|
|||
// Splits a given string on a given delimiter, populating a given
|
||||
// vector with the fields.
|
||||
void SplitString(const ::std::string& str, char delimiter,
|
||||
::std::vector<::std::string>* dest);
|
||||
::std::vector< ::std::string>* dest);
|
||||
|
||||
// The default argument to the template below for the case when the user does
|
||||
// not provide a name generator.
|
||||
|
@ -666,7 +685,7 @@ struct NameGeneratorSelector {
|
|||
};
|
||||
|
||||
template <typename NameGenerator>
|
||||
void GenerateNamesRecursively(Types0, std::vector<std::string>*, int) {}
|
||||
void GenerateNamesRecursively(internal::None, std::vector<std::string>*, int) {}
|
||||
|
||||
template <typename NameGenerator, typename Types>
|
||||
void GenerateNamesRecursively(Types, std::vector<std::string>* result, int i) {
|
||||
|
@ -733,7 +752,7 @@ class TypeParameterizedTest {
|
|||
|
||||
// The base case for the compile time recursion.
|
||||
template <GTEST_TEMPLATE_ Fixture, class TestSel>
|
||||
class TypeParameterizedTest<Fixture, TestSel, Types0> {
|
||||
class TypeParameterizedTest<Fixture, TestSel, internal::None> {
|
||||
public:
|
||||
static bool Register(const char* /*prefix*/, const CodeLocation&,
|
||||
const char* /*case_name*/, const char* /*test_names*/,
|
||||
|
@ -744,6 +763,11 @@ class TypeParameterizedTest<Fixture, TestSel, Types0> {
|
|||
}
|
||||
};
|
||||
|
||||
GTEST_API_ void RegisterTypeParameterizedTestSuite(const char* test_suite_name,
|
||||
CodeLocation code_location);
|
||||
GTEST_API_ void RegisterTypeParameterizedTestSuiteInstantiation(
|
||||
const char* case_name);
|
||||
|
||||
// TypeParameterizedTestSuite<Fixture, Tests, Types>::Register()
|
||||
// registers *all combinations* of 'Tests' and 'Types' with Google
|
||||
// Test. The return value is insignificant - we just need to return
|
||||
|
@ -756,13 +780,14 @@ class TypeParameterizedTestSuite {
|
|||
const char* test_names,
|
||||
const std::vector<std::string>& type_names =
|
||||
GenerateNames<DefaultNameGenerator, Types>()) {
|
||||
std::string test_name =
|
||||
StripTrailingSpaces(GetPrefixUntilComma(test_names));
|
||||
RegisterTypeParameterizedTestSuiteInstantiation(case_name);
|
||||
std::string test_name = StripTrailingSpaces(
|
||||
GetPrefixUntilComma(test_names));
|
||||
if (!state->TestExists(test_name)) {
|
||||
fprintf(stderr, "Failed to get code location for test %s.%s at %s.",
|
||||
case_name, test_name.c_str(),
|
||||
FormatFileLocation(code_location.file.c_str(), code_location.line)
|
||||
.c_str());
|
||||
FormatFileLocation(code_location.file.c_str(),
|
||||
code_location.line).c_str());
|
||||
fflush(stderr);
|
||||
posix::Abort();
|
||||
}
|
||||
|
@ -785,7 +810,7 @@ class TypeParameterizedTestSuite {
|
|||
|
||||
// The base case for the compile time recursion.
|
||||
template <GTEST_TEMPLATE_ Fixture, typename Types>
|
||||
class TypeParameterizedTestSuite<Fixture, Templates0, Types> {
|
||||
class TypeParameterizedTestSuite<Fixture, internal::None, Types> {
|
||||
public:
|
||||
static bool Register(const char* /*prefix*/, const CodeLocation&,
|
||||
const TypedTestSuitePState* /*state*/,
|
||||
|
@ -796,8 +821,6 @@ class TypeParameterizedTestSuite<Fixture, Templates0, Types> {
|
|||
}
|
||||
};
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// Returns the current OS stack trace as an std::string.
|
||||
//
|
||||
// The maximum number of stack frames to be included is specified by
|
||||
|
@ -808,8 +831,8 @@ class TypeParameterizedTestSuite<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.
|
||||
GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(UnitTest* unit_test,
|
||||
int skip_count);
|
||||
GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(
|
||||
UnitTest* unit_test, int skip_count);
|
||||
|
||||
// Helpers for suppressing warnings on unreachable code or constant
|
||||
// condition.
|
||||
|
@ -829,6 +852,16 @@ struct GTEST_API_ ConstCharPtr {
|
|||
const char* value;
|
||||
};
|
||||
|
||||
// Helper for declaring std::string within 'if' statement
|
||||
// in pre C++17 build environment.
|
||||
struct TrueWithString {
|
||||
TrueWithString() = default;
|
||||
explicit TrueWithString(const char* str) : value(str) {}
|
||||
explicit TrueWithString(const std::string& str) : value(str) {}
|
||||
explicit operator bool() const { return true; }
|
||||
std::string value;
|
||||
};
|
||||
|
||||
// A simple Linear Congruential Generator for generating random
|
||||
// numbers with a uniform distribution. Unlike rand() and srand(), it
|
||||
// doesn't use global state (and therefore can't interfere with user
|
||||
|
@ -836,18 +869,18 @@ struct GTEST_API_ ConstCharPtr {
|
|||
// but it's good enough for our purposes.
|
||||
class GTEST_API_ Random {
|
||||
public:
|
||||
static const UInt32 kMaxRange = 1u << 31;
|
||||
static const uint32_t kMaxRange = 1u << 31;
|
||||
|
||||
explicit Random(UInt32 seed) : state_(seed) {}
|
||||
explicit Random(uint32_t seed) : state_(seed) {}
|
||||
|
||||
void Reseed(UInt32 seed) { state_ = seed; }
|
||||
void Reseed(uint32_t seed) { state_ = seed; }
|
||||
|
||||
// Generates a random number from [0, range). Crashes if 'range' is
|
||||
// 0 or greater than kMaxRange.
|
||||
UInt32 Generate(UInt32 range);
|
||||
uint32_t Generate(uint32_t range);
|
||||
|
||||
private:
|
||||
UInt32 state_;
|
||||
uint32_t state_;
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
|
||||
};
|
||||
|
||||
|
@ -855,12 +888,34 @@ class GTEST_API_ Random {
|
|||
#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
|
||||
typename std::remove_const<typename std::remove_reference<T>::type>::type
|
||||
|
||||
// IsAProtocolMessage<T>::value is a compile-time bool constant that's
|
||||
// true if and only if T is type proto2::Message or a subclass of it.
|
||||
// HasDebugStringAndShortDebugString<T>::value is a compile-time bool constant
|
||||
// that's true if and only if T has methods DebugString() and ShortDebugString()
|
||||
// that return std::string.
|
||||
template <typename T>
|
||||
struct IsAProtocolMessage
|
||||
: public bool_constant<
|
||||
std::is_convertible<const T*, const ::proto2::Message*>::value> {};
|
||||
class HasDebugStringAndShortDebugString {
|
||||
private:
|
||||
template <typename C>
|
||||
static auto CheckDebugString(C*) -> typename std::is_same<
|
||||
std::string, decltype(std::declval<const C>().DebugString())>::type;
|
||||
template <typename>
|
||||
static std::false_type CheckDebugString(...);
|
||||
|
||||
template <typename C>
|
||||
static auto CheckShortDebugString(C*) -> typename std::is_same<
|
||||
std::string, decltype(std::declval<const C>().ShortDebugString())>::type;
|
||||
template <typename>
|
||||
static std::false_type CheckShortDebugString(...);
|
||||
|
||||
using HasDebugStringType = decltype(CheckDebugString<T>(nullptr));
|
||||
using HasShortDebugStringType = decltype(CheckShortDebugString<T>(nullptr));
|
||||
|
||||
public:
|
||||
static constexpr bool value =
|
||||
HasDebugStringType::value && HasShortDebugStringType::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool HasDebugStringAndShortDebugString<T>::value;
|
||||
|
||||
// When the compiler sees expression IsContainerTest<C>(0), if C is an
|
||||
// STL-style container class, the first overload of IsContainerTest
|
||||
|
@ -899,9 +954,7 @@ IsContainer IsContainerTest(int /* dummy */) {
|
|||
|
||||
typedef char IsNotContainer;
|
||||
template <class C>
|
||||
IsNotContainer IsContainerTest(long /* dummy */) {
|
||||
return '\0';
|
||||
}
|
||||
IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
|
||||
|
||||
// Trait to detect whether a type T is a hash table.
|
||||
// The heuristic used is that the type contains an inner type `hasher` and does
|
||||
|
@ -964,13 +1017,11 @@ bool ArrayEq(const T* lhs, size_t size, const U* rhs);
|
|||
|
||||
// This generic version is used when k is 0.
|
||||
template <typename T, typename U>
|
||||
inline bool ArrayEq(const T& lhs, const U& rhs) {
|
||||
return lhs == rhs;
|
||||
}
|
||||
inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
|
||||
|
||||
// This overload is used when k >= 1.
|
||||
template <typename T, typename U, size_t N>
|
||||
inline bool ArrayEq(const T (&lhs)[N], const U (&rhs)[N]) {
|
||||
inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
|
||||
return internal::ArrayEq(lhs, N, rhs);
|
||||
}
|
||||
|
||||
|
@ -980,7 +1031,8 @@ inline bool ArrayEq(const T (&lhs)[N], const U (&rhs)[N]) {
|
|||
template <typename T, typename U>
|
||||
bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
|
||||
for (size_t i = 0; i != size; i++) {
|
||||
if (!internal::ArrayEq(lhs[i], rhs[i])) return false;
|
||||
if (!internal::ArrayEq(lhs[i], rhs[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -990,7 +1042,8 @@ bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
|
|||
template <typename Iter, typename Element>
|
||||
Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
|
||||
for (Iter it = begin; it != end; ++it) {
|
||||
if (internal::ArrayEq(*it, elem)) return it;
|
||||
if (internal::ArrayEq(*it, elem))
|
||||
return it;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
@ -1004,13 +1057,11 @@ void CopyArray(const T* from, size_t size, U* to);
|
|||
|
||||
// This generic version is used when k is 0.
|
||||
template <typename T, typename U>
|
||||
inline void CopyArray(const T& from, U* to) {
|
||||
*to = from;
|
||||
}
|
||||
inline void CopyArray(const T& from, U* to) { *to = from; }
|
||||
|
||||
// This overload is used when k >= 1.
|
||||
template <typename T, typename U, size_t N>
|
||||
inline void CopyArray(const T (&from)[N], U (*to)[N]) {
|
||||
inline void CopyArray(const T(&from)[N], U(*to)[N]) {
|
||||
internal::CopyArray(from, N, *to);
|
||||
}
|
||||
|
||||
|
@ -1063,7 +1114,8 @@ class NativeArray {
|
|||
}
|
||||
|
||||
~NativeArray() {
|
||||
if (clone_ != &NativeArray::InitRef) delete[] array_;
|
||||
if (clone_ != &NativeArray::InitRef)
|
||||
delete[] array_;
|
||||
}
|
||||
|
||||
// STL-style container methods.
|
||||
|
@ -1071,7 +1123,8 @@ class NativeArray {
|
|||
const_iterator begin() const { return array_; }
|
||||
const_iterator end() const { return array_ + size_; }
|
||||
bool operator==(const NativeArray& rhs) const {
|
||||
return size() == rhs.size() && ArrayEq(begin(), size(), rhs.begin());
|
||||
return size() == rhs.size() &&
|
||||
ArrayEq(begin(), size(), rhs.begin());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1098,8 +1151,6 @@ class NativeArray {
|
|||
const Element* array_;
|
||||
size_t size_;
|
||||
void (NativeArray::*clone_)(const Element*, size_t);
|
||||
|
||||
GTEST_DISALLOW_ASSIGN_(NativeArray);
|
||||
};
|
||||
|
||||
// Backport of std::index_sequence.
|
||||
|
@ -1123,32 +1174,44 @@ struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
|
|||
// Backport of std::make_index_sequence.
|
||||
// It uses O(ln(N)) instantiation depth.
|
||||
template <size_t N>
|
||||
struct MakeIndexSequence
|
||||
: DoubleSequence<N % 2 == 1, typename MakeIndexSequence<N / 2>::type,
|
||||
struct MakeIndexSequenceImpl
|
||||
: DoubleSequence<N % 2 == 1, typename MakeIndexSequenceImpl<N / 2>::type,
|
||||
N / 2>::type {};
|
||||
|
||||
template <>
|
||||
struct MakeIndexSequence<0> : IndexSequence<> {};
|
||||
struct MakeIndexSequenceImpl<0> : IndexSequence<> {};
|
||||
|
||||
// FIXME: This implementation of ElemFromList is O(1) in instantiation depth,
|
||||
// but it is O(N^2) in total instantiations. Not sure if this is the best
|
||||
// tradeoff, as it will make it somewhat slow to compile.
|
||||
template <typename T, size_t, size_t>
|
||||
struct ElemFromListImpl {};
|
||||
template <size_t N>
|
||||
using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::type;
|
||||
|
||||
template <typename T, size_t I>
|
||||
struct ElemFromListImpl<T, I, I> {
|
||||
using type = T;
|
||||
template <typename... T>
|
||||
using IndexSequenceFor = typename MakeIndexSequence<sizeof...(T)>::type;
|
||||
|
||||
template <size_t>
|
||||
struct Ignore {
|
||||
Ignore(...); // NOLINT
|
||||
};
|
||||
|
||||
// Get the Nth element from T...
|
||||
// It uses O(1) instantiation depth.
|
||||
template <size_t N, typename I, typename... T>
|
||||
struct ElemFromList;
|
||||
template <typename>
|
||||
struct ElemFromListImpl;
|
||||
template <size_t... I>
|
||||
struct ElemFromListImpl<IndexSequence<I...>> {
|
||||
// We make Ignore a template to solve a problem with MSVC.
|
||||
// A non-template Ignore would work fine with `decltype(Ignore(I))...`, but
|
||||
// MSVC doesn't understand how to deal with that pack expansion.
|
||||
// Use `0 * I` to have a single instantiation of Ignore.
|
||||
template <typename R>
|
||||
static R Apply(Ignore<0 * I>..., R (*)(), ...);
|
||||
};
|
||||
|
||||
template <size_t N, size_t... I, typename... T>
|
||||
struct ElemFromList<N, IndexSequence<I...>, T...>
|
||||
: ElemFromListImpl<T, N, I>... {};
|
||||
template <size_t N, typename... T>
|
||||
struct ElemFromList {
|
||||
using type =
|
||||
decltype(ElemFromListImpl<typename MakeIndexSequence<N>::type>::Apply(
|
||||
static_cast<T (*)()>(nullptr)...));
|
||||
};
|
||||
|
||||
struct FlatTupleConstructTag {};
|
||||
|
||||
template <typename... T>
|
||||
class FlatTuple;
|
||||
|
@ -1158,11 +1221,11 @@ struct FlatTupleElemBase;
|
|||
|
||||
template <typename... T, size_t I>
|
||||
struct FlatTupleElemBase<FlatTuple<T...>, I> {
|
||||
using value_type =
|
||||
typename ElemFromList<I, typename MakeIndexSequence<sizeof...(T)>::type,
|
||||
T...>::type;
|
||||
using value_type = typename ElemFromList<I, T...>::type;
|
||||
FlatTupleElemBase() = default;
|
||||
explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
|
||||
template <typename Arg>
|
||||
explicit FlatTupleElemBase(FlatTupleConstructTag, Arg&& t)
|
||||
: value(std::forward<Arg>(t)) {}
|
||||
value_type value;
|
||||
};
|
||||
|
||||
|
@ -1174,13 +1237,35 @@ struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
|
|||
: FlatTupleElemBase<FlatTuple<T...>, Idx>... {
|
||||
using Indices = IndexSequence<Idx...>;
|
||||
FlatTupleBase() = default;
|
||||
explicit FlatTupleBase(T... t)
|
||||
: FlatTupleElemBase<FlatTuple<T...>, Idx>(std::move(t))... {}
|
||||
template <typename... Args>
|
||||
explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args)
|
||||
: FlatTupleElemBase<FlatTuple<T...>, Idx>(FlatTupleConstructTag{},
|
||||
std::forward<Args>(args))... {}
|
||||
|
||||
template <size_t I>
|
||||
const typename ElemFromList<I, T...>::type& Get() const {
|
||||
return FlatTupleElemBase<FlatTuple<T...>, I>::value;
|
||||
}
|
||||
|
||||
template <size_t I>
|
||||
typename ElemFromList<I, T...>::type& Get() {
|
||||
return FlatTupleElemBase<FlatTuple<T...>, I>::value;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
auto Apply(F&& f) -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) {
|
||||
return std::forward<F>(f)(Get<Idx>()...);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
auto Apply(F&& f) const -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) {
|
||||
return std::forward<F>(f)(Get<Idx>()...);
|
||||
}
|
||||
};
|
||||
|
||||
// Analog to std::tuple but with different tradeoffs.
|
||||
// This class minimizes the template instantiation depth, thus allowing more
|
||||
// elements that std::tuple would. std::tuple has been seen to require an
|
||||
// elements than std::tuple would. std::tuple has been seen to require an
|
||||
// instantiation depth of more than 10x the number of elements in some
|
||||
// implementations.
|
||||
// FlatTuple and ElemFromList are not recursive and have a fixed depth
|
||||
|
@ -1191,21 +1276,17 @@ template <typename... T>
|
|||
class FlatTuple
|
||||
: private FlatTupleBase<FlatTuple<T...>,
|
||||
typename MakeIndexSequence<sizeof...(T)>::type> {
|
||||
using Indices = typename FlatTuple::FlatTupleBase::Indices;
|
||||
using Indices = typename FlatTupleBase<
|
||||
FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type>::Indices;
|
||||
|
||||
public:
|
||||
FlatTuple() = default;
|
||||
explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
|
||||
template <typename... Args>
|
||||
explicit FlatTuple(FlatTupleConstructTag tag, Args&&... args)
|
||||
: FlatTuple::FlatTupleBase(tag, std::forward<Args>(args)...) {}
|
||||
|
||||
template <size_t I>
|
||||
const typename ElemFromList<I, Indices, T...>::type& Get() const {
|
||||
return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value;
|
||||
}
|
||||
|
||||
template <size_t I>
|
||||
typename ElemFromList<I, Indices, T...>::type& Get() {
|
||||
return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value;
|
||||
}
|
||||
using FlatTuple::FlatTupleBase::Apply;
|
||||
using FlatTuple::FlatTupleBase::Get;
|
||||
};
|
||||
|
||||
// Utility functions to be called with static_assert to induce deprecation
|
||||
|
@ -1238,9 +1319,25 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
|||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
|
||||
::testing::internal::AssertHelper(result_type, file, line, message) = \
|
||||
::testing::Message()
|
||||
namespace std {
|
||||
// Some standard library implementations use `struct tuple_size` and some use
|
||||
// `class tuple_size`. Clang warns about the mismatch.
|
||||
// https://reviews.llvm.org/D55466
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmismatched-tags"
|
||||
#endif
|
||||
template <typename... Ts>
|
||||
struct tuple_size<testing::internal::FlatTuple<Ts...>>
|
||||
: std::integral_constant<size_t, sizeof...(Ts)> {};
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
} // namespace std
|
||||
|
||||
#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
|
||||
::testing::internal::AssertHelper(result_type, file, line, message) \
|
||||
= ::testing::Message()
|
||||
|
||||
#define GTEST_MESSAGE_(message, result_type) \
|
||||
GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
|
||||
|
@ -1260,20 +1357,74 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
|||
// Suppress MSVC warning 4072 (unreachable code) for the code following
|
||||
// statement if it returns or throws (or doesn't return or throw in some
|
||||
// situations).
|
||||
// NOTE: The "else" is important to keep this expansion to prevent a top-level
|
||||
// "else" from attaching to our "if".
|
||||
#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
statement; \
|
||||
} else /* NOLINT */ \
|
||||
static_assert(true, "") // User must have a semicolon after expansion.
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
class NeverThrown {
|
||||
public:
|
||||
const char* what() const noexcept {
|
||||
return "this exception should never be thrown";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#if GTEST_HAS_RTTI
|
||||
|
||||
#define GTEST_EXCEPTION_TYPE_(e) ::testing::internal::GetTypeName(typeid(e))
|
||||
|
||||
#else // GTEST_HAS_RTTI
|
||||
|
||||
#define GTEST_EXCEPTION_TYPE_(e) \
|
||||
std::string { "an std::exception-derived error" }
|
||||
|
||||
#endif // GTEST_HAS_RTTI
|
||||
|
||||
#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) \
|
||||
catch (typename std::conditional< \
|
||||
std::is_same<typename std::remove_cv<typename std::remove_reference< \
|
||||
expected_exception>::type>::type, \
|
||||
std::exception>::value, \
|
||||
const ::testing::internal::NeverThrown&, const std::exception&>::type \
|
||||
e) { \
|
||||
gtest_msg.value = "Expected: " #statement \
|
||||
" throws an exception of type " #expected_exception \
|
||||
".\n Actual: it throws "; \
|
||||
gtest_msg.value += GTEST_EXCEPTION_TYPE_(e); \
|
||||
gtest_msg.value += " with description \""; \
|
||||
gtest_msg.value += e.what(); \
|
||||
gtest_msg.value += "\"."; \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
|
||||
}
|
||||
|
||||
#else // GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception)
|
||||
|
||||
#endif // GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::ConstCharPtr gtest_msg = "") { \
|
||||
if (::testing::internal::TrueWithString gtest_msg{}) { \
|
||||
bool gtest_caught_expected = false; \
|
||||
try { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} catch (expected_exception const&) { \
|
||||
gtest_caught_expected = true; \
|
||||
} catch (...) { \
|
||||
} \
|
||||
GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) \
|
||||
catch (...) { \
|
||||
gtest_msg.value = "Expected: " #statement \
|
||||
" throws an exception of type " #expected_exception \
|
||||
".\n Actual: it throws a different type."; \
|
||||
|
@ -1285,69 +1436,88 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
|||
".\n Actual: it throws nothing."; \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
|
||||
} \
|
||||
} else \
|
||||
} else /*NOLINT*/ \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \
|
||||
: fail(gtest_msg.value)
|
||||
: fail(gtest_msg.value.c_str())
|
||||
|
||||
#define GTEST_TEST_NO_THROW_(statement, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
try { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} catch (...) { \
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \
|
||||
catch (std::exception const& e) { \
|
||||
gtest_msg.value = "it throws "; \
|
||||
gtest_msg.value += GTEST_EXCEPTION_TYPE_(e); \
|
||||
gtest_msg.value += " with description \""; \
|
||||
gtest_msg.value += e.what(); \
|
||||
gtest_msg.value += "\"."; \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
|
||||
}
|
||||
|
||||
#else // GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_()
|
||||
|
||||
#endif // GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#define GTEST_TEST_NO_THROW_(statement, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::TrueWithString gtest_msg{}) { \
|
||||
try { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} \
|
||||
GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \
|
||||
catch (...) { \
|
||||
gtest_msg.value = "it throws."; \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
|
||||
} \
|
||||
} else \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__) \
|
||||
: fail("Expected: " #statement \
|
||||
" doesn't throw an exception.\n" \
|
||||
" Actual: it throws.")
|
||||
} \
|
||||
} else \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
|
||||
fail(("Expected: " #statement " doesn't throw an exception.\n" \
|
||||
" Actual: " + gtest_msg.value).c_str())
|
||||
|
||||
#define GTEST_TEST_ANY_THROW_(statement, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
bool gtest_caught_any = false; \
|
||||
try { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} catch (...) { \
|
||||
gtest_caught_any = true; \
|
||||
} \
|
||||
if (!gtest_caught_any) { \
|
||||
#define GTEST_TEST_ANY_THROW_(statement, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
bool gtest_caught_any = false; \
|
||||
try { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} \
|
||||
catch (...) { \
|
||||
gtest_caught_any = true; \
|
||||
} \
|
||||
if (!gtest_caught_any) { \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
|
||||
} \
|
||||
} else \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__) \
|
||||
: fail("Expected: " #statement \
|
||||
" throws an exception.\n" \
|
||||
" Actual: it doesn't.")
|
||||
} \
|
||||
} else \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
|
||||
fail("Expected: " #statement " throws an exception.\n" \
|
||||
" Actual: it doesn't.")
|
||||
|
||||
|
||||
// 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.
|
||||
// representation of expression as it was passed into the EXPECT_TRUE.
|
||||
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (const ::testing::AssertionResult gtest_ar_ = \
|
||||
::testing::AssertionResult(expression)) \
|
||||
; \
|
||||
else \
|
||||
fail(::testing::internal::GetBoolAssertionFailureMessage( \
|
||||
gtest_ar_, text, #actual, #expected) \
|
||||
.c_str())
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (const ::testing::AssertionResult gtest_ar_ = \
|
||||
::testing::AssertionResult(expression)) \
|
||||
; \
|
||||
else \
|
||||
fail(::testing::internal::GetBoolAssertionFailureMessage(\
|
||||
gtest_ar_, text, #actual, #expected).c_str())
|
||||
|
||||
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
|
||||
} \
|
||||
} else \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__) \
|
||||
: fail("Expected: " #statement \
|
||||
" doesn't generate new fatal " \
|
||||
"failures in the current thread.\n" \
|
||||
" Actual: it does.")
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
|
||||
} \
|
||||
} else \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
|
||||
fail("Expected: " #statement " doesn't generate new fatal " \
|
||||
"failures in the current thread.\n" \
|
||||
" Actual: it does.")
|
||||
|
||||
// Expands to the name of the class that implements the given test.
|
||||
#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
|
||||
|
@ -1362,13 +1532,16 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
|||
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
|
||||
: public parent_class { \
|
||||
public: \
|
||||
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \
|
||||
\
|
||||
private: \
|
||||
virtual void TestBody(); \
|
||||
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \
|
||||
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default; \
|
||||
~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||
test_name)); \
|
||||
GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||
test_name)); \
|
||||
\
|
||||
private: \
|
||||
void TestBody() override; \
|
||||
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \
|
||||
}; \
|
||||
\
|
||||
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||
|
@ -1384,4 +1557,4 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
|||
test_suite_name, test_name)>); \
|
||||
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
|
|
|
@ -27,12 +27,13 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Type and function utilities for implementing parameterized tests.
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
@ -41,20 +42,23 @@
|
|||
#include <memory>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/gtest-printers.h"
|
||||
#include "gtest/gtest-test-part.h"
|
||||
|
||||
namespace testing {
|
||||
// Input to a parameterized test name generator, describing a test parameter.
|
||||
// Consists of the parameter value and the integer parameter index.
|
||||
template <class ParamType>
|
||||
struct TestParamInfo {
|
||||
TestParamInfo(const ParamType& a_param, size_t an_index)
|
||||
: param(a_param), index(an_index) {}
|
||||
TestParamInfo(const ParamType& a_param, size_t an_index) :
|
||||
param(a_param),
|
||||
index(an_index) {}
|
||||
ParamType param;
|
||||
size_t index;
|
||||
};
|
||||
|
@ -80,10 +84,8 @@ namespace internal {
|
|||
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
|
||||
CodeLocation code_location);
|
||||
|
||||
template <typename>
|
||||
class ParamGeneratorInterface;
|
||||
template <typename>
|
||||
class ParamGenerator;
|
||||
template <typename> class ParamGeneratorInterface;
|
||||
template <typename> class ParamGenerator;
|
||||
|
||||
// Interface for iterating over elements provided by an implementation
|
||||
// of ParamGeneratorInterface<T>.
|
||||
|
@ -127,7 +129,8 @@ class ParamIterator {
|
|||
// ParamIterator assumes ownership of the impl_ pointer.
|
||||
ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
|
||||
ParamIterator& operator=(const ParamIterator& other) {
|
||||
if (this != &other) impl_.reset(other.impl_->Clone());
|
||||
if (this != &other)
|
||||
impl_.reset(other.impl_->Clone());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -154,7 +157,7 @@ class ParamIterator {
|
|||
private:
|
||||
friend class ParamGenerator<T>;
|
||||
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
|
||||
std::unique_ptr<ParamIteratorInterface<T>> impl_;
|
||||
std::unique_ptr<ParamIteratorInterface<T> > impl_;
|
||||
};
|
||||
|
||||
// ParamGeneratorInterface<T> is the binary interface to access generators
|
||||
|
@ -176,7 +179,7 @@ class ParamGeneratorInterface {
|
|||
// This class implements copy initialization semantics and the contained
|
||||
// ParamGeneratorInterface<T> instance is shared among all copies
|
||||
// of the original object. This is possible because that instance is immutable.
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
class ParamGenerator {
|
||||
public:
|
||||
typedef ParamIterator<T> iterator;
|
||||
|
@ -193,7 +196,7 @@ class ParamGenerator {
|
|||
iterator end() const { return iterator(impl_->End()); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<const ParamGeneratorInterface<T>> impl_;
|
||||
std::shared_ptr<const ParamGeneratorInterface<T> > impl_;
|
||||
};
|
||||
|
||||
// Generates values from a range of two comparable values. Can be used to
|
||||
|
@ -204,10 +207,8 @@ template <typename T, typename IncrementT>
|
|||
class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||
public:
|
||||
RangeGenerator(T begin, T end, IncrementT step)
|
||||
: begin_(begin),
|
||||
end_(end),
|
||||
step_(step),
|
||||
end_index_(CalculateEndIndex(begin, end, step)) {}
|
||||
: begin_(begin), end_(end),
|
||||
step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
|
||||
~RangeGenerator() override {}
|
||||
|
||||
ParamIteratorInterface<T>* Begin() const override {
|
||||
|
@ -250,9 +251,7 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
|||
private:
|
||||
Iterator(const Iterator& other)
|
||||
: ParamIteratorInterface<T>(),
|
||||
base_(other.base_),
|
||||
value_(other.value_),
|
||||
index_(other.index_),
|
||||
base_(other.base_), value_(other.value_), index_(other.index_),
|
||||
step_(other.step_) {}
|
||||
|
||||
// No implementation - assignment is unsupported.
|
||||
|
@ -264,10 +263,12 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
|||
const IncrementT step_;
|
||||
}; // class RangeGenerator::Iterator
|
||||
|
||||
static int CalculateEndIndex(const T& begin, const T& end,
|
||||
static int CalculateEndIndex(const T& begin,
|
||||
const T& end,
|
||||
const IncrementT& step) {
|
||||
int end_index = 0;
|
||||
for (T i = begin; i < end; i = static_cast<T>(i + step)) end_index++;
|
||||
for (T i = begin; i < end; i = static_cast<T>(i + step))
|
||||
end_index++;
|
||||
return end_index;
|
||||
}
|
||||
|
||||
|
@ -282,6 +283,7 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
|||
const int end_index_;
|
||||
}; // class RangeGenerator
|
||||
|
||||
|
||||
// Generates values from a pair of STL-style iterators. Used in the
|
||||
// ValuesIn() function. The elements are copied from the source range
|
||||
// since the source can be located on the stack, and the generator
|
||||
|
@ -339,13 +341,13 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
|||
<< "The program attempted to compare iterators "
|
||||
<< "from different generators." << std::endl;
|
||||
return iterator_ ==
|
||||
CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
|
||||
CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator(const Iterator& other)
|
||||
// The explicit constructor call suppresses a false warning
|
||||
// emitted by gcc when supplied with the -Wextra option.
|
||||
// The explicit constructor call suppresses a false warning
|
||||
// emitted by gcc when supplied with the -Wextra option.
|
||||
: ParamIteratorInterface<T>(),
|
||||
base_(other.base_),
|
||||
iterator_(other.iterator_) {}
|
||||
|
@ -392,8 +394,8 @@ template <class TestClass>
|
|||
class ParameterizedTestFactory : public TestFactoryBase {
|
||||
public:
|
||||
typedef typename TestClass::ParamType ParamType;
|
||||
explicit ParameterizedTestFactory(ParamType parameter)
|
||||
: parameter_(parameter) {}
|
||||
explicit ParameterizedTestFactory(ParamType parameter) :
|
||||
parameter_(parameter) {}
|
||||
Test* CreateTest() override {
|
||||
TestClass::SetParam(¶meter_);
|
||||
return new TestClass();
|
||||
|
@ -457,7 +459,7 @@ class ParameterizedTestSuiteInfoBase {
|
|||
|
||||
// Base part of test suite name for display purposes.
|
||||
virtual const std::string& GetTestSuiteName() const = 0;
|
||||
// Test case id to verify identity.
|
||||
// Test suite id to verify identity.
|
||||
virtual TypeId GetTestSuiteTypeId() const = 0;
|
||||
// UnitTest class invokes this method to register tests in this
|
||||
// test suite right before running them in RUN_ALL_TESTS macro.
|
||||
|
@ -472,6 +474,17 @@ class ParameterizedTestSuiteInfoBase {
|
|||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
|
||||
};
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Report a the name of a test_suit as safe to ignore
|
||||
// as the side effect of construction of this type.
|
||||
struct GTEST_API_ MarkAsIgnored {
|
||||
explicit MarkAsIgnored(const char* test_suite);
|
||||
};
|
||||
|
||||
GTEST_API_ void InsertSyntheticTestCase(const std::string& name,
|
||||
CodeLocation location, bool has_test_p);
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
|
||||
|
@ -494,11 +507,11 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
|||
CodeLocation code_location)
|
||||
: test_suite_name_(name), code_location_(code_location) {}
|
||||
|
||||
// Test case base name for display purposes.
|
||||
// Test suite base name for display purposes.
|
||||
const std::string& GetTestSuiteName() const override {
|
||||
return test_suite_name_;
|
||||
}
|
||||
// Test case id to verify identity.
|
||||
// Test suite id to verify identity.
|
||||
TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
|
||||
// TEST_P macro uses AddTestPattern() to record information
|
||||
// about a single test in a LocalTestInfo structure.
|
||||
|
@ -507,9 +520,10 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
|||
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
|
||||
// test suite base name and DoBar is test base name.
|
||||
void AddTestPattern(const char* test_suite_name, const char* test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* meta_factory) {
|
||||
tests_.push_back(std::shared_ptr<TestInfo>(
|
||||
new TestInfo(test_suite_name, test_base_name, meta_factory)));
|
||||
TestMetaFactoryBase<ParamType>* meta_factory,
|
||||
CodeLocation code_location) {
|
||||
tests_.push_back(std::shared_ptr<TestInfo>(new TestInfo(
|
||||
test_suite_name, test_base_name, meta_factory, code_location)));
|
||||
}
|
||||
// INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
|
||||
// about a generator.
|
||||
|
@ -522,17 +536,19 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
|||
return 0; // Return value used only to run this method in namespace scope.
|
||||
}
|
||||
// UnitTest class invokes this method to register tests in this test suite
|
||||
// test suites right before running tests in RUN_ALL_TESTS macro.
|
||||
// right before running tests in RUN_ALL_TESTS macro.
|
||||
// This method should not be called more than once on any single
|
||||
// instance of a ParameterizedTestSuiteInfoBase derived class.
|
||||
// UnitTest has a guard to prevent from calling this method more than once.
|
||||
void RegisterTests() override {
|
||||
bool generated_instantiations = false;
|
||||
|
||||
for (typename TestInfoContainer::iterator test_it = tests_.begin();
|
||||
test_it != tests_.end(); ++test_it) {
|
||||
std::shared_ptr<TestInfo> test_info = *test_it;
|
||||
for (typename InstantiationContainer::iterator gen_it =
|
||||
instantiations_.begin();
|
||||
gen_it != instantiations_.end(); ++gen_it) {
|
||||
instantiations_.begin(); gen_it != instantiations_.end();
|
||||
++gen_it) {
|
||||
const std::string& instantiation_name = gen_it->name;
|
||||
ParamGenerator<ParamType> generator((*gen_it->generator)());
|
||||
ParamNameGeneratorFunc* name_func = gen_it->name_func;
|
||||
|
@ -540,27 +556,30 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
|||
int line = gen_it->line;
|
||||
|
||||
std::string test_suite_name;
|
||||
if (!instantiation_name.empty())
|
||||
if ( !instantiation_name.empty() )
|
||||
test_suite_name = instantiation_name + "/";
|
||||
test_suite_name += test_info->test_suite_base_name;
|
||||
|
||||
size_t i = 0;
|
||||
std::set<std::string> test_param_names;
|
||||
for (typename ParamGenerator<ParamType>::iterator
|
||||
param_it = generator.begin();
|
||||
for (typename ParamGenerator<ParamType>::iterator param_it =
|
||||
generator.begin();
|
||||
param_it != generator.end(); ++param_it, ++i) {
|
||||
generated_instantiations = true;
|
||||
|
||||
Message test_name_stream;
|
||||
|
||||
std::string param_name =
|
||||
name_func(TestParamInfo<ParamType>(*param_it, i));
|
||||
std::string param_name = name_func(
|
||||
TestParamInfo<ParamType>(*param_it, i));
|
||||
|
||||
GTEST_CHECK_(IsValidParamName(param_name))
|
||||
<< "Parameterized test name '" << param_name
|
||||
<< "' is invalid, in " << file << " line " << line << std::endl;
|
||||
<< "' is invalid, in " << file
|
||||
<< " line " << line << std::endl;
|
||||
|
||||
GTEST_CHECK_(test_param_names.count(param_name) == 0)
|
||||
<< "Duplicate parameterized test name '" << param_name << "', in "
|
||||
<< file << " line " << line << std::endl;
|
||||
<< "Duplicate parameterized test name '" << param_name
|
||||
<< "', in " << file << " line " << line << std::endl;
|
||||
|
||||
test_param_names.insert(param_name);
|
||||
|
||||
|
@ -571,60 +590,72 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
|||
MakeAndRegisterTestInfo(
|
||||
test_suite_name.c_str(), test_name_stream.GetString().c_str(),
|
||||
nullptr, // No type parameter.
|
||||
PrintToString(*param_it).c_str(), code_location_,
|
||||
PrintToString(*param_it).c_str(), test_info->code_location,
|
||||
GetTestSuiteTypeId(),
|
||||
SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
|
||||
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
|
||||
test_info->test_meta_factory->CreateTestFactory(*param_it));
|
||||
} // for param_it
|
||||
} // for gen_it
|
||||
} // for test_it
|
||||
} // RegisterTests
|
||||
} // for gen_it
|
||||
} // for test_it
|
||||
|
||||
if (!generated_instantiations) {
|
||||
// There are no generaotrs, or they all generate nothing ...
|
||||
InsertSyntheticTestCase(GetTestSuiteName(), code_location_,
|
||||
!tests_.empty());
|
||||
}
|
||||
} // RegisterTests
|
||||
|
||||
private:
|
||||
// LocalTestInfo structure keeps information about a single test registered
|
||||
// with TEST_P macro.
|
||||
struct TestInfo {
|
||||
TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* a_test_meta_factory)
|
||||
TestMetaFactoryBase<ParamType>* a_test_meta_factory,
|
||||
CodeLocation a_code_location)
|
||||
: test_suite_base_name(a_test_suite_base_name),
|
||||
test_base_name(a_test_base_name),
|
||||
test_meta_factory(a_test_meta_factory) {}
|
||||
test_meta_factory(a_test_meta_factory),
|
||||
code_location(a_code_location) {}
|
||||
|
||||
const std::string test_suite_base_name;
|
||||
const std::string test_base_name;
|
||||
const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory;
|
||||
const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
|
||||
const CodeLocation code_location;
|
||||
};
|
||||
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo>>;
|
||||
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
|
||||
// Records data received from INSTANTIATE_TEST_SUITE_P macros:
|
||||
// <Instantiation name, Sequence generator creation function,
|
||||
// Name generator function, Source file, Source line>
|
||||
struct InstantiationInfo {
|
||||
InstantiationInfo(const std::string& name_in,
|
||||
GeneratorCreationFunc* generator_in,
|
||||
ParamNameGeneratorFunc* name_func_in, const char* file_in,
|
||||
int line_in)
|
||||
: name(name_in),
|
||||
generator(generator_in),
|
||||
name_func(name_func_in),
|
||||
file(file_in),
|
||||
line(line_in) {}
|
||||
InstantiationInfo(const std::string &name_in,
|
||||
GeneratorCreationFunc* generator_in,
|
||||
ParamNameGeneratorFunc* name_func_in,
|
||||
const char* file_in,
|
||||
int line_in)
|
||||
: name(name_in),
|
||||
generator(generator_in),
|
||||
name_func(name_func_in),
|
||||
file(file_in),
|
||||
line(line_in) {}
|
||||
|
||||
std::string name;
|
||||
GeneratorCreationFunc* generator;
|
||||
ParamNameGeneratorFunc* name_func;
|
||||
const char* file;
|
||||
int line;
|
||||
std::string name;
|
||||
GeneratorCreationFunc* generator;
|
||||
ParamNameGeneratorFunc* name_func;
|
||||
const char* file;
|
||||
int line;
|
||||
};
|
||||
typedef ::std::vector<InstantiationInfo> InstantiationContainer;
|
||||
|
||||
static bool IsValidParamName(const std::string& name) {
|
||||
// Check for empty string
|
||||
if (name.empty()) return false;
|
||||
if (name.empty())
|
||||
return false;
|
||||
|
||||
// Check for invalid characters
|
||||
for (std::string::size_type index = 0; index < name.size(); ++index) {
|
||||
if (!isalnum(name[index]) && name[index] != '_') return false;
|
||||
if (!IsAlNum(name[index]) && name[index] != '_')
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -678,7 +709,7 @@ class ParameterizedTestSuiteRegistry {
|
|||
// type we are looking for, so we downcast it to that type
|
||||
// without further checks.
|
||||
typed_test_info = CheckedDowncastToActualType<
|
||||
ParameterizedTestSuiteInfo<TestSuite>>(test_suite_info);
|
||||
ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -713,6 +744,34 @@ class ParameterizedTestSuiteRegistry {
|
|||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry);
|
||||
};
|
||||
|
||||
// Keep track of what type-parameterized test suite are defined and
|
||||
// where as well as which are intatiated. This allows susequently
|
||||
// identifying suits that are defined but never used.
|
||||
class TypeParameterizedTestSuiteRegistry {
|
||||
public:
|
||||
// Add a suite definition
|
||||
void RegisterTestSuite(const char* test_suite_name,
|
||||
CodeLocation code_location);
|
||||
|
||||
// Add an instantiation of a suit.
|
||||
void RegisterInstantiation(const char* test_suite_name);
|
||||
|
||||
// For each suit repored as defined but not reported as instantiation,
|
||||
// emit a test that reports that fact (configurably, as an error).
|
||||
void CheckForInstantiations();
|
||||
|
||||
private:
|
||||
struct TypeParameterizedTestSuiteInfo {
|
||||
explicit TypeParameterizedTestSuiteInfo(CodeLocation c)
|
||||
: code_location(c), instantiated(false) {}
|
||||
|
||||
CodeLocation code_location;
|
||||
bool instantiated;
|
||||
};
|
||||
|
||||
std::map<std::string, TypeParameterizedTestSuiteInfo> suites_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Forward declarations of ValuesIn(), which is implemented in
|
||||
|
@ -724,10 +783,15 @@ internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
|||
namespace internal {
|
||||
// Used in the Values() function to provide polymorphic capabilities.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100)
|
||||
#endif
|
||||
|
||||
template <typename... Ts>
|
||||
class ValueArray {
|
||||
public:
|
||||
ValueArray(Ts... v) : v_{std::move(v)...} {}
|
||||
explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {}
|
||||
|
||||
template <typename T>
|
||||
operator ParamGenerator<T>() const { // NOLINT
|
||||
|
@ -743,6 +807,10 @@ class ValueArray {
|
|||
FlatTuple<Ts...> v_;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <typename... T>
|
||||
class CartesianProductGenerator
|
||||
: public ParamGeneratorInterface<::std::tuple<T...>> {
|
||||
|
@ -768,8 +836,7 @@ class CartesianProductGenerator
|
|||
: public ParamIteratorInterface<ParamType> {
|
||||
public:
|
||||
IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
|
||||
const std::tuple<ParamGenerator<T>...>& generators,
|
||||
bool is_end)
|
||||
const std::tuple<ParamGenerator<T>...>& generators, bool is_end)
|
||||
: base_(base),
|
||||
begin_(std::get<I>(generators).begin()...),
|
||||
end_(std::get<I>(generators).end()...),
|
||||
|
@ -812,9 +879,9 @@ class CartesianProductGenerator
|
|||
if (AtEnd() && typed_other->AtEnd()) return true;
|
||||
|
||||
bool same = true;
|
||||
bool dummy[] = {(same = same &&
|
||||
std::get<I>(current_) ==
|
||||
std::get<I>(typed_other->current_))...};
|
||||
bool dummy[] = {
|
||||
(same = same && std::get<I>(current_) ==
|
||||
std::get<I>(typed_other->current_))...};
|
||||
(void)dummy;
|
||||
return same;
|
||||
}
|
||||
|
@ -877,4 +944,4 @@ class CartesianProductHolder {
|
|||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
|
|
|
@ -32,76 +32,83 @@
|
|||
// This header file defines the GTEST_OS_* macro.
|
||||
// It is separate from gtest-port.h so that custom/gtest-port.h can include it.
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
|
||||
// Determines the platform on which Google Test is compiled.
|
||||
#ifdef __CYGWIN__
|
||||
#define GTEST_OS_CYGWIN 1
|
||||
#elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||
#define GTEST_OS_WINDOWS_MINGW 1
|
||||
#define GTEST_OS_WINDOWS 1
|
||||
# define GTEST_OS_CYGWIN 1
|
||||
# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||
# define GTEST_OS_WINDOWS_MINGW 1
|
||||
# define GTEST_OS_WINDOWS 1
|
||||
#elif defined _WIN32
|
||||
#define GTEST_OS_WINDOWS 1
|
||||
#ifdef _WIN32_WCE
|
||||
#define GTEST_OS_WINDOWS_MOBILE 1
|
||||
#elif defined(WINAPI_FAMILY)
|
||||
#include <winapifamily.h>
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
#define GTEST_OS_WINDOWS_DESKTOP 1
|
||||
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
||||
#define GTEST_OS_WINDOWS_PHONE 1
|
||||
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
#define GTEST_OS_WINDOWS_RT 1
|
||||
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
|
||||
#define GTEST_OS_WINDOWS_PHONE 1
|
||||
#define GTEST_OS_WINDOWS_TV_TITLE 1
|
||||
#else
|
||||
// WINAPI_FAMILY defined but no known partition matched.
|
||||
// Default to desktop.
|
||||
#define GTEST_OS_WINDOWS_DESKTOP 1
|
||||
#endif
|
||||
#else
|
||||
#define GTEST_OS_WINDOWS_DESKTOP 1
|
||||
#endif // _WIN32_WCE
|
||||
# define GTEST_OS_WINDOWS 1
|
||||
# ifdef _WIN32_WCE
|
||||
# define GTEST_OS_WINDOWS_MOBILE 1
|
||||
# elif defined(WINAPI_FAMILY)
|
||||
# include <winapifamily.h>
|
||||
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
||||
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
||||
# define GTEST_OS_WINDOWS_PHONE 1
|
||||
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
# define GTEST_OS_WINDOWS_RT 1
|
||||
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
|
||||
# define GTEST_OS_WINDOWS_PHONE 1
|
||||
# define GTEST_OS_WINDOWS_TV_TITLE 1
|
||||
# else
|
||||
// WINAPI_FAMILY defined but no known partition matched.
|
||||
// Default to desktop.
|
||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
||||
# endif
|
||||
# else
|
||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
||||
# endif // _WIN32_WCE
|
||||
#elif defined __OS2__
|
||||
#define GTEST_OS_OS2 1
|
||||
# define GTEST_OS_OS2 1
|
||||
#elif defined __APPLE__
|
||||
#define GTEST_OS_MAC 1
|
||||
#if TARGET_OS_IPHONE
|
||||
#define GTEST_OS_IOS 1
|
||||
#endif
|
||||
# define GTEST_OS_MAC 1
|
||||
# include <TargetConditionals.h>
|
||||
# if TARGET_OS_IPHONE
|
||||
# define GTEST_OS_IOS 1
|
||||
# endif
|
||||
#elif defined __DragonFly__
|
||||
#define GTEST_OS_DRAGONFLY 1
|
||||
# define GTEST_OS_DRAGONFLY 1
|
||||
#elif defined __FreeBSD__
|
||||
#define GTEST_OS_FREEBSD 1
|
||||
# define GTEST_OS_FREEBSD 1
|
||||
#elif defined __Fuchsia__
|
||||
#define GTEST_OS_FUCHSIA 1
|
||||
# define GTEST_OS_FUCHSIA 1
|
||||
#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__)
|
||||
#define GTEST_OS_GNU_KFREEBSD 1
|
||||
# define GTEST_OS_GNU_KFREEBSD 1
|
||||
#elif defined __linux__
|
||||
#define GTEST_OS_LINUX 1
|
||||
#if defined __ANDROID__
|
||||
#define GTEST_OS_LINUX_ANDROID 1
|
||||
#endif
|
||||
# define GTEST_OS_LINUX 1
|
||||
# if defined __ANDROID__
|
||||
# define GTEST_OS_LINUX_ANDROID 1
|
||||
# endif
|
||||
#elif defined __MVS__
|
||||
#define GTEST_OS_ZOS 1
|
||||
# define GTEST_OS_ZOS 1
|
||||
#elif defined(__sun) && defined(__SVR4)
|
||||
#define GTEST_OS_SOLARIS 1
|
||||
# define GTEST_OS_SOLARIS 1
|
||||
#elif defined(_AIX)
|
||||
#define GTEST_OS_AIX 1
|
||||
# define GTEST_OS_AIX 1
|
||||
#elif defined(__hpux)
|
||||
#define GTEST_OS_HPUX 1
|
||||
# define GTEST_OS_HPUX 1
|
||||
#elif defined __native_client__
|
||||
#define GTEST_OS_NACL 1
|
||||
# define GTEST_OS_NACL 1
|
||||
#elif defined __NetBSD__
|
||||
#define GTEST_OS_NETBSD 1
|
||||
# define GTEST_OS_NETBSD 1
|
||||
#elif defined __OpenBSD__
|
||||
#define GTEST_OS_OPENBSD 1
|
||||
# define GTEST_OS_OPENBSD 1
|
||||
#elif defined __QNX__
|
||||
#define GTEST_OS_QNX 1
|
||||
# define GTEST_OS_QNX 1
|
||||
#elif defined(__HAIKU__)
|
||||
#define GTEST_OS_HAIKU 1
|
||||
#elif defined ESP8266
|
||||
#define GTEST_OS_ESP8266 1
|
||||
#elif defined ESP32
|
||||
#define GTEST_OS_ESP32 1
|
||||
#elif defined(__XTENSA__)
|
||||
#define GTEST_OS_XTENSA 1
|
||||
#endif // __CYGWIN__
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -38,15 +38,16 @@
|
|||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
// string.h is not guaranteed to provide strcpy on C++ Builder.
|
||||
#include <mem.h>
|
||||
# include <mem.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
@ -122,7 +123,8 @@ class GTEST_API_ String {
|
|||
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
||||
// A NULL C string is considered different to any non-NULL C string,
|
||||
// including the empty string.
|
||||
static bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs);
|
||||
static bool CaseInsensitiveCStringEquals(const char* lhs,
|
||||
const char* rhs);
|
||||
|
||||
// Compares two wide C strings, ignoring case. Returns true if and only if
|
||||
// they have the same content.
|
||||
|
@ -141,24 +143,27 @@ class GTEST_API_ String {
|
|||
|
||||
// Returns true if and only if the given string ends with the given suffix,
|
||||
// ignoring case. Any string is considered to end with an empty suffix.
|
||||
static bool EndsWithCaseInsensitive(const std::string& str,
|
||||
const std::string& suffix);
|
||||
static bool EndsWithCaseInsensitive(
|
||||
const std::string& str, const std::string& suffix);
|
||||
|
||||
// Formats an int value as "%02d".
|
||||
static std::string FormatIntWidth2(int value); // "%02d" for width == 2
|
||||
|
||||
// Formats an int value to given width with leading zeros.
|
||||
static std::string FormatIntWidthN(int value, int width);
|
||||
|
||||
// Formats an int value as "%X".
|
||||
static std::string FormatHexInt(int value);
|
||||
|
||||
// Formats an int value as "%X".
|
||||
static std::string FormatHexUInt32(UInt32 value);
|
||||
static std::string FormatHexUInt32(uint32_t value);
|
||||
|
||||
// Formats a byte as "%02X".
|
||||
static std::string FormatByte(unsigned char value);
|
||||
|
||||
private:
|
||||
String(); // Not meant to be instantiated.
|
||||
}; // class String
|
||||
}; // class String
|
||||
|
||||
// Gets the content of the stringstream's buffer as an std::string. Each '\0'
|
||||
// character in the buffer is replaced with "\\0".
|
||||
|
@ -167,4 +172,4 @@ GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
|
|||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,302 +0,0 @@
|
|||
$$ -*- mode: c++; -*-
|
||||
$var n = 50 $$ Maximum length of type lists we want to support.
|
||||
// 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.
|
||||
|
||||
|
||||
// Type utilities needed for implementing typed and type-parameterized
|
||||
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||
//
|
||||
// Currently we support at most $n types in a list, and at most $n
|
||||
// type-parameterized tests in one type-parameterized test suite.
|
||||
// Please contact googletestframework@googlegroups.com if you need
|
||||
// more.
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
||||
// libstdc++ (which is where cxxabi.h comes from).
|
||||
# if GTEST_HAS_CXXABI_H_
|
||||
# include <cxxabi.h>
|
||||
# elif defined(__HP_aCC)
|
||||
# include <acxx_demangle.h>
|
||||
# endif // GTEST_HASH_CXXABI_H_
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Canonicalizes a given name with respect to the Standard C++ Library.
|
||||
// This handles removing the inline namespace within `std` that is
|
||||
// used by various standard libraries (e.g., `std::__1`). Names outside
|
||||
// of namespace std are returned unmodified.
|
||||
inline std::string CanonicalizeForStdLibVersioning(std::string s) {
|
||||
static const char prefix[] = "std::__";
|
||||
if (s.compare(0, strlen(prefix), prefix) == 0) {
|
||||
std::string::size_type end = s.find("::", strlen(prefix));
|
||||
if (end != s.npos) {
|
||||
// Erase everything between the initial `std` and the second `::`.
|
||||
s.erase(strlen("std"), end - strlen("std"));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// GetTypeName<T>() returns a human-readable name of type T.
|
||||
// NB: This function is also used in Google Mock, so don't move it inside of
|
||||
// the typed-test-only section below.
|
||||
template <typename T>
|
||||
std::string GetTypeName() {
|
||||
# if GTEST_HAS_RTTI
|
||||
|
||||
const char* const name = typeid(T).name();
|
||||
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
|
||||
int status = 0;
|
||||
// gcc's implementation of typeid(T).name() mangles the type name,
|
||||
// so we have to demangle it.
|
||||
# if GTEST_HAS_CXXABI_H_
|
||||
using abi::__cxa_demangle;
|
||||
# endif // GTEST_HAS_CXXABI_H_
|
||||
char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
|
||||
const std::string name_str(status == 0 ? readable_name : name);
|
||||
free(readable_name);
|
||||
return CanonicalizeForStdLibVersioning(name_str);
|
||||
# else
|
||||
return name;
|
||||
# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
|
||||
|
||||
# else
|
||||
|
||||
return "<type>";
|
||||
|
||||
# endif // GTEST_HAS_RTTI
|
||||
}
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// A unique type used as the default value for the arguments of class
|
||||
// template Types. This allows us to simulate variadic templates
|
||||
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
||||
// support directly.
|
||||
struct None {};
|
||||
|
||||
// The following family of struct and struct templates are used to
|
||||
// represent type lists. In particular, TypesN<T1, T2, ..., TN>
|
||||
// represents a type list with N types (T1, T2, ..., and TN) in it.
|
||||
// Except for Types0, every struct in the family has two member types:
|
||||
// Head for the first type in the list, and Tail for the rest of the
|
||||
// list.
|
||||
|
||||
// The empty type list.
|
||||
struct Types0 {};
|
||||
|
||||
// Type lists of length 1, 2, 3, and so on.
|
||||
|
||||
template <typename T1>
|
||||
struct Types1 {
|
||||
typedef T1 Head;
|
||||
typedef Types0 Tail;
|
||||
};
|
||||
|
||||
$range i 2..n
|
||||
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k 2..i
|
||||
template <$for j, [[typename T$j]]>
|
||||
struct Types$i {
|
||||
typedef T1 Head;
|
||||
typedef Types$(i-1)<$for k, [[T$k]]> Tail;
|
||||
};
|
||||
|
||||
|
||||
]]
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// We don't want to require the users to write TypesN<...> directly,
|
||||
// as that would require them to count the length. Types<...> is much
|
||||
// easier to write, but generates horrible messages when there is a
|
||||
// compiler error, as gcc insists on printing out each template
|
||||
// argument, even if it has the default value (this means Types<int>
|
||||
// will appear as Types<int, None, None, ..., None> in the compiler
|
||||
// errors).
|
||||
//
|
||||
// Our solution is to combine the best part of the two approaches: a
|
||||
// user would write Types<T1, ..., TN>, and Google Test will translate
|
||||
// that to TypesN<T1, ..., TN> internally to make error messages
|
||||
// readable. The translation is done by the 'type' member of the
|
||||
// Types template.
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[typename T$i = internal::None]]>
|
||||
struct Types {
|
||||
typedef internal::Types$n<$for i, [[T$i]]> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Types<$for i, [[internal::None]]> {
|
||||
typedef internal::Types0 type;
|
||||
};
|
||||
|
||||
$range i 1..n-1
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k i+1..n
|
||||
template <$for j, [[typename T$j]]>
|
||||
struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
|
||||
typedef internal::Types$i<$for j, [[T$j]]> type;
|
||||
};
|
||||
|
||||
]]
|
||||
|
||||
namespace internal {
|
||||
|
||||
# define GTEST_TEMPLATE_ template <typename T> class
|
||||
|
||||
// The template "selector" struct TemplateSel<Tmpl> is used to
|
||||
// represent Tmpl, which must be a class template with one type
|
||||
// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
|
||||
// as the type Tmpl<T>. This allows us to actually instantiate the
|
||||
// template "selected" by TemplateSel<Tmpl>.
|
||||
//
|
||||
// This trick is necessary for simulating typedef for class templates,
|
||||
// which C++ doesn't support directly.
|
||||
template <GTEST_TEMPLATE_ Tmpl>
|
||||
struct TemplateSel {
|
||||
template <typename T>
|
||||
struct Bind {
|
||||
typedef Tmpl<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
# define GTEST_BIND_(TmplSel, T) \
|
||||
TmplSel::template Bind<T>::type
|
||||
|
||||
// A unique struct template used as the default value for the
|
||||
// arguments of class template Templates. This allows us to simulate
|
||||
// variadic templates (e.g. Templates<int>, Templates<int, double>,
|
||||
// and etc), which C++ doesn't support directly.
|
||||
template <typename T>
|
||||
struct NoneT {};
|
||||
|
||||
// The following family of struct and struct templates are used to
|
||||
// represent template lists. In particular, TemplatesN<T1, T2, ...,
|
||||
// TN> represents a list of N templates (T1, T2, ..., and TN). Except
|
||||
// for Templates0, every struct in the family has two member types:
|
||||
// Head for the selector of the first template in the list, and Tail
|
||||
// for the rest of the list.
|
||||
|
||||
// The empty template list.
|
||||
struct Templates0 {};
|
||||
|
||||
// Template lists of length 1, 2, 3, and so on.
|
||||
|
||||
template <GTEST_TEMPLATE_ T1>
|
||||
struct Templates1 {
|
||||
typedef TemplateSel<T1> Head;
|
||||
typedef Templates0 Tail;
|
||||
};
|
||||
|
||||
$range i 2..n
|
||||
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k 2..i
|
||||
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
||||
struct Templates$i {
|
||||
typedef TemplateSel<T1> Head;
|
||||
typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
|
||||
};
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// We don't want to require the users to write TemplatesN<...> directly,
|
||||
// as that would require them to count the length. Templates<...> is much
|
||||
// easier to write, but generates horrible messages when there is a
|
||||
// compiler error, as gcc insists on printing out each template
|
||||
// argument, even if it has the default value (this means Templates<list>
|
||||
// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
|
||||
// errors).
|
||||
//
|
||||
// Our solution is to combine the best part of the two approaches: a
|
||||
// user would write Templates<T1, ..., TN>, and Google Test will translate
|
||||
// that to TemplatesN<T1, ..., TN> internally to make error messages
|
||||
// readable. The translation is done by the 'type' member of the
|
||||
// Templates template.
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
|
||||
struct Templates {
|
||||
typedef Templates$n<$for i, [[T$i]]> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Templates<$for i, [[NoneT]]> {
|
||||
typedef Templates0 type;
|
||||
};
|
||||
|
||||
$range i 1..n-1
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k i+1..n
|
||||
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
||||
struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
|
||||
typedef Templates$i<$for j, [[T$j]]> type;
|
||||
};
|
||||
|
||||
]]
|
||||
|
||||
// The TypeList template makes it possible to use either a single type
|
||||
// or a Types<...> list in TYPED_TEST_SUITE() and
|
||||
// INSTANTIATE_TYPED_TEST_SUITE_P().
|
||||
|
||||
template <typename T>
|
||||
struct TypeList {
|
||||
typedef Types1<T> type;
|
||||
};
|
||||
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[typename T$i]]>
|
||||
struct TypeList<Types<$for i, [[T$i]]> > {
|
||||
typedef typename Types<$for i, [[T$i]]>::type type;
|
||||
};
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
|
@ -27,12 +27,14 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
// This provides interface PrimeTable that determines whether a number is a
|
||||
// prime and determines a next prime number. This interface is used
|
||||
// in Google Test samples demonstrating use of parameterized tests.
|
||||
|
||||
#ifndef GTEST_SAMPLES_PRIME_TABLES_H_
|
||||
#define GTEST_SAMPLES_PRIME_TABLES_H_
|
||||
#ifndef GOOGLETEST_SAMPLES_PRIME_TABLES_H_
|
||||
#define GOOGLETEST_SAMPLES_PRIME_TABLES_H_
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -55,7 +57,7 @@ class OnTheFlyPrimeTable : public PrimeTable {
|
|||
bool IsPrime(int n) const override {
|
||||
if (n <= 1) return false;
|
||||
|
||||
for (int i = 2; i * i <= n; i++) {
|
||||
for (int i = 2; i*i <= n; i++) {
|
||||
// n is divisible by an integer other than 1 and itself.
|
||||
if ((n % i) == 0) return false;
|
||||
}
|
||||
|
@ -64,11 +66,11 @@ class OnTheFlyPrimeTable : public PrimeTable {
|
|||
}
|
||||
|
||||
int GetNextPrime(int p) const override {
|
||||
for (int n = p + 1; n > 0; n++) {
|
||||
if (p < 0) return -1;
|
||||
|
||||
for (int n = p + 1;; n++) {
|
||||
if (IsPrime(n)) return n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -102,13 +104,13 @@ class PreCalculatedPrimeTable : public PrimeTable {
|
|||
|
||||
// Checks every candidate for prime number (we know that 2 is the only even
|
||||
// prime).
|
||||
for (int i = 2; i * i <= max; i += i % 2 + 1) {
|
||||
for (int i = 2; i*i <= max; i += i%2+1) {
|
||||
if (!is_prime_[i]) continue;
|
||||
|
||||
// Marks all multiples of i (except i itself) as non-prime.
|
||||
// We are starting here from i-th multiplier, because all smaller
|
||||
// complex numbers were already marked.
|
||||
for (int j = i * i; j <= max; j += i) {
|
||||
for (int j = i*i; j <= max; j += i) {
|
||||
is_prime_[j] = false;
|
||||
}
|
||||
}
|
||||
|
@ -121,4 +123,4 @@ class PreCalculatedPrimeTable : public PrimeTable {
|
|||
void operator=(const PreCalculatedPrimeTable& rhs);
|
||||
};
|
||||
|
||||
#endif // GTEST_SAMPLES_PRIME_TABLES_H_
|
||||
#endif // GOOGLETEST_SAMPLES_PRIME_TABLES_H_
|
||||
|
|
|
@ -52,9 +52,9 @@ bool IsPrime(int n) {
|
|||
// Now, we have that n is odd and n >= 3.
|
||||
|
||||
// Try to divide n by every odd number i, starting from 3
|
||||
for (int i = 3;; i += 2) {
|
||||
for (int i = 3; ; i += 2) {
|
||||
// We only have to try i up to the square root of n
|
||||
if (i > n / i) break;
|
||||
if (i > n/i) break;
|
||||
|
||||
// Now, we have i <= n/i < n.
|
||||
// If n is divisible by i, n is not prime.
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
// A sample program demonstrating using Google C++ testing framework.
|
||||
|
||||
#ifndef GTEST_SAMPLES_SAMPLE1_H_
|
||||
#define GTEST_SAMPLES_SAMPLE1_H_
|
||||
#ifndef GOOGLETEST_SAMPLES_SAMPLE1_H_
|
||||
#define GOOGLETEST_SAMPLES_SAMPLE1_H_
|
||||
|
||||
// Returns n! (the factorial of n). For negative n, n! is defined to be 1.
|
||||
int Factorial(int n);
|
||||
|
@ -38,4 +38,4 @@ int Factorial(int n);
|
|||
// Returns true if and only if n is a prime number.
|
||||
bool IsPrime(int n);
|
||||
|
||||
#endif // GTEST_SAMPLES_SAMPLE1_H_
|
||||
#endif // GOOGLETEST_SAMPLES_SAMPLE1_H_
|
||||
|
|
|
@ -26,6 +26,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.
|
||||
|
||||
|
||||
// This sample shows how to use Google Test listener API to implement
|
||||
// a primitive leak checker.
|
||||
|
||||
|
@ -103,15 +104,14 @@ TEST(ListenersTest, LeaksWater) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char **argv) {
|
||||
InitGoogleTest(&argc, argv);
|
||||
|
||||
bool check_for_leaks = false;
|
||||
if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0)
|
||||
if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0 )
|
||||
check_for_leaks = true;
|
||||
else
|
||||
printf("%s\n",
|
||||
"Run this program with --check_for_leaks to enable "
|
||||
printf("%s\n", "Run this program with --check_for_leaks to enable "
|
||||
"custom leak checking in the tests.");
|
||||
|
||||
// If we are given the --check_for_leaks command line flag, installs the
|
||||
|
|
|
@ -38,7 +38,7 @@ const char* MyString::CloneCString(const char* a_c_string) {
|
|||
if (a_c_string == nullptr) return nullptr;
|
||||
|
||||
const size_t len = strlen(a_c_string);
|
||||
char* const clone = new char[len + 1];
|
||||
char* const clone = new char[ len + 1 ];
|
||||
memcpy(clone, a_c_string, len + 1);
|
||||
|
||||
return clone;
|
||||
|
|
|
@ -29,11 +29,12 @@
|
|||
|
||||
// A sample program demonstrating using Google C++ testing framework.
|
||||
|
||||
#ifndef GTEST_SAMPLES_SAMPLE2_H_
|
||||
#define GTEST_SAMPLES_SAMPLE2_H_
|
||||
#ifndef GOOGLETEST_SAMPLES_SAMPLE2_H_
|
||||
#define GOOGLETEST_SAMPLES_SAMPLE2_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// A simple string class.
|
||||
class MyString {
|
||||
private:
|
||||
|
@ -76,4 +77,4 @@ class MyString {
|
|||
void Set(const char* c_string);
|
||||
};
|
||||
|
||||
#endif // GTEST_SAMPLES_SAMPLE2_H_
|
||||
#endif // GOOGLETEST_SAMPLES_SAMPLE2_H_
|
||||
|
|
|
@ -77,7 +77,8 @@ const char kHelloString[] = "Hello, world!";
|
|||
TEST(MyString, ConstructorFromCString) {
|
||||
const MyString s(kHelloString);
|
||||
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
|
||||
EXPECT_EQ(sizeof(kHelloString) / sizeof(kHelloString[0]) - 1, s.Length());
|
||||
EXPECT_EQ(sizeof(kHelloString)/sizeof(kHelloString[0]) - 1,
|
||||
s.Length());
|
||||
}
|
||||
|
||||
// Tests the copy c'tor.
|
||||
|
|
|
@ -29,11 +29,12 @@
|
|||
|
||||
// A sample program demonstrating using Google C++ testing framework.
|
||||
|
||||
#ifndef GTEST_SAMPLES_SAMPLE3_INL_H_
|
||||
#define GTEST_SAMPLES_SAMPLE3_INL_H_
|
||||
#ifndef GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
|
||||
#define GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
// Queue is a simple queue implemented as a singled-linked list.
|
||||
//
|
||||
// The element type must support copy constructor.
|
||||
|
@ -61,7 +62,7 @@ class QueueNode {
|
|||
: element_(an_element), next_(nullptr) {}
|
||||
|
||||
// We disable the default assignment operator and copy c'tor.
|
||||
const QueueNode& operator=(const QueueNode&);
|
||||
const QueueNode& operator = (const QueueNode&);
|
||||
QueueNode(const QueueNode&);
|
||||
|
||||
E element_;
|
||||
|
@ -83,7 +84,7 @@ class Queue {
|
|||
// 1. Deletes every node.
|
||||
QueueNode<E>* node = head_;
|
||||
QueueNode<E>* next = node->next();
|
||||
for (;;) {
|
||||
for (; ;) {
|
||||
delete node;
|
||||
node = next;
|
||||
if (node == nullptr) break;
|
||||
|
@ -161,11 +162,11 @@ class Queue {
|
|||
private:
|
||||
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.
|
||||
size_t size_; // The number of elements in the queue.
|
||||
|
||||
// We disallow copying a queue.
|
||||
Queue(const Queue&);
|
||||
const Queue& operator=(const Queue&);
|
||||
const Queue& operator = (const Queue&);
|
||||
};
|
||||
|
||||
#endif // GTEST_SAMPLES_SAMPLE3_INL_H_
|
||||
#endif // GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
|
||||
|
|
|
@ -85,19 +85,21 @@ class QueueTestSmpl3 : public testing::Test {
|
|||
// }
|
||||
|
||||
// A helper function that some test uses.
|
||||
static int Double(int n) { return 2 * n; }
|
||||
static int Double(int n) {
|
||||
return 2*n;
|
||||
}
|
||||
|
||||
// A helper function for testing Queue::Map().
|
||||
void MapTester(const Queue<int>* q) {
|
||||
void MapTester(const Queue<int> * q) {
|
||||
// Creates a new queue, where each element is twice as big as the
|
||||
// corresponding one in q.
|
||||
const Queue<int>* const new_q = q->Map(Double);
|
||||
const Queue<int> * const new_q = q->Map(Double);
|
||||
|
||||
// Verifies that the new queue has the same size as q.
|
||||
ASSERT_EQ(q->Size(), new_q->Size());
|
||||
|
||||
// Verifies the relationship between the elements of the two queues.
|
||||
for (const QueueNode<int> *n1 = q->Head(), *n2 = new_q->Head();
|
||||
for (const QueueNode<int>*n1 = q->Head(), *n2 = new_q->Head();
|
||||
n1 != nullptr; n1 = n1->next(), n2 = n2->next()) {
|
||||
EXPECT_EQ(2 * n1->element(), n2->element());
|
||||
}
|
||||
|
@ -122,7 +124,7 @@ TEST_F(QueueTestSmpl3, DefaultConstructor) {
|
|||
|
||||
// Tests Dequeue().
|
||||
TEST_F(QueueTestSmpl3, Dequeue) {
|
||||
int* n = q0_.Dequeue();
|
||||
int * n = q0_.Dequeue();
|
||||
EXPECT_TRUE(n == nullptr);
|
||||
|
||||
n = q1_.Dequeue();
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A sample program demonstrating using Google C++ testing framework.
|
||||
#ifndef GTEST_SAMPLES_SAMPLE4_H_
|
||||
#define GTEST_SAMPLES_SAMPLE4_H_
|
||||
#ifndef GOOGLETEST_SAMPLES_SAMPLE4_H_
|
||||
#define GOOGLETEST_SAMPLES_SAMPLE4_H_
|
||||
|
||||
// A simple monotonic counter.
|
||||
class Counter {
|
||||
|
@ -50,4 +50,4 @@ class Counter {
|
|||
void Print() const;
|
||||
};
|
||||
|
||||
#endif // GTEST_SAMPLES_SAMPLE4_H_
|
||||
#endif // GOOGLETEST_SAMPLES_SAMPLE4_H_
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
// This sample teaches how to reuse a test fixture in multiple test
|
||||
// cases by deriving sub-fixtures from it.
|
||||
//
|
||||
|
@ -80,6 +81,7 @@ class QuickTest : public testing::Test {
|
|||
time_t start_time_;
|
||||
};
|
||||
|
||||
|
||||
// We derive a fixture named IntegerFunctionTest from the QuickTest
|
||||
// fixture. All tests using this fixture will be automatically
|
||||
// required to be quick.
|
||||
|
@ -88,6 +90,7 @@ class IntegerFunctionTest : public QuickTest {
|
|||
// Therefore the body is empty.
|
||||
};
|
||||
|
||||
|
||||
// Now we can write tests in the IntegerFunctionTest test case.
|
||||
|
||||
// Tests Factorial()
|
||||
|
@ -107,6 +110,7 @@ TEST_F(IntegerFunctionTest, Factorial) {
|
|||
EXPECT_EQ(40320, Factorial(8));
|
||||
}
|
||||
|
||||
|
||||
// Tests IsPrime()
|
||||
TEST_F(IntegerFunctionTest, IsPrime) {
|
||||
// Tests negative input.
|
||||
|
@ -127,6 +131,7 @@ TEST_F(IntegerFunctionTest, IsPrime) {
|
|||
EXPECT_TRUE(IsPrime(23));
|
||||
}
|
||||
|
||||
|
||||
// The next test case (named "QueueTest") also needs to be quick, so
|
||||
// we derive another fixture from QuickTest.
|
||||
//
|
||||
|
@ -158,10 +163,13 @@ class QueueTest : public QuickTest {
|
|||
Queue<int> q2_;
|
||||
};
|
||||
|
||||
|
||||
// Now, let's write tests using the QueueTest fixture.
|
||||
|
||||
// Tests the default constructor.
|
||||
TEST_F(QueueTest, DefaultConstructor) { EXPECT_EQ(0u, q0_.Size()); }
|
||||
TEST_F(QueueTest, DefaultConstructor) {
|
||||
EXPECT_EQ(0u, q0_.Size());
|
||||
}
|
||||
|
||||
// Tests Dequeue().
|
||||
TEST_F(QueueTest, Dequeue) {
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
// This sample shows how to test common properties of multiple
|
||||
// implementations of the same interface (aka interface tests).
|
||||
|
||||
|
@ -72,8 +73,6 @@ class PrimeTableTest : public testing::Test {
|
|||
PrimeTable* const table_;
|
||||
};
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST
|
||||
|
||||
using testing::Types;
|
||||
|
||||
// Google Test offers two ways for reusing tests for different types.
|
||||
|
@ -133,10 +132,6 @@ TYPED_TEST(PrimeTableTest, CanGetNextPrime) {
|
|||
// in the type list specified in TYPED_TEST_SUITE. Sit back and be
|
||||
// happy that you don't have to define them multiple times.
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
using testing::Types;
|
||||
|
||||
// Sometimes, however, you don't yet know all the types that you want
|
||||
|
@ -156,7 +151,8 @@ using testing::Types;
|
|||
// the PrimeTableTest fixture defined earlier:
|
||||
|
||||
template <class T>
|
||||
class PrimeTableTest2 : public PrimeTableTest<T> {};
|
||||
class PrimeTableTest2 : public PrimeTableTest<T> {
|
||||
};
|
||||
|
||||
// Then, declare the test case. The argument is the name of the test
|
||||
// fixture, and also the name of the test case (as usual). The _P
|
||||
|
@ -218,5 +214,4 @@ INSTANTIATE_TYPED_TEST_SUITE_P(OnTheFlyAndPreCalculated, // Instance name
|
|||
PrimeTableTest2, // Test case name
|
||||
PrimeTableImplementations); // Type list
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST_P
|
||||
} // namespace
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
// This sample shows how to test common properties of multiple
|
||||
// implementations of an interface (aka interface tests) using
|
||||
// value-parameterized tests. Each test in the test case has
|
||||
|
@ -49,7 +50,9 @@ using ::testing::Values;
|
|||
// SetUp() method and delete them in TearDown() method.
|
||||
typedef PrimeTable* CreatePrimeTableFunc();
|
||||
|
||||
PrimeTable* CreateOnTheFlyPrimeTable() { return new OnTheFlyPrimeTable(); }
|
||||
PrimeTable* CreateOnTheFlyPrimeTable() {
|
||||
return new OnTheFlyPrimeTable();
|
||||
}
|
||||
|
||||
template <size_t max_precalculated>
|
||||
PrimeTable* CreatePreCalculatedPrimeTable() {
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
// This sample shows how to test code relying on some global flag variables.
|
||||
// Combine() helps with generating all possible combinations of such flags,
|
||||
// and each test is given one combination as a parameter.
|
||||
|
@ -48,8 +49,9 @@ class HybridPrimeTable : public PrimeTable {
|
|||
public:
|
||||
HybridPrimeTable(bool force_on_the_fly, int max_precalculated)
|
||||
: on_the_fly_impl_(new OnTheFlyPrimeTable),
|
||||
precalc_impl_(force_on_the_fly ? nullptr : new PreCalculatedPrimeTable(
|
||||
max_precalculated)),
|
||||
precalc_impl_(force_on_the_fly
|
||||
? nullptr
|
||||
: new PreCalculatedPrimeTable(max_precalculated)),
|
||||
max_precalculated_(max_precalculated) {}
|
||||
~HybridPrimeTable() override {
|
||||
delete on_the_fly_impl_;
|
||||
|
|
|
@ -26,6 +26,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.
|
||||
|
||||
|
||||
// This sample shows how to use Google Test listener API to implement
|
||||
// an alternative console output and how to use the UnitTest reflection API
|
||||
// to enumerate test cases and tests and to inspect their results.
|
||||
|
@ -58,23 +59,29 @@ class TersePrinter : public EmptyTestEventListener {
|
|||
|
||||
// Called before a test starts.
|
||||
void OnTestStart(const TestInfo& test_info) override {
|
||||
fprintf(stdout, "*** Test %s.%s starting.\n", test_info.test_case_name(),
|
||||
fprintf(stdout,
|
||||
"*** Test %s.%s starting.\n",
|
||||
test_info.test_case_name(),
|
||||
test_info.name());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// Called after a failed assertion or a SUCCEED() invocation.
|
||||
void OnTestPartResult(const TestPartResult& test_part_result) override {
|
||||
fprintf(stdout, "%s in %s:%d\n%s\n",
|
||||
fprintf(stdout,
|
||||
"%s in %s:%d\n%s\n",
|
||||
test_part_result.failed() ? "*** Failure" : "Success",
|
||||
test_part_result.file_name(), test_part_result.line_number(),
|
||||
test_part_result.file_name(),
|
||||
test_part_result.line_number(),
|
||||
test_part_result.summary());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// Called after a test ends.
|
||||
void OnTestEnd(const TestInfo& test_info) override {
|
||||
fprintf(stdout, "*** Test %s.%s ending.\n", test_info.test_case_name(),
|
||||
fprintf(stdout,
|
||||
"*** Test %s.%s ending.\n",
|
||||
test_info.test_case_name(),
|
||||
test_info.name());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
@ -94,15 +101,14 @@ TEST(CustomOutputTest, Fails) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char **argv) {
|
||||
InitGoogleTest(&argc, argv);
|
||||
|
||||
bool terse_output = false;
|
||||
if (argc > 1 && strcmp(argv[1], "--terse_output") == 0)
|
||||
if (argc > 1 && strcmp(argv[1], "--terse_output") == 0 )
|
||||
terse_output = true;
|
||||
else
|
||||
printf("%s\n",
|
||||
"Run this program with --terse_output to change the way "
|
||||
printf("%s\n", "Run this program with --terse_output to change the way "
|
||||
"it prints its output.");
|
||||
|
||||
UnitTest& unit_test = *UnitTest::GetInstance();
|
||||
|
@ -143,7 +149,8 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
// Test that were meant to fail should not affect the test program outcome.
|
||||
if (unexpectedly_failed_tests == 0) ret_val = 0;
|
||||
if (unexpectedly_failed_tests == 0)
|
||||
ret_val = 0;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# Please Note:
|
||||
|
||||
Files in this directory are no longer supported by the maintainers. They
|
||||
represent mosty historical artifacts and supported by the community only. There
|
||||
is no guarantee whatsoever that these scripts still work.
|
|
@ -78,7 +78,7 @@ def HeaderPreamble(n):
|
|||
}
|
||||
|
||||
return (
|
||||
"""// Copyright 2006, Google Inc.
|
||||
"""// Copyright 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -111,6 +111,8 @@ def HeaderPreamble(n):
|
|||
// '%(command)s'. DO NOT EDIT BY HAND!
|
||||
//
|
||||
// Implements a family of generic predicate assertion macros.
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
|
@ -246,8 +248,10 @@ AssertionResult AssertPred%(n)sHelper(const char* pred_text""" % DEFS
|
|||
|
||||
impl += ' << ") evaluates to false, where"'
|
||||
|
||||
impl += Iter(n, """
|
||||
<< "\\n" << e%s << " evaluates to " << v%s""")
|
||||
impl += Iter(
|
||||
n, """
|
||||
<< "\\n" << e%s << " evaluates to " << ::testing::PrintToString(v%s)"""
|
||||
)
|
||||
|
||||
impl += """;
|
||||
}
|
||||
|
@ -333,7 +337,7 @@ def UnitTestPreamble():
|
|||
}
|
||||
|
||||
return (
|
||||
"""// Copyright 2006, Google Inc.
|
||||
"""// Copyright 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -427,7 +431,7 @@ def TestsForArity(n):
|
|||
}
|
||||
|
||||
tests = (
|
||||
"""// Sample functions/functors for testing %(arity)s predicate assertions.
|
||||
"""// Sample functions/functors for testing %(arity)s predicate assertions.
|
||||
|
||||
// A %(arity)s predicate function.
|
||||
template <%(types)s>
|
||||
|
@ -435,9 +439,8 @@ bool PredFunction%(n)s(%(tvs)s) {
|
|||
return %(v_sum)s > 0;
|
||||
}
|
||||
|
||||
// The following two functions are needed to circumvent a bug in
|
||||
// gcc 2.95.3, which sometimes has problem with the above template
|
||||
// function.
|
||||
// The following two functions are needed because a compiler doesn't have
|
||||
// a context yet to know which template function must be instantiated.
|
||||
bool PredFunction%(n)sInt(%(int_vs)s) {
|
||||
return %(v_sum)s > 0;
|
||||
}
|
||||
|
@ -510,7 +513,7 @@ struct PredFormatFunctor%(n)s {
|
|||
|
||||
class Predicate%(n)sTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
void SetUp() override {
|
||||
expected_to_finish_ = true;
|
||||
finished_ = false;""" % DEFS
|
||||
|
||||
|
@ -520,7 +523,7 @@ class Predicate%(n)sTest : public testing::Test {
|
|||
"""
|
||||
|
||||
tests += """
|
||||
virtual void TearDown() {
|
||||
void TearDown() override {
|
||||
// Verifies that each of the predicate's arguments was evaluated
|
||||
// exactly once."""
|
||||
|
||||
|
@ -540,10 +543,10 @@ class Predicate%(n)sTest : public testing::Test {
|
|||
}
|
||||
}
|
||||
|
||||
// true iff the test function is expected to run to finish.
|
||||
// true if and only if the test function is expected to run to finish.
|
||||
static bool expected_to_finish_;
|
||||
|
||||
// true iff the test function did run to finish.
|
||||
// true if and only if the test function did run to finish.
|
||||
static bool finished_;
|
||||
""" % DEFS
|
||||
|
||||
|
@ -572,12 +575,12 @@ typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest;
|
|||
"""Returns the test for a predicate assertion macro.
|
||||
|
||||
Args:
|
||||
use_format: true iff the assertion is a *_PRED_FORMAT*.
|
||||
use_assert: true iff the assertion is a ASSERT_*.
|
||||
expect_failure: true iff the assertion is expected to fail.
|
||||
use_functor: true iff the first argument of the assertion is
|
||||
use_format: true if and only if the assertion is a *_PRED_FORMAT*.
|
||||
use_assert: true if and only if the assertion is a ASSERT_*.
|
||||
expect_failure: true if and only if the assertion is expected to fail.
|
||||
use_functor: true if and only if the first argument of the assertion is
|
||||
a functor (as opposed to a function)
|
||||
use_user_type: true iff the predicate functor/function takes
|
||||
use_user_type: true if and only if the predicate functor/function takes
|
||||
argument(s) of a user-defined type.
|
||||
|
||||
Example:
|
||||
|
@ -588,7 +591,7 @@ typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest;
|
|||
|
||||
if use_assert:
|
||||
assrt = 'ASSERT' # 'assert' is reserved, so we cannot use
|
||||
# that identifier here.
|
||||
# that identifier here.
|
||||
else:
|
||||
assrt = 'EXPECT'
|
||||
|
||||
|
|
|
@ -1,855 +0,0 @@
|
|||
#!/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.2.0 - 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'\[\[\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 StripMetaComments(str):
|
||||
"""Strip meta comments from each line in the given string."""
|
||||
|
||||
# First, completely remove lines containing nothing but a meta
|
||||
# comment, including the trailing \n.
|
||||
str = re.sub(r'^\s*\$\$.*\n', '', str)
|
||||
|
||||
# Then, remove meta comments from contentful lines.
|
||||
return re.sub(r'\s*\$\$.*', '', str)
|
||||
|
||||
|
||||
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 == '$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):
|
||||
"""A generator that yields the tokens in the given string."""
|
||||
if s != '':
|
||||
lines = s.splitlines(True)
|
||||
for token in TokenizeLines(lines, Cursor(0, 0)):
|
||||
yield token
|
||||
|
||||
|
||||
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 ParseToAST(pump_src_text):
|
||||
"""Convert the given Pump source text into an AST."""
|
||||
tokens = list(Tokenize(pump_src_text))
|
||||
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 IsSingleLineComment(cur_line):
|
||||
return '//' in cur_line
|
||||
|
||||
|
||||
def IsInPreprocessorDirective(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 WrapPreprocessorDirective(line, output):
|
||||
WrapCode(line, ' \\', output)
|
||||
|
||||
|
||||
def WrapPlainCode(line, output):
|
||||
WrapCode(line, '', output)
|
||||
|
||||
|
||||
def IsMultiLineIWYUPragma(line):
|
||||
return re.search(r'/\* IWYU pragma: ', line)
|
||||
|
||||
|
||||
def IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
||||
return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or
|
||||
re.match(r'^#include\s', line) or
|
||||
# Don't break IWYU pragmas, either; that causes iwyu.py problems.
|
||||
re.search(r'// IWYU pragma: ', line))
|
||||
|
||||
|
||||
def WrapLongLine(line, output):
|
||||
line = line.rstrip()
|
||||
if len(line) <= 80:
|
||||
output.append(line)
|
||||
elif IsSingleLineComment(line):
|
||||
if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
||||
# The style guide made an exception to allow long header guard lines,
|
||||
# includes and IWYU pragmas.
|
||||
output.append(line)
|
||||
else:
|
||||
WrapComment(line, output)
|
||||
elif IsInPreprocessorDirective(output, line):
|
||||
if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
||||
# The style guide made an exception to allow long header guard lines,
|
||||
# includes and IWYU pragmas.
|
||||
output.append(line)
|
||||
else:
|
||||
WrapPreprocessorDirective(line, output)
|
||||
elif IsMultiLineIWYUPragma(line):
|
||||
output.append(line)
|
||||
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 ConvertFromPumpSource(src_text):
|
||||
"""Return the text generated from the given Pump source text."""
|
||||
ast = ParseToAST(StripMetaComments(src_text))
|
||||
output = Output()
|
||||
RunCode(Env(), ast, output)
|
||||
return BeautifyCode(output.string)
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) == 1:
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
|
||||
file_path = argv[-1]
|
||||
output_str = ConvertFromPumpSource(file(file_path, 'r').read())
|
||||
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)
|
|
@ -37,7 +37,7 @@ SYNOPSIS
|
|||
interlinked wiki files. When we release a new version of
|
||||
Google Test or Google Mock, we need to branch the wiki files
|
||||
such that users of a specific version of Google Test/Mock can
|
||||
look up documenation relevant for that version. This script
|
||||
look up documentation relevant for that version. This script
|
||||
automates that process by:
|
||||
|
||||
- branching the current wiki pages (which document the
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2010 Google Inc. All Rights Reserved.
|
||||
|
||||
"""Runs program specified in the command line with the substituted PATH.
|
||||
|
||||
This script is needed for to support building under Pulse which is unable
|
||||
to override the existing PATH variable.
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
SUBST_PATH_ENV_VAR_NAME = "SUBST_PATH"
|
||||
|
||||
def main():
|
||||
if SUBST_PATH_ENV_VAR_NAME in os.environ:
|
||||
os.environ["PATH"] = os.environ[SUBST_PATH_ENV_VAR_NAME]
|
||||
|
||||
exit_code = subprocess.Popen(sys.argv[1:]).wait()
|
||||
|
||||
# exit_code is negative (-signal) if the process has been terminated by
|
||||
# a signal. Returning negative exit code is not portable and so we return
|
||||
# 100 instead.
|
||||
if exit_code < 0:
|
||||
exit_code = 100
|
||||
|
||||
sys.exit(exit_code)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,18 +1,33 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2007 Google Inc.
|
||||
# Copyright 2007, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""Tool for uploading diffs from a version control system to the codereview app.
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "gtest/gtest-death-test.h"
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
@ -39,44 +40,44 @@
|
|||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
#if GTEST_OS_MAC
|
||||
#include <crt_externs.h>
|
||||
#endif // GTEST_OS_MAC
|
||||
# if GTEST_OS_MAC
|
||||
# include <crt_externs.h>
|
||||
# endif // GTEST_OS_MAC
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <limits.h>
|
||||
|
||||
#if GTEST_OS_LINUX
|
||||
#include <signal.h>
|
||||
#endif // GTEST_OS_LINUX
|
||||
# if GTEST_OS_LINUX
|
||||
# include <signal.h>
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
#include <stdarg.h>
|
||||
# include <stdarg.h>
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
# include <windows.h>
|
||||
# else
|
||||
# include <sys/mman.h>
|
||||
# include <sys/wait.h>
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
#if GTEST_OS_QNX
|
||||
#include <spawn.h>
|
||||
#endif // GTEST_OS_QNX
|
||||
# if GTEST_OS_QNX
|
||||
# include <spawn.h>
|
||||
# endif // GTEST_OS_QNX
|
||||
|
||||
#if GTEST_OS_FUCHSIA
|
||||
#include <lib/fdio/fd.h>
|
||||
#include <lib/fdio/io.h>
|
||||
#include <lib/fdio/spawn.h>
|
||||
#include <lib/zx/channel.h>
|
||||
#include <lib/zx/port.h>
|
||||
#include <lib/zx/process.h>
|
||||
#include <lib/zx/socket.h>
|
||||
#include <zircon/processargs.h>
|
||||
#include <zircon/syscalls.h>
|
||||
#include <zircon/syscalls/policy.h>
|
||||
#include <zircon/syscalls/port.h>
|
||||
#endif // GTEST_OS_FUCHSIA
|
||||
# if GTEST_OS_FUCHSIA
|
||||
# include <lib/fdio/fd.h>
|
||||
# include <lib/fdio/io.h>
|
||||
# include <lib/fdio/spawn.h>
|
||||
# include <lib/zx/channel.h>
|
||||
# include <lib/zx/port.h>
|
||||
# include <lib/zx/process.h>
|
||||
# include <lib/zx/socket.h>
|
||||
# include <zircon/processargs.h>
|
||||
# include <zircon/syscalls.h>
|
||||
# include <zircon/syscalls/policy.h>
|
||||
# include <zircon/syscalls/port.h>
|
||||
# endif // GTEST_OS_FUCHSIA
|
||||
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
|
@ -133,9 +134,9 @@ namespace internal {
|
|||
|
||||
// Valid only for fast death tests. Indicates the code is running in the
|
||||
// child process of a fast style death test.
|
||||
#if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
static bool g_in_fast_death_test_child = false;
|
||||
#endif
|
||||
# endif
|
||||
|
||||
// Returns a Boolean value indicating whether the caller is currently
|
||||
// executing in the context of the death test child process. Tools such as
|
||||
|
@ -143,13 +144,13 @@ static bool g_in_fast_death_test_child = false;
|
|||
// tests. IMPORTANT: This is an internal utility. Using it may break the
|
||||
// implementation of death tests. User code MUST NOT use it.
|
||||
bool InDeathTestChild() {
|
||||
#if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
// On Windows and Fuchsia, death tests are thread-safe regardless of the value
|
||||
// of the death_test_style flag.
|
||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe")
|
||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
||||
|
@ -161,38 +162,40 @@ bool InDeathTestChild() {
|
|||
} // namespace internal
|
||||
|
||||
// ExitedWithCode constructor.
|
||||
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {}
|
||||
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
|
||||
}
|
||||
|
||||
// ExitedWithCode function-call operator.
|
||||
bool ExitedWithCode::operator()(int exit_status) const {
|
||||
#if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
return exit_status == exit_code_;
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
|
||||
|
||||
#endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
}
|
||||
|
||||
#if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
// KilledBySignal constructor.
|
||||
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {}
|
||||
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
|
||||
}
|
||||
|
||||
// KilledBySignal function-call operator.
|
||||
bool KilledBySignal::operator()(int exit_status) const {
|
||||
#if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
||||
# if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
||||
{
|
||||
bool result;
|
||||
if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
||||
# endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
||||
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
|
||||
}
|
||||
#endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
@ -203,23 +206,23 @@ namespace internal {
|
|||
static std::string ExitSummary(int exit_code) {
|
||||
Message m;
|
||||
|
||||
#if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
m << "Exited with exit status " << exit_code;
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
if (WIFEXITED(exit_code)) {
|
||||
m << "Exited with exit status " << WEXITSTATUS(exit_code);
|
||||
} else if (WIFSIGNALED(exit_code)) {
|
||||
m << "Terminated by signal " << WTERMSIG(exit_code);
|
||||
}
|
||||
#ifdef WCOREDUMP
|
||||
# ifdef WCOREDUMP
|
||||
if (WCOREDUMP(exit_code)) {
|
||||
m << " (core dumped)";
|
||||
}
|
||||
#endif
|
||||
#endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
# endif
|
||||
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
return m.GetString();
|
||||
}
|
||||
|
@ -230,7 +233,7 @@ bool ExitedUnsuccessfully(int exit_status) {
|
|||
return !ExitedWithCode(0)(exit_status);
|
||||
}
|
||||
|
||||
#if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
// Generates a textual failure message when a death test finds more than
|
||||
// one thread running, or cannot determine the number of threads, prior
|
||||
// to executing the given statement. It is the responsibility of the
|
||||
|
@ -245,13 +248,13 @@ static std::string DeathTestThreadWarning(size_t thread_count) {
|
|||
msg << "detected " << thread_count << " threads.";
|
||||
}
|
||||
msg << " See "
|
||||
"https://github.com/google/googletest/blob/master/googletest/docs/"
|
||||
"https://github.com/google/googletest/blob/master/docs/"
|
||||
"advanced.md#death-tests-and-threads"
|
||||
<< " for more explanation and suggested solutions, especially if"
|
||||
<< " this is the last message you see before your test times out.";
|
||||
return msg.GetString();
|
||||
}
|
||||
#endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
|
||||
// Flag characters for reporting a death test that did not die.
|
||||
static const char kDeathTestLived = 'L';
|
||||
|
@ -301,14 +304,14 @@ static void DeathTestAbort(const std::string& message) {
|
|||
|
||||
// A replacement for CHECK that calls DeathTestAbort if the assertion
|
||||
// fails.
|
||||
#define GTEST_DEATH_TEST_CHECK_(expression) \
|
||||
do { \
|
||||
if (!::testing::internal::IsTrue(expression)) { \
|
||||
DeathTestAbort(::std::string("CHECK failed: File ") + __FILE__ + \
|
||||
", line " + \
|
||||
::testing::internal::StreamableToString(__LINE__) + \
|
||||
": " + #expression); \
|
||||
} \
|
||||
# define GTEST_DEATH_TEST_CHECK_(expression) \
|
||||
do { \
|
||||
if (!::testing::internal::IsTrue(expression)) { \
|
||||
DeathTestAbort( \
|
||||
::std::string("CHECK failed: File ") + __FILE__ + ", line " \
|
||||
+ ::testing::internal::StreamableToString(__LINE__) + ": " \
|
||||
+ #expression); \
|
||||
} \
|
||||
} while (::testing::internal::AlwaysFalse())
|
||||
|
||||
// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
|
||||
|
@ -318,23 +321,23 @@ static void DeathTestAbort(const std::string& message) {
|
|||
// evaluates the expression as long as it evaluates to -1 and sets
|
||||
// errno to EINTR. If the expression evaluates to -1 but errno is
|
||||
// something other than EINTR, DeathTestAbort is called.
|
||||
#define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
|
||||
do { \
|
||||
int gtest_retval; \
|
||||
do { \
|
||||
gtest_retval = (expression); \
|
||||
} while (gtest_retval == -1 && errno == EINTR); \
|
||||
if (gtest_retval == -1) { \
|
||||
DeathTestAbort(::std::string("CHECK failed: File ") + __FILE__ + \
|
||||
", line " + \
|
||||
::testing::internal::StreamableToString(__LINE__) + \
|
||||
": " + #expression + " != -1"); \
|
||||
} \
|
||||
# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
|
||||
do { \
|
||||
int gtest_retval; \
|
||||
do { \
|
||||
gtest_retval = (expression); \
|
||||
} while (gtest_retval == -1 && errno == EINTR); \
|
||||
if (gtest_retval == -1) { \
|
||||
DeathTestAbort( \
|
||||
::std::string("CHECK failed: File ") + __FILE__ + ", line " \
|
||||
+ ::testing::internal::StreamableToString(__LINE__) + ": " \
|
||||
+ #expression + " != -1"); \
|
||||
} \
|
||||
} while (::testing::internal::AlwaysFalse())
|
||||
|
||||
// Returns the message describing the last system error in errno.
|
||||
std::string GetLastErrnoDescription() {
|
||||
return errno == 0 ? "" : posix::StrError(errno);
|
||||
return errno == 0 ? "" : posix::StrError(errno);
|
||||
}
|
||||
|
||||
// This is called from a death test parent process to read a failure
|
||||
|
@ -367,9 +370,8 @@ static void FailFromInternalError(int fd) {
|
|||
DeathTest::DeathTest() {
|
||||
TestInfo* const info = GetUnitTestImpl()->current_test_info();
|
||||
if (info == nullptr) {
|
||||
DeathTestAbort(
|
||||
"Cannot run a death test outside of a TEST or "
|
||||
"TEST_F construct");
|
||||
DeathTestAbort("Cannot run a death test outside of a TEST or "
|
||||
"TEST_F construct");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -498,7 +500,9 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
|
|||
set_read_fd(-1);
|
||||
}
|
||||
|
||||
std::string DeathTestImpl::GetErrorLogs() { return GetCapturedStderr(); }
|
||||
std::string DeathTestImpl::GetErrorLogs() {
|
||||
return GetCapturedStderr();
|
||||
}
|
||||
|
||||
// Signals that the death test code which should have exited, didn't.
|
||||
// Should be called only in a death test child process.
|
||||
|
@ -508,11 +512,9 @@ void DeathTestImpl::Abort(AbortReason reason) {
|
|||
// The parent process considers the death test to be a failure if
|
||||
// it finds any data in our pipe. So, here we write a single flag byte
|
||||
// to the pipe, then exit.
|
||||
const char status_ch = reason == TEST_DID_NOT_DIE
|
||||
? kDeathTestLived
|
||||
: reason == TEST_THREW_EXCEPTION
|
||||
? kDeathTestThrew
|
||||
: kDeathTestReturned;
|
||||
const char status_ch =
|
||||
reason == TEST_DID_NOT_DIE ? kDeathTestLived :
|
||||
reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
|
||||
// We are leaking the descriptor here because on some platforms (i.e.,
|
||||
|
@ -531,7 +533,7 @@ void DeathTestImpl::Abort(AbortReason reason) {
|
|||
// much easier.
|
||||
static ::std::string FormatDeathTestOutput(const ::std::string& output) {
|
||||
::std::string ret;
|
||||
for (size_t at = 0;;) {
|
||||
for (size_t at = 0; ; ) {
|
||||
const size_t line_end = output.find('\n', at);
|
||||
ret += "[ DEATH ] ";
|
||||
if (line_end == ::std::string::npos) {
|
||||
|
@ -566,7 +568,8 @@ static ::std::string FormatDeathTestOutput(const ::std::string& output) {
|
|||
// the first failing condition, in the order given above, is the one that is
|
||||
// reported. Also sets the last death test message string.
|
||||
bool DeathTestImpl::Passed(bool status_ok) {
|
||||
if (!spawned()) return false;
|
||||
if (!spawned())
|
||||
return false;
|
||||
|
||||
const std::string error_message = GetErrorLogs();
|
||||
|
||||
|
@ -577,18 +580,15 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
|||
switch (outcome()) {
|
||||
case LIVED:
|
||||
buffer << " Result: failed to die.\n"
|
||||
<< " Error msg:\n"
|
||||
<< FormatDeathTestOutput(error_message);
|
||||
<< " Error msg:\n" << FormatDeathTestOutput(error_message);
|
||||
break;
|
||||
case THREW:
|
||||
buffer << " Result: threw an exception.\n"
|
||||
<< " Error msg:\n"
|
||||
<< FormatDeathTestOutput(error_message);
|
||||
<< " Error msg:\n" << FormatDeathTestOutput(error_message);
|
||||
break;
|
||||
case RETURNED:
|
||||
buffer << " Result: illegal return in test statement.\n"
|
||||
<< " Error msg:\n"
|
||||
<< FormatDeathTestOutput(error_message);
|
||||
<< " Error msg:\n" << FormatDeathTestOutput(error_message);
|
||||
break;
|
||||
case DIED:
|
||||
if (status_ok) {
|
||||
|
@ -605,8 +605,7 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
|||
} else {
|
||||
buffer << " Result: died but not with expected exit code:\n"
|
||||
<< " " << ExitSummary(status()) << "\n"
|
||||
<< "Actual msg:\n"
|
||||
<< FormatDeathTestOutput(error_message);
|
||||
<< "Actual msg:\n" << FormatDeathTestOutput(error_message);
|
||||
}
|
||||
break;
|
||||
case IN_PROGRESS:
|
||||
|
@ -619,7 +618,7 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
|||
return success;
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
// WindowsDeathTest implements death tests on Windows. Due to the
|
||||
// specifics of starting new processes on Windows, death tests there are
|
||||
// always threadsafe, and Google Test considers the
|
||||
|
@ -680,12 +679,14 @@ class WindowsDeathTest : public DeathTestImpl {
|
|||
// status, or 0 if no child process exists. As a side effect, sets the
|
||||
// outcome data member.
|
||||
int WindowsDeathTest::Wait() {
|
||||
if (!spawned()) return 0;
|
||||
if (!spawned())
|
||||
return 0;
|
||||
|
||||
// Wait until the child either signals that it has acquired the write end
|
||||
// of the pipe or it dies.
|
||||
const HANDLE wait_handles[2] = {child_handle_.Get(), event_handle_.Get()};
|
||||
switch (::WaitForMultipleObjects(2, wait_handles,
|
||||
const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
|
||||
switch (::WaitForMultipleObjects(2,
|
||||
wait_handles,
|
||||
FALSE, // Waits for any of the handles.
|
||||
INFINITE)) {
|
||||
case WAIT_OBJECT_0:
|
||||
|
@ -706,8 +707,9 @@ int WindowsDeathTest::Wait() {
|
|||
// returns immediately if the child has already exited, regardless of
|
||||
// whether previous calls to WaitForMultipleObjects synchronized on this
|
||||
// handle or not.
|
||||
GTEST_DEATH_TEST_CHECK_(WAIT_OBJECT_0 ==
|
||||
::WaitForSingleObject(child_handle_.Get(), INFINITE));
|
||||
GTEST_DEATH_TEST_CHECK_(
|
||||
WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
|
||||
INFINITE));
|
||||
DWORD status_code;
|
||||
GTEST_DEATH_TEST_CHECK_(
|
||||
::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
|
||||
|
@ -740,12 +742,12 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
|||
SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
|
||||
nullptr, TRUE};
|
||||
HANDLE read_handle, write_handle;
|
||||
GTEST_DEATH_TEST_CHECK_(::CreatePipe(&read_handle, &write_handle,
|
||||
&handles_are_inheritable,
|
||||
0) // Default buffer size.
|
||||
!= FALSE);
|
||||
set_read_fd(
|
||||
::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle), O_RDONLY));
|
||||
GTEST_DEATH_TEST_CHECK_(
|
||||
::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
|
||||
0) // Default buffer size.
|
||||
!= FALSE);
|
||||
set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
|
||||
O_RDONLY));
|
||||
write_handle_.Reset(write_handle);
|
||||
event_handle_.Reset(::CreateEvent(
|
||||
&handles_are_inheritable,
|
||||
|
@ -757,23 +759,24 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
|||
kFilterFlag + "=" + info->test_suite_name() +
|
||||
"." + info->name();
|
||||
const std::string internal_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" +
|
||||
file_ + "|" + StreamableToString(line_) + "|" +
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
|
||||
"=" + file_ + "|" + StreamableToString(line_) + "|" +
|
||||
StreamableToString(death_test_index) + "|" +
|
||||
StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
|
||||
// size_t has the same width as pointers on both 32-bit and 64-bit
|
||||
// Windows platforms.
|
||||
// See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
|
||||
"|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) + "|" +
|
||||
StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
|
||||
"|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
|
||||
"|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
|
||||
|
||||
char executable_path[_MAX_PATH + 1]; // NOLINT
|
||||
GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
|
||||
executable_path,
|
||||
_MAX_PATH));
|
||||
|
||||
std::string command_line = std::string(::GetCommandLineA()) + " " +
|
||||
filter_flag + " \"" + internal_flag + "\"";
|
||||
std::string command_line =
|
||||
std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
|
||||
internal_flag + "\"";
|
||||
|
||||
DeathTest::set_last_death_test_message("");
|
||||
|
||||
|
@ -806,7 +809,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
|||
return OVERSEE_TEST;
|
||||
}
|
||||
|
||||
#elif GTEST_OS_FUCHSIA
|
||||
# elif GTEST_OS_FUCHSIA
|
||||
|
||||
class FuchsiaDeathTest : public DeathTestImpl {
|
||||
public:
|
||||
|
@ -852,13 +855,18 @@ class Arguments {
|
|||
template <typename Str>
|
||||
void AddArguments(const ::std::vector<Str>& arguments) {
|
||||
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
|
||||
i != arguments.end(); ++i) {
|
||||
i != arguments.end();
|
||||
++i) {
|
||||
args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
|
||||
}
|
||||
}
|
||||
char* const* Argv() { return &args_[0]; }
|
||||
char* const* Argv() {
|
||||
return &args_[0];
|
||||
}
|
||||
|
||||
int size() { return args_.size() - 1; }
|
||||
int size() {
|
||||
return static_cast<int>(args_.size()) - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char*> args_;
|
||||
|
@ -872,7 +880,8 @@ int FuchsiaDeathTest::Wait() {
|
|||
const int kSocketKey = 1;
|
||||
const int kExceptionKey = 2;
|
||||
|
||||
if (!spawned()) return 0;
|
||||
if (!spawned())
|
||||
return 0;
|
||||
|
||||
// Create a port to wait for socket/task/exception events.
|
||||
zx_status_t status_zx;
|
||||
|
@ -882,18 +891,17 @@ int FuchsiaDeathTest::Wait() {
|
|||
|
||||
// Register to wait for the child process to terminate.
|
||||
status_zx = child_process_.wait_async(
|
||||
port, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
|
||||
port, kProcessKey, ZX_PROCESS_TERMINATED, 0);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
// Register to wait for the socket to be readable or closed.
|
||||
status_zx = stderr_socket_.wait_async(
|
||||
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
|
||||
ZX_WAIT_ASYNC_ONCE);
|
||||
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
// Register to wait for an exception.
|
||||
status_zx = exception_channel_.wait_async(
|
||||
port, kExceptionKey, ZX_CHANNEL_READABLE, ZX_WAIT_ASYNC_ONCE);
|
||||
port, kExceptionKey, ZX_CHANNEL_READABLE, 0);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
bool process_terminated = false;
|
||||
|
@ -923,9 +931,9 @@ int FuchsiaDeathTest::Wait() {
|
|||
size_t old_length = captured_stderr_.length();
|
||||
size_t bytes_read = 0;
|
||||
captured_stderr_.resize(old_length + kBufferSize);
|
||||
status_zx =
|
||||
stderr_socket_.read(0, &captured_stderr_.front() + old_length,
|
||||
kBufferSize, &bytes_read);
|
||||
status_zx = stderr_socket_.read(
|
||||
0, &captured_stderr_.front() + old_length, kBufferSize,
|
||||
&bytes_read);
|
||||
captured_stderr_.resize(old_length + bytes_read);
|
||||
} while (status_zx == ZX_OK);
|
||||
if (status_zx == ZX_ERR_PEER_CLOSED) {
|
||||
|
@ -933,8 +941,7 @@ int FuchsiaDeathTest::Wait() {
|
|||
} else {
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
|
||||
status_zx = stderr_socket_.wait_async(
|
||||
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
|
||||
ZX_WAIT_ASYNC_ONCE);
|
||||
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
}
|
||||
} else {
|
||||
|
@ -951,8 +958,8 @@ int FuchsiaDeathTest::Wait() {
|
|||
nullptr, nullptr);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(buffer.exited);
|
||||
set_status(buffer.return_code);
|
||||
GTEST_DEATH_TEST_CHECK_(buffer.flags & ZX_INFO_PROCESS_FLAG_EXITED);
|
||||
set_status(static_cast<int>(buffer.return_code));
|
||||
return status();
|
||||
}
|
||||
|
||||
|
@ -982,10 +989,11 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
|||
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||
kFilterFlag + "=" + info->test_suite_name() +
|
||||
"." + info->name();
|
||||
const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||
kInternalRunDeathTestFlag + "=" + file_ +
|
||||
"|" + StreamableToString(line_) + "|" +
|
||||
StreamableToString(death_test_index);
|
||||
const std::string internal_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
||||
+ file_ + "|"
|
||||
+ StreamableToString(line_) + "|"
|
||||
+ StreamableToString(death_test_index);
|
||||
Arguments args;
|
||||
args.AddArguments(GetInjectableArgvs());
|
||||
args.AddArgument(filter_flag.c_str());
|
||||
|
@ -1008,7 +1016,8 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
|||
|
||||
// Create a socket pair will be used to receive the child process' stderr.
|
||||
zx::socket stderr_producer_socket;
|
||||
status = zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
|
||||
status =
|
||||
zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
|
||||
GTEST_DEATH_TEST_CHECK_(status >= 0);
|
||||
int stderr_producer_fd = -1;
|
||||
status =
|
||||
|
@ -1025,32 +1034,35 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
|||
|
||||
// Create a child job.
|
||||
zx_handle_t child_job = ZX_HANDLE_INVALID;
|
||||
status = zx_job_create(zx_job_default(), 0, &child_job);
|
||||
status = zx_job_create(zx_job_default(), 0, & child_job);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
zx_policy_basic_t policy;
|
||||
policy.condition = ZX_POL_NEW_ANY;
|
||||
policy.policy = ZX_POL_ACTION_ALLOW;
|
||||
status = zx_job_set_policy(child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC,
|
||||
&policy, 1);
|
||||
status = zx_job_set_policy(
|
||||
child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
|
||||
// Create an exception channel attached to the |child_job|, to allow
|
||||
// us to suppress the system default exception handler from firing.
|
||||
status = zx_task_create_exception_channel(
|
||||
child_job, 0, exception_channel_.reset_and_get_address());
|
||||
status =
|
||||
zx_task_create_exception_channel(
|
||||
child_job, 0, exception_channel_.reset_and_get_address());
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
|
||||
// Spawn the child process.
|
||||
status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0],
|
||||
args.Argv(), nullptr, 2, spawn_actions,
|
||||
child_process_.reset_and_get_address(), nullptr);
|
||||
status = fdio_spawn_etc(
|
||||
child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
|
||||
2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
|
||||
set_spawned(true);
|
||||
return OVERSEE_TEST;
|
||||
}
|
||||
|
||||
std::string FuchsiaDeathTest::GetErrorLogs() { return captured_stderr_; }
|
||||
std::string FuchsiaDeathTest::GetErrorLogs() {
|
||||
return captured_stderr_;
|
||||
}
|
||||
|
||||
#else // We are neither on Windows, nor on Fuchsia.
|
||||
|
||||
|
@ -1081,7 +1093,8 @@ ForkingDeathTest::ForkingDeathTest(const char* a_statement,
|
|||
// status, or 0 if no child process exists. As a side effect, sets the
|
||||
// outcome data member.
|
||||
int ForkingDeathTest::Wait() {
|
||||
if (!spawned()) return 0;
|
||||
if (!spawned())
|
||||
return 0;
|
||||
|
||||
ReadAndInterpretStatusByte();
|
||||
|
||||
|
@ -1160,11 +1173,11 @@ class ExecDeathTest : public ForkingDeathTest {
|
|||
private:
|
||||
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
|
||||
::std::vector<std::string> args = GetInjectableArgvs();
|
||||
#if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
||||
# if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
||||
::std::vector<std::string> extra_args =
|
||||
GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
|
||||
args.insert(args.end(), extra_args.begin(), extra_args.end());
|
||||
#endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
||||
# endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
||||
return args;
|
||||
}
|
||||
// The name of the file in which the death test is located.
|
||||
|
@ -1191,11 +1204,14 @@ class Arguments {
|
|||
template <typename Str>
|
||||
void AddArguments(const ::std::vector<Str>& arguments) {
|
||||
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
|
||||
i != arguments.end(); ++i) {
|
||||
i != arguments.end();
|
||||
++i) {
|
||||
args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
|
||||
}
|
||||
}
|
||||
char* const* Argv() { return &args_[0]; }
|
||||
char* const* Argv() {
|
||||
return &args_[0];
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char*> args_;
|
||||
|
@ -1208,21 +1224,9 @@ struct ExecDeathTestArgs {
|
|||
int close_fd; // File descriptor to close; the read end of a pipe
|
||||
};
|
||||
|
||||
#if GTEST_OS_MAC
|
||||
inline char** GetEnviron() {
|
||||
// When Google Test is built as a framework on MacOS X, the environ variable
|
||||
// is unavailable. Apple's documentation (man environ) recommends using
|
||||
// _NSGetEnviron() instead.
|
||||
return *_NSGetEnviron();
|
||||
}
|
||||
#else
|
||||
// Some POSIX platforms expect you to declare environ. extern "C" makes
|
||||
// it reside in the global namespace.
|
||||
# if GTEST_OS_QNX
|
||||
extern "C" char** environ;
|
||||
inline char** GetEnviron() { return environ; }
|
||||
#endif // GTEST_OS_MAC
|
||||
|
||||
#if !GTEST_OS_QNX
|
||||
# else // GTEST_OS_QNX
|
||||
// The main function for a threadsafe-style death test child process.
|
||||
// This function is called in a clone()-ed process and thus must avoid
|
||||
// any potentially unsafe operations like malloc or libc functions.
|
||||
|
@ -1242,19 +1246,20 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// We can safely call execve() as it's a direct system call. We
|
||||
// We can safely call execv() as it's almost a direct system call. We
|
||||
// cannot use execvp() as it's a libc function and thus potentially
|
||||
// unsafe. Since execve() doesn't search the PATH, the user must
|
||||
// unsafe. Since execv() doesn't search the PATH, the user must
|
||||
// invoke the test program via a valid path that contains at least
|
||||
// one path separator.
|
||||
execve(args->argv[0], args->argv, GetEnviron());
|
||||
DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
|
||||
original_dir + " failed: " + GetLastErrnoDescription());
|
||||
execv(args->argv[0], args->argv);
|
||||
DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " +
|
||||
original_dir + " failed: " +
|
||||
GetLastErrnoDescription());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif // !GTEST_OS_QNX
|
||||
# endif // GTEST_OS_QNX
|
||||
|
||||
#if GTEST_HAS_CLONE
|
||||
# if GTEST_HAS_CLONE
|
||||
// Two utility routines that together determine the direction the stack
|
||||
// grows.
|
||||
// This could be accomplished more elegantly by a single recursive
|
||||
|
@ -1266,24 +1271,29 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
|||
// correct answer.
|
||||
static void StackLowerThanAddress(const void* ptr,
|
||||
bool* result) GTEST_NO_INLINE_;
|
||||
// Make sure sanitizers do not tamper with the stack here.
|
||||
// Ideally, we want to use `__builtin_frame_address` instead of a local variable
|
||||
// address with sanitizer disabled, but it does not work when the
|
||||
// compiler optimizes the stack frame out, which happens on PowerPC targets.
|
||||
// HWAddressSanitizer add a random tag to the MSB of the local variable address,
|
||||
// making comparison result unpredictable.
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
static void StackLowerThanAddress(const void* ptr, bool* result) {
|
||||
int dummy;
|
||||
*result = (&dummy < ptr);
|
||||
int dummy = 0;
|
||||
*result = std::less<const void*>()(&dummy, ptr);
|
||||
}
|
||||
|
||||
// Make sure AddressSanitizer does not tamper with the stack here.
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
static bool StackGrowsDown() {
|
||||
int dummy;
|
||||
int dummy = 0;
|
||||
bool result;
|
||||
StackLowerThanAddress(&dummy, &result);
|
||||
return result;
|
||||
}
|
||||
#endif // GTEST_HAS_CLONE
|
||||
# endif // GTEST_HAS_CLONE
|
||||
|
||||
// Spawns a child process with the same executable as the current process in
|
||||
// a thread-safe manner and instructs it to run the death test. The
|
||||
|
@ -1293,10 +1303,10 @@ static bool StackGrowsDown() {
|
|||
// spawn(2) there instead. The function dies with an error message if
|
||||
// anything goes wrong.
|
||||
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||
ExecDeathTestArgs args = {argv, close_fd};
|
||||
ExecDeathTestArgs args = { argv, close_fd };
|
||||
pid_t child_pid = -1;
|
||||
|
||||
#if GTEST_OS_QNX
|
||||
# if GTEST_OS_QNX
|
||||
// Obtains the current directory and sets it to be closed in the child
|
||||
// process.
|
||||
const int cwd_fd = open(".", O_RDONLY);
|
||||
|
@ -1317,18 +1327,17 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
|||
int fd_flags;
|
||||
// Set close_fd to be closed after spawn.
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||
fcntl(close_fd, F_SETFD, fd_flags | FD_CLOEXEC));
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
|
||||
fd_flags | FD_CLOEXEC));
|
||||
struct inheritance inherit = {0};
|
||||
// spawn is a system call.
|
||||
child_pid =
|
||||
spawn(args.argv[0], 0, nullptr, &inherit, args.argv, GetEnviron());
|
||||
child_pid = spawn(args.argv[0], 0, nullptr, &inherit, args.argv, environ);
|
||||
// Restores the current working directory.
|
||||
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
||||
|
||||
#else // GTEST_OS_QNX
|
||||
#if GTEST_OS_LINUX
|
||||
# else // GTEST_OS_QNX
|
||||
# if GTEST_OS_LINUX
|
||||
// When a SIGPROF signal is received while fork() or clone() are executing,
|
||||
// the process may hang. To avoid this, we ignore SIGPROF here and re-enable
|
||||
// it after the call to fork()/clone() is complete.
|
||||
|
@ -1337,16 +1346,16 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
|||
memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
|
||||
sigemptyset(&ignore_sigprof_action.sa_mask);
|
||||
ignore_sigprof_action.sa_handler = SIG_IGN;
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||
sigaction(SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
|
||||
#endif // GTEST_OS_LINUX
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
|
||||
SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
#if GTEST_HAS_CLONE
|
||||
# if GTEST_HAS_CLONE
|
||||
const bool use_fork = GTEST_FLAG(death_test_use_fork);
|
||||
|
||||
if (!use_fork) {
|
||||
static const bool stack_grows_down = StackGrowsDown();
|
||||
const auto stack_size = static_cast<size_t>(getpagesize());
|
||||
const auto stack_size = static_cast<size_t>(getpagesize() * 2);
|
||||
// MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
|
||||
void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
|
@ -1361,7 +1370,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
|||
const size_t kMaxStackAlignment = 64;
|
||||
void* const stack_top =
|
||||
static_cast<char*>(stack) +
|
||||
(stack_grows_down ? stack_size - kMaxStackAlignment : 0);
|
||||
(stack_grows_down ? stack_size - kMaxStackAlignment : 0);
|
||||
GTEST_DEATH_TEST_CHECK_(
|
||||
static_cast<size_t>(stack_size) > kMaxStackAlignment &&
|
||||
reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0);
|
||||
|
@ -1370,19 +1379,19 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
|||
|
||||
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
||||
}
|
||||
#else
|
||||
# else
|
||||
const bool use_fork = true;
|
||||
#endif // GTEST_HAS_CLONE
|
||||
# endif // GTEST_HAS_CLONE
|
||||
|
||||
if (use_fork && (child_pid = fork()) == 0) {
|
||||
ExecDeathTestChildMain(&args);
|
||||
_exit(0);
|
||||
ExecDeathTestChildMain(&args);
|
||||
_exit(0);
|
||||
}
|
||||
#endif // GTEST_OS_QNX
|
||||
#if GTEST_OS_LINUX
|
||||
# endif // GTEST_OS_QNX
|
||||
# if GTEST_OS_LINUX
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||
sigaction(SIGPROF, &saved_sigprof_action, nullptr));
|
||||
#endif // GTEST_OS_LINUX
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
||||
return child_pid;
|
||||
|
@ -1413,11 +1422,11 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
|||
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||
kFilterFlag + "=" + info->test_suite_name() +
|
||||
"." + info->name();
|
||||
const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||
kInternalRunDeathTestFlag + "=" + file_ +
|
||||
"|" + StreamableToString(line_) + "|" +
|
||||
StreamableToString(death_test_index) + "|" +
|
||||
StreamableToString(pipe_fd[1]);
|
||||
const std::string internal_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
||||
+ file_ + "|" + StreamableToString(line_) + "|"
|
||||
+ StreamableToString(death_test_index) + "|"
|
||||
+ StreamableToString(pipe_fd[1]);
|
||||
Arguments args;
|
||||
args.AddArguments(GetArgvsForDeathTestChildProcess());
|
||||
args.AddArgument(filter_flag.c_str());
|
||||
|
@ -1438,7 +1447,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
|||
return OVERSEE_TEST;
|
||||
}
|
||||
|
||||
#endif // !GTEST_OS_WINDOWS
|
||||
# endif // !GTEST_OS_WINDOWS
|
||||
|
||||
// Creates a concrete DeathTest-derived class that depends on the
|
||||
// --gtest_death_test_style flag, and sets the pointer pointed to
|
||||
|
@ -1452,15 +1461,15 @@ bool DefaultDeathTestFactory::Create(const char* statement,
|
|||
UnitTestImpl* const impl = GetUnitTestImpl();
|
||||
const InternalRunDeathTestFlag* const flag =
|
||||
impl->internal_run_death_test_flag();
|
||||
const int death_test_index =
|
||||
impl->current_test_info()->increment_death_test_count();
|
||||
const int death_test_index = impl->current_test_info()
|
||||
->increment_death_test_count();
|
||||
|
||||
if (flag != nullptr) {
|
||||
if (death_test_index > flag->index()) {
|
||||
DeathTest::set_last_death_test_message(
|
||||
"Death test count (" + StreamableToString(death_test_index) +
|
||||
") somehow exceeded expected maximum (" +
|
||||
StreamableToString(flag->index()) + ")");
|
||||
"Death test count (" + StreamableToString(death_test_index)
|
||||
+ ") somehow exceeded expected maximum ("
|
||||
+ StreamableToString(flag->index()) + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1471,21 +1480,21 @@ bool DefaultDeathTestFactory::Create(const char* statement,
|
|||
}
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
||||
GTEST_FLAG(death_test_style) == "fast") {
|
||||
*test = new WindowsDeathTest(statement, std::move(matcher), file, line);
|
||||
}
|
||||
|
||||
#elif GTEST_OS_FUCHSIA
|
||||
# elif GTEST_OS_FUCHSIA
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
||||
GTEST_FLAG(death_test_style) == "fast") {
|
||||
*test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
|
||||
}
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe") {
|
||||
*test = new ExecDeathTest(statement, std::move(matcher), file, line);
|
||||
|
@ -1493,28 +1502,28 @@ bool DefaultDeathTestFactory::Create(const char* statement,
|
|||
*test = new NoExecDeathTest(statement, std::move(matcher));
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
else { // NOLINT - this is more readable than unbalanced brackets inside #if.
|
||||
DeathTest::set_last_death_test_message("Unknown death test style \"" +
|
||||
GTEST_FLAG(death_test_style) +
|
||||
"\" encountered");
|
||||
DeathTest::set_last_death_test_message(
|
||||
"Unknown death test style \"" + GTEST_FLAG(death_test_style)
|
||||
+ "\" encountered");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
// Recreates the pipe and event handles from the provided parameters,
|
||||
// signals the event, and returns a file descriptor wrapped around the pipe
|
||||
// handle. This function is called in the child process only.
|
||||
static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||
size_t write_handle_as_size_t,
|
||||
size_t event_handle_as_size_t) {
|
||||
size_t write_handle_as_size_t,
|
||||
size_t event_handle_as_size_t) {
|
||||
AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
|
||||
FALSE, // Non-inheritable.
|
||||
parent_process_id));
|
||||
FALSE, // Non-inheritable.
|
||||
parent_process_id));
|
||||
if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
|
||||
DeathTestAbort("Unable to open parent process " +
|
||||
StreamableToString(parent_process_id));
|
||||
|
@ -1522,7 +1531,8 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
|||
|
||||
GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
|
||||
|
||||
const HANDLE write_handle = reinterpret_cast<HANDLE>(write_handle_as_size_t);
|
||||
const HANDLE write_handle =
|
||||
reinterpret_cast<HANDLE>(write_handle_as_size_t);
|
||||
HANDLE dup_write_handle;
|
||||
|
||||
// The newly initialized handle is accessible only in the parent
|
||||
|
@ -1544,7 +1554,9 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
|||
HANDLE dup_event_handle;
|
||||
|
||||
if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
|
||||
::GetCurrentProcess(), &dup_event_handle, 0x0, FALSE,
|
||||
::GetCurrentProcess(), &dup_event_handle,
|
||||
0x0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS)) {
|
||||
DeathTestAbort("Unable to duplicate the event handle " +
|
||||
StreamableToString(event_handle_as_size_t) +
|
||||
|
@ -1566,7 +1578,7 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
|||
|
||||
return write_fd;
|
||||
}
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Returns a newly created InternalRunDeathTestFlag object with fields
|
||||
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
||||
|
@ -1582,41 +1594,45 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
|
|||
SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
|
||||
int write_fd = -1;
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
|
||||
unsigned int parent_process_id = 0;
|
||||
size_t write_handle_as_size_t = 0;
|
||||
size_t event_handle_as_size_t = 0;
|
||||
|
||||
if (fields.size() != 6 || !ParseNaturalNumber(fields[1], &line) ||
|
||||
!ParseNaturalNumber(fields[2], &index) ||
|
||||
!ParseNaturalNumber(fields[3], &parent_process_id) ||
|
||||
!ParseNaturalNumber(fields[4], &write_handle_as_size_t) ||
|
||||
!ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
|
||||
if (fields.size() != 6
|
||||
|| !ParseNaturalNumber(fields[1], &line)
|
||||
|| !ParseNaturalNumber(fields[2], &index)
|
||||
|| !ParseNaturalNumber(fields[3], &parent_process_id)
|
||||
|| !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
|
||||
|| !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
|
||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
|
||||
GTEST_FLAG(internal_run_death_test));
|
||||
}
|
||||
write_fd = GetStatusFileDescriptor(parent_process_id, write_handle_as_size_t,
|
||||
write_fd = GetStatusFileDescriptor(parent_process_id,
|
||||
write_handle_as_size_t,
|
||||
event_handle_as_size_t);
|
||||
|
||||
#elif GTEST_OS_FUCHSIA
|
||||
# elif GTEST_OS_FUCHSIA
|
||||
|
||||
if (fields.size() != 3 || !ParseNaturalNumber(fields[1], &line) ||
|
||||
!ParseNaturalNumber(fields[2], &index)) {
|
||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
|
||||
GTEST_FLAG(internal_run_death_test));
|
||||
if (fields.size() != 3
|
||||
|| !ParseNaturalNumber(fields[1], &line)
|
||||
|| !ParseNaturalNumber(fields[2], &index)) {
|
||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
|
||||
+ GTEST_FLAG(internal_run_death_test));
|
||||
}
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
if (fields.size() != 4 || !ParseNaturalNumber(fields[1], &line) ||
|
||||
!ParseNaturalNumber(fields[2], &index) ||
|
||||
!ParseNaturalNumber(fields[3], &write_fd)) {
|
||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
|
||||
GTEST_FLAG(internal_run_death_test));
|
||||
if (fields.size() != 4
|
||||
|| !ParseNaturalNumber(fields[1], &line)
|
||||
|| !ParseNaturalNumber(fields[2], &index)
|
||||
|| !ParseNaturalNumber(fields[3], &write_fd)) {
|
||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
|
||||
+ GTEST_FLAG(internal_run_death_test));
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
|
||||
}
|
||||
|
|
|
@ -34,25 +34,25 @@
|
|||
#include "gtest/gtest-message.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
#include <windows.h>
|
||||
# include <windows.h>
|
||||
#elif GTEST_OS_WINDOWS
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
# include <direct.h>
|
||||
# include <io.h>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#include <climits> // Some Linux distributions define PATH_MAX here.
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
# include <limits.h>
|
||||
# include <climits> // Some Linux distributions define PATH_MAX here.
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
#define GTEST_PATH_MAX_ _MAX_PATH
|
||||
# define GTEST_PATH_MAX_ _MAX_PATH
|
||||
#elif defined(PATH_MAX)
|
||||
#define GTEST_PATH_MAX_ PATH_MAX
|
||||
# define GTEST_PATH_MAX_ PATH_MAX
|
||||
#elif defined(_XOPEN_PATH_MAX)
|
||||
#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
|
||||
# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
|
||||
#else
|
||||
#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
||||
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
namespace testing {
|
||||
|
@ -66,16 +66,16 @@ namespace internal {
|
|||
const char kPathSeparator = '\\';
|
||||
const char kAlternatePathSeparator = '/';
|
||||
const char kAlternatePathSeparatorString[] = "/";
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
# 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
|
||||
// provides a reasonable fallback.
|
||||
const char kCurrentDirectoryString[] = "\\";
|
||||
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
|
||||
const DWORD kInvalidFileAttributes = 0xffffffff;
|
||||
#else
|
||||
# else
|
||||
const char kCurrentDirectoryString[] = ".\\";
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
# endif // GTEST_OS_WINDOWS_MOBILE
|
||||
#else
|
||||
const char kPathSeparator = '/';
|
||||
const char kCurrentDirectoryString[] = "./";
|
||||
|
@ -92,23 +92,24 @@ static bool IsPathSeparator(char c) {
|
|||
|
||||
// Returns the current working directory, or "" if unsuccessful.
|
||||
FilePath FilePath::GetCurrentDir() {
|
||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
|
||||
GTEST_OS_WINDOWS_RT || ARDUINO || defined(ESP_PLATFORM)
|
||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
|
||||
GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 || \
|
||||
GTEST_OS_XTENSA
|
||||
// These platforms do not have a current directory, so we just return
|
||||
// something reasonable.
|
||||
return FilePath(kCurrentDirectoryString);
|
||||
#elif GTEST_OS_WINDOWS
|
||||
char cwd[GTEST_PATH_MAX_ + 1] = {'\0'};
|
||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
|
||||
#else
|
||||
char cwd[GTEST_PATH_MAX_ + 1] = {'\0'};
|
||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||
char* result = getcwd(cwd, sizeof(cwd));
|
||||
#if GTEST_OS_NACL
|
||||
# if GTEST_OS_NACL
|
||||
// getcwd will likely fail in NaCl due to the sandbox, so return something
|
||||
// reasonable. The user may have provided a shim implementation for getcwd,
|
||||
// however, so fallback only when failure is detected.
|
||||
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
|
||||
#endif // GTEST_OS_NACL
|
||||
# endif // GTEST_OS_NACL
|
||||
return FilePath(result == nullptr ? "" : cwd);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
@ -120,8 +121,8 @@ FilePath FilePath::GetCurrentDir() {
|
|||
FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||
const std::string dot_extension = std::string(".") + extension;
|
||||
if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
|
||||
return FilePath(
|
||||
pathname_.substr(0, pathname_.length() - dot_extension.length()));
|
||||
return FilePath(pathname_.substr(
|
||||
0, pathname_.length() - dot_extension.length()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -177,14 +178,15 @@ FilePath FilePath::RemoveFileName() const {
|
|||
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||
// On Windows platform, uses \ as the separator rather than /.
|
||||
FilePath FilePath::MakeFileName(const FilePath& directory,
|
||||
const FilePath& base_name, int number,
|
||||
const FilePath& base_name,
|
||||
int number,
|
||||
const char* extension) {
|
||||
std::string file;
|
||||
if (number == 0) {
|
||||
file = base_name.string() + "." + extension;
|
||||
} else {
|
||||
file =
|
||||
base_name.string() + "_" + StreamableToString(number) + "." + extension;
|
||||
file = base_name.string() + "_" + StreamableToString(number)
|
||||
+ "." + extension;
|
||||
}
|
||||
return ConcatPaths(directory, FilePath(file));
|
||||
}
|
||||
|
@ -193,7 +195,8 @@ FilePath FilePath::MakeFileName(const FilePath& directory,
|
|||
// On Windows, uses \ as the separator rather than /.
|
||||
FilePath FilePath::ConcatPaths(const FilePath& directory,
|
||||
const FilePath& relative_path) {
|
||||
if (directory.IsEmpty()) return relative_path;
|
||||
if (directory.IsEmpty())
|
||||
return relative_path;
|
||||
const FilePath dir(directory.RemoveTrailingPathSeparator());
|
||||
return FilePath(dir.string() + kPathSeparator + relative_path.string());
|
||||
}
|
||||
|
@ -204,10 +207,10 @@ bool FilePath::FileOrDirectoryExists() const {
|
|||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
|
||||
const DWORD attributes = GetFileAttributes(unicode);
|
||||
delete[] unicode;
|
||||
delete [] unicode;
|
||||
return attributes != kInvalidFileAttributes;
|
||||
#else
|
||||
posix::StatStruct file_stat;
|
||||
posix::StatStruct file_stat{};
|
||||
return posix::Stat(pathname_.c_str(), &file_stat) == 0;
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
@ -219,8 +222,8 @@ bool FilePath::DirectoryExists() const {
|
|||
#if GTEST_OS_WINDOWS
|
||||
// Don't strip off trailing separator if path is a root directory on
|
||||
// Windows (like "C:\\").
|
||||
const FilePath& path(IsRootDirectory() ? *this
|
||||
: RemoveTrailingPathSeparator());
|
||||
const FilePath& path(IsRootDirectory() ? *this :
|
||||
RemoveTrailingPathSeparator());
|
||||
#else
|
||||
const FilePath& path(*this);
|
||||
#endif
|
||||
|
@ -228,15 +231,15 @@ bool FilePath::DirectoryExists() const {
|
|||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
|
||||
const DWORD attributes = GetFileAttributes(unicode);
|
||||
delete[] unicode;
|
||||
delete [] unicode;
|
||||
if ((attributes != kInvalidFileAttributes) &&
|
||||
(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
result = true;
|
||||
}
|
||||
#else
|
||||
posix::StatStruct file_stat;
|
||||
result =
|
||||
posix::Stat(path.c_str(), &file_stat) == 0 && posix::IsDir(file_stat);
|
||||
posix::StatStruct file_stat{};
|
||||
result = posix::Stat(path.c_str(), &file_stat) == 0 &&
|
||||
posix::IsDir(file_stat);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
return result;
|
||||
|
@ -256,9 +259,11 @@ bool FilePath::IsRootDirectory() const {
|
|||
bool FilePath::IsAbsolutePath() const {
|
||||
const char* const name = pathname_.c_str();
|
||||
#if GTEST_OS_WINDOWS
|
||||
return pathname_.length() >= 3 && ((name[0] >= 'a' && name[0] <= 'z') ||
|
||||
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
||||
name[1] == ':' && IsPathSeparator(name[2]);
|
||||
return pathname_.length() >= 3 &&
|
||||
((name[0] >= 'a' && name[0] <= 'z') ||
|
||||
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
||||
name[1] == ':' &&
|
||||
IsPathSeparator(name[2]);
|
||||
#else
|
||||
return IsPathSeparator(name[0]);
|
||||
#endif
|
||||
|
@ -316,9 +321,12 @@ bool FilePath::CreateFolder() const {
|
|||
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
||||
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
||||
int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
|
||||
delete[] unicode;
|
||||
delete [] unicode;
|
||||
#elif GTEST_OS_WINDOWS
|
||||
int result = _mkdir(pathname_.c_str());
|
||||
#elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA
|
||||
// do nothing
|
||||
int result = 0;
|
||||
#else
|
||||
int result = mkdir(pathname_.c_str(), 0777);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
@ -333,40 +341,28 @@ 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 IsDirectory() ? FilePath(pathname_.substr(0, pathname_.length() - 1))
|
||||
: *this;
|
||||
return IsDirectory()
|
||||
? FilePath(pathname_.substr(0, pathname_.length() - 1))
|
||||
: *this;
|
||||
}
|
||||
|
||||
// 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 "..".
|
||||
void FilePath::Normalize() {
|
||||
if (pathname_.c_str() == nullptr) {
|
||||
pathname_ = "";
|
||||
return;
|
||||
}
|
||||
const char* src = pathname_.c_str();
|
||||
char* const dest = new char[pathname_.length() + 1];
|
||||
char* dest_ptr = dest;
|
||||
memset(dest_ptr, 0, pathname_.length() + 1);
|
||||
auto out = pathname_.begin();
|
||||
|
||||
while (*src != '\0') {
|
||||
*dest_ptr = *src;
|
||||
if (!IsPathSeparator(*src)) {
|
||||
src++;
|
||||
for (const char character : pathname_) {
|
||||
if (!IsPathSeparator(character)) {
|
||||
*(out++) = character;
|
||||
} else if (out == pathname_.begin() || *std::prev(out) != kPathSeparator) {
|
||||
*(out++) = kPathSeparator;
|
||||
} else {
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
if (*dest_ptr == kAlternatePathSeparator) {
|
||||
*dest_ptr = kPathSeparator;
|
||||
}
|
||||
#endif
|
||||
while (IsPathSeparator(*src)) src++;
|
||||
continue;
|
||||
}
|
||||
dest_ptr++;
|
||||
}
|
||||
*dest_ptr = '\0';
|
||||
pathname_ = dest;
|
||||
delete[] dest;
|
||||
|
||||
pathname_.erase(out, pathname_.end());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
|
|
@ -31,17 +31,18 @@
|
|||
// This file contains purely Google Test's internal implementation. Please
|
||||
// DO NOT #INCLUDE IT IN A USER PROGRAM.
|
||||
|
||||
#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#define GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#ifndef GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#define GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
#include <errno.h>
|
||||
# include <errno.h>
|
||||
#endif // !_WIN32_WCE
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
|
||||
#include <string.h> // For memmove.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -49,19 +50,19 @@
|
|||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
#if GTEST_CAN_STREAM_RESULTS_
|
||||
#include <arpa/inet.h> // NOLINT
|
||||
#include <netdb.h> // NOLINT
|
||||
# include <arpa/inet.h> // NOLINT
|
||||
# include <netdb.h> // NOLINT
|
||||
#endif
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
#include <windows.h> // NOLINT
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# include <windows.h> // NOLINT
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gtest/gtest-spi.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
4251 /* class A needs to have dll-interface to be used by clients of class B */)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
namespace testing {
|
||||
|
||||
|
@ -83,9 +84,11 @@ const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
|
|||
const char kBreakOnFailureFlag[] = "break_on_failure";
|
||||
const char kCatchExceptionsFlag[] = "catch_exceptions";
|
||||
const char kColorFlag[] = "color";
|
||||
const char kFailFast[] = "fail_fast";
|
||||
const char kFilterFlag[] = "filter";
|
||||
const char kListTestsFlag[] = "list_tests";
|
||||
const char kOutputFlag[] = "output";
|
||||
const char kBriefFlag[] = "brief";
|
||||
const char kPrintTimeFlag[] = "print_time";
|
||||
const char kPrintUTF8Flag[] = "print_utf8";
|
||||
const char kRandomSeedFlag[] = "random_seed";
|
||||
|
@ -122,21 +125,21 @@ GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
|
|||
//
|
||||
// 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);
|
||||
GTEST_API_ bool ParseInt32Flag(
|
||||
const char* str, const char* flag, int32_t* value);
|
||||
|
||||
// Returns a random seed in range [1, kMaxRandomSeed] based on the
|
||||
// given --gtest_random_seed flag value.
|
||||
inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
|
||||
const unsigned int raw_seed =
|
||||
(random_seed_flag == 0) ? static_cast<unsigned int>(GetTimeInMillis())
|
||||
: static_cast<unsigned int>(random_seed_flag);
|
||||
inline int GetRandomSeedFromFlag(int32_t random_seed_flag) {
|
||||
const unsigned int raw_seed = (random_seed_flag == 0) ?
|
||||
static_cast<unsigned int>(GetTimeInMillis()) :
|
||||
static_cast<unsigned int>(random_seed_flag);
|
||||
|
||||
// Normalizes the actual seed to range [1, kMaxRandomSeed] such that
|
||||
// it's easy to type.
|
||||
const int normalized_seed =
|
||||
static_cast<int>((raw_seed - 1U) %
|
||||
static_cast<unsigned int>(kMaxRandomSeed)) +
|
||||
1;
|
||||
static_cast<unsigned int>(kMaxRandomSeed)) + 1;
|
||||
return normalized_seed;
|
||||
}
|
||||
|
||||
|
@ -163,10 +166,12 @@ class GTestFlagSaver {
|
|||
color_ = GTEST_FLAG(color);
|
||||
death_test_style_ = GTEST_FLAG(death_test_style);
|
||||
death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
|
||||
fail_fast_ = GTEST_FLAG(fail_fast);
|
||||
filter_ = GTEST_FLAG(filter);
|
||||
internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
|
||||
list_tests_ = GTEST_FLAG(list_tests);
|
||||
output_ = GTEST_FLAG(output);
|
||||
brief_ = GTEST_FLAG(brief);
|
||||
print_time_ = GTEST_FLAG(print_time);
|
||||
print_utf8_ = GTEST_FLAG(print_utf8);
|
||||
random_seed_ = GTEST_FLAG(random_seed);
|
||||
|
@ -186,9 +191,11 @@ class GTestFlagSaver {
|
|||
GTEST_FLAG(death_test_style) = death_test_style_;
|
||||
GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
|
||||
GTEST_FLAG(filter) = filter_;
|
||||
GTEST_FLAG(fail_fast) = fail_fast_;
|
||||
GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
|
||||
GTEST_FLAG(list_tests) = list_tests_;
|
||||
GTEST_FLAG(output) = output_;
|
||||
GTEST_FLAG(brief) = brief_;
|
||||
GTEST_FLAG(print_time) = print_time_;
|
||||
GTEST_FLAG(print_utf8) = print_utf8_;
|
||||
GTEST_FLAG(random_seed) = random_seed_;
|
||||
|
@ -207,16 +214,18 @@ class GTestFlagSaver {
|
|||
std::string color_;
|
||||
std::string death_test_style_;
|
||||
bool death_test_use_fork_;
|
||||
bool fail_fast_;
|
||||
std::string filter_;
|
||||
std::string internal_run_death_test_;
|
||||
bool list_tests_;
|
||||
std::string output_;
|
||||
bool brief_;
|
||||
bool print_time_;
|
||||
bool print_utf8_;
|
||||
internal::Int32 random_seed_;
|
||||
internal::Int32 repeat_;
|
||||
int32_t random_seed_;
|
||||
int32_t repeat_;
|
||||
bool shuffle_;
|
||||
internal::Int32 stack_trace_depth_;
|
||||
int32_t stack_trace_depth_;
|
||||
std::string stream_result_to_;
|
||||
bool throw_on_failure_;
|
||||
} GTEST_ATTRIBUTE_UNUSED_;
|
||||
|
@ -227,7 +236,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 converted
|
||||
// to "(Invalid Unicode 0xXXXXXXXX)".
|
||||
GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
|
||||
GTEST_API_ std::string CodePointToUtf8(uint32_t code_point);
|
||||
|
||||
// Converts a wide string to a narrow string in UTF-8 encoding.
|
||||
// The wide string is assumed to have the following encoding:
|
||||
|
@ -260,17 +269,17 @@ 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
|
||||
// Parses the environment variable var as a 32-bit integer. If it is unset,
|
||||
// returns default_val. If it is not a 32-bit integer, prints an error and
|
||||
// and aborts.
|
||||
GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
|
||||
GTEST_API_ int32_t Int32FromEnvOrDie(const char* env_var, int32_t default_val);
|
||||
|
||||
// Given the total number of shards, the shard index, and the test id,
|
||||
// returns true if and only if 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.
|
||||
GTEST_API_ bool ShouldRunTestOnShard(int total_shards, int shard_index,
|
||||
int test_id);
|
||||
GTEST_API_ bool ShouldRunTestOnShard(
|
||||
int total_shards, int shard_index, int test_id);
|
||||
|
||||
// STL container utilities.
|
||||
|
||||
|
@ -282,7 +291,8 @@ inline int CountIf(const Container& c, Predicate predicate) {
|
|||
// Solaris has a non-standard signature.
|
||||
int count = 0;
|
||||
for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
|
||||
if (predicate(*it)) ++count;
|
||||
if (predicate(*it))
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -312,9 +322,9 @@ 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 << "].";
|
||||
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
|
||||
|
@ -322,7 +332,7 @@ void ShuffleRange(internal::Random* random, int begin, int end,
|
|||
const int last_in_range = begin + range_width - 1;
|
||||
const int selected =
|
||||
begin +
|
||||
static_cast<int>(random->Generate(static_cast<UInt32>(range_width)));
|
||||
static_cast<int>(random->Generate(static_cast<uint32_t>(range_width)));
|
||||
std::swap((*v)[static_cast<size_t>(selected)],
|
||||
(*v)[static_cast<size_t>(last_in_range)]);
|
||||
}
|
||||
|
@ -384,13 +394,6 @@ class GTEST_API_ UnitTestOptions {
|
|||
|
||||
// Functions for processing the gtest_filter flag.
|
||||
|
||||
// Returns true if and only if the wildcard pattern matches the string.
|
||||
// The first ':' or '\0' character in pattern marks the end of it.
|
||||
//
|
||||
// This recursive algorithm isn't very efficient, but is clear and
|
||||
// works well enough for matching test names, which are short.
|
||||
static bool PatternMatchesString(const char* pattern, const char* str);
|
||||
|
||||
// Returns true if and only if the user-specified filter matches the test
|
||||
// suite name and the test name.
|
||||
static bool FilterMatchesTest(const std::string& test_suite_name,
|
||||
|
@ -473,7 +476,7 @@ struct TraceInfo {
|
|||
// This is the default global test part result reporter used in UnitTestImpl.
|
||||
// This class should only be used by UnitTestImpl.
|
||||
class DefaultGlobalTestPartResultReporter
|
||||
: public TestPartResultReporterInterface {
|
||||
: public TestPartResultReporterInterface {
|
||||
public:
|
||||
explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
|
||||
// Implements the TestPartResultReporterInterface. Reports the test part
|
||||
|
@ -593,7 +596,7 @@ class GTEST_API_ UnitTestImpl {
|
|||
return index < 0 ? nullptr : test_suites_[static_cast<size_t>(i)];
|
||||
}
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
const TestCase* GetTestCase(int i) const { return GetTestSuite(i); }
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
@ -645,10 +648,10 @@ class GTEST_API_ UnitTestImpl {
|
|||
// Arguments:
|
||||
//
|
||||
// test_suite_name: name of the test suite
|
||||
// type_param: the name of the test's type parameter, or NULL if
|
||||
// this is not a typed or a type-parameterized test.
|
||||
// set_up_tc: pointer to the function that sets up the test suite
|
||||
// tear_down_tc: pointer to the function that tears down the test suite
|
||||
// type_param: the name of the test's type parameter, or NULL if
|
||||
// this is not a typed or a type-parameterized test.
|
||||
// set_up_tc: pointer to the function that sets up the test suite
|
||||
// tear_down_tc: pointer to the function that tears down the test suite
|
||||
TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param,
|
||||
internal::SetUpTestSuiteFunc set_up_tc,
|
||||
internal::TearDownTestSuiteFunc tear_down_tc);
|
||||
|
@ -672,6 +675,7 @@ class GTEST_API_ UnitTestImpl {
|
|||
void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
|
||||
internal::TearDownTestSuiteFunc tear_down_tc,
|
||||
TestInfo* test_info) {
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
// In order to support thread-safe death tests, we need to
|
||||
// remember the original working directory when the test program
|
||||
// was first invoked. We cannot do this in RUN_ALL_TESTS(), as
|
||||
|
@ -684,6 +688,7 @@ class GTEST_API_ UnitTestImpl {
|
|||
GTEST_CHECK_(!original_working_dir_.IsEmpty())
|
||||
<< "Failed to get the current working directory.";
|
||||
}
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
GetTestSuite(test_info->test_suite_name(), test_info->type_param(),
|
||||
set_up_tc, tear_down_tc)
|
||||
|
@ -696,6 +701,17 @@ class GTEST_API_ UnitTestImpl {
|
|||
return parameterized_test_registry_;
|
||||
}
|
||||
|
||||
std::set<std::string>* ignored_parameterized_test_suites() {
|
||||
return &ignored_parameterized_test_suites_;
|
||||
}
|
||||
|
||||
// Returns TypeParameterizedTestSuiteRegistry object used to keep track of
|
||||
// type-parameterized tests and instantiations of them.
|
||||
internal::TypeParameterizedTestSuiteRegistry&
|
||||
type_parameterized_test_registry() {
|
||||
return type_parameterized_test_registry_;
|
||||
}
|
||||
|
||||
// Sets the TestSuite object for the test that's currently running.
|
||||
void set_current_test_suite(TestSuite* a_current_test_suite) {
|
||||
current_test_suite_ = a_current_test_suite;
|
||||
|
@ -728,7 +744,9 @@ class GTEST_API_ UnitTestImpl {
|
|||
}
|
||||
|
||||
// Clears the results of ad-hoc test assertions.
|
||||
void ClearAdHocTestResult() { ad_hoc_test_result_.Clear(); }
|
||||
void ClearAdHocTestResult() {
|
||||
ad_hoc_test_result_.Clear();
|
||||
}
|
||||
|
||||
// Adds a TestProperty to the current TestResult object when invoked in a
|
||||
// context of a test or a test suite, or to the global property set. If the
|
||||
|
@ -736,7 +754,10 @@ class GTEST_API_ UnitTestImpl {
|
|||
// updated.
|
||||
void RecordProperty(const TestProperty& test_property);
|
||||
|
||||
enum ReactionToSharding { HONOR_SHARDING_PROTOCOL, IGNORE_SHARDING_PROTOCOL };
|
||||
enum ReactionToSharding {
|
||||
HONOR_SHARDING_PROTOCOL,
|
||||
IGNORE_SHARDING_PROTOCOL
|
||||
};
|
||||
|
||||
// Matches the full name of each test against the user-specified
|
||||
// filter to decide whether the test should run, then records the
|
||||
|
@ -867,6 +888,12 @@ class GTEST_API_ UnitTestImpl {
|
|||
// ParameterizedTestRegistry object used to register value-parameterized
|
||||
// tests.
|
||||
internal::ParameterizedTestSuiteRegistry parameterized_test_registry_;
|
||||
internal::TypeParameterizedTestSuiteRegistry
|
||||
type_parameterized_test_registry_;
|
||||
|
||||
// The set holding the name of parameterized
|
||||
// test suites that may go uninstantiated.
|
||||
std::set<std::string> ignored_parameterized_test_suites_;
|
||||
|
||||
// Indicates whether RegisterParameterizedTests() has been called already.
|
||||
bool parameterized_tests_registered_;
|
||||
|
@ -959,9 +986,8 @@ 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);
|
||||
GTEST_API_ bool MatchRepetitionAndRegexAtHead(
|
||||
bool escaped, char ch, char repeat, const char* regex, const char* str);
|
||||
GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
|
||||
|
||||
#endif // GTEST_USES_SIMPLE_RE
|
||||
|
@ -992,22 +1018,11 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
|
|||
errno = 0;
|
||||
|
||||
char* end;
|
||||
// BiggestConvertible is the largest integer type that system-provided
|
||||
// string-to-number conversion routines can return.
|
||||
|
||||
#if GTEST_OS_WINDOWS && !defined(__GNUC__)
|
||||
|
||||
// MSVC and C++ Builder define __int64 instead of the standard long long.
|
||||
typedef unsigned __int64 BiggestConvertible;
|
||||
const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
|
||||
|
||||
#else
|
||||
|
||||
typedef unsigned long long BiggestConvertible; // NOLINT
|
||||
const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
|
||||
|
||||
#endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
|
||||
// BiggestConvertible is the largest integer type that system-provided
|
||||
// string-to-number conversion routines can return.
|
||||
using BiggestConvertible = unsigned long long; // NOLINT
|
||||
|
||||
const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); // NOLINT
|
||||
const bool parse_success = *end == '\0' && errno == 0;
|
||||
|
||||
GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
|
||||
|
@ -1074,7 +1089,8 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
}
|
||||
|
||||
~SocketWriter() override {
|
||||
if (sockfd_ != -1) CloseConnection();
|
||||
if (sockfd_ != -1)
|
||||
CloseConnection();
|
||||
}
|
||||
|
||||
// Sends a string to the socket.
|
||||
|
@ -1084,8 +1100,9 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
|
||||
const auto len = static_cast<size_t>(message.length());
|
||||
if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
|
||||
GTEST_LOG_(WARNING) << "stream_result_to: failed to stream to "
|
||||
<< host_name_ << ":" << port_num_;
|
||||
GTEST_LOG_(WARNING)
|
||||
<< "stream_result_to: failed to stream to "
|
||||
<< host_name_ << ":" << port_num_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1118,9 +1135,7 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
}
|
||||
|
||||
explicit StreamingListener(AbstractSocketWriter* socket_writer)
|
||||
: socket_writer_(socket_writer) {
|
||||
Start();
|
||||
}
|
||||
: socket_writer_(socket_writer) { Start(); }
|
||||
|
||||
void OnTestProgramStart(const UnitTest& /* unit_test */) override {
|
||||
SendLn("event=TestProgramStart");
|
||||
|
@ -1143,19 +1158,19 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
|
||||
void OnTestIterationEnd(const UnitTest& unit_test,
|
||||
int /* iteration */) override {
|
||||
SendLn("event=TestIterationEnd&passed=" + FormatBool(unit_test.Passed()) +
|
||||
"&elapsed_time=" + StreamableToString(unit_test.elapsed_time()) +
|
||||
"ms");
|
||||
SendLn("event=TestIterationEnd&passed=" +
|
||||
FormatBool(unit_test.Passed()) + "&elapsed_time=" +
|
||||
StreamableToString(unit_test.elapsed_time()) + "ms");
|
||||
}
|
||||
|
||||
// Note that "event=TestCaseStart" is a wire format and has to remain
|
||||
// "case" for compatibilty
|
||||
// "case" for compatibility
|
||||
void OnTestCaseStart(const TestCase& test_case) override {
|
||||
SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
|
||||
}
|
||||
|
||||
// Note that "event=TestCaseEnd" is a wire format and has to remain
|
||||
// "case" for compatibilty
|
||||
// "case" for compatibility
|
||||
void OnTestCaseEnd(const TestCase& test_case) override {
|
||||
SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) +
|
||||
"&elapsed_time=" + StreamableToString(test_case.elapsed_time()) +
|
||||
|
@ -1168,16 +1183,17 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
|
||||
void OnTestEnd(const TestInfo& test_info) override {
|
||||
SendLn("event=TestEnd&passed=" +
|
||||
FormatBool((test_info.result())->Passed()) + "&elapsed_time=" +
|
||||
FormatBool((test_info.result())->Passed()) +
|
||||
"&elapsed_time=" +
|
||||
StreamableToString((test_info.result())->elapsed_time()) + "ms");
|
||||
}
|
||||
|
||||
void OnTestPartResult(const TestPartResult& test_part_result) override {
|
||||
const char* file_name = test_part_result.file_name();
|
||||
if (file_name == nullptr) file_name = "";
|
||||
SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + "&line=" +
|
||||
StreamableToString(test_part_result.line_number()) + "&message=" +
|
||||
UrlEncode(test_part_result.message()));
|
||||
SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
|
||||
"&line=" + StreamableToString(test_part_result.line_number()) +
|
||||
"&message=" + UrlEncode(test_part_result.message()));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1202,4 +1218,4 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#endif // GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
|
|
|
@ -58,40 +58,40 @@ Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
|
|||
// s.
|
||||
Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const absl::string_view&>::Matcher(const std::string& s) {
|
||||
Matcher<const internal::StringView&>::Matcher(const std::string& s) {
|
||||
*this = Eq(s);
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const absl::string_view&>::Matcher(const char* s) {
|
||||
Matcher<const internal::StringView&>::Matcher(const char* s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const absl::string_view&>::Matcher(absl::string_view s) {
|
||||
Matcher<const internal::StringView&>::Matcher(internal::StringView s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<absl::string_view>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||
Matcher<internal::StringView>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||
|
||||
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<absl::string_view>::Matcher(const char* s) {
|
||||
Matcher<internal::StringView>::Matcher(const char* s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<absl::string_view>::Matcher(absl::string_view s) {
|
||||
Matcher<internal::StringView>::Matcher(internal::StringView s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
} // namespace testing
|
||||
|
|
|
@ -27,55 +27,57 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <sys/stat.h>
|
||||
#include <map> // Used in ThreadLocal.
|
||||
#ifdef _MSC_VER
|
||||
#include <crtdbg.h>
|
||||
#endif // _MSC_VER
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# include <sys/stat.h>
|
||||
# include <map> // Used in ThreadLocal.
|
||||
# ifdef _MSC_VER
|
||||
# include <crtdbg.h>
|
||||
# endif // _MSC_VER
|
||||
#else
|
||||
#include <unistd.h>
|
||||
# include <unistd.h>
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#if GTEST_OS_MAC
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach/vm_map.h>
|
||||
# include <mach/mach_init.h>
|
||||
# include <mach/task.h>
|
||||
# include <mach/vm_map.h>
|
||||
#endif // GTEST_OS_MAC
|
||||
|
||||
#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
|
||||
GTEST_OS_NETBSD || GTEST_OS_OPENBSD
|
||||
#include <sys/sysctl.h>
|
||||
#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
# include <sys/sysctl.h>
|
||||
# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
|
||||
# include <sys/user.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if GTEST_OS_QNX
|
||||
#include <devctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/procfs.h>
|
||||
# include <devctl.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/procfs.h>
|
||||
#endif // GTEST_OS_QNX
|
||||
|
||||
#if GTEST_OS_AIX
|
||||
#include <procinfo.h>
|
||||
#include <sys/types.h>
|
||||
# include <procinfo.h>
|
||||
# include <sys/types.h>
|
||||
#endif // GTEST_OS_AIX
|
||||
|
||||
#if GTEST_OS_FUCHSIA
|
||||
#include <zircon/process.h>
|
||||
#include <zircon/syscalls.h>
|
||||
# include <zircon/process.h>
|
||||
# include <zircon/syscalls.h>
|
||||
#endif // GTEST_OS_FUCHSIA
|
||||
|
||||
#include "gtest/gtest-spi.h"
|
||||
|
@ -129,7 +131,8 @@ size_t GetThreadCount() {
|
|||
if (status == KERN_SUCCESS) {
|
||||
// task_threads allocates resources in thread_list and we need to free them
|
||||
// to avoid leaks.
|
||||
vm_deallocate(task, reinterpret_cast<vm_address_t>(thread_list),
|
||||
vm_deallocate(task,
|
||||
reinterpret_cast<vm_address_t>(thread_list),
|
||||
sizeof(thread_t) * thread_count);
|
||||
return static_cast<size_t>(thread_count);
|
||||
} else {
|
||||
|
@ -138,7 +141,7 @@ size_t GetThreadCount() {
|
|||
}
|
||||
|
||||
#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
|
||||
GTEST_OS_NETBSD
|
||||
GTEST_OS_NETBSD
|
||||
|
||||
#if GTEST_OS_NETBSD
|
||||
#undef KERN_PROC
|
||||
|
@ -181,12 +184,12 @@ size_t GetThreadCount() {
|
|||
// we cannot detect it.
|
||||
size_t GetThreadCount() {
|
||||
int mib[] = {
|
||||
CTL_KERN,
|
||||
KERN_PROC,
|
||||
KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
|
||||
getpid(),
|
||||
sizeof(struct kinfo_proc),
|
||||
0,
|
||||
CTL_KERN,
|
||||
KERN_PROC,
|
||||
KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
|
||||
getpid(),
|
||||
sizeof(struct kinfo_proc),
|
||||
0,
|
||||
};
|
||||
u_int miblen = sizeof(mib) / sizeof(mib[0]);
|
||||
|
||||
|
@ -195,7 +198,8 @@ size_t GetThreadCount() {
|
|||
if (sysctl(mib, miblen, NULL, &size, NULL, 0)) {
|
||||
return 0;
|
||||
}
|
||||
mib[5] = size / mib[4];
|
||||
|
||||
mib[5] = static_cast<int>(size / static_cast<size_t>(mib[4]));
|
||||
|
||||
// populate array of structs
|
||||
struct kinfo_proc info[mib[5]];
|
||||
|
@ -204,9 +208,10 @@ size_t GetThreadCount() {
|
|||
}
|
||||
|
||||
// exclude empty members
|
||||
int nthreads = 0;
|
||||
for (int i = 0; i < size / mib[4]; i++) {
|
||||
if (info[i].p_tid != -1) nthreads++;
|
||||
size_t nthreads = 0;
|
||||
for (size_t i = 0; i < size / static_cast<size_t>(mib[4]); i++) {
|
||||
if (info[i].p_tid != -1)
|
||||
nthreads++;
|
||||
}
|
||||
return nthreads;
|
||||
}
|
||||
|
@ -249,9 +254,13 @@ size_t GetThreadCount() {
|
|||
size_t GetThreadCount() {
|
||||
int dummy_buffer;
|
||||
size_t avail;
|
||||
zx_status_t status =
|
||||
zx_object_get_info(zx_process_self(), ZX_INFO_PROCESS_THREADS,
|
||||
&dummy_buffer, 0, nullptr, &avail);
|
||||
zx_status_t status = zx_object_get_info(
|
||||
zx_process_self(),
|
||||
ZX_INFO_PROCESS_THREADS,
|
||||
&dummy_buffer,
|
||||
0,
|
||||
nullptr,
|
||||
&avail);
|
||||
if (status == ZX_OK) {
|
||||
return avail;
|
||||
} else {
|
||||
|
@ -271,17 +280,27 @@ size_t GetThreadCount() {
|
|||
|
||||
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
||||
|
||||
void SleepMilliseconds(int n) { ::Sleep(static_cast<DWORD>(n)); }
|
||||
void SleepMilliseconds(int n) {
|
||||
::Sleep(static_cast<DWORD>(n));
|
||||
}
|
||||
|
||||
AutoHandle::AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
|
||||
AutoHandle::AutoHandle()
|
||||
: handle_(INVALID_HANDLE_VALUE) {}
|
||||
|
||||
AutoHandle::AutoHandle(Handle handle) : handle_(handle) {}
|
||||
AutoHandle::AutoHandle(Handle handle)
|
||||
: handle_(handle) {}
|
||||
|
||||
AutoHandle::~AutoHandle() { Reset(); }
|
||||
AutoHandle::~AutoHandle() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
AutoHandle::Handle AutoHandle::Get() const { return handle_; }
|
||||
AutoHandle::Handle AutoHandle::Get() const {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
void AutoHandle::Reset() { Reset(INVALID_HANDLE_VALUE); }
|
||||
void AutoHandle::Reset() {
|
||||
Reset(INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
void AutoHandle::Reset(HANDLE handle) {
|
||||
// Resetting with the same handle we already own is invalid.
|
||||
|
@ -293,7 +312,7 @@ void AutoHandle::Reset(HANDLE handle) {
|
|||
} else {
|
||||
GTEST_CHECK_(!IsCloseable())
|
||||
<< "Resetting a valid handle to itself is likely a programmer error "
|
||||
"and thus not allowed.";
|
||||
"and thus not allowed.";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,10 +330,13 @@ Notification::Notification()
|
|||
GTEST_CHECK_(event_.Get() != nullptr);
|
||||
}
|
||||
|
||||
void Notification::Notify() { GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE); }
|
||||
void Notification::Notify() {
|
||||
GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
|
||||
}
|
||||
|
||||
void Notification::WaitForNotification() {
|
||||
GTEST_CHECK_(::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
|
||||
GTEST_CHECK_(
|
||||
::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
Mutex::Mutex()
|
||||
|
@ -369,7 +391,8 @@ namespace {
|
|||
// MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
// critical_section_ = new CRITICAL_SECTION;
|
||||
//
|
||||
class MemoryIsNotDeallocated {
|
||||
class MemoryIsNotDeallocated
|
||||
{
|
||||
public:
|
||||
MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
|
||||
old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||
|
@ -403,7 +426,7 @@ void Mutex::ThreadSafeLazyInit() {
|
|||
// are the first to test it and need to perform the initialization.
|
||||
owner_thread_id_ = 0;
|
||||
{
|
||||
// Use RAII to flag that following mem alloc is never deallocated.
|
||||
// Use RAII to flag that following mem alloc is never deallocated.
|
||||
#ifdef _MSC_VER
|
||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
#endif // _MSC_VER
|
||||
|
@ -412,13 +435,15 @@ void Mutex::ThreadSafeLazyInit() {
|
|||
::InitializeCriticalSection(critical_section_);
|
||||
// Updates the critical_section_init_phase_ to 2 to signal
|
||||
// initialization complete.
|
||||
GTEST_CHECK_(::InterlockedCompareExchange(&critical_section_init_phase_,
|
||||
2L, 1L) == 1L);
|
||||
GTEST_CHECK_(::InterlockedCompareExchange(
|
||||
&critical_section_init_phase_, 2L, 1L) ==
|
||||
1L);
|
||||
break;
|
||||
case 1:
|
||||
// Somebody else is already initializing the mutex; spin until they
|
||||
// are done.
|
||||
while (::InterlockedCompareExchange(&critical_section_init_phase_, 2L,
|
||||
while (::InterlockedCompareExchange(&critical_section_init_phase_,
|
||||
2L,
|
||||
2L) != 2L) {
|
||||
// Possibly yields the rest of the thread's time slice to other
|
||||
// threads.
|
||||
|
@ -452,8 +477,8 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
|||
param, // Parameter to ThreadMainStatic
|
||||
0x0, // Default creation flags.
|
||||
&thread_id); // Need a valid pointer for the call to work under Win98.
|
||||
GTEST_CHECK_(thread_handle != nullptr) << "CreateThread failed with error "
|
||||
<< ::GetLastError() << ".";
|
||||
GTEST_CHECK_(thread_handle != nullptr)
|
||||
<< "CreateThread failed with error " << ::GetLastError() << ".";
|
||||
if (thread_handle == nullptr) {
|
||||
delete param;
|
||||
}
|
||||
|
@ -463,7 +488,9 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
|||
private:
|
||||
struct ThreadMainParam {
|
||||
ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
|
||||
: runnable_(runnable), thread_can_start_(thread_can_start) {}
|
||||
: runnable_(runnable),
|
||||
thread_can_start_(thread_can_start) {
|
||||
}
|
||||
std::unique_ptr<Runnable> runnable_;
|
||||
// Does not own.
|
||||
Notification* thread_can_start_;
|
||||
|
@ -486,12 +513,15 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
|||
|
||||
} // namespace
|
||||
|
||||
ThreadWithParamBase::ThreadWithParamBase(Runnable* runnable,
|
||||
ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable,
|
||||
Notification* thread_can_start)
|
||||
: thread_(
|
||||
ThreadWithParamSupport::CreateThread(runnable, thread_can_start)) {}
|
||||
: thread_(ThreadWithParamSupport::CreateThread(runnable,
|
||||
thread_can_start)) {
|
||||
}
|
||||
|
||||
ThreadWithParamBase::~ThreadWithParamBase() { Join(); }
|
||||
ThreadWithParamBase::~ThreadWithParamBase() {
|
||||
Join();
|
||||
}
|
||||
|
||||
void ThreadWithParamBase::Join() {
|
||||
GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
|
||||
|
@ -508,6 +538,9 @@ class ThreadLocalRegistryImpl {
|
|||
// Returns a value that can be used to identify the thread from other threads.
|
||||
static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
|
||||
const ThreadLocalBase* thread_local_instance) {
|
||||
#ifdef _MSC_VER
|
||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
#endif // _MSC_VER
|
||||
DWORD current_thread = ::GetCurrentThreadId();
|
||||
MutexLock lock(&mutex_);
|
||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||
|
@ -515,10 +548,8 @@ class ThreadLocalRegistryImpl {
|
|||
ThreadIdToThreadLocals::iterator thread_local_pos =
|
||||
thread_to_thread_locals->find(current_thread);
|
||||
if (thread_local_pos == thread_to_thread_locals->end()) {
|
||||
thread_local_pos =
|
||||
thread_to_thread_locals
|
||||
->insert(std::make_pair(current_thread, ThreadLocalValues()))
|
||||
.first;
|
||||
thread_local_pos = thread_to_thread_locals->insert(
|
||||
std::make_pair(current_thread, ThreadLocalValues())).first;
|
||||
StartWatcherThreadFor(current_thread);
|
||||
}
|
||||
ThreadLocalValues& thread_local_values = thread_local_pos->second;
|
||||
|
@ -546,8 +577,9 @@ class ThreadLocalRegistryImpl {
|
|||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||
GetThreadLocalsMapLocked();
|
||||
for (ThreadIdToThreadLocals::iterator it =
|
||||
thread_to_thread_locals->begin();
|
||||
it != thread_to_thread_locals->end(); ++it) {
|
||||
thread_to_thread_locals->begin();
|
||||
it != thread_to_thread_locals->end();
|
||||
++it) {
|
||||
ThreadLocalValues& thread_local_values = it->second;
|
||||
ThreadLocalValues::iterator value_pos =
|
||||
thread_local_values.find(thread_local_instance);
|
||||
|
@ -577,8 +609,9 @@ class ThreadLocalRegistryImpl {
|
|||
if (thread_local_pos != thread_to_thread_locals->end()) {
|
||||
ThreadLocalValues& thread_local_values = thread_local_pos->second;
|
||||
for (ThreadLocalValues::iterator value_pos =
|
||||
thread_local_values.begin();
|
||||
value_pos != thread_local_values.end(); ++value_pos) {
|
||||
thread_local_values.begin();
|
||||
value_pos != thread_local_values.end();
|
||||
++value_pos) {
|
||||
value_holders.push_back(value_pos->second);
|
||||
}
|
||||
thread_to_thread_locals->erase(thread_local_pos);
|
||||
|
@ -604,8 +637,9 @@ class ThreadLocalRegistryImpl {
|
|||
static void StartWatcherThreadFor(DWORD thread_id) {
|
||||
// The returned handle will be kept in thread_map and closed by
|
||||
// watcher_thread in WatcherThreadFunc.
|
||||
HANDLE thread =
|
||||
::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id);
|
||||
HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
|
||||
FALSE,
|
||||
thread_id);
|
||||
GTEST_CHECK_(thread != nullptr);
|
||||
// We need to pass a valid thread ID pointer into CreateThread for it
|
||||
// to work correctly under Win98.
|
||||
|
@ -630,7 +664,8 @@ class ThreadLocalRegistryImpl {
|
|||
static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
|
||||
const ThreadIdAndHandle* tah =
|
||||
reinterpret_cast<const ThreadIdAndHandle*>(param);
|
||||
GTEST_CHECK_(::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
|
||||
GTEST_CHECK_(
|
||||
::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
|
||||
OnThreadExit(tah->first);
|
||||
::CloseHandle(tah->second);
|
||||
delete tah;
|
||||
|
@ -653,17 +688,17 @@ class ThreadLocalRegistryImpl {
|
|||
static Mutex thread_map_mutex_;
|
||||
};
|
||||
|
||||
Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);
|
||||
Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex);
|
||||
Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex); // NOLINT
|
||||
Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex); // NOLINT
|
||||
|
||||
ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
|
||||
const ThreadLocalBase* thread_local_instance) {
|
||||
const ThreadLocalBase* thread_local_instance) {
|
||||
return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
|
||||
thread_local_instance);
|
||||
}
|
||||
|
||||
void ThreadLocalRegistry::OnThreadLocalDestroyed(
|
||||
const ThreadLocalBase* thread_local_instance) {
|
||||
const ThreadLocalBase* thread_local_instance) {
|
||||
ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
|
||||
}
|
||||
|
||||
|
@ -751,7 +786,7 @@ bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
|
|||
bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
|
||||
bool IsAsciiWordChar(char ch) {
|
||||
return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
|
||||
('0' <= ch && ch <= '9') || ch == '_';
|
||||
('0' <= ch && ch <= '9') || ch == '_';
|
||||
}
|
||||
|
||||
// Returns true if and only if "\\c" is a supported escape sequence.
|
||||
|
@ -764,28 +799,17 @@ bool IsValidEscape(char c) {
|
|||
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
||||
if (escaped) { // "\\p" where p is pattern_char.
|
||||
switch (pattern_char) {
|
||||
case 'd':
|
||||
return IsAsciiDigit(ch);
|
||||
case 'D':
|
||||
return !IsAsciiDigit(ch);
|
||||
case 'f':
|
||||
return ch == '\f';
|
||||
case 'n':
|
||||
return ch == '\n';
|
||||
case 'r':
|
||||
return ch == '\r';
|
||||
case 's':
|
||||
return IsAsciiWhiteSpace(ch);
|
||||
case 'S':
|
||||
return !IsAsciiWhiteSpace(ch);
|
||||
case 't':
|
||||
return ch == '\t';
|
||||
case 'v':
|
||||
return ch == '\v';
|
||||
case 'w':
|
||||
return IsAsciiWordChar(ch);
|
||||
case 'W':
|
||||
return !IsAsciiWordChar(ch);
|
||||
case 'd': return IsAsciiDigit(ch);
|
||||
case 'D': return !IsAsciiDigit(ch);
|
||||
case 'f': return ch == '\f';
|
||||
case 'n': return ch == '\n';
|
||||
case 'r': return ch == '\r';
|
||||
case 's': return IsAsciiWhiteSpace(ch);
|
||||
case 'S': return !IsAsciiWhiteSpace(ch);
|
||||
case 't': return ch == '\t';
|
||||
case 'v': return ch == '\v';
|
||||
case 'w': return IsAsciiWordChar(ch);
|
||||
case 'W': return !IsAsciiWordChar(ch);
|
||||
}
|
||||
return IsAsciiPunct(pattern_char) && pattern_char == ch;
|
||||
}
|
||||
|
@ -796,8 +820,7 @@ bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
|||
// Helper function used by ValidateRegex() to format error messages.
|
||||
static std::string FormatRegexSyntaxError(const char* regex, int index) {
|
||||
return (Message() << "Syntax error at index " << index
|
||||
<< " in simple regular expression \"" << regex << "\": ")
|
||||
.GetString();
|
||||
<< " in simple regular expression \"" << regex << "\": ").GetString();
|
||||
}
|
||||
|
||||
// Generates non-fatal failures and returns false if regex is invalid;
|
||||
|
@ -839,12 +862,12 @@ bool ValidateRegex(const char* regex) {
|
|||
<< "'$' can only appear at the end.";
|
||||
is_valid = false;
|
||||
} else if (IsInSet(ch, "()[]{}|")) {
|
||||
ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'" << ch
|
||||
<< "' is unsupported.";
|
||||
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
|
||||
<< "'" << ch << "' is unsupported.";
|
||||
is_valid = false;
|
||||
} else if (IsRepeat(ch) && !prev_repeatable) {
|
||||
ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'" << ch
|
||||
<< "' can only follow a repeatable token.";
|
||||
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
|
||||
<< "'" << ch << "' can only follow a repeatable token.";
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
|
@ -862,10 +885,12 @@ bool ValidateRegex(const char* regex) {
|
|||
// characters to be indexable by size_t, in which case the test will
|
||||
// probably time out anyway. We are fine with this limitation as
|
||||
// std::string has it too.
|
||||
bool MatchRepetitionAndRegexAtHead(bool escaped, char c, char repeat,
|
||||
const char* regex, const char* str) {
|
||||
bool MatchRepetitionAndRegexAtHead(
|
||||
bool escaped, char c, char repeat, const char* regex,
|
||||
const char* str) {
|
||||
const size_t min_count = (repeat == '+') ? 1 : 0;
|
||||
const size_t max_count = (repeat == '?') ? 1 : static_cast<size_t>(-1) - 1;
|
||||
const size_t max_count = (repeat == '?') ? 1 :
|
||||
static_cast<size_t>(-1) - 1;
|
||||
// We cannot call numeric_limits::max() as it conflicts with the
|
||||
// max() macro on Windows.
|
||||
|
||||
|
@ -878,7 +903,8 @@ bool MatchRepetitionAndRegexAtHead(bool escaped, char c, char repeat,
|
|||
// greedy match.
|
||||
return true;
|
||||
}
|
||||
if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) return false;
|
||||
if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -892,23 +918,25 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
|
|||
|
||||
// "$" only matches the end of a string. Note that regex being
|
||||
// valid guarantees that there's nothing after "$" in it.
|
||||
if (*regex == '$') return *str == '\0';
|
||||
if (*regex == '$')
|
||||
return *str == '\0';
|
||||
|
||||
// Is the first thing in regex an escape sequence?
|
||||
const bool escaped = *regex == '\\';
|
||||
if (escaped) ++regex;
|
||||
if (escaped)
|
||||
++regex;
|
||||
if (IsRepeat(regex[1])) {
|
||||
// MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
|
||||
// here's an indirect recursion. It terminates as the regex gets
|
||||
// shorter in each recursion.
|
||||
return MatchRepetitionAndRegexAtHead(escaped, regex[0], regex[1], regex + 2,
|
||||
str);
|
||||
return MatchRepetitionAndRegexAtHead(
|
||||
escaped, regex[0], regex[1], regex + 2, str);
|
||||
} else {
|
||||
// regex isn't empty, isn't "$", and doesn't start with a
|
||||
// repetition. We match the first atom of regex with the first
|
||||
// character of str and recurse.
|
||||
return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
|
||||
MatchRegexAtHead(regex + 1, str + 1);
|
||||
MatchRegexAtHead(regex + 1, str + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -923,11 +951,13 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
|
|||
bool MatchRegexAnywhere(const char* regex, const char* str) {
|
||||
if (regex == nullptr || str == nullptr) return false;
|
||||
|
||||
if (*regex == '^') return MatchRegexAtHead(regex + 1, str);
|
||||
if (*regex == '^')
|
||||
return MatchRegexAtHead(regex + 1, str);
|
||||
|
||||
// A successful match can be anywhere in str.
|
||||
do {
|
||||
if (MatchRegexAtHead(regex, str)) return true;
|
||||
if (MatchRegexAtHead(regex, str))
|
||||
return true;
|
||||
} while (*str++ != '\0');
|
||||
return false;
|
||||
}
|
||||
|
@ -990,7 +1020,7 @@ const char kUnknownFile[] = "unknown file";
|
|||
|
||||
// Formats a source file path and a line number as they would appear
|
||||
// in an error message from the compiler used to compile this code.
|
||||
GTEST_API_::std::string FormatFileLocation(const char* file, int line) {
|
||||
GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
|
||||
const std::string file_name(file == nullptr ? kUnknownFile : file);
|
||||
|
||||
if (line < 0) {
|
||||
|
@ -1008,8 +1038,8 @@ GTEST_API_::std::string FormatFileLocation(const char* file, int line) {
|
|||
// FormatFileLocation in order to contrast the two functions.
|
||||
// Note that FormatCompilerIndependentFileLocation() does NOT append colon
|
||||
// to the file location it produces, unlike FormatFileLocation().
|
||||
GTEST_API_::std::string FormatCompilerIndependentFileLocation(const char* file,
|
||||
int line) {
|
||||
GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
|
||||
const char* file, int line) {
|
||||
const std::string file_name(file == nullptr ? kUnknownFile : file);
|
||||
|
||||
if (line < 0)
|
||||
|
@ -1021,14 +1051,11 @@ GTEST_API_::std::string FormatCompilerIndependentFileLocation(const char* file,
|
|||
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
|
||||
: severity_(severity) {
|
||||
const char* const marker =
|
||||
severity == GTEST_INFO
|
||||
? "[ INFO ]"
|
||||
: severity == GTEST_WARNING
|
||||
? "[WARNING]"
|
||||
: severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
|
||||
GetStream() << ::std::endl
|
||||
<< marker << " " << FormatFileLocation(file, line).c_str()
|
||||
<< ": ";
|
||||
severity == GTEST_INFO ? "[ INFO ]" :
|
||||
severity == GTEST_WARNING ? "[WARNING]" :
|
||||
severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
|
||||
GetStream() << ::std::endl << marker << " "
|
||||
<< FormatFileLocation(file, line).c_str() << ": ";
|
||||
}
|
||||
|
||||
// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
|
||||
|
@ -1051,26 +1078,27 @@ class CapturedStream {
|
|||
public:
|
||||
// The ctor redirects the stream to a temporary file.
|
||||
explicit 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
|
||||
# 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);
|
||||
const UINT success = ::GetTempFileNameA(temp_dir_path, "gtest_redir",
|
||||
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;
|
||||
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. We use /tmp on most systems, and /sdcard on Android.
|
||||
// That's because Android doesn't have /tmp.
|
||||
#if GTEST_OS_LINUX_ANDROID
|
||||
# else
|
||||
// There's no guarantee that a test has write access to the current
|
||||
// directory, so we create the temporary file in a temporary directory.
|
||||
std::string name_template;
|
||||
|
||||
# if GTEST_OS_LINUX_ANDROID
|
||||
// Note: Android applications are expected to call the framework's
|
||||
// Context.getExternalStorageDirectory() method through JNI to get
|
||||
// the location of the world-writable SD Card directory. However,
|
||||
|
@ -1082,24 +1110,55 @@ class CapturedStream {
|
|||
// The location /data/local/tmp is directly accessible from native code.
|
||||
// '/sdcard' and other variants cannot be relied on, as they are not
|
||||
// guaranteed to be mounted, or may have a delay in mounting.
|
||||
char name_template[] = "/data/local/tmp/gtest_captured_stream.XXXXXX";
|
||||
#else
|
||||
char name_template[] = "/tmp/captured_stream.XXXXXX";
|
||||
#endif // GTEST_OS_LINUX_ANDROID
|
||||
const int captured_fd = mkstemp(name_template);
|
||||
name_template = "/data/local/tmp/";
|
||||
# elif GTEST_OS_IOS
|
||||
char user_temp_dir[PATH_MAX + 1];
|
||||
|
||||
// Documented alternative to NSTemporaryDirectory() (for obtaining creating
|
||||
// a temporary directory) at
|
||||
// https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
|
||||
//
|
||||
// _CS_DARWIN_USER_TEMP_DIR (as well as _CS_DARWIN_USER_CACHE_DIR) is not
|
||||
// documented in the confstr() man page at
|
||||
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/confstr.3.html#//apple_ref/doc/man/3/confstr
|
||||
// but are still available, according to the WebKit patches at
|
||||
// https://trac.webkit.org/changeset/262004/webkit
|
||||
// https://trac.webkit.org/changeset/263705/webkit
|
||||
//
|
||||
// The confstr() implementation falls back to getenv("TMPDIR"). See
|
||||
// https://opensource.apple.com/source/Libc/Libc-1439.100.3/gen/confstr.c.auto.html
|
||||
::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir, sizeof(user_temp_dir));
|
||||
|
||||
name_template = user_temp_dir;
|
||||
if (name_template.back() != GTEST_PATH_SEP_[0])
|
||||
name_template.push_back(GTEST_PATH_SEP_[0]);
|
||||
# else
|
||||
name_template = "/tmp/";
|
||||
# endif
|
||||
name_template.append("gtest_captured_stream.XXXXXX");
|
||||
|
||||
// mkstemp() modifies the string bytes in place, and does not go beyond the
|
||||
// string's length. This results in well-defined behavior in C++17.
|
||||
//
|
||||
// The const_cast is needed below C++17. The constraints on std::string
|
||||
// implementations in C++11 and above make assumption behind the const_cast
|
||||
// fairly safe.
|
||||
const int captured_fd = ::mkstemp(const_cast<char*>(name_template.data()));
|
||||
if (captured_fd == -1) {
|
||||
GTEST_LOG_(WARNING)
|
||||
<< "Failed to create tmp file " << name_template
|
||||
<< " for test; does the test have access to the /tmp directory?";
|
||||
}
|
||||
filename_ = name_template;
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
filename_ = std::move(name_template);
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
fflush(nullptr);
|
||||
dup2(captured_fd, fd_);
|
||||
close(captured_fd);
|
||||
}
|
||||
|
||||
~CapturedStream() { remove(filename_.c_str()); }
|
||||
~CapturedStream() {
|
||||
remove(filename_.c_str());
|
||||
}
|
||||
|
||||
std::string GetCapturedString() {
|
||||
if (uncaptured_fd_ != -1) {
|
||||
|
@ -1176,6 +1235,10 @@ std::string GetCapturedStderr() {
|
|||
|
||||
#endif // GTEST_HAS_STREAM_REDIRECTION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
size_t GetFileSize(FILE* file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
return static_cast<size_t>(ftell(file));
|
||||
|
@ -1193,8 +1256,7 @@ std::string ReadEntireFile(FILE* file) {
|
|||
// Keeps reading the file until we cannot read further or the
|
||||
// pre-determined file size is reached.
|
||||
do {
|
||||
bytes_last_read =
|
||||
fread(buffer + bytes_read, 1, file_size - bytes_read, file);
|
||||
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
|
||||
bytes_read += bytes_last_read;
|
||||
} while (bytes_last_read > 0 && bytes_read < file_size);
|
||||
|
||||
|
@ -1258,7 +1320,7 @@ static std::string FlagToEnvVar(const char* flag) {
|
|||
// Parses 'str' for a 32-bit signed integer. If successful, writes
|
||||
// the result to *value and returns true; otherwise leaves *value
|
||||
// unchanged and returns false.
|
||||
bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
|
||||
bool ParseInt32(const Message& src_text, const char* str, int32_t* value) {
|
||||
// Parses the environment variable as a decimal integer.
|
||||
char* end = nullptr;
|
||||
const long long_value = strtol(str, &end, 10); // NOLINT
|
||||
|
@ -1275,13 +1337,13 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Is the parsed value in the range of an Int32?
|
||||
const Int32 result = static_cast<Int32>(long_value);
|
||||
// Is the parsed value in the range of an int32_t?
|
||||
const auto result = static_cast<int32_t>(long_value);
|
||||
if (long_value == LONG_MAX || long_value == LONG_MIN ||
|
||||
// The parsed value overflows as a long. (strtol() returns
|
||||
// LONG_MAX or LONG_MIN when the input overflows.)
|
||||
result != long_value
|
||||
// The parsed value overflows as an Int32.
|
||||
// The parsed value overflows as an int32_t.
|
||||
) {
|
||||
Message msg;
|
||||
msg << "WARNING: " << src_text
|
||||
|
@ -1314,7 +1376,7 @@ bool BoolFromGTestEnv(const char* flag, bool default_value) {
|
|||
// Reads and returns a 32-bit integer stored in the environment
|
||||
// variable corresponding to the given flag; if it isn't set or
|
||||
// doesn't represent a valid 32-bit integer, returns default_value.
|
||||
Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
||||
int32_t Int32FromGTestEnv(const char* flag, int32_t default_value) {
|
||||
#if defined(GTEST_GET_INT32_FROM_ENV_)
|
||||
return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
|
||||
#else
|
||||
|
@ -1325,9 +1387,9 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
|||
return default_value;
|
||||
}
|
||||
|
||||
Int32 result = default_value;
|
||||
if (!ParseInt32(Message() << "Environment variable " << env_var, string_value,
|
||||
&result)) {
|
||||
int32_t result = default_value;
|
||||
if (!ParseInt32(Message() << "Environment variable " << env_var,
|
||||
string_value, &result)) {
|
||||
printf("The default value %s is used.\n",
|
||||
(Message() << default_value).GetString().c_str());
|
||||
fflush(stdout);
|
||||
|
@ -1346,7 +1408,7 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
|||
// not check that the flag is 'output'
|
||||
// In essence this checks an env variable called XML_OUTPUT_FILE
|
||||
// and if it is set we prepend "xml:" to its value, if it not set we return ""
|
||||
std::string OutputFlagAlsoCheckEnvVar() {
|
||||
std::string OutputFlagAlsoCheckEnvVar(){
|
||||
std::string default_value_for_output_flag = "";
|
||||
const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
|
||||
if (nullptr != xml_output_file_env) {
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
// Google Test - The Google C++ Testing and Mocking Framework
|
||||
//
|
||||
// This file implements a universal value printer that can print a
|
||||
|
@ -41,11 +42,16 @@
|
|||
// defines Foo.
|
||||
|
||||
#include "gtest/gtest-printers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <cwchar>
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "src/gtest-internal-inl.h"
|
||||
|
||||
|
@ -95,15 +101,25 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
|||
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
|
||||
*os << " ... ";
|
||||
// Rounds up to 2-byte boundary.
|
||||
const size_t resume_pos = (count - kChunkSize + 1) / 2 * 2;
|
||||
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
|
||||
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
|
||||
}
|
||||
*os << ">";
|
||||
}
|
||||
|
||||
// Helpers for widening a character to char32_t. Since the standard does not
|
||||
// specify if char / wchar_t is signed or unsigned, it is important to first
|
||||
// convert it to the unsigned type of the same width before widening it to
|
||||
// char32_t.
|
||||
template <typename CharType>
|
||||
char32_t ToChar32(CharType in) {
|
||||
return static_cast<char32_t>(
|
||||
static_cast<typename std::make_unsigned<CharType>::type>(in));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace internal2 {
|
||||
namespace internal {
|
||||
|
||||
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
|
||||
// given object. The delegation simplifies the implementation, which
|
||||
|
@ -115,30 +131,29 @@ void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
|
|||
PrintBytesInObjectToImpl(obj_bytes, count, os);
|
||||
}
|
||||
|
||||
} // namespace internal2
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Depending on the value of a char (or wchar_t), we print it in one
|
||||
// of three formats:
|
||||
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
|
||||
// - as a hexadecimal escape sequence (e.g. '\x7F'), or
|
||||
// - as a special escape sequence (e.g. '\r', '\n').
|
||||
enum CharFormat { kAsIs, kHexEscape, kSpecialEscape };
|
||||
enum CharFormat {
|
||||
kAsIs,
|
||||
kHexEscape,
|
||||
kSpecialEscape
|
||||
};
|
||||
|
||||
// Returns true if c is a printable ASCII character. We test the
|
||||
// value of c directly instead of calling isprint(), which is buggy on
|
||||
// Windows Mobile.
|
||||
inline bool IsPrintableAscii(wchar_t c) { return 0x20 <= c && c <= 0x7E; }
|
||||
inline bool IsPrintableAscii(char32_t c) { return 0x20 <= c && c <= 0x7E; }
|
||||
|
||||
// Prints a wide or narrow char c as a character literal without the
|
||||
// quotes, escaping it when necessary; returns how c was formatted.
|
||||
// The template argument UnsignedChar is the unsigned version of Char,
|
||||
// which is the type of c.
|
||||
template <typename UnsignedChar, typename Char>
|
||||
// Prints c (of type char, char8_t, char16_t, char32_t, or wchar_t) as a
|
||||
// character literal without the quotes, escaping it when necessary; returns how
|
||||
// c was formatted.
|
||||
template <typename Char>
|
||||
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||
wchar_t w_c = static_cast<wchar_t>(c);
|
||||
switch (w_c) {
|
||||
const char32_t u_c = ToChar32(c);
|
||||
switch (u_c) {
|
||||
case L'\0':
|
||||
*os << "\\0";
|
||||
break;
|
||||
|
@ -170,13 +185,12 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
|||
*os << "\\v";
|
||||
break;
|
||||
default:
|
||||
if (IsPrintableAscii(w_c)) {
|
||||
if (IsPrintableAscii(u_c)) {
|
||||
*os << static_cast<char>(c);
|
||||
return kAsIs;
|
||||
} else {
|
||||
ostream::fmtflags flags = os->flags();
|
||||
*os << "\\x" << std::hex << std::uppercase
|
||||
<< static_cast<int>(static_cast<UnsignedChar>(c));
|
||||
*os << "\\x" << std::hex << std::uppercase << static_cast<int>(u_c);
|
||||
os->flags(flags);
|
||||
return kHexEscape;
|
||||
}
|
||||
|
@ -184,9 +198,9 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
|||
return kSpecialEscape;
|
||||
}
|
||||
|
||||
// Prints a wchar_t c as if it's part of a string literal, escaping it when
|
||||
// Prints a char32_t c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||
static CharFormat PrintAsStringLiteralTo(char32_t c, ostream* os) {
|
||||
switch (c) {
|
||||
case L'\'':
|
||||
*os << "'";
|
||||
|
@ -195,32 +209,75 @@ static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
|||
*os << "\\\"";
|
||||
return kSpecialEscape;
|
||||
default:
|
||||
return PrintAsCharLiteralTo<wchar_t>(c, os);
|
||||
return PrintAsCharLiteralTo(c, os);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(signed char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(unsigned char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
static const char* GetCharWidthPrefix(char8_t) {
|
||||
return "u8";
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* GetCharWidthPrefix(char16_t) {
|
||||
return "u";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(char32_t) {
|
||||
return "U";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(wchar_t) {
|
||||
return "L";
|
||||
}
|
||||
|
||||
// Prints a char c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(
|
||||
static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
// Prints a wide or narrow character c and its code. '\0' is printed
|
||||
// as "'\\0'", other unprintable characters are also properly escaped
|
||||
// using the standard C++ escape sequence. The template argument
|
||||
// UnsignedChar is the unsigned version of Char, which is the type of c.
|
||||
template <typename UnsignedChar, typename Char>
|
||||
#ifdef __cpp_char8_t
|
||||
static CharFormat PrintAsStringLiteralTo(char8_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
#endif
|
||||
|
||||
static CharFormat PrintAsStringLiteralTo(char16_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
// Prints a character c (of type char, char8_t, char16_t, char32_t, or wchar_t)
|
||||
// and its code. '\0' is printed as "'\\0'", other unprintable characters are
|
||||
// also properly escaped using the standard C++ escape sequence.
|
||||
template <typename Char>
|
||||
void PrintCharAndCodeTo(Char c, ostream* os) {
|
||||
// First, print c as a literal in the most readable form we can find.
|
||||
*os << ((sizeof(c) > 1) ? "L'" : "'");
|
||||
const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
|
||||
*os << GetCharWidthPrefix(c) << "'";
|
||||
const CharFormat format = PrintAsCharLiteralTo(c, os);
|
||||
*os << "'";
|
||||
|
||||
// To aid user debugging, we also print c's code in decimal, unless
|
||||
// it's 0 (in which case c was printed as '\\0', making the code
|
||||
// obvious).
|
||||
if (c == 0) return;
|
||||
if (c == 0)
|
||||
return;
|
||||
*os << " (" << static_cast<int>(c);
|
||||
|
||||
// For more convenience, we print c's code again in hexadecimal,
|
||||
|
@ -234,28 +291,32 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
|
|||
*os << ")";
|
||||
}
|
||||
|
||||
void PrintTo(unsigned char c, ::std::ostream* os) {
|
||||
PrintCharAndCodeTo<unsigned char>(c, os);
|
||||
}
|
||||
void PrintTo(signed char c, ::std::ostream* os) {
|
||||
PrintCharAndCodeTo<unsigned char>(c, os);
|
||||
}
|
||||
void PrintTo(unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
|
||||
void PrintTo(signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
|
||||
|
||||
// Prints a wchar_t as a symbol if it is printable or as its internal
|
||||
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
|
||||
void PrintTo(wchar_t wc, ostream* os) { PrintCharAndCodeTo<wchar_t>(wc, os); }
|
||||
void PrintTo(wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); }
|
||||
|
||||
// TODO(dcheng): Consider making this delegate to PrintCharAndCodeTo() as well.
|
||||
void PrintTo(char32_t c, ::std::ostream* os) {
|
||||
*os << std::hex << "U+" << std::uppercase << std::setfill('0') << std::setw(4)
|
||||
<< static_cast<uint32_t>(c);
|
||||
}
|
||||
|
||||
// Prints the given array of characters to the ostream. CharType must be either
|
||||
// char or wchar_t.
|
||||
// char, char8_t, char16_t, char32_t, or wchar_t.
|
||||
// The array starts at begin, the length is len, it may include '\0' characters
|
||||
// and may not be NUL-terminated.
|
||||
template <typename CharType>
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static CharFormat
|
||||
PrintCharsAsStringTo(const CharType* begin, size_t len, ostream* os) {
|
||||
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
||||
*os << kQuoteBegin;
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
static CharFormat PrintCharsAsStringTo(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
const char* const quote_prefix = GetCharWidthPrefix(*begin);
|
||||
*os << quote_prefix << "\"";
|
||||
bool is_previous_hex = false;
|
||||
CharFormat print_format = kAsIs;
|
||||
for (size_t index = 0; index < len; ++index) {
|
||||
|
@ -264,7 +325,7 @@ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
|||
// Previous character is of '\x..' form and this character can be
|
||||
// interpreted as another hexadecimal digit in its number. Break string to
|
||||
// disambiguate.
|
||||
*os << "\" " << kQuoteBegin;
|
||||
*os << "\" " << quote_prefix << "\"";
|
||||
}
|
||||
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
|
||||
// Remember if any characters required hex escaping.
|
||||
|
@ -279,11 +340,12 @@ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
|||
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
||||
// 'begin'. CharType must be either char or wchar_t.
|
||||
template <typename CharType>
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static void
|
||||
UniversalPrintCharArray(const CharType* begin, size_t len,
|
||||
ostream* os) {
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
static void UniversalPrintCharArray(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
// The code
|
||||
// const char kFoo[] = "foo";
|
||||
// generates an array of 4, not 3, elements, with the last one being '\0'.
|
||||
|
@ -309,22 +371,57 @@ void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
|
|||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
// Prints a (const) char8_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char8_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Prints a (const) char16_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char16_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints a (const) char32_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char32_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints a (const) wchar_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints the given C string to the ostream.
|
||||
void PrintTo(const char* s, ostream* os) {
|
||||
namespace {
|
||||
|
||||
// Prints a null-terminated C-style string to the ostream.
|
||||
template <typename Char>
|
||||
void PrintCStringTo(const Char* s, ostream* os) {
|
||||
if (s == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||
PrintCharsAsStringTo(s, strlen(s), os);
|
||||
PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void PrintTo(const char* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
void PrintTo(const char8_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
#endif
|
||||
|
||||
void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
// MSVC compiler can be configured to define whar_t as a typedef
|
||||
// of unsigned short. Defining an overload for const wchar_t* in that case
|
||||
// would cause pointers to unsigned shorts be printed as wide strings,
|
||||
|
@ -333,41 +430,34 @@ void PrintTo(const char* s, ostream* os) {
|
|||
// wchar_t is implemented as a native type.
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
// Prints the given wide C string to the ostream.
|
||||
void PrintTo(const wchar_t* s, ostream* os) {
|
||||
if (s == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||
PrintCharsAsStringTo(s, wcslen(s), os);
|
||||
}
|
||||
}
|
||||
void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
#endif // wchar_t is native
|
||||
|
||||
namespace {
|
||||
|
||||
bool ContainsUnprintableControlCodes(const char* str, size_t length) {
|
||||
const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
|
||||
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
unsigned char ch = *s++;
|
||||
if (std::iscntrl(ch)) {
|
||||
switch (ch) {
|
||||
switch (ch) {
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t <= 0xbf; }
|
||||
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
|
||||
|
||||
bool IsValidUTF8(const char* str, size_t length) {
|
||||
const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
|
||||
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
|
||||
|
||||
for (size_t i = 0; i < length;) {
|
||||
unsigned char lead = s[i++];
|
||||
|
@ -380,13 +470,15 @@ bool IsValidUTF8(const char* str, size_t length) {
|
|||
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
|
||||
++i; // 2-byte character
|
||||
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
|
||||
IsUTF8TrailByte(s[i]) && IsUTF8TrailByte(s[i + 1]) &&
|
||||
IsUTF8TrailByte(s[i]) &&
|
||||
IsUTF8TrailByte(s[i + 1]) &&
|
||||
// check for non-shortest form and surrogate
|
||||
(lead != 0xe0 || s[i] >= 0xa0) &&
|
||||
(lead != 0xed || s[i] < 0xa0)) {
|
||||
i += 2; // 3-byte character
|
||||
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
|
||||
IsUTF8TrailByte(s[i]) && IsUTF8TrailByte(s[i + 1]) &&
|
||||
IsUTF8TrailByte(s[i]) &&
|
||||
IsUTF8TrailByte(s[i + 1]) &&
|
||||
IsUTF8TrailByte(s[i + 2]) &&
|
||||
// check for non-shortest form
|
||||
(lead != 0xf0 || s[i] >= 0x90) &&
|
||||
|
@ -416,6 +508,20 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
|
||||
void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||
|
||||
#include "gtest/gtest-test-part.h"
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "src/gtest-internal-inl.h"
|
||||
|
||||
namespace testing {
|
||||
|
@ -46,7 +48,9 @@ std::string TestPartResult::ExtractSummary(const char* message) {
|
|||
|
||||
// Prints a TestPartResult object.
|
||||
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
||||
return os << result.file_name() << ":" << result.line_number() << ": "
|
||||
return os << internal::FormatFileLocation(result.file_name(),
|
||||
result.line_number())
|
||||
<< " "
|
||||
<< (result.type() == TestPartResult::kSuccess
|
||||
? "Success"
|
||||
: result.type() == TestPartResult::kSkip
|
||||
|
@ -82,8 +86,8 @@ namespace internal {
|
|||
|
||||
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
|
||||
: has_new_fatal_failure_(false),
|
||||
original_reporter_(
|
||||
GetUnitTestImpl()->GetTestPartResultReporterForCurrentThread()) {
|
||||
original_reporter_(GetUnitTestImpl()->
|
||||
GetTestPartResultReporterForCurrentThread()) {
|
||||
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
|
||||
}
|
||||
|
||||
|
@ -94,7 +98,8 @@ HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
|
|||
|
||||
void HasNewFatalFailureHelper::ReportTestPartResult(
|
||||
const TestPartResult& result) {
|
||||
if (result.fatally_failed()) has_new_fatal_failure_ = true;
|
||||
if (result.fatally_failed())
|
||||
has_new_fatal_failure_ = true;
|
||||
original_reporter_->ReportTestPartResult(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
#include "gtest/gtest-typed-test.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
@ -34,12 +35,11 @@
|
|||
namespace testing {
|
||||
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++;
|
||||
while (IsSpace(*str))
|
||||
str++;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,10 @@ static std::vector<std::string> SplitIntoTestNames(const char* src) {
|
|||
// registered_tests_; returns registered_tests if successful, or
|
||||
// aborts the program otherwise.
|
||||
const char* TypedTestSuitePState::VerifyRegisteredTestNames(
|
||||
const char* file, int line, const char* registered_tests) {
|
||||
const char* test_suite_name, const char* file, int line,
|
||||
const char* registered_tests) {
|
||||
RegisterTypeParameterizedTestSuite(test_suite_name, CodeLocation(file, line));
|
||||
|
||||
typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
|
||||
registered_ = true;
|
||||
|
||||
|
@ -73,16 +76,7 @@ const char* TypedTestSuitePState::VerifyRegisteredTestNames(
|
|||
continue;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (RegisteredTestIter it = registered_tests_.begin();
|
||||
it != registered_tests_.end(); ++it) {
|
||||
if (name == it->first) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (registered_tests_.count(name) != 0) {
|
||||
tests.insert(name);
|
||||
} else {
|
||||
errors << "No test named " << name
|
||||
|
@ -91,7 +85,8 @@ const char* TypedTestSuitePState::VerifyRegisteredTestNames(
|
|||
}
|
||||
|
||||
for (RegisteredTestIter it = registered_tests_.begin();
|
||||
it != registered_tests_.end(); ++it) {
|
||||
it != registered_tests_.end();
|
||||
++it) {
|
||||
if (tests.count(it->first) == 0) {
|
||||
errors << "You forgot to list test " << it->first << ".\n";
|
||||
}
|
||||
|
@ -108,7 +103,5 @@ const char* TypedTestSuitePState::VerifyRegisteredTestNames(
|
|||
return registered_tests;
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -30,11 +30,20 @@
|
|||
#include <cstdio>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#ifdef ARDUINO
|
||||
void setup() { testing::InitGoogleTest(); }
|
||||
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
|
||||
#if GTEST_OS_ESP8266
|
||||
extern "C" {
|
||||
#endif
|
||||
void setup() {
|
||||
testing::InitGoogleTest();
|
||||
}
|
||||
|
||||
void loop() { RUN_ALL_TESTS(); }
|
||||
|
||||
#if GTEST_OS_ESP8266
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
GTEST_API_ int main(int argc, char **argv) {
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
# (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: misterg@google.com (Gennadiy Civil)
|
||||
#
|
||||
# Bazel BUILD for The Google C++ Testing Framework (Google Test)
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_test")
|
||||
|
@ -37,6 +35,8 @@ load("@rules_python//python:defs.bzl", "py_library", "py_test")
|
|||
|
||||
licenses(["notice"])
|
||||
|
||||
package(default_visibility = ["//:__subpackages__"])
|
||||
|
||||
#on windows exclude gtest-tuple.h
|
||||
cc_test(
|
||||
name = "gtest_all_test",
|
||||
|
@ -56,15 +56,19 @@ cc_test(
|
|||
"gtest-listener_test.cc",
|
||||
"gtest-unittest-api_test.cc",
|
||||
"googletest-param-test-test.cc",
|
||||
"googletest-param-test2-test.cc",
|
||||
"googletest-catch-exceptions-test_.cc",
|
||||
"googletest-color-test_.cc",
|
||||
"googletest-env-var-test_.cc",
|
||||
"googletest-failfast-unittest_.cc",
|
||||
"googletest-filter-unittest_.cc",
|
||||
"googletest-global-environment-unittest_.cc",
|
||||
"googletest-break-on-failure-unittest_.cc",
|
||||
"googletest-listener-test.cc",
|
||||
"googletest-output-test_.cc",
|
||||
"googletest-list-tests-unittest_.cc",
|
||||
"googletest-shuffle-test_.cc",
|
||||
"googletest-setuptestsuite-test_.cc",
|
||||
"googletest-uninitialized-test_.cc",
|
||||
"googletest-death-test_ex_test.cc",
|
||||
"googletest-param-test-test",
|
||||
|
@ -79,6 +83,10 @@ cc_test(
|
|||
copts = select({
|
||||
"//:windows": ["-DGTEST_USE_OWN_TR1_TUPLE=0"],
|
||||
"//conditions:default": ["-DGTEST_USE_OWN_TR1_TUPLE=1"],
|
||||
}) + select({
|
||||
# Ensure MSVC treats source files as UTF-8 encoded.
|
||||
"//:msvc_compiler": ["-utf-8"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
includes = [
|
||||
"googletest",
|
||||
|
@ -142,7 +150,6 @@ cc_test(
|
|||
name = "gtest_unittest",
|
||||
size = "small",
|
||||
srcs = ["gtest_unittest.cc"],
|
||||
args = ["--heap_check=strict"],
|
||||
shard_count = 2,
|
||||
deps = ["//:gtest_main"],
|
||||
)
|
||||
|
@ -153,6 +160,7 @@ py_library(
|
|||
name = "gtest_test_utils",
|
||||
testonly = 1,
|
||||
srcs = ["gtest_test_utils.py"],
|
||||
imports = ["."],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
|
@ -222,6 +230,21 @@ py_test(
|
|||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "googletest-failfast-unittest_",
|
||||
testonly = 1,
|
||||
srcs = ["googletest-failfast-unittest_.cc"],
|
||||
deps = ["//:gtest"],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "googletest-failfast-unittest",
|
||||
size = "medium",
|
||||
srcs = ["googletest-failfast-unittest.py"],
|
||||
data = [":googletest-failfast-unittest_"],
|
||||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "googletest-filter-unittest_",
|
||||
testonly = 1,
|
||||
|
@ -237,6 +260,21 @@ py_test(
|
|||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "googletest-global-environment-unittest_",
|
||||
testonly = 1,
|
||||
srcs = ["googletest-global-environment-unittest_.cc"],
|
||||
deps = ["//:gtest"],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "googletest-global-environment-unittest",
|
||||
size = "medium",
|
||||
srcs = ["googletest-global-environment-unittest.py"],
|
||||
data = [":googletest-global-environment-unittest_"],
|
||||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "googletest-break-on-failure-unittest_",
|
||||
testonly = 1,
|
||||
|
@ -295,6 +333,14 @@ cc_test(
|
|||
deps = ["//:gtest_main"],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "gtest_skip_check_output_test",
|
||||
size = "small",
|
||||
srcs = ["gtest_skip_check_output_test.py"],
|
||||
data = [":gtest_skip_test"],
|
||||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "gtest_skip_environment_check_output_test",
|
||||
size = "small",
|
||||
|
@ -415,6 +461,21 @@ py_test(
|
|||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "googletest-setuptestsuite-test_",
|
||||
testonly = 1,
|
||||
srcs = ["googletest-setuptestsuite-test_.cc"],
|
||||
deps = ["//:gtest_main"],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "googletest-setuptestsuite-test",
|
||||
size = "medium",
|
||||
srcs = ["googletest-setuptestsuite-test.py"],
|
||||
data = [":googletest-setuptestsuite-test_"],
|
||||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "googletest-uninitialized-test_",
|
||||
testonly = 1,
|
||||
|
@ -509,6 +570,10 @@ py_test(
|
|||
size = "small",
|
||||
srcs = ["googletest-param-test-invalid-name1-test.py"],
|
||||
data = [":googletest-param-test-invalid-name1-test_"],
|
||||
tags = [
|
||||
"no_test_msvc2015",
|
||||
"no_test_msvc2017",
|
||||
],
|
||||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
||||
|
@ -517,5 +582,9 @@ py_test(
|
|||
size = "small",
|
||||
srcs = ["googletest-param-test-invalid-name2-test.py"],
|
||||
data = [":googletest-param-test-invalid-name2-test_"],
|
||||
tags = [
|
||||
"no_test_msvc2015",
|
||||
"no_test_msvc2017",
|
||||
],
|
||||
deps = [":gtest_test_utils"],
|
||||
)
|
||||
|
|
|
@ -32,18 +32,18 @@
|
|||
// exceptions, and the output is verified by
|
||||
// googletest-catch-exceptions-test.py.
|
||||
|
||||
#include <stdio.h> // NOLINT
|
||||
#include <stdio.h> // NOLINT
|
||||
#include <stdlib.h> // For exit().
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#if GTEST_HAS_SEH
|
||||
#include <windows.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
#include <exception> // For set_terminate().
|
||||
#include <stdexcept>
|
||||
# include <exception> // For set_terminate().
|
||||
# include <stdexcept>
|
||||
#endif
|
||||
|
||||
using testing::Test;
|
||||
|
@ -93,7 +93,9 @@ class SehExceptionInTearDownTest : public Test {
|
|||
|
||||
TEST_F(SehExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
|
||||
|
||||
TEST(SehExceptionTest, ThrowsSehException) { RaiseException(42, 0, 0, NULL); }
|
||||
TEST(SehExceptionTest, ThrowsSehException) {
|
||||
RaiseException(42, 0, 0, NULL);
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_SEH
|
||||
|
||||
|
@ -267,7 +269,9 @@ TEST_F(CxxExceptionInTestBodyTest, ThrowsStdCxxException) {
|
|||
throw std::runtime_error("Standard C++ exception");
|
||||
}
|
||||
|
||||
TEST(CxxExceptionTest, ThrowsNonStdCxxException) { throw "C-string"; }
|
||||
TEST(CxxExceptionTest, ThrowsNonStdCxxException) {
|
||||
throw "C-string";
|
||||
}
|
||||
|
||||
// This terminate handler aborts the program using exit() rather than abort().
|
||||
// This avoids showing pop-ups on Windows systems and core dumps on Unix-like
|
||||
|
|
|
@ -40,25 +40,25 @@ using testing::internal::AlwaysTrue;
|
|||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
#include <fcntl.h> // For O_BINARY
|
||||
#include <direct.h> // For chdir().
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h> // For waitpid.
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
# include <fcntl.h> // For O_BINARY
|
||||
# include <direct.h> // For chdir().
|
||||
# include <io.h>
|
||||
# else
|
||||
# include <unistd.h>
|
||||
# include <sys/wait.h> // For waitpid.
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
# include <limits.h>
|
||||
# include <signal.h>
|
||||
# include <stdio.h>
|
||||
|
||||
#if GTEST_OS_LINUX
|
||||
#include <sys/time.h>
|
||||
#endif // GTEST_OS_LINUX
|
||||
# if GTEST_OS_LINUX
|
||||
# include <sys/time.h>
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
#include "gtest/gtest-spi.h"
|
||||
#include "src/gtest-internal-inl.h"
|
||||
# include "gtest/gtest-spi.h"
|
||||
# include "src/gtest-internal-inl.h"
|
||||
|
||||
namespace posix = ::testing::internal::posix;
|
||||
|
||||
|
@ -90,7 +90,6 @@ class ReplaceDeathTestFactory {
|
|||
unit_test_impl_->death_test_factory_.release();
|
||||
unit_test_impl_->death_test_factory_.reset(old_factory_);
|
||||
}
|
||||
|
||||
private:
|
||||
// Prevents copying ReplaceDeathTestFactory objects.
|
||||
ReplaceDeathTestFactory(const ReplaceDeathTestFactory&);
|
||||
|
@ -117,7 +116,8 @@ void DieWithMessage(const ::std::string& message) {
|
|||
// 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);
|
||||
if (AlwaysTrue())
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
void DieInside(const ::std::string& function) {
|
||||
|
@ -137,7 +137,8 @@ class TestForDeathTest : public testing::Test {
|
|||
|
||||
// A method of the test fixture that may die.
|
||||
void MemberFunction() {
|
||||
if (should_die_) DieInside("MemberFunction");
|
||||
if (should_die_)
|
||||
DieInside("MemberFunction");
|
||||
}
|
||||
|
||||
// True if and only if MemberFunction() should die.
|
||||
|
@ -152,7 +153,8 @@ class MayDie {
|
|||
|
||||
// A member function that may die.
|
||||
void MemberFunction() const {
|
||||
if (should_die_) DieInside("MayDie::MemberFunction");
|
||||
if (should_die_)
|
||||
DieInside("MayDie::MemberFunction");
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -171,7 +173,8 @@ int NonVoidFunction() {
|
|||
|
||||
// A unary function that may die.
|
||||
void DieIf(bool should_die) {
|
||||
if (should_die) DieInside("DieIf");
|
||||
if (should_die)
|
||||
DieInside("DieIf");
|
||||
}
|
||||
|
||||
// A binary function that may die.
|
||||
|
@ -192,16 +195,16 @@ void DeathTestSubroutine() {
|
|||
int DieInDebugElse12(int* sideeffect) {
|
||||
if (sideeffect) *sideeffect = 12;
|
||||
|
||||
#ifndef NDEBUG
|
||||
# ifndef NDEBUG
|
||||
|
||||
DieInside("DieInDebugElse12");
|
||||
|
||||
#endif // NDEBUG
|
||||
# endif // NDEBUG
|
||||
|
||||
return 12;
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
|
||||
// Death in dbg due to Windows CRT assertion failure, not opt.
|
||||
int DieInCRTDebugElse12(int* sideeffect) {
|
||||
|
@ -221,7 +224,7 @@ int DieInCRTDebugElse12(int* sideeffect) {
|
|||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
// Tests the ExitedWithCode predicate.
|
||||
TEST(ExitStatusPredicateTest, ExitedWithCode) {
|
||||
|
@ -234,7 +237,7 @@ TEST(ExitStatusPredicateTest, ExitedWithCode) {
|
|||
EXPECT_FALSE(testing::ExitedWithCode(1)(0));
|
||||
}
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
// Returns the exit status of a process that calls _exit(2) with a
|
||||
// given exit code. This is a helper function for the
|
||||
|
@ -267,14 +270,14 @@ static int KilledExitStatus(int signum) {
|
|||
|
||||
// Tests the ExitedWithCode predicate.
|
||||
TEST(ExitStatusPredicateTest, ExitedWithCode) {
|
||||
const int status0 = NormalExitStatus(0);
|
||||
const int status1 = NormalExitStatus(1);
|
||||
const int status0 = NormalExitStatus(0);
|
||||
const int status1 = NormalExitStatus(1);
|
||||
const int status42 = NormalExitStatus(42);
|
||||
const testing::ExitedWithCode pred0(0);
|
||||
const testing::ExitedWithCode pred1(1);
|
||||
const testing::ExitedWithCode pred42(42);
|
||||
EXPECT_PRED1(pred0, status0);
|
||||
EXPECT_PRED1(pred1, status1);
|
||||
EXPECT_PRED1(pred0, status0);
|
||||
EXPECT_PRED1(pred1, status1);
|
||||
EXPECT_PRED1(pred42, status42);
|
||||
EXPECT_FALSE(pred0(status1));
|
||||
EXPECT_FALSE(pred42(status0));
|
||||
|
@ -293,8 +296,15 @@ TEST(ExitStatusPredicateTest, KilledBySignal) {
|
|||
EXPECT_FALSE(pred_kill(status_segv));
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
// The following code intentionally tests a suboptimal syntax.
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdangling-else"
|
||||
#pragma GCC diagnostic ignored "-Wempty-body"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#endif
|
||||
// Tests that the death test macros expand to code which may or may not
|
||||
// be followed by operator<<, and that in either case the complete text
|
||||
// comprises only a single C++ statement.
|
||||
|
@ -310,15 +320,19 @@ TEST_F(TestForDeathTest, SingleStatement) {
|
|||
// doesn't expand into an "if" statement without an "else"
|
||||
;
|
||||
|
||||
if (AlwaysFalse()) ASSERT_DEATH(return, "") << "did not die";
|
||||
if (AlwaysFalse())
|
||||
ASSERT_DEATH(return, "") << "did not die";
|
||||
|
||||
if (AlwaysFalse())
|
||||
;
|
||||
else
|
||||
EXPECT_DEATH(_exit(1), "") << 1 << 2 << 3;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if GTEST_USES_PCRE
|
||||
# if GTEST_USES_PCRE
|
||||
|
||||
void DieWithEmbeddedNul() {
|
||||
fprintf(stderr, "Hello%cmy null world.\n", '\0');
|
||||
|
@ -333,7 +347,7 @@ TEST_F(TestForDeathTest, EmbeddedNulInMessage) {
|
|||
ASSERT_DEATH(DieWithEmbeddedNul(), "my null world");
|
||||
}
|
||||
|
||||
#endif // GTEST_USES_PCRE
|
||||
# endif // GTEST_USES_PCRE
|
||||
|
||||
// Tests that death test macros expand to code which interacts well with switch
|
||||
// statements.
|
||||
|
@ -343,12 +357,12 @@ TEST_F(TestForDeathTest, SwitchStatement) {
|
|||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4065)
|
||||
|
||||
switch (0)
|
||||
default:
|
||||
ASSERT_DEATH(_exit(1), "") << "exit in default switch handler";
|
||||
default:
|
||||
ASSERT_DEATH(_exit(1), "") << "exit in default switch handler";
|
||||
|
||||
switch (0)
|
||||
case 0:
|
||||
EXPECT_DEATH(_exit(1), "") << "exit in switch case";
|
||||
case 0:
|
||||
EXPECT_DEATH(_exit(1), "") << "exit in switch case";
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
}
|
||||
|
@ -382,23 +396,24 @@ TEST_F(TestForDeathTest, FastDeathTestInChangedDir) {
|
|||
ASSERT_DEATH(_exit(1), "");
|
||||
}
|
||||
|
||||
#if GTEST_OS_LINUX
|
||||
void SigprofAction(int, siginfo_t*, void*) { /* no op */
|
||||
}
|
||||
# if GTEST_OS_LINUX
|
||||
void SigprofAction(int, siginfo_t*, void*) { /* no op */ }
|
||||
|
||||
// Sets SIGPROF action and ITIMER_PROF timer (interval: 1ms).
|
||||
void SetSigprofActionAndTimer() {
|
||||
struct itimerval timer;
|
||||
timer.it_interval.tv_sec = 0;
|
||||
timer.it_interval.tv_usec = 1;
|
||||
timer.it_value = timer.it_interval;
|
||||
ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, nullptr));
|
||||
struct sigaction signal_action;
|
||||
memset(&signal_action, 0, sizeof(signal_action));
|
||||
sigemptyset(&signal_action.sa_mask);
|
||||
signal_action.sa_sigaction = SigprofAction;
|
||||
signal_action.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, nullptr));
|
||||
// timer comes second, to avoid SIGPROF premature delivery, as suggested at
|
||||
// https://www.gnu.org/software/libc/manual/html_node/Setting-an-Alarm.html
|
||||
struct itimerval timer;
|
||||
timer.it_interval.tv_sec = 0;
|
||||
timer.it_interval.tv_usec = 1;
|
||||
timer.it_value = timer.it_interval;
|
||||
ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, nullptr));
|
||||
}
|
||||
|
||||
// Disables ITIMER_PROF timer and ignores SIGPROF signal.
|
||||
|
@ -433,7 +448,7 @@ TEST_F(TestForDeathTest, ThreadSafeSigprofActionSet) {
|
|||
DisableSigprofActionAndTimer(&old_signal_action);
|
||||
EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
|
||||
}
|
||||
#endif // GTEST_OS_LINUX
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
// Repeats a representative sample of death tests in the "threadsafe" style:
|
||||
|
||||
|
@ -472,11 +487,13 @@ TEST_F(TestForDeathTest, MixedStyles) {
|
|||
EXPECT_DEATH(_exit(1), "");
|
||||
}
|
||||
|
||||
#if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
|
||||
# if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
|
||||
|
||||
bool pthread_flag;
|
||||
|
||||
void SetPthreadFlag() { pthread_flag = true; }
|
||||
void SetPthreadFlag() {
|
||||
pthread_flag = true;
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
|
||||
if (!testing::GTEST_FLAG(death_test_use_fork)) {
|
||||
|
@ -488,7 +505,7 @@ TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
|
|||
}
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
|
||||
# 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) {
|
||||
|
@ -510,7 +527,7 @@ TEST_F(TestForDeathTest, AcceptsAnythingConvertibleToRE) {
|
|||
const testing::internal::RE regex(regex_c_str);
|
||||
EXPECT_DEATH(GlobalFunction(), regex);
|
||||
|
||||
#if !GTEST_USES_PCRE
|
||||
# if !GTEST_USES_PCRE
|
||||
|
||||
const ::std::string regex_std_str(regex_c_str);
|
||||
EXPECT_DEATH(GlobalFunction(), regex_std_str);
|
||||
|
@ -519,7 +536,7 @@ TEST_F(TestForDeathTest, AcceptsAnythingConvertibleToRE) {
|
|||
// lifetime extension of the pointer is not sufficient.
|
||||
EXPECT_DEATH(GlobalFunction(), ::std::string(regex_c_str).c_str());
|
||||
|
||||
#endif // !GTEST_USES_PCRE
|
||||
# endif // !GTEST_USES_PCRE
|
||||
}
|
||||
|
||||
// Tests that a non-void function can be used in a death test.
|
||||
|
@ -534,7 +551,9 @@ TEST_F(TestForDeathTest, FunctionWithParameter) {
|
|||
}
|
||||
|
||||
// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
|
||||
TEST_F(TestForDeathTest, OutsideFixture) { DeathTestSubroutine(); }
|
||||
TEST_F(TestForDeathTest, OutsideFixture) {
|
||||
DeathTestSubroutine();
|
||||
}
|
||||
|
||||
// Tests that death tests can be done inside a loop.
|
||||
TEST_F(TestForDeathTest, InsideLoop) {
|
||||
|
@ -545,28 +564,25 @@ TEST_F(TestForDeathTest, InsideLoop) {
|
|||
|
||||
// Tests that a compound statement can be used in a death test.
|
||||
TEST_F(TestForDeathTest, CompoundStatement) {
|
||||
EXPECT_DEATH(
|
||||
{ // NOLINT
|
||||
const int x = 2;
|
||||
const int y = x + 1;
|
||||
DieIfLessThan(x, y);
|
||||
},
|
||||
"DieIfLessThan");
|
||||
EXPECT_DEATH({ // NOLINT
|
||||
const int x = 2;
|
||||
const int y = x + 1;
|
||||
DieIfLessThan(x, y);
|
||||
},
|
||||
"DieIfLessThan");
|
||||
}
|
||||
|
||||
// Tests that code that doesn't die causes a death test to fail.
|
||||
TEST_F(TestForDeathTest, DoesNotDie) {
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(DieIf(false), "DieIf"), "failed to die");
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(DieIf(false), "DieIf"),
|
||||
"failed to die");
|
||||
}
|
||||
|
||||
// Tests that a death test fails when the error message isn't expected.
|
||||
TEST_F(TestForDeathTest, ErrorMessageMismatch) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
EXPECT_DEATH(DieIf(true), "DieIfLessThan")
|
||||
<< "End of death test message.";
|
||||
},
|
||||
"died but not with expected error");
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
EXPECT_DEATH(DieIf(true), "DieIfLessThan") << "End of death test message.";
|
||||
}, "died but not with expected error");
|
||||
}
|
||||
|
||||
// On exit, *aborted will be true if and only if the EXPECT_DEATH()
|
||||
|
@ -580,20 +596,19 @@ void ExpectDeathTestHelper(bool* aborted) {
|
|||
// Tests that EXPECT_DEATH doesn't abort the test on failure.
|
||||
TEST_F(TestForDeathTest, EXPECT_DEATH) {
|
||||
bool aborted = true;
|
||||
EXPECT_NONFATAL_FAILURE(ExpectDeathTestHelper(&aborted), "failed to die");
|
||||
EXPECT_NONFATAL_FAILURE(ExpectDeathTestHelper(&aborted),
|
||||
"failed to die");
|
||||
EXPECT_FALSE(aborted);
|
||||
}
|
||||
|
||||
// Tests that ASSERT_DEATH does abort the test on failure.
|
||||
TEST_F(TestForDeathTest, ASSERT_DEATH) {
|
||||
static bool aborted;
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
aborted = true;
|
||||
ASSERT_DEATH(DieIf(false), "DieIf"); // This assertion should fail.
|
||||
aborted = false;
|
||||
},
|
||||
"failed to die");
|
||||
EXPECT_FATAL_FAILURE({ // NOLINT
|
||||
aborted = true;
|
||||
ASSERT_DEATH(DieIf(false), "DieIf"); // This assertion should fail.
|
||||
aborted = false;
|
||||
}, "failed to die");
|
||||
EXPECT_TRUE(aborted);
|
||||
}
|
||||
|
||||
|
@ -638,20 +653,20 @@ TEST_F(TestForDeathTest, TestExpectDebugDeath) {
|
|||
EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), regex)
|
||||
<< "Must accept a streamed message";
|
||||
|
||||
#ifdef NDEBUG
|
||||
# ifdef NDEBUG
|
||||
|
||||
// Checks that the assignment occurs in opt mode (sideeffect).
|
||||
EXPECT_EQ(12, sideeffect);
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
// Checks that the assignment does not occur in dbg mode (no sideeffect).
|
||||
EXPECT_EQ(0, sideeffect);
|
||||
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
|
||||
// Tests that EXPECT_DEBUG_DEATH works as expected when in debug mode
|
||||
// the Windows CRT crashes the process with an assertion failure.
|
||||
|
@ -670,20 +685,20 @@ TEST_F(TestForDeathTest, CRTDebugDeath) {
|
|||
EXPECT_DEBUG_DEATH(DieInCRTDebugElse12(&sideeffect), regex)
|
||||
<< "Must accept a streamed message";
|
||||
|
||||
#ifdef NDEBUG
|
||||
# ifdef NDEBUG
|
||||
|
||||
// Checks that the assignment occurs in opt mode (sideeffect).
|
||||
EXPECT_EQ(12, sideeffect);
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
// Checks that the assignment does not occur in dbg mode (no sideeffect).
|
||||
EXPECT_EQ(0, sideeffect);
|
||||
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Tests that ASSERT_DEBUG_DEATH works as expected, that is, you can stream a
|
||||
// message to it, and in debug mode it:
|
||||
|
@ -698,20 +713,20 @@ TEST_F(TestForDeathTest, TestAssertDebugDeath) {
|
|||
ASSERT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death.*DieInDebugElse12")
|
||||
<< "Must accept a streamed message";
|
||||
|
||||
#ifdef NDEBUG
|
||||
# ifdef NDEBUG
|
||||
|
||||
// Checks that the assignment occurs in opt mode (sideeffect).
|
||||
EXPECT_EQ(12, sideeffect);
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
// Checks that the assignment does not occur in dbg mode (no sideeffect).
|
||||
EXPECT_EQ(0, sideeffect);
|
||||
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
# ifndef NDEBUG
|
||||
|
||||
void ExpectDebugDeathHelper(bool* aborted) {
|
||||
*aborted = true;
|
||||
|
@ -719,21 +734,18 @@ void ExpectDebugDeathHelper(bool* aborted) {
|
|||
*aborted = false;
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
TEST(PopUpDeathTest, DoesNotShowPopUpOnAbort) {
|
||||
printf(
|
||||
"This test should be considered failing if it shows "
|
||||
"any pop-up dialogs.\n");
|
||||
printf("This test should be considered failing if it shows "
|
||||
"any pop-up dialogs.\n");
|
||||
fflush(stdout);
|
||||
|
||||
EXPECT_DEATH(
|
||||
{
|
||||
testing::GTEST_FLAG(catch_exceptions) = false;
|
||||
abort();
|
||||
},
|
||||
"");
|
||||
EXPECT_DEATH({
|
||||
testing::GTEST_FLAG(catch_exceptions) = false;
|
||||
abort();
|
||||
}, "");
|
||||
}
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Tests that EXPECT_DEBUG_DEATH in debug mode does not abort
|
||||
// the function.
|
||||
|
@ -824,44 +836,42 @@ TEST_F(TestForDeathTest, AssertDebugDeathAborts10) {
|
|||
EXPECT_TRUE(aborted);
|
||||
}
|
||||
|
||||
#endif // _NDEBUG
|
||||
# endif // _NDEBUG
|
||||
|
||||
// Tests the *_EXIT family of macros, using a variety of predicates.
|
||||
static void TestExitMacros() {
|
||||
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
|
||||
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
|
||||
ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
|
||||
// Of all signals effects on the process exit code, only those of SIGABRT
|
||||
// are documented on Windows.
|
||||
// See https://msdn.microsoft.com/en-us/query-bi/m/dwwzkt4c.
|
||||
EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), "") << "b_ar";
|
||||
|
||||
#elif !GTEST_OS_FUCHSIA
|
||||
# elif !GTEST_OS_FUCHSIA
|
||||
|
||||
// Fuchsia has no unix signals.
|
||||
EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo";
|
||||
ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar";
|
||||
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "")
|
||||
<< "This failure is expected, too.";
|
||||
},
|
||||
"This failure is expected, too.");
|
||||
EXPECT_FATAL_FAILURE({ // NOLINT
|
||||
ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "")
|
||||
<< "This failure is expected, too.";
|
||||
}, "This failure is expected, too.");
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "")
|
||||
<< "This failure is expected.";
|
||||
},
|
||||
"This failure is expected.");
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "")
|
||||
<< "This failure is expected.";
|
||||
}, "This failure is expected.");
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, ExitMacros) { TestExitMacros(); }
|
||||
TEST_F(TestForDeathTest, ExitMacros) {
|
||||
TestExitMacros();
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, ExitMacrosUsingFork) {
|
||||
testing::GTEST_FLAG(death_test_use_fork) = true;
|
||||
|
@ -870,40 +880,39 @@ TEST_F(TestForDeathTest, ExitMacrosUsingFork) {
|
|||
|
||||
TEST_F(TestForDeathTest, InvalidStyle) {
|
||||
testing::GTEST_FLAG(death_test_style) = "rococo";
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
EXPECT_DEATH(_exit(0), "") << "This failure is expected.";
|
||||
},
|
||||
"This failure is expected.");
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
EXPECT_DEATH(_exit(0), "") << "This failure is expected.";
|
||||
}, "This failure is expected.");
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, DeathTestFailedOutput) {
|
||||
testing::GTEST_FLAG(death_test_style) = "fast";
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_DEATH(DieWithMessage("death\n"), "expected message"),
|
||||
EXPECT_DEATH(DieWithMessage("death\n"),
|
||||
"expected message"),
|
||||
"Actual msg:\n"
|
||||
"[ DEATH ] death\n");
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, DeathTestUnexpectedReturnOutput) {
|
||||
testing::GTEST_FLAG(death_test_style) = "fast";
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(
|
||||
{
|
||||
fprintf(stderr, "returning\n");
|
||||
fflush(stderr);
|
||||
return;
|
||||
},
|
||||
""),
|
||||
" Result: illegal return in test statement.\n"
|
||||
" Error msg:\n"
|
||||
"[ DEATH ] returning\n");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_DEATH({
|
||||
fprintf(stderr, "returning\n");
|
||||
fflush(stderr);
|
||||
return;
|
||||
}, ""),
|
||||
" Result: illegal return in test statement.\n"
|
||||
" Error msg:\n"
|
||||
"[ DEATH ] returning\n");
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, DeathTestBadExitCodeOutput) {
|
||||
testing::GTEST_FLAG(death_test_style) = "fast";
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_EXIT(DieWithMessage("exiting with rc 1\n"),
|
||||
testing::ExitedWithCode(3), "expected message"),
|
||||
testing::ExitedWithCode(3),
|
||||
"expected message"),
|
||||
" Result: died but not with expected exit code:\n"
|
||||
" Exited with exit status 1\n"
|
||||
"Actual msg:\n"
|
||||
|
@ -936,8 +945,8 @@ class MockDeathTestFactory : public DeathTestFactory {
|
|||
int line, DeathTest** test) override;
|
||||
|
||||
// Sets the parameters for subsequent calls to Create.
|
||||
void SetParameters(bool create, DeathTest::TestRole role, int status,
|
||||
bool passed);
|
||||
void SetParameters(bool create, DeathTest::TestRole role,
|
||||
int status, bool passed);
|
||||
|
||||
// Accessors.
|
||||
int AssumeRoleCalls() const { return assume_role_calls_; }
|
||||
|
@ -979,15 +988,17 @@ class MockDeathTestFactory : public DeathTestFactory {
|
|||
bool test_deleted_;
|
||||
};
|
||||
|
||||
|
||||
// A DeathTest implementation useful in testing. It returns values set
|
||||
// at its creation from its various inherited DeathTest methods, and
|
||||
// reports calls to those methods to its parent MockDeathTestFactory
|
||||
// object.
|
||||
class MockDeathTest : public DeathTest {
|
||||
public:
|
||||
MockDeathTest(MockDeathTestFactory* parent, TestRole role, int status,
|
||||
bool passed)
|
||||
: parent_(parent), role_(role), status_(status), passed_(passed) {}
|
||||
MockDeathTest(MockDeathTestFactory *parent,
|
||||
TestRole role, int status, bool passed) :
|
||||
parent_(parent), role_(role), status_(status), passed_(passed) {
|
||||
}
|
||||
~MockDeathTest() override { parent_->test_deleted_ = true; }
|
||||
TestRole AssumeRole() override {
|
||||
++parent_->assume_role_calls_;
|
||||
|
@ -1012,6 +1023,7 @@ class MockDeathTest : public DeathTest {
|
|||
const bool passed_;
|
||||
};
|
||||
|
||||
|
||||
// MockDeathTestFactory constructor.
|
||||
MockDeathTestFactory::MockDeathTestFactory()
|
||||
: create_(true),
|
||||
|
@ -1021,10 +1033,13 @@ MockDeathTestFactory::MockDeathTestFactory()
|
|||
assume_role_calls_(0),
|
||||
wait_calls_(0),
|
||||
passed_args_(),
|
||||
abort_args_() {}
|
||||
abort_args_() {
|
||||
}
|
||||
|
||||
|
||||
// Sets the parameters for subsequent calls to Create.
|
||||
void MockDeathTestFactory::SetParameters(bool create, DeathTest::TestRole role,
|
||||
void MockDeathTestFactory::SetParameters(bool create,
|
||||
DeathTest::TestRole role,
|
||||
int status, bool passed) {
|
||||
create_ = create;
|
||||
role_ = role;
|
||||
|
@ -1037,6 +1052,7 @@ void MockDeathTestFactory::SetParameters(bool create, DeathTest::TestRole role,
|
|||
abort_args_.clear();
|
||||
}
|
||||
|
||||
|
||||
// Sets test to NULL (if create_ is false) or to the address of a new
|
||||
// MockDeathTest object with parameters taken from the last call
|
||||
// to SetParameters (if create_ is true). Always returns true.
|
||||
|
@ -1076,12 +1092,10 @@ class MacroLogicDeathTest : public testing::Test {
|
|||
// test cannot be run directly from a test routine that uses a
|
||||
// MockDeathTest, or the remainder of the routine will not be executed.
|
||||
static void RunReturningDeathTest(bool* flag) {
|
||||
ASSERT_DEATH(
|
||||
{ // NOLINT
|
||||
*flag = true;
|
||||
return;
|
||||
},
|
||||
"");
|
||||
ASSERT_DEATH({ // NOLINT
|
||||
*flag = true;
|
||||
return;
|
||||
}, "");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1166,7 +1180,8 @@ TEST_F(MacroLogicDeathTest, ChildDoesNotDie) {
|
|||
// _exit(2) is called in that case by ForkingDeathTest, but not by
|
||||
// our MockDeathTest.
|
||||
ASSERT_EQ(2U, factory_->AbortCalls());
|
||||
EXPECT_EQ(DeathTest::TEST_DID_NOT_DIE, factory_->AbortArgument(0));
|
||||
EXPECT_EQ(DeathTest::TEST_DID_NOT_DIE,
|
||||
factory_->AbortArgument(0));
|
||||
EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
|
||||
factory_->AbortArgument(1));
|
||||
EXPECT_TRUE(factory_->TestDeleted());
|
||||
|
@ -1182,16 +1197,12 @@ TEST(SuccessRegistrationDeathTest, NoSuccessPart) {
|
|||
TEST(StreamingAssertionsDeathTest, DeathTest) {
|
||||
EXPECT_DEATH(_exit(1), "") << "unexpected failure";
|
||||
ASSERT_DEATH(_exit(1), "") << "unexpected failure";
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
EXPECT_DEATH(_exit(0), "") << "expected failure";
|
||||
},
|
||||
"expected failure");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
ASSERT_DEATH(_exit(0), "") << "expected failure";
|
||||
},
|
||||
"expected failure");
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
EXPECT_DEATH(_exit(0), "") << "expected failure";
|
||||
}, "expected failure");
|
||||
EXPECT_FATAL_FAILURE({ // NOLINT
|
||||
ASSERT_DEATH(_exit(0), "") << "expected failure";
|
||||
}, "expected failure");
|
||||
}
|
||||
|
||||
// Tests that GetLastErrnoDescription returns an empty string when the
|
||||
|
@ -1203,7 +1214,7 @@ TEST(GetLastErrnoDescription, GetLastErrnoDescriptionWorks) {
|
|||
EXPECT_STREQ("", GetLastErrnoDescription().c_str());
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
TEST(AutoHandleTest, AutoHandleWorks) {
|
||||
HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
ASSERT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
|
@ -1228,15 +1239,15 @@ TEST(AutoHandleTest, AutoHandleWorks) {
|
|||
testing::internal::AutoHandle auto_handle2;
|
||||
EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle2.Get());
|
||||
}
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
typedef unsigned __int64 BiggestParsable;
|
||||
typedef signed __int64 BiggestSignedParsable;
|
||||
#else
|
||||
# else
|
||||
typedef unsigned long long BiggestParsable;
|
||||
typedef signed long long BiggestSignedParsable;
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
// We cannot use std::numeric_limits<T>::max() as it clashes with the
|
||||
// max() macro defined by <windows.h>.
|
||||
|
@ -1327,11 +1338,11 @@ TEST(ParseNaturalNumberTest, WorksForShorterIntegers) {
|
|||
EXPECT_EQ(123, char_result);
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS
|
||||
TEST(EnvironmentTest, HandleFitsIntoSizeT) {
|
||||
ASSERT_TRUE(sizeof(HANDLE) <= sizeof(size_t));
|
||||
}
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED trigger
|
||||
// failures when death tests are available on the system.
|
||||
|
@ -1349,25 +1360,21 @@ TEST(ConditionalDeathMacrosDeathTest, ExpectsDeathWhenDeathTestsAvailable) {
|
|||
TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInFastStyle) {
|
||||
testing::GTEST_FLAG(death_test_style) = "fast";
|
||||
EXPECT_FALSE(InDeathTestChild());
|
||||
EXPECT_DEATH(
|
||||
{
|
||||
fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
|
||||
fflush(stderr);
|
||||
_exit(1);
|
||||
},
|
||||
"Inside");
|
||||
EXPECT_DEATH({
|
||||
fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
|
||||
fflush(stderr);
|
||||
_exit(1);
|
||||
}, "Inside");
|
||||
}
|
||||
|
||||
TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInThreadSafeStyle) {
|
||||
testing::GTEST_FLAG(death_test_style) = "threadsafe";
|
||||
EXPECT_FALSE(InDeathTestChild());
|
||||
EXPECT_DEATH(
|
||||
{
|
||||
fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
|
||||
fflush(stderr);
|
||||
_exit(1);
|
||||
},
|
||||
"Inside");
|
||||
EXPECT_DEATH({
|
||||
fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
|
||||
fflush(stderr);
|
||||
_exit(1);
|
||||
}, "Inside");
|
||||
}
|
||||
|
||||
void DieWithMessage(const char* message) {
|
||||
|
@ -1379,7 +1386,11 @@ void DieWithMessage(const char* message) {
|
|||
TEST(MatcherDeathTest, DoesNotBreakBareRegexMatching) {
|
||||
// googletest tests this, of course; here we ensure that including googlemock
|
||||
// has not broken it.
|
||||
#if GTEST_USES_POSIX_RE
|
||||
EXPECT_DEATH(DieWithMessage("O, I die, Horatio."), "I d[aeiou]e");
|
||||
#else
|
||||
EXPECT_DEATH(DieWithMessage("O, I die, Horatio."), "I di?e");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(MatcherDeathTest, MonomorphicMatcherMatches) {
|
||||
|
@ -1467,6 +1478,13 @@ TEST(ConditionalDeathMacrosTest, AssertDeatDoesNotReturnhIfUnsupported) {
|
|||
|
||||
namespace {
|
||||
|
||||
// The following code intentionally tests a suboptimal syntax.
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdangling-else"
|
||||
#pragma GCC diagnostic ignored "-Wempty-body"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#endif
|
||||
// Tests that the death test macros expand to code which may or may not
|
||||
// be followed by operator<<, and that in either case the complete text
|
||||
// comprises only a single C++ statement.
|
||||
|
@ -1484,13 +1502,17 @@ TEST(ConditionalDeathMacrosSyntaxDeathTest, SingleStatement) {
|
|||
// doesn't expand into an "if" statement without an "else"
|
||||
; // NOLINT
|
||||
|
||||
if (AlwaysFalse()) ASSERT_DEATH_IF_SUPPORTED(return, "") << "did not die";
|
||||
if (AlwaysFalse())
|
||||
ASSERT_DEATH_IF_SUPPORTED(return, "") << "did not die";
|
||||
|
||||
if (AlwaysFalse())
|
||||
; // NOLINT
|
||||
else
|
||||
EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << 1 << 2 << 3;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// Tests that conditional death test macros expand to code which interacts
|
||||
// well with switch statements.
|
||||
|
@ -1500,18 +1522,21 @@ TEST(ConditionalDeathMacrosSyntaxDeathTest, SwitchStatement) {
|
|||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4065)
|
||||
|
||||
switch (0)
|
||||
default:
|
||||
ASSERT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in default switch handler";
|
||||
default:
|
||||
ASSERT_DEATH_IF_SUPPORTED(_exit(1), "")
|
||||
<< "exit in default switch handler";
|
||||
|
||||
switch (0)
|
||||
case 0:
|
||||
EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in switch case";
|
||||
case 0:
|
||||
EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in switch case";
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
}
|
||||
|
||||
// Tests that a test case whose name ends with "DeathTest" works fine
|
||||
// on Windows.
|
||||
TEST(NotADeathTest, Test) { SUCCEED(); }
|
||||
TEST(NotADeathTest, Test) {
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -35,15 +35,15 @@
|
|||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
#if GTEST_HAS_SEH
|
||||
#include <windows.h> // For RaiseException().
|
||||
#endif
|
||||
# if GTEST_HAS_SEH
|
||||
# include <windows.h> // For RaiseException().
|
||||
# endif
|
||||
|
||||
#include "gtest/gtest-spi.h"
|
||||
# include "gtest/gtest-spi.h"
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
# if GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#include <exception> // For std::exception.
|
||||
# include <exception> // For std::exception.
|
||||
|
||||
// Tests that death tests report thrown exceptions as failures and that the
|
||||
// exceptions do not escape death test macros.
|
||||
|
@ -59,7 +59,7 @@ TEST(CxxExceptionDeathTest, ExceptionIsFailure) {
|
|||
|
||||
class TestException : public std::exception {
|
||||
public:
|
||||
const char* what() const throw() override { return "exceptional message"; }
|
||||
const char* what() const noexcept override { return "exceptional message"; }
|
||||
};
|
||||
|
||||
TEST(CxxExceptionDeathTest, PrintsMessageForStdExceptions) {
|
||||
|
@ -67,11 +67,12 @@ TEST(CxxExceptionDeathTest, PrintsMessageForStdExceptions) {
|
|||
EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
|
||||
"exceptional message");
|
||||
// Verifies that the location is mentioned in the failure text.
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""), __FILE__);
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
|
||||
__FILE__);
|
||||
}
|
||||
#endif // GTEST_HAS_EXCEPTIONS
|
||||
# endif // GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#if GTEST_HAS_SEH
|
||||
# if GTEST_HAS_SEH
|
||||
// Tests that enabling interception of SEH exceptions with the
|
||||
// catch_exceptions flag does not interfere with SEH exceptions being
|
||||
// treated as death by death tests.
|
||||
|
@ -80,7 +81,7 @@ TEST(SehExceptionDeasTest, CatchExceptionsDoesNotInterfere) {
|
|||
<< "with catch_exceptions "
|
||||
<< (testing::GTEST_FLAG(catch_exceptions) ? "enabled" : "disabled");
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
|
|
|
@ -85,9 +85,12 @@ class GTestEnvVarTest(gtest_test_utils.TestCase):
|
|||
|
||||
TestFlag('break_on_failure', '1', '0')
|
||||
TestFlag('color', 'yes', 'auto')
|
||||
SetEnvVar('TESTBRIDGE_TEST_RUNNER_FAIL_FAST', None) # For 'fail_fast' test
|
||||
TestFlag('fail_fast', '1', '0')
|
||||
TestFlag('filter', 'FooTest.Bar', '*')
|
||||
SetEnvVar('XML_OUTPUT_FILE', None) # For 'output' test
|
||||
TestFlag('output', 'xml:tmp/foo.xml', '')
|
||||
TestFlag('brief', '1', '0')
|
||||
TestFlag('print_time', '0', '1')
|
||||
TestFlag('repeat', '999', '1')
|
||||
TestFlag('throw_on_failure', '1', '0')
|
||||
|
|
|
@ -72,6 +72,11 @@ void PrintFlag(const char* flag) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (strcmp(flag, "fail_fast") == 0) {
|
||||
cout << GTEST_FLAG(fail_fast);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(flag, "filter") == 0) {
|
||||
cout << GTEST_FLAG(filter);
|
||||
return;
|
||||
|
@ -82,6 +87,11 @@ void PrintFlag(const char* flag) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (strcmp(flag, "brief") == 0) {
|
||||
cout << GTEST_FLAG(brief);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(flag, "print_time") == 0) {
|
||||
cout << GTEST_FLAG(print_time);
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,410 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2020 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.
|
||||
|
||||
"""Unit test for Google Test fail_fast.
|
||||
|
||||
A user can specify if a Google Test program should continue test execution
|
||||
after a test failure via the GTEST_FAIL_FAST environment variable or the
|
||||
--gtest_fail_fast flag. The default value of the flag can also be changed
|
||||
by Bazel fail fast environment variable TESTBRIDGE_TEST_RUNNER_FAIL_FAST.
|
||||
|
||||
This script tests such functionality by invoking googletest-failfast-unittest_
|
||||
(a program written with Google Test) with different environments and command
|
||||
line flags.
|
||||
"""
|
||||
|
||||
import os
|
||||
import gtest_test_utils
|
||||
|
||||
# Constants.
|
||||
|
||||
# Bazel testbridge environment variable for fail fast
|
||||
BAZEL_FAIL_FAST_ENV_VAR = 'TESTBRIDGE_TEST_RUNNER_FAIL_FAST'
|
||||
|
||||
# The environment variable for specifying fail fast.
|
||||
FAIL_FAST_ENV_VAR = 'GTEST_FAIL_FAST'
|
||||
|
||||
# The command line flag for specifying fail fast.
|
||||
FAIL_FAST_FLAG = 'gtest_fail_fast'
|
||||
|
||||
# The command line flag to run disabled tests.
|
||||
RUN_DISABLED_FLAG = 'gtest_also_run_disabled_tests'
|
||||
|
||||
# The command line flag for specifying a filter.
|
||||
FILTER_FLAG = 'gtest_filter'
|
||||
|
||||
# Command to run the googletest-failfast-unittest_ program.
|
||||
COMMAND = gtest_test_utils.GetTestExecutablePath(
|
||||
'googletest-failfast-unittest_')
|
||||
|
||||
# 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
|
||||
|
||||
# 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:
|
||||
environ[env_var] = value
|
||||
elif env_var in environ:
|
||||
del environ[env_var]
|
||||
|
||||
|
||||
def RunAndReturnOutput(test_suite=None, fail_fast=None, run_disabled=False):
|
||||
"""Runs the test program and returns its output."""
|
||||
|
||||
args = []
|
||||
xml_path = os.path.join(gtest_test_utils.GetTempDir(),
|
||||
'.GTestFailFastUnitTest.xml')
|
||||
args += ['--gtest_output=xml:' + xml_path]
|
||||
if fail_fast is not None:
|
||||
if isinstance(fail_fast, str):
|
||||
args += ['--%s=%s' % (FAIL_FAST_FLAG, fail_fast)]
|
||||
elif fail_fast:
|
||||
args += ['--%s' % FAIL_FAST_FLAG]
|
||||
else:
|
||||
args += ['--no%s' % FAIL_FAST_FLAG]
|
||||
if test_suite:
|
||||
args += ['--%s=%s.*' % (FILTER_FLAG, test_suite)]
|
||||
if run_disabled:
|
||||
args += ['--%s' % RUN_DISABLED_FLAG]
|
||||
txt_out = gtest_test_utils.Subprocess([COMMAND] + args, env=environ).output
|
||||
with open(xml_path) as xml_file:
|
||||
return txt_out, xml_file.read()
|
||||
|
||||
|
||||
# The unit test.
|
||||
class GTestFailFastUnitTest(gtest_test_utils.TestCase):
|
||||
"""Tests the env variable or the command line flag for fail_fast."""
|
||||
|
||||
def testDefaultBehavior(self):
|
||||
"""Tests the behavior of not specifying the fail_fast."""
|
||||
|
||||
txt, _ = RunAndReturnOutput()
|
||||
self.assertIn('22 FAILED TEST', txt)
|
||||
|
||||
def testGoogletestFlag(self):
|
||||
txt, _ = RunAndReturnOutput(test_suite='HasSimpleTest', fail_fast=True)
|
||||
self.assertIn('1 FAILED TEST', txt)
|
||||
self.assertIn('[ SKIPPED ] 3 tests', txt)
|
||||
|
||||
txt, _ = RunAndReturnOutput(test_suite='HasSimpleTest', fail_fast=False)
|
||||
self.assertIn('4 FAILED TEST', txt)
|
||||
self.assertNotIn('[ SKIPPED ]', txt)
|
||||
|
||||
def testGoogletestEnvVar(self):
|
||||
"""Tests the behavior of specifying fail_fast via Googletest env var."""
|
||||
|
||||
try:
|
||||
SetEnvVar(FAIL_FAST_ENV_VAR, '1')
|
||||
txt, _ = RunAndReturnOutput('HasSimpleTest')
|
||||
self.assertIn('1 FAILED TEST', txt)
|
||||
self.assertIn('[ SKIPPED ] 3 tests', txt)
|
||||
|
||||
SetEnvVar(FAIL_FAST_ENV_VAR, '0')
|
||||
txt, _ = RunAndReturnOutput('HasSimpleTest')
|
||||
self.assertIn('4 FAILED TEST', txt)
|
||||
self.assertNotIn('[ SKIPPED ]', txt)
|
||||
finally:
|
||||
SetEnvVar(FAIL_FAST_ENV_VAR, None)
|
||||
|
||||
def testBazelEnvVar(self):
|
||||
"""Tests the behavior of specifying fail_fast via Bazel testbridge."""
|
||||
|
||||
try:
|
||||
SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '1')
|
||||
txt, _ = RunAndReturnOutput('HasSimpleTest')
|
||||
self.assertIn('1 FAILED TEST', txt)
|
||||
self.assertIn('[ SKIPPED ] 3 tests', txt)
|
||||
|
||||
SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '0')
|
||||
txt, _ = RunAndReturnOutput('HasSimpleTest')
|
||||
self.assertIn('4 FAILED TEST', txt)
|
||||
self.assertNotIn('[ SKIPPED ]', txt)
|
||||
finally:
|
||||
SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, None)
|
||||
|
||||
def testFlagOverridesEnvVar(self):
|
||||
"""Tests precedence of flag over env var."""
|
||||
|
||||
try:
|
||||
SetEnvVar(FAIL_FAST_ENV_VAR, '0')
|
||||
txt, _ = RunAndReturnOutput('HasSimpleTest', True)
|
||||
self.assertIn('1 FAILED TEST', txt)
|
||||
self.assertIn('[ SKIPPED ] 3 tests', txt)
|
||||
finally:
|
||||
SetEnvVar(FAIL_FAST_ENV_VAR, None)
|
||||
|
||||
def testGoogletestEnvVarOverridesBazelEnvVar(self):
|
||||
"""Tests that the Googletest native env var over Bazel testbridge."""
|
||||
|
||||
try:
|
||||
SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '0')
|
||||
SetEnvVar(FAIL_FAST_ENV_VAR, '1')
|
||||
txt, _ = RunAndReturnOutput('HasSimpleTest')
|
||||
self.assertIn('1 FAILED TEST', txt)
|
||||
self.assertIn('[ SKIPPED ] 3 tests', txt)
|
||||
finally:
|
||||
SetEnvVar(FAIL_FAST_ENV_VAR, None)
|
||||
SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, None)
|
||||
|
||||
def testEventListener(self):
|
||||
txt, _ = RunAndReturnOutput(test_suite='HasSkipTest', fail_fast=True)
|
||||
self.assertIn('1 FAILED TEST', txt)
|
||||
self.assertIn('[ SKIPPED ] 3 tests', txt)
|
||||
for expected_count, callback in [(1, 'OnTestSuiteStart'),
|
||||
(5, 'OnTestStart'),
|
||||
(5, 'OnTestEnd'),
|
||||
(5, 'OnTestPartResult'),
|
||||
(1, 'OnTestSuiteEnd')]:
|
||||
self.assertEqual(
|
||||
expected_count, txt.count(callback),
|
||||
'Expected %d calls to callback %s match count on output: %s ' %
|
||||
(expected_count, callback, txt))
|
||||
|
||||
txt, _ = RunAndReturnOutput(test_suite='HasSkipTest', fail_fast=False)
|
||||
self.assertIn('3 FAILED TEST', txt)
|
||||
self.assertIn('[ SKIPPED ] 1 test', txt)
|
||||
for expected_count, callback in [(1, 'OnTestSuiteStart'),
|
||||
(5, 'OnTestStart'),
|
||||
(5, 'OnTestEnd'),
|
||||
(5, 'OnTestPartResult'),
|
||||
(1, 'OnTestSuiteEnd')]:
|
||||
self.assertEqual(
|
||||
expected_count, txt.count(callback),
|
||||
'Expected %d calls to callback %s match count on output: %s ' %
|
||||
(expected_count, callback, txt))
|
||||
|
||||
def assertXmlResultCount(self, result, count, xml):
|
||||
self.assertEqual(
|
||||
count, xml.count('result="%s"' % result),
|
||||
'Expected \'result="%s"\' match count of %s: %s ' %
|
||||
(result, count, xml))
|
||||
|
||||
def assertXmlStatusCount(self, status, count, xml):
|
||||
self.assertEqual(
|
||||
count, xml.count('status="%s"' % status),
|
||||
'Expected \'status="%s"\' match count of %s: %s ' %
|
||||
(status, count, xml))
|
||||
|
||||
def assertFailFastXmlAndTxtOutput(self,
|
||||
fail_fast,
|
||||
test_suite,
|
||||
passed_count,
|
||||
failure_count,
|
||||
skipped_count,
|
||||
suppressed_count,
|
||||
run_disabled=False):
|
||||
"""Assert XML and text output of a test execution."""
|
||||
|
||||
txt, xml = RunAndReturnOutput(test_suite, fail_fast, run_disabled)
|
||||
if failure_count > 0:
|
||||
self.assertIn('%s FAILED TEST' % failure_count, txt)
|
||||
if suppressed_count > 0:
|
||||
self.assertIn('%s DISABLED TEST' % suppressed_count, txt)
|
||||
if skipped_count > 0:
|
||||
self.assertIn('[ SKIPPED ] %s tests' % skipped_count, txt)
|
||||
self.assertXmlStatusCount('run',
|
||||
passed_count + failure_count + skipped_count, xml)
|
||||
self.assertXmlStatusCount('notrun', suppressed_count, xml)
|
||||
self.assertXmlResultCount('completed', passed_count + failure_count, xml)
|
||||
self.assertXmlResultCount('skipped', skipped_count, xml)
|
||||
self.assertXmlResultCount('suppressed', suppressed_count, xml)
|
||||
|
||||
def assertFailFastBehavior(self,
|
||||
test_suite,
|
||||
passed_count,
|
||||
failure_count,
|
||||
skipped_count,
|
||||
suppressed_count,
|
||||
run_disabled=False):
|
||||
"""Assert --fail_fast via flag."""
|
||||
|
||||
for fail_fast in ('true', '1', 't', True):
|
||||
self.assertFailFastXmlAndTxtOutput(fail_fast, test_suite, passed_count,
|
||||
failure_count, skipped_count,
|
||||
suppressed_count, run_disabled)
|
||||
|
||||
def assertNotFailFastBehavior(self,
|
||||
test_suite,
|
||||
passed_count,
|
||||
failure_count,
|
||||
skipped_count,
|
||||
suppressed_count,
|
||||
run_disabled=False):
|
||||
"""Assert --nofail_fast via flag."""
|
||||
|
||||
for fail_fast in ('false', '0', 'f', False):
|
||||
self.assertFailFastXmlAndTxtOutput(fail_fast, test_suite, passed_count,
|
||||
failure_count, skipped_count,
|
||||
suppressed_count, run_disabled)
|
||||
|
||||
def testFlag_HasFixtureTest(self):
|
||||
"""Tests the behavior of fail_fast and TEST_F."""
|
||||
self.assertFailFastBehavior(
|
||||
test_suite='HasFixtureTest',
|
||||
passed_count=1,
|
||||
failure_count=1,
|
||||
skipped_count=3,
|
||||
suppressed_count=0)
|
||||
self.assertNotFailFastBehavior(
|
||||
test_suite='HasFixtureTest',
|
||||
passed_count=1,
|
||||
failure_count=4,
|
||||
skipped_count=0,
|
||||
suppressed_count=0)
|
||||
|
||||
def testFlag_HasSimpleTest(self):
|
||||
"""Tests the behavior of fail_fast and TEST."""
|
||||
self.assertFailFastBehavior(
|
||||
test_suite='HasSimpleTest',
|
||||
passed_count=1,
|
||||
failure_count=1,
|
||||
skipped_count=3,
|
||||
suppressed_count=0)
|
||||
self.assertNotFailFastBehavior(
|
||||
test_suite='HasSimpleTest',
|
||||
passed_count=1,
|
||||
failure_count=4,
|
||||
skipped_count=0,
|
||||
suppressed_count=0)
|
||||
|
||||
def testFlag_HasParametersTest(self):
|
||||
"""Tests the behavior of fail_fast and TEST_P."""
|
||||
self.assertFailFastBehavior(
|
||||
test_suite='HasParametersSuite/HasParametersTest',
|
||||
passed_count=0,
|
||||
failure_count=1,
|
||||
skipped_count=3,
|
||||
suppressed_count=0)
|
||||
self.assertNotFailFastBehavior(
|
||||
test_suite='HasParametersSuite/HasParametersTest',
|
||||
passed_count=0,
|
||||
failure_count=4,
|
||||
skipped_count=0,
|
||||
suppressed_count=0)
|
||||
|
||||
def testFlag_HasDisabledTest(self):
|
||||
"""Tests the behavior of fail_fast and Disabled test cases."""
|
||||
self.assertFailFastBehavior(
|
||||
test_suite='HasDisabledTest',
|
||||
passed_count=1,
|
||||
failure_count=1,
|
||||
skipped_count=2,
|
||||
suppressed_count=1,
|
||||
run_disabled=False)
|
||||
self.assertNotFailFastBehavior(
|
||||
test_suite='HasDisabledTest',
|
||||
passed_count=1,
|
||||
failure_count=3,
|
||||
skipped_count=0,
|
||||
suppressed_count=1,
|
||||
run_disabled=False)
|
||||
|
||||
def testFlag_HasDisabledRunDisabledTest(self):
|
||||
"""Tests the behavior of fail_fast and Disabled test cases enabled."""
|
||||
self.assertFailFastBehavior(
|
||||
test_suite='HasDisabledTest',
|
||||
passed_count=1,
|
||||
failure_count=1,
|
||||
skipped_count=3,
|
||||
suppressed_count=0,
|
||||
run_disabled=True)
|
||||
self.assertNotFailFastBehavior(
|
||||
test_suite='HasDisabledTest',
|
||||
passed_count=1,
|
||||
failure_count=4,
|
||||
skipped_count=0,
|
||||
suppressed_count=0,
|
||||
run_disabled=True)
|
||||
|
||||
def testFlag_HasDisabledSuiteTest(self):
|
||||
"""Tests the behavior of fail_fast and Disabled test suites."""
|
||||
self.assertFailFastBehavior(
|
||||
test_suite='DISABLED_HasDisabledSuite',
|
||||
passed_count=0,
|
||||
failure_count=0,
|
||||
skipped_count=0,
|
||||
suppressed_count=5,
|
||||
run_disabled=False)
|
||||
self.assertNotFailFastBehavior(
|
||||
test_suite='DISABLED_HasDisabledSuite',
|
||||
passed_count=0,
|
||||
failure_count=0,
|
||||
skipped_count=0,
|
||||
suppressed_count=5,
|
||||
run_disabled=False)
|
||||
|
||||
def testFlag_HasDisabledSuiteRunDisabledTest(self):
|
||||
"""Tests the behavior of fail_fast and Disabled test suites enabled."""
|
||||
self.assertFailFastBehavior(
|
||||
test_suite='DISABLED_HasDisabledSuite',
|
||||
passed_count=1,
|
||||
failure_count=1,
|
||||
skipped_count=3,
|
||||
suppressed_count=0,
|
||||
run_disabled=True)
|
||||
self.assertNotFailFastBehavior(
|
||||
test_suite='DISABLED_HasDisabledSuite',
|
||||
passed_count=1,
|
||||
failure_count=4,
|
||||
skipped_count=0,
|
||||
suppressed_count=0,
|
||||
run_disabled=True)
|
||||
|
||||
if SUPPORTS_DEATH_TESTS:
|
||||
|
||||
def testFlag_HasDeathTest(self):
|
||||
"""Tests the behavior of fail_fast and death tests."""
|
||||
self.assertFailFastBehavior(
|
||||
test_suite='HasDeathTest',
|
||||
passed_count=1,
|
||||
failure_count=1,
|
||||
skipped_count=3,
|
||||
suppressed_count=0)
|
||||
self.assertNotFailFastBehavior(
|
||||
test_suite='HasDeathTest',
|
||||
passed_count=1,
|
||||
failure_count=4,
|
||||
skipped_count=0,
|
||||
suppressed_count=0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
gtest_test_utils.Main()
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright 2005, 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.
|
||||
|
||||
|
||||
// Unit test for Google Test test filters.
|
||||
//
|
||||
// A user can specify which test(s) in a Google Test program to run via
|
||||
// either the GTEST_FILTER environment variable or the --gtest_filter
|
||||
// flag. This is used for testing such functionality.
|
||||
//
|
||||
// The program will be invoked from a Python unit test. Don't run it
|
||||
// directly.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Test HasFixtureTest.
|
||||
|
||||
class HasFixtureTest : public testing::Test {};
|
||||
|
||||
TEST_F(HasFixtureTest, Test0) {}
|
||||
|
||||
TEST_F(HasFixtureTest, Test1) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST_F(HasFixtureTest, Test2) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST_F(HasFixtureTest, Test3) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST_F(HasFixtureTest, Test4) { FAIL() << "Expected failure."; }
|
||||
|
||||
// Test HasSimpleTest.
|
||||
|
||||
TEST(HasSimpleTest, Test0) {}
|
||||
|
||||
TEST(HasSimpleTest, Test1) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(HasSimpleTest, Test2) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(HasSimpleTest, Test3) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(HasSimpleTest, Test4) { FAIL() << "Expected failure."; }
|
||||
|
||||
// Test HasDisabledTest.
|
||||
|
||||
TEST(HasDisabledTest, Test0) {}
|
||||
|
||||
TEST(HasDisabledTest, DISABLED_Test1) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(HasDisabledTest, Test2) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(HasDisabledTest, Test3) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(HasDisabledTest, Test4) { FAIL() << "Expected failure."; }
|
||||
|
||||
// Test HasDeathTest
|
||||
|
||||
TEST(HasDeathTest, Test0) { EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*"); }
|
||||
|
||||
TEST(HasDeathTest, Test1) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(FAIL() << "Expected failure.", ".*");
|
||||
}
|
||||
|
||||
TEST(HasDeathTest, Test2) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(FAIL() << "Expected failure.", ".*");
|
||||
}
|
||||
|
||||
TEST(HasDeathTest, Test3) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(FAIL() << "Expected failure.", ".*");
|
||||
}
|
||||
|
||||
TEST(HasDeathTest, Test4) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(FAIL() << "Expected failure.", ".*");
|
||||
}
|
||||
|
||||
// Test DISABLED_HasDisabledSuite
|
||||
|
||||
TEST(DISABLED_HasDisabledSuite, Test0) {}
|
||||
|
||||
TEST(DISABLED_HasDisabledSuite, Test1) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(DISABLED_HasDisabledSuite, Test2) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(DISABLED_HasDisabledSuite, Test3) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(DISABLED_HasDisabledSuite, Test4) { FAIL() << "Expected failure."; }
|
||||
|
||||
// Test HasParametersTest
|
||||
|
||||
class HasParametersTest : public testing::TestWithParam<int> {};
|
||||
|
||||
TEST_P(HasParametersTest, Test1) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST_P(HasParametersTest, Test2) { FAIL() << "Expected failure."; }
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(HasParametersSuite, HasParametersTest,
|
||||
testing::Values(1, 2));
|
||||
|
||||
class MyTestListener : public ::testing::EmptyTestEventListener {
|
||||
void OnTestSuiteStart(const ::testing::TestSuite& test_suite) override {
|
||||
printf("We are in OnTestSuiteStart of %s.\n", test_suite.name());
|
||||
}
|
||||
|
||||
void OnTestStart(const ::testing::TestInfo& test_info) override {
|
||||
printf("We are in OnTestStart of %s.%s.\n", test_info.test_suite_name(),
|
||||
test_info.name());
|
||||
}
|
||||
|
||||
void OnTestPartResult(
|
||||
const ::testing::TestPartResult& test_part_result) override {
|
||||
printf("We are in OnTestPartResult %s:%d.\n", test_part_result.file_name(),
|
||||
test_part_result.line_number());
|
||||
}
|
||||
|
||||
void OnTestEnd(const ::testing::TestInfo& test_info) override {
|
||||
printf("We are in OnTestEnd of %s.%s.\n", test_info.test_suite_name(),
|
||||
test_info.name());
|
||||
}
|
||||
|
||||
void OnTestSuiteEnd(const ::testing::TestSuite& test_suite) override {
|
||||
printf("We are in OnTestSuiteEnd of %s.\n", test_suite.name());
|
||||
}
|
||||
};
|
||||
|
||||
TEST(HasSkipTest, Test0) { SUCCEED() << "Expected success."; }
|
||||
|
||||
TEST(HasSkipTest, Test1) { GTEST_SKIP() << "Expected skip."; }
|
||||
|
||||
TEST(HasSkipTest, Test2) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(HasSkipTest, Test3) { FAIL() << "Expected failure."; }
|
||||
|
||||
TEST(HasSkipTest, Test4) { FAIL() << "Expected failure."; }
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
::testing::UnitTest::GetInstance()->listeners().Append(new MyTestListener());
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
|
@ -40,10 +40,10 @@
|
|||
#include "src/gtest-internal-inl.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
#include <windows.h> // NOLINT
|
||||
# include <windows.h> // NOLINT
|
||||
#elif GTEST_OS_WINDOWS
|
||||
#include <direct.h> // NOLINT
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
# include <direct.h> // NOLINT
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
@ -55,16 +55,16 @@ namespace {
|
|||
int remove(const char* path) {
|
||||
LPCWSTR wpath = String::AnsiToUtf16(path);
|
||||
int ret = DeleteFile(wpath) ? 0 : -1;
|
||||
delete[] wpath;
|
||||
delete [] wpath;
|
||||
return ret;
|
||||
}
|
||||
// Windows CE doesn't have the _rmdir C function.
|
||||
int _rmdir(const char* path) {
|
||||
FilePath filepath(path);
|
||||
LPCWSTR wpath =
|
||||
String::AnsiToUtf16(filepath.RemoveTrailingPathSeparator().c_str());
|
||||
LPCWSTR wpath = String::AnsiToUtf16(
|
||||
filepath.RemoveTrailingPathSeparator().c_str());
|
||||
int ret = RemoveDirectory(wpath) ? 0 : -1;
|
||||
delete[] wpath;
|
||||
delete [] wpath;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -78,18 +78,18 @@ TEST(GetCurrentDirTest, ReturnsCurrentDir) {
|
|||
const FilePath cwd = FilePath::GetCurrentDir();
|
||||
posix::ChDir(original_dir.c_str());
|
||||
|
||||
#if GTEST_OS_WINDOWS || GTEST_OS_OS2
|
||||
# if GTEST_OS_WINDOWS || GTEST_OS_OS2
|
||||
|
||||
// Skips the ":".
|
||||
const char* const cwd_without_drive = strchr(cwd.c_str(), ':');
|
||||
ASSERT_TRUE(cwd_without_drive != NULL);
|
||||
EXPECT_STREQ(GTEST_PATH_SEP_, cwd_without_drive + 1);
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
EXPECT_EQ(GTEST_PATH_SEP_, cwd.string());
|
||||
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
@ -112,34 +112,33 @@ TEST(RemoveDirectoryNameTest, WhenEmptyName) {
|
|||
|
||||
// RemoveDirectoryName "afile" -> "afile"
|
||||
TEST(RemoveDirectoryNameTest, ButNoDirectory) {
|
||||
EXPECT_EQ("afile", FilePath("afile").RemoveDirectoryName().string());
|
||||
EXPECT_EQ("afile",
|
||||
FilePath("afile").RemoveDirectoryName().string());
|
||||
}
|
||||
|
||||
// RemoveDirectoryName "/afile" -> "afile"
|
||||
TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileName) {
|
||||
EXPECT_EQ("afile",
|
||||
FilePath(GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
|
||||
FilePath(GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
|
||||
}
|
||||
|
||||
// RemoveDirectoryName "adir/" -> ""
|
||||
TEST(RemoveDirectoryNameTest, WhereThereIsNoFileName) {
|
||||
EXPECT_EQ("",
|
||||
FilePath("adir" GTEST_PATH_SEP_).RemoveDirectoryName().string());
|
||||
FilePath("adir" GTEST_PATH_SEP_).RemoveDirectoryName().string());
|
||||
}
|
||||
|
||||
// RemoveDirectoryName "adir/afile" -> "afile"
|
||||
TEST(RemoveDirectoryNameTest, ShouldGiveFileName) {
|
||||
EXPECT_EQ(
|
||||
"afile",
|
||||
EXPECT_EQ("afile",
|
||||
FilePath("adir" GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
|
||||
}
|
||||
|
||||
// RemoveDirectoryName "adir/subdir/afile" -> "afile"
|
||||
TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileName) {
|
||||
EXPECT_EQ("afile",
|
||||
FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
|
||||
.RemoveDirectoryName()
|
||||
.string());
|
||||
FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
|
||||
.RemoveDirectoryName().string());
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
|
@ -183,7 +182,7 @@ TEST(RemoveFileNameTest, EmptyName) {
|
|||
// RemoveFileName "adir/" -> "adir/"
|
||||
TEST(RemoveFileNameTest, ButNoFile) {
|
||||
EXPECT_EQ("adir" GTEST_PATH_SEP_,
|
||||
FilePath("adir" GTEST_PATH_SEP_).RemoveFileName().string());
|
||||
FilePath("adir" GTEST_PATH_SEP_).RemoveFileName().string());
|
||||
}
|
||||
|
||||
// RemoveFileName "adir/afile" -> "adir/"
|
||||
|
@ -195,15 +194,14 @@ TEST(RemoveFileNameTest, GivesDirName) {
|
|||
// RemoveFileName "adir/subdir/afile" -> "adir/subdir/"
|
||||
TEST(RemoveFileNameTest, GivesDirAndSubDirName) {
|
||||
EXPECT_EQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
|
||||
FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
|
||||
.RemoveFileName()
|
||||
.string());
|
||||
FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
|
||||
.RemoveFileName().string());
|
||||
}
|
||||
|
||||
// RemoveFileName "/afile" -> "/"
|
||||
TEST(RemoveFileNameTest, GivesRootDir) {
|
||||
EXPECT_EQ(GTEST_PATH_SEP_,
|
||||
FilePath(GTEST_PATH_SEP_ "afile").RemoveFileName().string());
|
||||
FilePath(GTEST_PATH_SEP_ "afile").RemoveFileName().string());
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
|
@ -237,43 +235,44 @@ TEST(RemoveFileNameTest, GivesRootDirForAlternateSeparator) {
|
|||
#endif
|
||||
|
||||
TEST(MakeFileNameTest, GenerateWhenNumberIsZero) {
|
||||
FilePath actual =
|
||||
FilePath::MakeFileName(FilePath("foo"), FilePath("bar"), 0, "xml");
|
||||
FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
|
||||
0, "xml");
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
|
||||
}
|
||||
|
||||
TEST(MakeFileNameTest, GenerateFileNameNumberGtZero) {
|
||||
FilePath actual =
|
||||
FilePath::MakeFileName(FilePath("foo"), FilePath("bar"), 12, "xml");
|
||||
FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
|
||||
12, "xml");
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.string());
|
||||
}
|
||||
|
||||
TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberIsZero) {
|
||||
FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
|
||||
FilePath("bar"), 0, "xml");
|
||||
FilePath("bar"), 0, "xml");
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
|
||||
}
|
||||
|
||||
TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberGtZero) {
|
||||
FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
|
||||
FilePath("bar"), 12, "xml");
|
||||
FilePath("bar"), 12, "xml");
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.string());
|
||||
}
|
||||
|
||||
TEST(MakeFileNameTest, GenerateWhenNumberIsZeroAndDirIsEmpty) {
|
||||
FilePath actual =
|
||||
FilePath::MakeFileName(FilePath(""), FilePath("bar"), 0, "xml");
|
||||
FilePath actual = FilePath::MakeFileName(FilePath(""), FilePath("bar"),
|
||||
0, "xml");
|
||||
EXPECT_EQ("bar.xml", actual.string());
|
||||
}
|
||||
|
||||
TEST(MakeFileNameTest, GenerateWhenNumberIsNotZeroAndDirIsEmpty) {
|
||||
FilePath actual =
|
||||
FilePath::MakeFileName(FilePath(""), FilePath("bar"), 14, "xml");
|
||||
FilePath actual = FilePath::MakeFileName(FilePath(""), FilePath("bar"),
|
||||
14, "xml");
|
||||
EXPECT_EQ("bar_14.xml", actual.string());
|
||||
}
|
||||
|
||||
TEST(ConcatPathsTest, WorksWhenDirDoesNotEndWithPathSep) {
|
||||
FilePath actual = FilePath::ConcatPaths(FilePath("foo"), FilePath("bar.xml"));
|
||||
FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
|
||||
FilePath("bar.xml"));
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
|
||||
}
|
||||
|
||||
|
@ -284,7 +283,8 @@ TEST(ConcatPathsTest, WorksWhenPath1EndsWithPathSep) {
|
|||
}
|
||||
|
||||
TEST(ConcatPathsTest, Path1BeingEmpty) {
|
||||
FilePath actual = FilePath::ConcatPaths(FilePath(""), FilePath("bar.xml"));
|
||||
FilePath actual = FilePath::ConcatPaths(FilePath(""),
|
||||
FilePath("bar.xml"));
|
||||
EXPECT_EQ("bar.xml", actual.string());
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,8 @@ TEST(ConcatPathsTest, Path2BeingEmpty) {
|
|||
}
|
||||
|
||||
TEST(ConcatPathsTest, BothPathBeingEmpty) {
|
||||
FilePath actual = FilePath::ConcatPaths(FilePath(""), FilePath(""));
|
||||
FilePath actual = FilePath::ConcatPaths(FilePath(""),
|
||||
FilePath(""));
|
||||
EXPECT_EQ("", actual.string());
|
||||
}
|
||||
|
||||
|
@ -306,16 +307,16 @@ TEST(ConcatPathsTest, Path1ContainsPathSep) {
|
|||
}
|
||||
|
||||
TEST(ConcatPathsTest, Path2ContainsPathSep) {
|
||||
FilePath actual =
|
||||
FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_),
|
||||
FilePath("bar" GTEST_PATH_SEP_ "bar.xml"));
|
||||
FilePath actual = FilePath::ConcatPaths(
|
||||
FilePath("foo" GTEST_PATH_SEP_),
|
||||
FilePath("bar" GTEST_PATH_SEP_ "bar.xml"));
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "bar.xml",
|
||||
actual.string());
|
||||
}
|
||||
|
||||
TEST(ConcatPathsTest, Path2EndsWithPathSep) {
|
||||
FilePath actual =
|
||||
FilePath::ConcatPaths(FilePath("foo"), FilePath("bar" GTEST_PATH_SEP_));
|
||||
FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
|
||||
FilePath("bar" GTEST_PATH_SEP_));
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_, actual.string());
|
||||
}
|
||||
|
||||
|
@ -331,8 +332,7 @@ TEST(RemoveTrailingPathSeparatorTest, FileNoSlashString) {
|
|||
|
||||
// RemoveTrailingPathSeparator "foo/" -> "foo"
|
||||
TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveTrailingSeparator) {
|
||||
EXPECT_EQ(
|
||||
"foo",
|
||||
EXPECT_EQ("foo",
|
||||
FilePath("foo" GTEST_PATH_SEP_).RemoveTrailingPathSeparator().string());
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
EXPECT_EQ("foo", FilePath("foo/").RemoveTrailingPathSeparator().string());
|
||||
|
@ -343,19 +343,18 @@ TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveTrailingSeparator) {
|
|||
TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveLastSeparator) {
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
|
||||
FilePath("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_)
|
||||
.RemoveTrailingPathSeparator()
|
||||
.string());
|
||||
.RemoveTrailingPathSeparator().string());
|
||||
}
|
||||
|
||||
// RemoveTrailingPathSeparator "foo/bar" -> "foo/bar"
|
||||
TEST(RemoveTrailingPathSeparatorTest, ShouldReturnUnmodified) {
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar", FilePath("foo" GTEST_PATH_SEP_ "bar")
|
||||
.RemoveTrailingPathSeparator()
|
||||
.string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
|
||||
FilePath("foo" GTEST_PATH_SEP_ "bar")
|
||||
.RemoveTrailingPathSeparator().string());
|
||||
}
|
||||
|
||||
TEST(DirectoryTest, RootDirectoryExists) {
|
||||
#if GTEST_OS_WINDOWS // We are on Windows.
|
||||
#if GTEST_OS_WINDOWS // We are on Windows.
|
||||
char current_drive[_MAX_PATH]; // NOLINT
|
||||
current_drive[0] = static_cast<char>(_getdrive() + 'A' - 1);
|
||||
current_drive[1] = ':';
|
||||
|
@ -394,12 +393,12 @@ TEST(DirectoryTest, EmptyPathDirectoryDoesNotExist) {
|
|||
|
||||
TEST(DirectoryTest, CurrentDirectoryExists) {
|
||||
#if GTEST_OS_WINDOWS // We are on Windows.
|
||||
#ifndef _WIN32_CE // Windows CE doesn't have a current directory.
|
||||
# ifndef _WIN32_CE // Windows CE doesn't have a current directory.
|
||||
|
||||
EXPECT_TRUE(FilePath(".").DirectoryExists());
|
||||
EXPECT_TRUE(FilePath(".\\").DirectoryExists());
|
||||
|
||||
#endif // _WIN32_CE
|
||||
# endif // _WIN32_CE
|
||||
#else
|
||||
EXPECT_TRUE(FilePath(".").DirectoryExists());
|
||||
EXPECT_TRUE(FilePath("./").DirectoryExists());
|
||||
|
@ -412,30 +411,29 @@ TEST(NormalizeTest, MultipleConsecutiveSepaparatorsInMidstring) {
|
|||
FilePath("foo" GTEST_PATH_SEP_ "bar").string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
|
||||
FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
|
||||
EXPECT_EQ(
|
||||
"foo" GTEST_PATH_SEP_ "bar",
|
||||
FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar")
|
||||
.string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
|
||||
FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_
|
||||
GTEST_PATH_SEP_ "bar").string());
|
||||
}
|
||||
|
||||
// "/bar" == //bar" == "///bar"
|
||||
TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringStart) {
|
||||
EXPECT_EQ(GTEST_PATH_SEP_ "bar", FilePath(GTEST_PATH_SEP_ "bar").string());
|
||||
EXPECT_EQ(GTEST_PATH_SEP_ "bar",
|
||||
FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
|
||||
EXPECT_EQ(
|
||||
GTEST_PATH_SEP_ "bar",
|
||||
FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
|
||||
FilePath(GTEST_PATH_SEP_ "bar").string());
|
||||
EXPECT_EQ(GTEST_PATH_SEP_ "bar",
|
||||
FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
|
||||
EXPECT_EQ(GTEST_PATH_SEP_ "bar",
|
||||
FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
|
||||
}
|
||||
|
||||
// "foo/" == foo//" == "foo///"
|
||||
TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringEnd) {
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_, FilePath("foo" GTEST_PATH_SEP_).string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
|
||||
EXPECT_EQ(
|
||||
"foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
|
||||
FilePath("foo" GTEST_PATH_SEP_).string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
|
@ -444,10 +442,12 @@ TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringEnd) {
|
|||
// regardless of their combination (e.g. "foo\" =="foo/\" ==
|
||||
// "foo\\/").
|
||||
TEST(NormalizeTest, MixAlternateSeparatorAtStringEnd) {
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_, FilePath("foo/").string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo/").string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo" GTEST_PATH_SEP_ "/").string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_, FilePath("foo//" GTEST_PATH_SEP_).string());
|
||||
EXPECT_EQ("foo" GTEST_PATH_SEP_,
|
||||
FilePath("foo//" GTEST_PATH_SEP_).string());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -478,15 +478,15 @@ TEST(AssignmentOperatorTest, ConstAssignedToNonConst) {
|
|||
class DirectoryCreationTest : public Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
testdata_path_.Set(
|
||||
FilePath(TempDir() + GetCurrentExecutableName().string() +
|
||||
"_directory_creation" GTEST_PATH_SEP_ "test" GTEST_PATH_SEP_));
|
||||
testdata_path_.Set(FilePath(
|
||||
TempDir() + GetCurrentExecutableName().string() +
|
||||
"_directory_creation" GTEST_PATH_SEP_ "test" GTEST_PATH_SEP_));
|
||||
testdata_file_.Set(testdata_path_.RemoveTrailingPathSeparator());
|
||||
|
||||
unique_file0_.Set(
|
||||
FilePath::MakeFileName(testdata_path_, FilePath("unique"), 0, "txt"));
|
||||
unique_file1_.Set(
|
||||
FilePath::MakeFileName(testdata_path_, FilePath("unique"), 1, "txt"));
|
||||
unique_file0_.Set(FilePath::MakeFileName(testdata_path_, FilePath("unique"),
|
||||
0, "txt"));
|
||||
unique_file1_.Set(FilePath::MakeFileName(testdata_path_, FilePath("unique"),
|
||||
1, "txt"));
|
||||
|
||||
remove(testdata_file_.c_str());
|
||||
remove(unique_file0_.c_str());
|
||||
|
@ -512,8 +512,8 @@ class DirectoryCreationTest : public Test {
|
|||
// a directory named 'test' from a file named 'test'. Example names:
|
||||
FilePath testdata_path_; // "/tmp/directory_creation/test/"
|
||||
FilePath testdata_file_; // "/tmp/directory_creation/test"
|
||||
FilePath unique_file0_; // "/tmp/directory_creation/test/unique.txt"
|
||||
FilePath unique_file1_; // "/tmp/directory_creation/test/unique_1.txt"
|
||||
FilePath unique_file0_; // "/tmp/directory_creation/test/unique.txt"
|
||||
FilePath unique_file1_; // "/tmp/directory_creation/test/unique_1.txt"
|
||||
};
|
||||
|
||||
TEST_F(DirectoryCreationTest, CreateDirectoriesRecursively) {
|
||||
|
@ -530,8 +530,8 @@ TEST_F(DirectoryCreationTest, CreateDirectoriesForAlreadyExistingPath) {
|
|||
}
|
||||
|
||||
TEST_F(DirectoryCreationTest, CreateDirectoriesAndUniqueFilename) {
|
||||
FilePath file_path(FilePath::GenerateUniqueFileName(
|
||||
testdata_path_, FilePath("unique"), "txt"));
|
||||
FilePath file_path(FilePath::GenerateUniqueFileName(testdata_path_,
|
||||
FilePath("unique"), "txt"));
|
||||
EXPECT_EQ(unique_file0_.string(), file_path.string());
|
||||
EXPECT_FALSE(file_path.FileOrDirectoryExists()); // file not there
|
||||
|
||||
|
@ -540,8 +540,8 @@ TEST_F(DirectoryCreationTest, CreateDirectoriesAndUniqueFilename) {
|
|||
CreateTextFile(file_path.c_str());
|
||||
EXPECT_TRUE(file_path.FileOrDirectoryExists());
|
||||
|
||||
FilePath file_path2(FilePath::GenerateUniqueFileName(
|
||||
testdata_path_, FilePath("unique"), "txt"));
|
||||
FilePath file_path2(FilePath::GenerateUniqueFileName(testdata_path_,
|
||||
FilePath("unique"), "txt"));
|
||||
EXPECT_EQ(unique_file1_.string(), file_path2.string());
|
||||
EXPECT_FALSE(file_path2.FileOrDirectoryExists()); // file not there
|
||||
CreateTextFile(file_path2.c_str());
|
||||
|
@ -614,16 +614,14 @@ TEST(FilePathTest, IsAbsolutePath) {
|
|||
EXPECT_FALSE(FilePath("is" GTEST_PATH_SEP_ "relative").IsAbsolutePath());
|
||||
EXPECT_FALSE(FilePath("").IsAbsolutePath());
|
||||
#if GTEST_OS_WINDOWS
|
||||
EXPECT_TRUE(
|
||||
FilePath("c:\\" GTEST_PATH_SEP_ "is_not" GTEST_PATH_SEP_ "relative")
|
||||
.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());
|
||||
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());
|
||||
.IsAbsolutePath());
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
// Unit test for Google Test test filters.
|
||||
//
|
||||
// A user can specify which test(s) in a Google Test program to run via
|
||||
|
@ -42,57 +43,87 @@ namespace {
|
|||
|
||||
// Test case FooTest.
|
||||
|
||||
class FooTest : public testing::Test {};
|
||||
class FooTest : public testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(FooTest, Abc) {}
|
||||
TEST_F(FooTest, Abc) {
|
||||
}
|
||||
|
||||
TEST_F(FooTest, Xyz) { FAIL() << "Expected failure."; }
|
||||
TEST_F(FooTest, Xyz) {
|
||||
FAIL() << "Expected failure.";
|
||||
}
|
||||
|
||||
// Test case BarTest.
|
||||
|
||||
TEST(BarTest, TestOne) {}
|
||||
TEST(BarTest, TestOne) {
|
||||
}
|
||||
|
||||
TEST(BarTest, TestTwo) {}
|
||||
TEST(BarTest, TestTwo) {
|
||||
}
|
||||
|
||||
TEST(BarTest, TestThree) {}
|
||||
TEST(BarTest, TestThree) {
|
||||
}
|
||||
|
||||
TEST(BarTest, DISABLED_TestFour) { FAIL() << "Expected failure."; }
|
||||
TEST(BarTest, DISABLED_TestFour) {
|
||||
FAIL() << "Expected failure.";
|
||||
}
|
||||
|
||||
TEST(BarTest, DISABLED_TestFive) { FAIL() << "Expected failure."; }
|
||||
TEST(BarTest, DISABLED_TestFive) {
|
||||
FAIL() << "Expected failure.";
|
||||
}
|
||||
|
||||
// Test case BazTest.
|
||||
|
||||
TEST(BazTest, TestOne) { FAIL() << "Expected failure."; }
|
||||
TEST(BazTest, TestOne) {
|
||||
FAIL() << "Expected failure.";
|
||||
}
|
||||
|
||||
TEST(BazTest, TestA) {}
|
||||
TEST(BazTest, TestA) {
|
||||
}
|
||||
|
||||
TEST(BazTest, TestB) {}
|
||||
TEST(BazTest, TestB) {
|
||||
}
|
||||
|
||||
TEST(BazTest, DISABLED_TestC) { FAIL() << "Expected failure."; }
|
||||
TEST(BazTest, DISABLED_TestC) {
|
||||
FAIL() << "Expected failure.";
|
||||
}
|
||||
|
||||
// Test case HasDeathTest
|
||||
|
||||
TEST(HasDeathTest, Test1) { EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*"); }
|
||||
TEST(HasDeathTest, Test1) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
|
||||
}
|
||||
|
||||
// We need at least two death tests to make sure that the all death tests
|
||||
// aren't on the first shard.
|
||||
TEST(HasDeathTest, Test2) { EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*"); }
|
||||
TEST(HasDeathTest, Test2) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
|
||||
}
|
||||
|
||||
// Test case FoobarTest
|
||||
|
||||
TEST(DISABLED_FoobarTest, Test1) { FAIL() << "Expected failure."; }
|
||||
TEST(DISABLED_FoobarTest, Test1) {
|
||||
FAIL() << "Expected failure.";
|
||||
}
|
||||
|
||||
TEST(DISABLED_FoobarTest, DISABLED_Test2) { FAIL() << "Expected failure."; }
|
||||
TEST(DISABLED_FoobarTest, DISABLED_Test2) {
|
||||
FAIL() << "Expected failure.";
|
||||
}
|
||||
|
||||
// Test case FoobarbazTest
|
||||
|
||||
TEST(DISABLED_FoobarbazTest, TestA) { FAIL() << "Expected failure."; }
|
||||
TEST(DISABLED_FoobarbazTest, TestA) {
|
||||
FAIL() << "Expected failure.";
|
||||
}
|
||||
|
||||
class ParamTest : public testing::TestWithParam<int> {};
|
||||
class ParamTest : public testing::TestWithParam<int> {
|
||||
};
|
||||
|
||||
TEST_P(ParamTest, TestX) {}
|
||||
TEST_P(ParamTest, TestX) {
|
||||
}
|
||||
|
||||
TEST_P(ParamTest, TestY) {}
|
||||
TEST_P(ParamTest, TestY) {
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(SeqP, ParamTest, testing::Values(1, 2));
|
||||
INSTANTIATE_TEST_SUITE_P(SeqQ, ParamTest, testing::Values(5, 6));
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
# Copyright 2021 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.
|
||||
"""Unit test for Google Test's global test environment behavior.
|
||||
|
||||
A user can specify a global test environment via
|
||||
testing::AddGlobalTestEnvironment. Failures in the global environment should
|
||||
result in all unit tests being skipped.
|
||||
|
||||
This script tests such functionality by invoking
|
||||
googletest-global-environment-unittest_ (a program written with Google Test).
|
||||
"""
|
||||
|
||||
import gtest_test_utils
|
||||
|
||||
|
||||
def RunAndReturnOutput():
|
||||
"""Runs the test program and returns its output."""
|
||||
|
||||
return gtest_test_utils.Subprocess([
|
||||
gtest_test_utils.GetTestExecutablePath(
|
||||
'googletest-global-environment-unittest_')
|
||||
]).output
|
||||
|
||||
|
||||
class GTestGlobalEnvironmentUnitTest(gtest_test_utils.TestCase):
|
||||
"""Tests global test environment failures."""
|
||||
|
||||
def testEnvironmentSetUpFails(self):
|
||||
"""Tests the behavior of not specifying the fail_fast."""
|
||||
|
||||
# Run the test.
|
||||
txt = RunAndReturnOutput()
|
||||
|
||||
# We should see the text of the global environment setup error.
|
||||
self.assertIn('Canned environment setup error', txt)
|
||||
|
||||
# Our test should have been skipped due to the error, and not treated as a
|
||||
# pass.
|
||||
self.assertIn('[ SKIPPED ] 1 test', txt)
|
||||
self.assertIn('[ PASSED ] 0 tests', txt)
|
||||
|
||||
# The test case shouldn't have been run.
|
||||
self.assertNotIn('Unexpected call', txt)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
gtest_test_utils.Main()
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2005, 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.
|
||||
|
||||
// Unit test for Google Test global test environments.
|
||||
//
|
||||
// The program will be invoked from a Python unit test. Don't run it
|
||||
// directly.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// An environment that always fails in its SetUp method.
|
||||
class FailingEnvironment final : public ::testing::Environment {
|
||||
public:
|
||||
void SetUp() override { FAIL() << "Canned environment setup error"; }
|
||||
};
|
||||
|
||||
// Register the environment.
|
||||
auto* const g_environment_ =
|
||||
::testing::AddGlobalTestEnvironment(new FailingEnvironment);
|
||||
|
||||
// A test that doesn't actually run.
|
||||
TEST(SomeTest, DoesFoo) { FAIL() << "Unexpected call"; }
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
|
@ -58,9 +58,9 @@ else:
|
|||
|
||||
EXPECTED_NON_EMPTY = {
|
||||
u'tests':
|
||||
24,
|
||||
26,
|
||||
u'failures':
|
||||
4,
|
||||
5,
|
||||
u'disabled':
|
||||
2,
|
||||
u'errors':
|
||||
|
@ -158,9 +158,9 @@ EXPECTED_NON_EMPTY = {
|
|||
u'name':
|
||||
u'SkippedTest',
|
||||
u'tests':
|
||||
1,
|
||||
3,
|
||||
u'failures':
|
||||
0,
|
||||
1,
|
||||
u'disabled':
|
||||
0,
|
||||
u'errors':
|
||||
|
@ -176,6 +176,32 @@ EXPECTED_NON_EMPTY = {
|
|||
u'time': u'*',
|
||||
u'timestamp': u'*',
|
||||
u'classname': u'SkippedTest'
|
||||
}, {
|
||||
u'name': u'SkippedWithMessage',
|
||||
u'status': u'RUN',
|
||||
u'result': u'SKIPPED',
|
||||
u'time': u'*',
|
||||
u'timestamp': u'*',
|
||||
u'classname': u'SkippedTest'
|
||||
}, {
|
||||
u'name':
|
||||
u'SkippedAfterFailure',
|
||||
u'status':
|
||||
u'RUN',
|
||||
u'result':
|
||||
u'COMPLETED',
|
||||
u'time':
|
||||
u'*',
|
||||
u'timestamp':
|
||||
u'*',
|
||||
u'classname':
|
||||
u'SkippedTest',
|
||||
u'failures': [{
|
||||
u'failure': u'gtest_xml_output_unittest_.cc:*\n'
|
||||
u'Expected equality of these values:\n'
|
||||
u' 1\n 2' + STACK_TRACE_TEMPLATE,
|
||||
u'type': u''
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
u'name':
|
||||
|
@ -586,15 +612,59 @@ EXPECTED_FILTERED = {
|
|||
}],
|
||||
}
|
||||
|
||||
EXPECTED_EMPTY = {
|
||||
u'tests': 0,
|
||||
u'failures': 0,
|
||||
u'disabled': 0,
|
||||
u'errors': 0,
|
||||
u'time': u'*',
|
||||
u'timestamp': u'*',
|
||||
u'name': u'AllTests',
|
||||
u'testsuites': [],
|
||||
EXPECTED_NO_TEST = {
|
||||
u'tests':
|
||||
0,
|
||||
u'failures':
|
||||
0,
|
||||
u'disabled':
|
||||
0,
|
||||
u'errors':
|
||||
0,
|
||||
u'time':
|
||||
u'*',
|
||||
u'timestamp':
|
||||
u'*',
|
||||
u'name':
|
||||
u'AllTests',
|
||||
u'testsuites': [{
|
||||
u'name':
|
||||
u'NonTestSuiteFailure',
|
||||
u'tests':
|
||||
1,
|
||||
u'failures':
|
||||
1,
|
||||
u'disabled':
|
||||
0,
|
||||
u'skipped':
|
||||
0,
|
||||
u'errors':
|
||||
0,
|
||||
u'time':
|
||||
u'*',
|
||||
u'timestamp':
|
||||
u'*',
|
||||
u'testsuite': [{
|
||||
u'name':
|
||||
u'',
|
||||
u'status':
|
||||
u'RUN',
|
||||
u'result':
|
||||
u'COMPLETED',
|
||||
u'time':
|
||||
u'*',
|
||||
u'timestamp':
|
||||
u'*',
|
||||
u'classname':
|
||||
u'',
|
||||
u'failures': [{
|
||||
u'failure': u'gtest_no_test_unittest.cc:*\n'
|
||||
u'Expected equality of these values:\n'
|
||||
u' 1\n 2' + STACK_TRACE_TEMPLATE,
|
||||
u'type': u'',
|
||||
}]
|
||||
}]
|
||||
}],
|
||||
}
|
||||
|
||||
GTEST_PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
|
||||
|
@ -619,14 +689,14 @@ class GTestJsonOutputUnitTest(gtest_test_utils.TestCase):
|
|||
"""
|
||||
self._TestJsonOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY, 1)
|
||||
|
||||
def testEmptyJsonOutput(self):
|
||||
def testNoTestJsonOutput(self):
|
||||
"""Verifies JSON output for a Google Test binary without actual tests.
|
||||
|
||||
Runs a test program that generates an empty JSON output, and
|
||||
tests that the JSON output is expected.
|
||||
Runs a test program that generates an JSON output for a binary with no
|
||||
tests, and tests that the JSON output is expected.
|
||||
"""
|
||||
|
||||
self._TestJsonOutput('gtest_no_test_unittest', EXPECTED_EMPTY, 0)
|
||||
self._TestJsonOutput('gtest_no_test_unittest', EXPECTED_NO_TEST, 0)
|
||||
|
||||
def testTimestampValue(self):
|
||||
"""Checks whether the timestamp attribute in the JSON output is valid.
|
||||
|
|
|
@ -27,6 +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.
|
||||
|
||||
|
||||
// Unit test for Google Test's --gtest_list_tests flag.
|
||||
//
|
||||
// A user can ask Google Test to list all tests that will run
|
||||
|
@ -39,27 +40,38 @@
|
|||
#include "gtest/gtest.h"
|
||||
|
||||
// Several different test cases and tests that will be listed.
|
||||
TEST(Foo, Bar1) {}
|
||||
TEST(Foo, Bar1) {
|
||||
}
|
||||
|
||||
TEST(Foo, Bar2) {}
|
||||
TEST(Foo, Bar2) {
|
||||
}
|
||||
|
||||
TEST(Foo, DISABLED_Bar3) {}
|
||||
TEST(Foo, DISABLED_Bar3) {
|
||||
}
|
||||
|
||||
TEST(Abc, Xyz) {}
|
||||
TEST(Abc, Xyz) {
|
||||
}
|
||||
|
||||
TEST(Abc, Def) {}
|
||||
TEST(Abc, Def) {
|
||||
}
|
||||
|
||||
TEST(FooBar, Baz) {}
|
||||
TEST(FooBar, Baz) {
|
||||
}
|
||||
|
||||
class FooTest : public testing::Test {};
|
||||
class FooTest : public testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(FooTest, Test1) {}
|
||||
TEST_F(FooTest, Test1) {
|
||||
}
|
||||
|
||||
TEST_F(FooTest, DISABLED_Test2) {}
|
||||
TEST_F(FooTest, DISABLED_Test2) {
|
||||
}
|
||||
|
||||
TEST_F(FooTest, Test3) {}
|
||||
TEST_F(FooTest, Test3) {
|
||||
}
|
||||
|
||||
TEST(FooDeathTest, Test1) {}
|
||||
TEST(FooDeathTest, Test1) {
|
||||
}
|
||||
|
||||
// A group of value-parameterized tests.
|
||||
|
||||
|
@ -74,66 +86,70 @@ class MyType {
|
|||
};
|
||||
|
||||
// Teaches Google Test how to print a MyType.
|
||||
void PrintTo(const MyType& x, std::ostream* os) { *os << x.value(); }
|
||||
void PrintTo(const MyType& x, std::ostream* os) {
|
||||
*os << x.value();
|
||||
}
|
||||
|
||||
class ValueParamTest : public testing::TestWithParam<MyType> {};
|
||||
class ValueParamTest : public testing::TestWithParam<MyType> {
|
||||
};
|
||||
|
||||
TEST_P(ValueParamTest, TestA) {}
|
||||
TEST_P(ValueParamTest, TestA) {
|
||||
}
|
||||
|
||||
TEST_P(ValueParamTest, TestB) {}
|
||||
TEST_P(ValueParamTest, TestB) {
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
MyInstantiation, ValueParamTest,
|
||||
testing::Values(
|
||||
MyType("one line"), MyType("two\nlines"),
|
||||
MyType("a "
|
||||
"very\nloooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
||||
"ooooong line"))); // NOLINT
|
||||
testing::Values(MyType("one line"),
|
||||
MyType("two\nlines"),
|
||||
MyType("a very\nloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line"))); // NOLINT
|
||||
|
||||
// A group of typed tests.
|
||||
|
||||
// A deliberately long type name for testing the line-truncating
|
||||
// behavior when printing a type parameter.
|
||||
class
|
||||
VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName { // NOLINT
|
||||
class VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName { // NOLINT
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TypedTest : public testing::Test {};
|
||||
class TypedTest : public testing::Test {
|
||||
};
|
||||
|
||||
template <typename T, int kSize>
|
||||
class MyArray {};
|
||||
class MyArray {
|
||||
};
|
||||
|
||||
typedef testing::Types<
|
||||
VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName, // NOLINT
|
||||
int*, MyArray<bool, 42> >
|
||||
MyTypes;
|
||||
typedef testing::Types<VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName, // NOLINT
|
||||
int*, MyArray<bool, 42> > MyTypes;
|
||||
|
||||
TYPED_TEST_SUITE(TypedTest, MyTypes);
|
||||
|
||||
TYPED_TEST(TypedTest, TestA) {}
|
||||
TYPED_TEST(TypedTest, TestA) {
|
||||
}
|
||||
|
||||
TYPED_TEST(TypedTest, TestB) {}
|
||||
TYPED_TEST(TypedTest, TestB) {
|
||||
}
|
||||
|
||||
// A group of type-parameterized tests.
|
||||
|
||||
template <typename T>
|
||||
class TypeParamTest : public testing::Test {};
|
||||
class TypeParamTest : public testing::Test {
|
||||
};
|
||||
|
||||
TYPED_TEST_SUITE_P(TypeParamTest);
|
||||
|
||||
TYPED_TEST_P(TypeParamTest, TestA) {}
|
||||
TYPED_TEST_P(TypeParamTest, TestA) {
|
||||
}
|
||||
|
||||
TYPED_TEST_P(TypeParamTest, TestB) {}
|
||||
TYPED_TEST_P(TypeParamTest, TestB) {
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_SUITE_P(TypeParamTest, TestA, TestB);
|
||||
|
||||
INSTANTIATE_TYPED_TEST_SUITE_P(My, TypeParamTest, MyTypes);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
|
|
|
@ -65,8 +65,8 @@ class EventRecordingListener : public TestEventListener {
|
|||
void OnTestIterationStart(const UnitTest& /*unit_test*/,
|
||||
int iteration) override {
|
||||
Message message;
|
||||
message << GetFullMethodName("OnTestIterationStart") << "(" << iteration
|
||||
<< ")";
|
||||
message << GetFullMethodName("OnTestIterationStart")
|
||||
<< "(" << iteration << ")";
|
||||
g_events->push_back(message.GetString());
|
||||
}
|
||||
|
||||
|
@ -112,8 +112,8 @@ class EventRecordingListener : public TestEventListener {
|
|||
void OnTestIterationEnd(const UnitTest& /*unit_test*/,
|
||||
int iteration) override {
|
||||
Message message;
|
||||
message << GetFullMethodName("OnTestIterationEnd") << "(" << iteration
|
||||
<< ")";
|
||||
message << GetFullMethodName("OnTestIterationEnd")
|
||||
<< "(" << iteration << ")";
|
||||
g_events->push_back(message.GetString());
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,9 @@ class EventRecordingListener : public TestEventListener {
|
|||
}
|
||||
|
||||
private:
|
||||
std::string GetFullMethodName(const char* name) { return name_ + "." + name; }
|
||||
std::string GetFullMethodName(const char* name) {
|
||||
return name_ + "." + name;
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
};
|
||||
|
@ -250,21 +252,22 @@ void VerifyResults(const std::vector<std::string>& data,
|
|||
EXPECT_EQ(expected_data_size, actual_size);
|
||||
|
||||
// Compares the common prefix.
|
||||
const size_t shorter_size =
|
||||
expected_data_size <= actual_size ? expected_data_size : actual_size;
|
||||
const size_t shorter_size = expected_data_size <= actual_size ?
|
||||
expected_data_size : actual_size;
|
||||
size_t i = 0;
|
||||
for (; i < shorter_size; ++i) {
|
||||
ASSERT_STREQ(expected_data[i], data[i].c_str()) << "at position " << i;
|
||||
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 #%lu: %s\n", static_cast<unsigned long>(i),
|
||||
data[i].c_str());
|
||||
printf(" Actual event #%lu: %s\n",
|
||||
static_cast<unsigned long>(i), data[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char **argv) {
|
||||
std::vector<std::string> events;
|
||||
g_events = &events;
|
||||
InitGoogleTest(&argc, argv);
|
||||
|
@ -502,12 +505,14 @@ int main(int argc, char** argv) {
|
|||
"1st.OnTestProgramEnd"};
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
VerifyResults(events, expected_events,
|
||||
sizeof(expected_events) / sizeof(expected_events[0]));
|
||||
VerifyResults(events,
|
||||
expected_events,
|
||||
sizeof(expected_events)/sizeof(expected_events[0]));
|
||||
|
||||
// We need to check manually for ad hoc test failures that happen after
|
||||
// RUN_ALL_TESTS finishes.
|
||||
if (UnitTest::GetInstance()->Failed()) ret_val = 1;
|
||||
if (UnitTest::GetInstance()->Failed())
|
||||
ret_val = 1;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
|
|
@ -69,9 +69,8 @@ TEST(MessageTest, StreamsFloat) {
|
|||
|
||||
// Tests streaming a double.
|
||||
TEST(MessageTest, StreamsDouble) {
|
||||
const std::string s =
|
||||
(Message() << 1260570880.4555497 << " " << 1260572265.1954534)
|
||||
.GetString();
|
||||
const std::string s = (Message() << 1260570880.4555497 << " "
|
||||
<< 1260572265.1954534).GetString();
|
||||
// Both numbers should be printed with enough precision.
|
||||
EXPECT_PRED_FORMAT2(testing::IsSubstring, "1260570880.45", s.c_str());
|
||||
EXPECT_PRED_FORMAT2(testing::IsSubstring, " 1260572265.19", s.c_str());
|
||||
|
@ -109,7 +108,8 @@ TEST(MessageTest, StreamsString) {
|
|||
|
||||
// Tests that we can output strings containing embedded NULs.
|
||||
TEST(MessageTest, StreamsStringWithEmbeddedNUL) {
|
||||
const char char_array_with_nul[] = "Here's a NUL\0 and some more string";
|
||||
const char char_array_with_nul[] =
|
||||
"Here's a NUL\0 and some more string";
|
||||
const ::std::string string_with_nul(char_array_with_nul,
|
||||
sizeof(char_array_with_nul) - 1);
|
||||
EXPECT_EQ("Here's a NUL\\0 and some more string",
|
||||
|
@ -129,11 +129,10 @@ TEST(MessageTest, StreamsInt) {
|
|||
// Tests that basic IO manipulators (endl, ends, and flush) can be
|
||||
// streamed to Message.
|
||||
TEST(MessageTest, StreamsBasicIoManip) {
|
||||
EXPECT_EQ(
|
||||
"Line 1.\nA NUL char \\0 in line 2.",
|
||||
(Message() << "Line 1." << std::endl
|
||||
<< "A NUL char " << std::ends << std::flush << " in line 2.")
|
||||
.GetString());
|
||||
EXPECT_EQ("Line 1.\nA NUL char \\0 in line 2.",
|
||||
(Message() << "Line 1." << std::endl
|
||||
<< "A NUL char " << std::ends << std::flush
|
||||
<< " in line 2.").GetString());
|
||||
}
|
||||
|
||||
// Tests Message::GetString()
|
||||
|
|
|
@ -39,9 +39,12 @@
|
|||
#include "gtest/gtest.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
#include <windows.h>
|
||||
# include <windows.h>
|
||||
#elif GTEST_OS_WINDOWS
|
||||
#include <direct.h>
|
||||
# include <direct.h>
|
||||
#elif GTEST_OS_OS2
|
||||
// For strcasecmp on OS/2
|
||||
#include <strings.h>
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
#include "src/gtest-internal-inl.h"
|
||||
|
@ -82,9 +85,9 @@ 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().string() + ".xml"))
|
||||
.string();
|
||||
GetAbsolutePathOf(
|
||||
FilePath(std::string("path") + GTEST_PATH_SEP_ +
|
||||
GetCurrentExecutableName().string() + ".xml")).string();
|
||||
const std::string& output_file =
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
#if GTEST_OS_WINDOWS
|
||||
|
@ -112,10 +115,13 @@ TEST(OutputFileHelpersTest, GetCurrentExecutableName) {
|
|||
const bool success = exe_str == "app";
|
||||
#else
|
||||
const bool success =
|
||||
exe_str == "googletest-options-test" || exe_str == "gtest_all_test" ||
|
||||
exe_str == "lt-gtest_all_test" || exe_str == "gtest_dll_test";
|
||||
exe_str == "googletest-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;
|
||||
if (!success)
|
||||
FAIL() << "GetCurrentExecutableName() returns " << exe_str;
|
||||
}
|
||||
|
||||
#if !GTEST_OS_FUCHSIA
|
||||
|
@ -139,26 +145,23 @@ class XmlOutputChangeDirTest : public Test {
|
|||
|
||||
TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefault) {
|
||||
GTEST_FLAG(output) = "";
|
||||
EXPECT_EQ(
|
||||
FilePath::ConcatPaths(original_working_dir_, FilePath("test_detail.xml"))
|
||||
.string(),
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile());
|
||||
EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
|
||||
FilePath("test_detail.xml")).string(),
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile());
|
||||
}
|
||||
|
||||
TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefaultXML) {
|
||||
GTEST_FLAG(output) = "xml";
|
||||
EXPECT_EQ(
|
||||
FilePath::ConcatPaths(original_working_dir_, FilePath("test_detail.xml"))
|
||||
.string(),
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile());
|
||||
EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
|
||||
FilePath("test_detail.xml")).string(),
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile());
|
||||
}
|
||||
|
||||
TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativeFile) {
|
||||
GTEST_FLAG(output) = "xml:filename.abc";
|
||||
EXPECT_EQ(
|
||||
FilePath::ConcatPaths(original_working_dir_, FilePath("filename.abc"))
|
||||
.string(),
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile());
|
||||
EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
|
||||
FilePath("filename.abc")).string(),
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile());
|
||||
}
|
||||
|
||||
TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativePath) {
|
||||
|
@ -167,8 +170,7 @@ TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativePath) {
|
|||
FilePath::ConcatPaths(
|
||||
original_working_dir_,
|
||||
FilePath(std::string("path") + GTEST_PATH_SEP_ +
|
||||
GetCurrentExecutableName().string() + ".xml"))
|
||||
.string();
|
||||
GetCurrentExecutableName().string() + ".xml")).string();
|
||||
const std::string& output_file =
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile();
|
||||
#if GTEST_OS_WINDOWS
|
||||
|
@ -184,7 +186,7 @@ TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsoluteFile) {
|
|||
EXPECT_EQ(FilePath("c:\\tmp\\filename.abc").string(),
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile());
|
||||
#else
|
||||
GTEST_FLAG(output) = "xml:/tmp/filename.abc";
|
||||
GTEST_FLAG(output) ="xml:/tmp/filename.abc";
|
||||
EXPECT_EQ(FilePath("/tmp/filename.abc").string(),
|
||||
UnitTestOptions::GetAbsolutePathToOutputFile());
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@ Expected equality of these values:
|
|||
3
|
||||
Stack trace: (omitted)
|
||||
|
||||
[0;32m[==========] [mRunning 85 tests from 40 test suites.
|
||||
[0;32m[==========] [mRunning 88 tests from 41 test suites.
|
||||
[0;32m[----------] [mGlobal test environment set-up.
|
||||
FooEnvironment::SetUp() called.
|
||||
BarEnvironment::SetUp() called.
|
||||
|
@ -982,6 +982,43 @@ Expected failure
|
|||
Stack trace: (omitted)
|
||||
|
||||
[0;31m[ FAILED ] [mPrintingStrings/ParamTest.Failure/a, where GetParam() = "a"
|
||||
[0;32m[----------] [m3 tests from GoogleTestVerification
|
||||
[0;32m[ RUN ] [mGoogleTestVerification.UninstantiatedParameterizedTestSuite<NoTests>
|
||||
googletest-output-test_.cc:#: Failure
|
||||
Parameterized test suite NoTests is instantiated via INSTANTIATE_TEST_SUITE_P, but no tests are defined via TEST_P . No test cases will run.
|
||||
|
||||
Ideally, INSTANTIATE_TEST_SUITE_P should only ever be invoked from code that always depend on code that provides TEST_P. Failing to do so is often an indication of dead code, e.g. the last TEST_P was removed but the rest got left behind.
|
||||
|
||||
To suppress this error for this test suite, insert the following line (in a non-header) in the namespace it is defined in:
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NoTests);
|
||||
Stack trace: (omitted)
|
||||
|
||||
[0;31m[ FAILED ] [mGoogleTestVerification.UninstantiatedParameterizedTestSuite<NoTests>
|
||||
[0;32m[ RUN ] [mGoogleTestVerification.UninstantiatedParameterizedTestSuite<DetectNotInstantiatedTest>
|
||||
googletest-output-test_.cc:#: Failure
|
||||
Parameterized test suite DetectNotInstantiatedTest is defined via TEST_P, but never instantiated. None of the test cases will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only ones provided expand to nothing.
|
||||
|
||||
Ideally, TEST_P definitions should only ever be included as part of binaries that intend to use them. (As opposed to, for example, being placed in a library that may be linked in to get other utilities.)
|
||||
|
||||
To suppress this error for this test suite, insert the following line (in a non-header) in the namespace it is defined in:
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DetectNotInstantiatedTest);
|
||||
Stack trace: (omitted)
|
||||
|
||||
[0;31m[ FAILED ] [mGoogleTestVerification.UninstantiatedParameterizedTestSuite<DetectNotInstantiatedTest>
|
||||
[0;32m[ RUN ] [mGoogleTestVerification.UninstantiatedTypeParameterizedTestSuite<DetectNotInstantiatedTypesTest>
|
||||
googletest-output-test_.cc:#: Failure
|
||||
Type parameterized test suite DetectNotInstantiatedTypesTest is defined via REGISTER_TYPED_TEST_SUITE_P, but never instantiated via INSTANTIATE_TYPED_TEST_SUITE_P. None of the test cases will run.
|
||||
|
||||
Ideally, TYPED_TEST_P definitions should only ever be included as part of binaries that intend to use them. (As opposed to, for example, being placed in a library that may be linked in to get other utilities.)
|
||||
|
||||
To suppress this error for this test suite, insert the following line (in a non-header) in the namespace it is defined in:
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DetectNotInstantiatedTypesTest);
|
||||
Stack trace: (omitted)
|
||||
|
||||
[0;31m[ FAILED ] [mGoogleTestVerification.UninstantiatedTypeParameterizedTestSuite<DetectNotInstantiatedTypesTest>
|
||||
[0;32m[----------] [mGlobal test environment tear-down
|
||||
BarEnvironment::TearDown() called.
|
||||
googletest-output-test_.cc:#: Failure
|
||||
|
@ -995,9 +1032,9 @@ Failed
|
|||
Expected fatal failure.
|
||||
Stack trace: (omitted)
|
||||
|
||||
[0;32m[==========] [m85 tests from 40 test suites ran.
|
||||
[0;32m[==========] [m88 tests from 41 test suites ran.
|
||||
[0;32m[ PASSED ] [m31 tests.
|
||||
[0;31m[ FAILED ] [m54 tests, listed below:
|
||||
[0;31m[ FAILED ] [m57 tests, listed below:
|
||||
[0;31m[ FAILED ] [mNonfatalFailureTest.EscapesStringOperands
|
||||
[0;31m[ FAILED ] [mNonfatalFailureTest.DiffForLongStrings
|
||||
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInSubroutine
|
||||
|
@ -1052,8 +1089,11 @@ Stack trace: (omitted)
|
|||
[0;31m[ FAILED ] [mBadDynamicFixture2.Derived
|
||||
[0;31m[ FAILED ] [mPrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
|
||||
[0;31m[ FAILED ] [mPrintingStrings/ParamTest.Failure/a, where GetParam() = "a"
|
||||
[0;31m[ FAILED ] [mGoogleTestVerification.UninstantiatedParameterizedTestSuite<NoTests>
|
||||
[0;31m[ FAILED ] [mGoogleTestVerification.UninstantiatedParameterizedTestSuite<DetectNotInstantiatedTest>
|
||||
[0;31m[ FAILED ] [mGoogleTestVerification.UninstantiatedTypeParameterizedTestSuite<DetectNotInstantiatedTypesTest>
|
||||
|
||||
54 FAILED TESTS
|
||||
57 FAILED TESTS
|
||||
[0;33m YOU HAVE 1 DISABLED TEST
|
||||
|
||||
[mNote: Google Test filter = FatalFailureTest.*:LoggingTest.*
|
||||
|
|
|
@ -29,7 +29,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.
|
||||
|
||||
"""Tests the text output of Google C++ Testing and Mocking Framework.
|
||||
r"""Tests the text output of Google C++ Testing and Mocking Framework.
|
||||
|
||||
To update the golden file:
|
||||
googletest_output_test.py --build_dir=BUILD/DIR --gengolden
|
||||
|
@ -331,7 +331,7 @@ if __name__ == '__main__':
|
|||
if CAN_GENERATE_GOLDEN_FILE:
|
||||
output = GetOutputOfAllCommands()
|
||||
golden_file = open(GOLDEN_PATH, 'wb')
|
||||
golden_file.write(output)
|
||||
golden_file.write(output.encode())
|
||||
golden_file.close()
|
||||
else:
|
||||
message = (
|
||||
|
|
|
@ -56,7 +56,9 @@ namespace posix = ::testing::internal::posix;
|
|||
// Tests catching fatal failures.
|
||||
|
||||
// A subroutine used by the following test.
|
||||
void TestEq1(int x) { ASSERT_EQ(1, x); }
|
||||
void TestEq1(int x) {
|
||||
ASSERT_EQ(1, x);
|
||||
}
|
||||
|
||||
// This function calls a test subroutine, catches the fatal failure it
|
||||
// generates, and then returns early.
|
||||
|
@ -74,19 +76,24 @@ void TryTestSubroutine() {
|
|||
FAIL() << "This should never be reached.";
|
||||
}
|
||||
|
||||
TEST(PassingTest, PassingTest1) {}
|
||||
TEST(PassingTest, PassingTest1) {
|
||||
}
|
||||
|
||||
TEST(PassingTest, PassingTest2) {}
|
||||
TEST(PassingTest, PassingTest2) {
|
||||
}
|
||||
|
||||
// Tests that parameters of failing parameterized tests are printed in the
|
||||
// failing test summary.
|
||||
class FailingParamTest : public testing::TestWithParam<int> {};
|
||||
|
||||
TEST_P(FailingParamTest, Fails) { EXPECT_EQ(1, GetParam()); }
|
||||
TEST_P(FailingParamTest, Fails) {
|
||||
EXPECT_EQ(1, GetParam());
|
||||
}
|
||||
|
||||
// This generates a test which will fail. Google Test is expected to print
|
||||
// its parameter when it outputs the list of all failed tests.
|
||||
INSTANTIATE_TEST_SUITE_P(PrintingFailingParams, FailingParamTest,
|
||||
INSTANTIATE_TEST_SUITE_P(PrintingFailingParams,
|
||||
FailingParamTest,
|
||||
testing::Values(2));
|
||||
|
||||
// Tests that an empty value for the test suite basename yields just
|
||||
|
@ -139,16 +146,18 @@ TEST(FatalFailureTest, FatalFailureInNestedSubroutine) {
|
|||
// Tests HasFatalFailure() after a failed EXPECT check.
|
||||
TEST(FatalFailureTest, NonfatalFailureInSubroutine) {
|
||||
printf("(expecting a failure on false)\n");
|
||||
EXPECT_TRUE(false); // Generates a nonfatal failure
|
||||
EXPECT_TRUE(false); // Generates a nonfatal failure
|
||||
ASSERT_FALSE(HasFatalFailure()); // This should succeed.
|
||||
}
|
||||
|
||||
// Tests interleaving user logging and Google Test assertions.
|
||||
TEST(LoggingTest, InterleavingLoggingAndAssertions) {
|
||||
static const int a[4] = {3, 9, 2, 6};
|
||||
static const int a[4] = {
|
||||
3, 9, 2, 6
|
||||
};
|
||||
|
||||
printf("(expecting 2 failures on (3) >= (a[i]))\n");
|
||||
for (int i = 0; i < static_cast<int>(sizeof(a) / sizeof(*a)); i++) {
|
||||
for (int i = 0; i < static_cast<int>(sizeof(a)/sizeof(*a)); i++) {
|
||||
printf("i == %d\n", i);
|
||||
EXPECT_GE(3, a[i]);
|
||||
}
|
||||
|
@ -288,14 +297,16 @@ struct CheckPoints {
|
|||
static void ThreadWithScopedTrace(CheckPoints* check_points) {
|
||||
{
|
||||
SCOPED_TRACE("Trace B");
|
||||
ADD_FAILURE() << "Expected failure #1 (in thread B, only trace B alive).";
|
||||
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).";
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #4 (in thread B, only trace A alive).";
|
||||
check_points->n3.Notify();
|
||||
}
|
||||
|
||||
|
@ -314,9 +325,11 @@ TEST(SCOPED_TRACETest, WorksConcurrently) {
|
|||
check_points.n2.Notify();
|
||||
check_points.n3.WaitForNotification();
|
||||
|
||||
ADD_FAILURE() << "Expected failure #5 (in thread A, only trace A alive).";
|
||||
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).";
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #6 (in thread A, no trace alive).";
|
||||
thread.Join();
|
||||
}
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
@ -399,7 +412,9 @@ class FatalFailureInFixtureConstructorTest : public testing::Test {
|
|||
}
|
||||
|
||||
private:
|
||||
void Init() { FAIL() << "Expected failure #1, in the test fixture c'tor."; }
|
||||
void Init() {
|
||||
FAIL() << "Expected failure #1, in the test fixture c'tor.";
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FatalFailureInFixtureConstructorTest, FailureInConstructor) {
|
||||
|
@ -421,7 +436,9 @@ class NonFatalFailureInSetUpTest : public testing::Test {
|
|||
void TearDown() override { FAIL() << "Expected failure #3, in TearDown()."; }
|
||||
|
||||
private:
|
||||
void Deinit() { FAIL() << "Expected failure #4, in the test fixture d'tor."; }
|
||||
void Deinit() {
|
||||
FAIL() << "Expected failure #4, in the test fixture d'tor.";
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(NonFatalFailureInSetUpTest, FailureInSetUp) {
|
||||
|
@ -441,7 +458,9 @@ class FatalFailureInSetUpTest : public testing::Test {
|
|||
void TearDown() override { FAIL() << "Expected failure #2, in TearDown()."; }
|
||||
|
||||
private:
|
||||
void Deinit() { FAIL() << "Expected failure #3, in the test fixture d'tor."; }
|
||||
void Deinit() {
|
||||
FAIL() << "Expected failure #3, in the test fixture d'tor.";
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FatalFailureInSetUpTest, FailureInSetUp) {
|
||||
|
@ -457,63 +476,6 @@ TEST(GtestFailAtTest, MessageContainsSpecifiedFileAndLineNumber) {
|
|||
GTEST_FAIL_AT("foo.cc", 42) << "Expected fatal failure in foo.cc";
|
||||
}
|
||||
|
||||
#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.
|
||||
void SetUp() override {
|
||||
thread_.reset(new ThreadWithParam<SpawnThreadNotifications*>(
|
||||
&ThreadRoutine, ¬ifications_, nullptr));
|
||||
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.
|
||||
void TearDown() override {
|
||||
notifications_.spawn_thread_ok_to_terminate.Notify();
|
||||
}
|
||||
|
||||
private:
|
||||
SpawnThreadNotifications notifications_;
|
||||
std::unique_ptr<ThreadWithParam<SpawnThreadNotifications*> > thread_;
|
||||
};
|
||||
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
// The MixedUpTestSuiteTest 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
|
||||
|
@ -526,12 +488,14 @@ class DeathTestAndMultiThreadsTest : public testing::Test {
|
|||
|
||||
namespace foo {
|
||||
|
||||
class MixedUpTestSuiteTest : public testing::Test {};
|
||||
class MixedUpTestSuiteTest : public testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(MixedUpTestSuiteTest, FirstTestFromNamespaceFoo) {}
|
||||
TEST_F(MixedUpTestSuiteTest, SecondTestFromNamespaceFoo) {}
|
||||
|
||||
class MixedUpTestSuiteWithSameTestNameTest : public testing::Test {};
|
||||
class MixedUpTestSuiteWithSameTestNameTest : public testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(MixedUpTestSuiteWithSameTestNameTest,
|
||||
TheSecondTestWithThisNameShouldFail) {}
|
||||
|
@ -540,14 +504,16 @@ TEST_F(MixedUpTestSuiteWithSameTestNameTest,
|
|||
|
||||
namespace bar {
|
||||
|
||||
class MixedUpTestSuiteTest : public testing::Test {};
|
||||
class MixedUpTestSuiteTest : public testing::Test {
|
||||
};
|
||||
|
||||
// The following two tests are expected to fail. We rely on the
|
||||
// golden file to check that Google Test generates the right error message.
|
||||
TEST_F(MixedUpTestSuiteTest, ThisShouldFail) {}
|
||||
TEST_F(MixedUpTestSuiteTest, ThisShouldFailToo) {}
|
||||
|
||||
class MixedUpTestSuiteWithSameTestNameTest : public testing::Test {};
|
||||
class MixedUpTestSuiteWithSameTestNameTest : public testing::Test {
|
||||
};
|
||||
|
||||
// Expected to fail. We rely on the golden file to check that Google Test
|
||||
// generates the right error message.
|
||||
|
@ -561,7 +527,8 @@ TEST_F(MixedUpTestSuiteWithSameTestNameTest,
|
|||
// test case checks the scenario where TEST_F appears before TEST, and
|
||||
// the second one checks where TEST appears before TEST_F.
|
||||
|
||||
class TEST_F_before_TEST_in_same_test_case : public testing::Test {};
|
||||
class TEST_F_before_TEST_in_same_test_case : public testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(TEST_F_before_TEST_in_same_test_case, DefinedUsingTEST_F) {}
|
||||
|
||||
|
@ -569,13 +536,15 @@ TEST_F(TEST_F_before_TEST_in_same_test_case, DefinedUsingTEST_F) {}
|
|||
// generates the right error message.
|
||||
TEST(TEST_F_before_TEST_in_same_test_case, DefinedUsingTESTAndShouldFail) {}
|
||||
|
||||
class TEST_before_TEST_F_in_same_test_case : public testing::Test {};
|
||||
class TEST_before_TEST_F_in_same_test_case : public testing::Test {
|
||||
};
|
||||
|
||||
TEST(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST) {}
|
||||
|
||||
// Expected to fail. We rely on the golden file to check that Google Test
|
||||
// generates the right error message.
|
||||
TEST_F(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST_FAndShouldFail) {}
|
||||
TEST_F(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST_FAndShouldFail) {
|
||||
}
|
||||
|
||||
// Used for testing EXPECT_NONFATAL_FAILURE() and EXPECT_FATAL_FAILURE().
|
||||
int global_integer = 0;
|
||||
|
@ -583,9 +552,9 @@ int global_integer = 0;
|
|||
// Tests that EXPECT_NONFATAL_FAILURE() can reference global variables.
|
||||
TEST(ExpectNonfatalFailureTest, CanReferenceGlobalVariables) {
|
||||
global_integer = 0;
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ EXPECT_EQ(1, global_integer) << "Expected non-fatal failure."; },
|
||||
"Expected non-fatal failure.");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
EXPECT_EQ(1, global_integer) << "Expected non-fatal failure.";
|
||||
}, "Expected non-fatal failure.");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_NONFATAL_FAILURE() can reference local variables
|
||||
|
@ -594,48 +563,53 @@ TEST(ExpectNonfatalFailureTest, CanReferenceLocalVariables) {
|
|||
int m = 0;
|
||||
static int n;
|
||||
n = 1;
|
||||
EXPECT_NONFATAL_FAILURE({ EXPECT_EQ(m, n) << "Expected non-fatal failure."; },
|
||||
"Expected non-fatal failure.");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
EXPECT_EQ(m, n) << "Expected non-fatal failure.";
|
||||
}, "Expected non-fatal failure.");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_NONFATAL_FAILURE() succeeds when there is exactly
|
||||
// one non-fatal failure and no fatal failure.
|
||||
TEST(ExpectNonfatalFailureTest, SucceedsWhenThereIsOneNonfatalFailure) {
|
||||
EXPECT_NONFATAL_FAILURE({ ADD_FAILURE() << "Expected non-fatal failure."; },
|
||||
"Expected non-fatal failure.");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
ADD_FAILURE() << "Expected non-fatal failure.";
|
||||
}, "Expected non-fatal failure.");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_NONFATAL_FAILURE() fails when there is no
|
||||
// non-fatal failure.
|
||||
TEST(ExpectNonfatalFailureTest, FailsWhenThereIsNoNonfatalFailure) {
|
||||
printf("(expecting a failure)\n");
|
||||
EXPECT_NONFATAL_FAILURE({}, "");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
}, "");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_NONFATAL_FAILURE() fails when there are two
|
||||
// non-fatal failures.
|
||||
TEST(ExpectNonfatalFailureTest, FailsWhenThereAreTwoNonfatalFailures) {
|
||||
printf("(expecting a failure)\n");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{
|
||||
ADD_FAILURE() << "Expected non-fatal failure 1.";
|
||||
ADD_FAILURE() << "Expected non-fatal failure 2.";
|
||||
},
|
||||
"");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
ADD_FAILURE() << "Expected non-fatal failure 1.";
|
||||
ADD_FAILURE() << "Expected non-fatal failure 2.";
|
||||
}, "");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_NONFATAL_FAILURE() fails when there is one fatal
|
||||
// failure.
|
||||
TEST(ExpectNonfatalFailureTest, FailsWhenThereIsOneFatalFailure) {
|
||||
printf("(expecting a failure)\n");
|
||||
EXPECT_NONFATAL_FAILURE({ FAIL() << "Expected fatal failure."; }, "");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
FAIL() << "Expected fatal failure.";
|
||||
}, "");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
|
||||
// tested returns.
|
||||
TEST(ExpectNonfatalFailureTest, FailsWhenStatementReturns) {
|
||||
printf("(expecting a failure)\n");
|
||||
EXPECT_NONFATAL_FAILURE({ return; }, "");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
return;
|
||||
}, "");
|
||||
}
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
@ -645,8 +619,10 @@ TEST(ExpectNonfatalFailureTest, FailsWhenStatementReturns) {
|
|||
TEST(ExpectNonfatalFailureTest, FailsWhenStatementThrows) {
|
||||
printf("(expecting a failure)\n");
|
||||
try {
|
||||
EXPECT_NONFATAL_FAILURE({ throw 0; }, "");
|
||||
} catch (int) { // NOLINT
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
throw 0;
|
||||
}, "");
|
||||
} catch(int) { // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,9 +631,9 @@ TEST(ExpectNonfatalFailureTest, FailsWhenStatementThrows) {
|
|||
// Tests that EXPECT_FATAL_FAILURE() can reference global variables.
|
||||
TEST(ExpectFatalFailureTest, CanReferenceGlobalVariables) {
|
||||
global_integer = 0;
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{ ASSERT_EQ(1, global_integer) << "Expected fatal failure."; },
|
||||
"Expected fatal failure.");
|
||||
EXPECT_FATAL_FAILURE({
|
||||
ASSERT_EQ(1, global_integer) << "Expected fatal failure.";
|
||||
}, "Expected fatal failure.");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_FATAL_FAILURE() can reference local static
|
||||
|
@ -665,51 +641,58 @@ TEST(ExpectFatalFailureTest, CanReferenceGlobalVariables) {
|
|||
TEST(ExpectFatalFailureTest, CanReferenceLocalStaticVariables) {
|
||||
static int n;
|
||||
n = 1;
|
||||
EXPECT_FATAL_FAILURE({ ASSERT_EQ(0, n) << "Expected fatal failure."; },
|
||||
"Expected fatal failure.");
|
||||
EXPECT_FATAL_FAILURE({
|
||||
ASSERT_EQ(0, n) << "Expected fatal failure.";
|
||||
}, "Expected fatal failure.");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_FATAL_FAILURE() succeeds when there is exactly
|
||||
// one fatal failure and no non-fatal failure.
|
||||
TEST(ExpectFatalFailureTest, SucceedsWhenThereIsOneFatalFailure) {
|
||||
EXPECT_FATAL_FAILURE({ FAIL() << "Expected fatal failure."; },
|
||||
"Expected fatal failure.");
|
||||
EXPECT_FATAL_FAILURE({
|
||||
FAIL() << "Expected fatal failure.";
|
||||
}, "Expected fatal failure.");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_FATAL_FAILURE() fails when there is no fatal
|
||||
// failure.
|
||||
TEST(ExpectFatalFailureTest, FailsWhenThereIsNoFatalFailure) {
|
||||
printf("(expecting a failure)\n");
|
||||
EXPECT_FATAL_FAILURE({}, "");
|
||||
EXPECT_FATAL_FAILURE({
|
||||
}, "");
|
||||
}
|
||||
|
||||
// A helper for generating a fatal failure.
|
||||
void FatalFailure() { FAIL() << "Expected fatal failure."; }
|
||||
void FatalFailure() {
|
||||
FAIL() << "Expected fatal failure.";
|
||||
}
|
||||
|
||||
// Tests that EXPECT_FATAL_FAILURE() fails when there are two
|
||||
// fatal failures.
|
||||
TEST(ExpectFatalFailureTest, FailsWhenThereAreTwoFatalFailures) {
|
||||
printf("(expecting a failure)\n");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
FatalFailure();
|
||||
FatalFailure();
|
||||
},
|
||||
"");
|
||||
EXPECT_FATAL_FAILURE({
|
||||
FatalFailure();
|
||||
FatalFailure();
|
||||
}, "");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_FATAL_FAILURE() fails when there is one non-fatal
|
||||
// failure.
|
||||
TEST(ExpectFatalFailureTest, FailsWhenThereIsOneNonfatalFailure) {
|
||||
printf("(expecting a failure)\n");
|
||||
EXPECT_FATAL_FAILURE({ ADD_FAILURE() << "Expected non-fatal failure."; }, "");
|
||||
EXPECT_FATAL_FAILURE({
|
||||
ADD_FAILURE() << "Expected non-fatal failure.";
|
||||
}, "");
|
||||
}
|
||||
|
||||
// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
|
||||
// tested returns.
|
||||
TEST(ExpectFatalFailureTest, FailsWhenStatementReturns) {
|
||||
printf("(expecting a failure)\n");
|
||||
EXPECT_FATAL_FAILURE({ return; }, "");
|
||||
EXPECT_FATAL_FAILURE({
|
||||
return;
|
||||
}, "");
|
||||
}
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
@ -719,8 +702,10 @@ TEST(ExpectFatalFailureTest, FailsWhenStatementReturns) {
|
|||
TEST(ExpectFatalFailureTest, FailsWhenStatementThrows) {
|
||||
printf("(expecting a failure)\n");
|
||||
try {
|
||||
EXPECT_FATAL_FAILURE({ throw 0; }, "");
|
||||
} catch (int) { // NOLINT
|
||||
EXPECT_FATAL_FAILURE({
|
||||
throw 0;
|
||||
}, "");
|
||||
} catch(int) { // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,24 +717,42 @@ std::string ParamNameFunc(const testing::TestParamInfo<std::string>& info) {
|
|||
return info.param;
|
||||
}
|
||||
|
||||
class ParamTest : public testing::TestWithParam<std::string> {};
|
||||
class ParamTest : public testing::TestWithParam<std::string> {
|
||||
};
|
||||
|
||||
TEST_P(ParamTest, Success) { EXPECT_EQ("a", GetParam()); }
|
||||
TEST_P(ParamTest, Success) {
|
||||
EXPECT_EQ("a", GetParam());
|
||||
}
|
||||
|
||||
TEST_P(ParamTest, Failure) { EXPECT_EQ("b", GetParam()) << "Expected failure"; }
|
||||
TEST_P(ParamTest, Failure) {
|
||||
EXPECT_EQ("b", GetParam()) << "Expected failure";
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(PrintingStrings, ParamTest,
|
||||
testing::Values(std::string("a")), ParamNameFunc);
|
||||
INSTANTIATE_TEST_SUITE_P(PrintingStrings,
|
||||
ParamTest,
|
||||
testing::Values(std::string("a")),
|
||||
ParamNameFunc);
|
||||
|
||||
// This #ifdef block tests the output of typed tests.
|
||||
#if GTEST_HAS_TYPED_TEST
|
||||
// The case where a suite has INSTANTIATE_TEST_SUITE_P but not TEST_P.
|
||||
using NoTests = ParamTest;
|
||||
INSTANTIATE_TEST_SUITE_P(ThisIsOdd, NoTests, ::testing::Values("Hello"));
|
||||
|
||||
// fails under kErrorOnUninstantiatedParameterizedTest=true
|
||||
class DetectNotInstantiatedTest : public testing::TestWithParam<int> {};
|
||||
TEST_P(DetectNotInstantiatedTest, Used) { }
|
||||
|
||||
// This would make the test failure from the above go away.
|
||||
// INSTANTIATE_TEST_SUITE_P(Fix, DetectNotInstantiatedTest, testing::Values(1));
|
||||
|
||||
template <typename T>
|
||||
class TypedTest : public testing::Test {};
|
||||
class TypedTest : public testing::Test {
|
||||
};
|
||||
|
||||
TYPED_TEST_SUITE(TypedTest, testing::Types<int>);
|
||||
|
||||
TYPED_TEST(TypedTest, Success) { EXPECT_EQ(0, TypeParam()); }
|
||||
TYPED_TEST(TypedTest, Success) {
|
||||
EXPECT_EQ(0, TypeParam());
|
||||
}
|
||||
|
||||
TYPED_TEST(TypedTest, Failure) {
|
||||
EXPECT_EQ(1, TypeParam()) << "Expected failure";
|
||||
|
@ -777,17 +780,15 @@ TYPED_TEST(TypedTestWithNames, Success) {}
|
|||
|
||||
TYPED_TEST(TypedTestWithNames, Failure) { FAIL(); }
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST
|
||||
|
||||
// This #ifdef block tests the output of type-parameterized tests.
|
||||
#if GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
template <typename T>
|
||||
class TypedTestP : public testing::Test {};
|
||||
class TypedTestP : public testing::Test {
|
||||
};
|
||||
|
||||
TYPED_TEST_SUITE_P(TypedTestP);
|
||||
|
||||
TYPED_TEST_P(TypedTestP, Success) { EXPECT_EQ(0U, TypeParam()); }
|
||||
TYPED_TEST_P(TypedTestP, Success) {
|
||||
EXPECT_EQ(0U, TypeParam());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(TypedTestP, Failure) {
|
||||
EXPECT_EQ(1U, TypeParam()) << "Expected failure";
|
||||
|
@ -812,57 +813,71 @@ class TypedTestPNames {
|
|||
};
|
||||
|
||||
INSTANTIATE_TYPED_TEST_SUITE_P(UnsignedCustomName, TypedTestP, UnsignedTypes,
|
||||
TypedTestPNames);
|
||||
TypedTestPNames);
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST_P
|
||||
template <typename T>
|
||||
class DetectNotInstantiatedTypesTest : public testing::Test {};
|
||||
TYPED_TEST_SUITE_P(DetectNotInstantiatedTypesTest);
|
||||
TYPED_TEST_P(DetectNotInstantiatedTypesTest, Used) {
|
||||
TypeParam instantiate;
|
||||
(void)instantiate;
|
||||
}
|
||||
REGISTER_TYPED_TEST_SUITE_P(DetectNotInstantiatedTypesTest, Used);
|
||||
|
||||
// kErrorOnUninstantiatedTypeParameterizedTest=true would make the above fail.
|
||||
// Adding the following would make that test failure go away.
|
||||
//
|
||||
// typedef ::testing::Types<char, int, unsigned int> MyTypes;
|
||||
// INSTANTIATE_TYPED_TEST_SUITE_P(All, DetectNotInstantiatedTypesTest, MyTypes);
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
// We rely on the golden file to verify that tests whose test case
|
||||
// name ends with DeathTest are run first.
|
||||
|
||||
TEST(ADeathTest, ShouldRunFirst) {}
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST
|
||||
TEST(ADeathTest, ShouldRunFirst) {
|
||||
}
|
||||
|
||||
// We rely on the golden file to verify that typed tests whose test
|
||||
// case name ends with DeathTest are run first.
|
||||
|
||||
template <typename T>
|
||||
class ATypedDeathTest : public testing::Test {};
|
||||
class ATypedDeathTest : public testing::Test {
|
||||
};
|
||||
|
||||
typedef testing::Types<int, double> NumericTypes;
|
||||
TYPED_TEST_SUITE(ATypedDeathTest, NumericTypes);
|
||||
|
||||
TYPED_TEST(ATypedDeathTest, ShouldRunFirst) {}
|
||||
TYPED_TEST(ATypedDeathTest, ShouldRunFirst) {
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// We rely on the golden file to verify that type-parameterized tests
|
||||
// whose test case name ends with DeathTest are run first.
|
||||
|
||||
template <typename T>
|
||||
class ATypeParamDeathTest : public testing::Test {};
|
||||
class ATypeParamDeathTest : public testing::Test {
|
||||
};
|
||||
|
||||
TYPED_TEST_SUITE_P(ATypeParamDeathTest);
|
||||
|
||||
TYPED_TEST_P(ATypeParamDeathTest, ShouldRunFirst) {}
|
||||
TYPED_TEST_P(ATypeParamDeathTest, ShouldRunFirst) {
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_SUITE_P(ATypeParamDeathTest, ShouldRunFirst);
|
||||
|
||||
INSTANTIATE_TYPED_TEST_SUITE_P(My, ATypeParamDeathTest, NumericTypes);
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
// Tests various failure conditions of
|
||||
// EXPECT_{,NON}FATAL_FAILURE{,_ON_ALL_THREADS}.
|
||||
class ExpectFailureTest : public testing::Test {
|
||||
public: // Must be public and not protected due to a bug in g++ 3.4.2.
|
||||
enum FailureMode { FATAL_FAILURE, NONFATAL_FAILURE };
|
||||
enum FailureMode {
|
||||
FATAL_FAILURE,
|
||||
NONFATAL_FAILURE
|
||||
};
|
||||
static void AddFailure(FailureMode failure) {
|
||||
if (failure == FATAL_FAILURE) {
|
||||
FAIL() << "Expected fatal failure.";
|
||||
|
@ -878,13 +893,11 @@ TEST_F(ExpectFailureTest, ExpectFatalFailure) {
|
|||
EXPECT_FATAL_FAILURE(SUCCEED(), "Expected fatal failure.");
|
||||
// Expected fatal failure, but got a non-fatal failure.
|
||||
printf("(expecting 1 failure)\n");
|
||||
EXPECT_FATAL_FAILURE(AddFailure(NONFATAL_FAILURE),
|
||||
"Expected non-fatal "
|
||||
EXPECT_FATAL_FAILURE(AddFailure(NONFATAL_FAILURE), "Expected non-fatal "
|
||||
"failure.");
|
||||
// Wrong message.
|
||||
printf("(expecting 1 failure)\n");
|
||||
EXPECT_FATAL_FAILURE(AddFailure(FATAL_FAILURE),
|
||||
"Some other fatal failure "
|
||||
EXPECT_FATAL_FAILURE(AddFailure(FATAL_FAILURE), "Some other fatal failure "
|
||||
"expected.");
|
||||
}
|
||||
|
||||
|
@ -897,8 +910,7 @@ TEST_F(ExpectFailureTest, ExpectNonFatalFailure) {
|
|||
EXPECT_NONFATAL_FAILURE(AddFailure(FATAL_FAILURE), "Expected fatal failure.");
|
||||
// Wrong message.
|
||||
printf("(expecting 1 failure)\n");
|
||||
EXPECT_NONFATAL_FAILURE(AddFailure(NONFATAL_FAILURE),
|
||||
"Some other non-fatal "
|
||||
EXPECT_NONFATAL_FAILURE(AddFailure(NONFATAL_FAILURE), "Some other non-fatal "
|
||||
"failure.");
|
||||
}
|
||||
|
||||
|
@ -963,8 +975,7 @@ TEST_F(ExpectFailureTest, ExpectFatalFailureOnAllThreads) {
|
|||
TEST_F(ExpectFailureTest, ExpectNonFatalFailureOnAllThreads) {
|
||||
// Expected non-fatal failure, but succeeds.
|
||||
printf("(expecting 1 failure)\n");
|
||||
EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(SUCCEED(),
|
||||
"Expected non-fatal "
|
||||
EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(SUCCEED(), "Expected non-fatal "
|
||||
"failure.");
|
||||
// Expected non-fatal failure, but got a fatal failure.
|
||||
printf("(expecting 1 failure)\n");
|
||||
|
@ -1018,7 +1029,7 @@ auto dynamic_test = (
|
|||
"BadDynamicFixture1", "TestBase", nullptr, nullptr, __FILE__, __LINE__,
|
||||
[]() -> testing::Test* { return new DynamicTest<true>; }),
|
||||
|
||||
// Register two tests with the same fixture incorrectly by ommiting the
|
||||
// Register two tests with the same fixture incorrectly by omitting the
|
||||
// return type.
|
||||
testing::RegisterTest(
|
||||
"BadDynamicFixture2", "FixtureBase", nullptr, nullptr, __FILE__,
|
||||
|
@ -1054,7 +1065,7 @@ class BarEnvironment : public testing::Environment {
|
|||
// The idea is to use Google Test to run all the tests we have defined (some
|
||||
// of them are intended to fail), and then compare the test results
|
||||
// with the "golden" file.
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char **argv) {
|
||||
testing::GTEST_FLAG(print_time) = false;
|
||||
|
||||
// We just run the tests, knowing some of them are intended to fail.
|
||||
|
@ -1071,18 +1082,19 @@ int main(int argc, char** argv) {
|
|||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
if (testing::internal::GTEST_FLAG(internal_run_death_test) != "") {
|
||||
// Skip the usual output capturing if we're running as the child
|
||||
// process of an threadsafe-style death test.
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Skip the usual output capturing if we're running as the child
|
||||
// process of an threadsafe-style death test.
|
||||
# if GTEST_OS_WINDOWS
|
||||
posix::FReopen("nul:", "w", stdout);
|
||||
#else
|
||||
# else
|
||||
posix::FReopen("/dev/null", "w", stdout);
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
if (internal_skip_environment_and_ad_hoc_tests) return RUN_ALL_TESTS();
|
||||
if (internal_skip_environment_and_ad_hoc_tests)
|
||||
return RUN_ALL_TESTS();
|
||||
|
||||
// Registers two global test environments.
|
||||
// The golden file verifies that they are set up in the order they
|
||||
|
@ -1090,7 +1102,7 @@ int main(int argc, char** argv) {
|
|||
testing::AddGlobalTestEnvironment(new FooEnvironment);
|
||||
testing::AddGlobalTestEnvironment(new BarEnvironment);
|
||||
#if _MSC_VER
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4127
|
||||
#endif // _MSC_VER
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4127
|
||||
#endif // _MSC_VER
|
||||
return RunAllTests();
|
||||
}
|
||||
|
|
|
@ -27,14 +27,17 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
class DummyTest : public ::testing::TestWithParam<const char *> {};
|
||||
|
||||
TEST_P(DummyTest, Dummy) {}
|
||||
TEST_P(DummyTest, Dummy) {
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(InvalidTestName, DummyTest,
|
||||
INSTANTIATE_TEST_SUITE_P(InvalidTestName,
|
||||
DummyTest,
|
||||
::testing::Values("InvalidWithQuotes"),
|
||||
::testing::PrintToStringParamName());
|
||||
|
||||
|
@ -44,3 +47,4 @@ int main(int argc, char *argv[]) {
|
|||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,19 +27,22 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
class DummyTest : public ::testing::TestWithParam<const char *> {};
|
||||
|
||||
std::string StringParamTestSuffix(
|
||||
const testing::TestParamInfo<const char *> &info) {
|
||||
const testing::TestParamInfo<const char*>& info) {
|
||||
return std::string(info.param);
|
||||
}
|
||||
|
||||
TEST_P(DummyTest, Dummy) {}
|
||||
TEST_P(DummyTest, Dummy) {
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DuplicateTestNames, DummyTest,
|
||||
INSTANTIATE_TEST_SUITE_P(DuplicateTestNames,
|
||||
DummyTest,
|
||||
::testing::Values("a", "b", "a", "c"),
|
||||
StringParamTestSuffix);
|
||||
} // namespace
|
||||
|
@ -48,3 +51,5 @@ int main(int argc, char *argv[]) {
|
|||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,15 +34,16 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
# include <algorithm>
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
# include <set>
|
||||
# include <sstream>
|
||||
# include <string>
|
||||
# include <vector>
|
||||
|
||||
#include "src/gtest-internal-inl.h" // for UnitTestOptions
|
||||
#include "test/googletest-param-test-test.h"
|
||||
# include "src/gtest-internal-inl.h" // for UnitTestOptions
|
||||
# include "test/googletest-param-test-test.h"
|
||||
|
||||
using ::std::vector;
|
||||
using ::std::sort;
|
||||
|
@ -84,14 +85,15 @@ void VerifyGenerator(const ParamGenerator<T>& generator,
|
|||
// 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)
|
||||
<< "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.\n";
|
||||
<< "At the presumed end of sequence when accessing via an iterator "
|
||||
<< "created with the copy constructor.\n";
|
||||
|
||||
// Test the iterator assignment. The following lines verify that
|
||||
// the sequence accessed via an iterator initialized via the
|
||||
|
@ -103,14 +105,15 @@ void VerifyGenerator(const ParamGenerator<T>& generator,
|
|||
<< "At element " << i << " when accessing via an iterator "
|
||||
<< "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)
|
||||
<< "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.\n";
|
||||
<< "At the presumed end of sequence when accessing via an iterator "
|
||||
<< "created with the assignment operator.\n";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -213,7 +216,8 @@ class DogAdder {
|
|||
DogAdder(const DogAdder& other) : value_(other.value_.c_str()) {}
|
||||
|
||||
DogAdder operator=(const DogAdder& other) {
|
||||
if (this != &other) value_ = other.value_;
|
||||
if (this != &other)
|
||||
value_ = other.value_;
|
||||
return *this;
|
||||
}
|
||||
DogAdder operator+(const DogAdder& other) const {
|
||||
|
@ -221,7 +225,9 @@ class DogAdder {
|
|||
msg << value_.c_str() << other.value_.c_str();
|
||||
return DogAdder(msg.GetString().c_str());
|
||||
}
|
||||
bool operator<(const DogAdder& other) const { return value_ < other.value_; }
|
||||
bool operator<(const DogAdder& other) const {
|
||||
return value_ < other.value_;
|
||||
}
|
||||
const std::string& value() const { return value_; }
|
||||
|
||||
private:
|
||||
|
@ -366,17 +372,19 @@ TEST(ValuesTest, ValuesWorksForValuesOfCompatibleTypes) {
|
|||
}
|
||||
|
||||
TEST(ValuesTest, ValuesWorksForMaxLengthList) {
|
||||
const ParamGenerator<int> gen =
|
||||
Values(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150,
|
||||
160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280,
|
||||
290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410,
|
||||
420, 430, 440, 450, 460, 470, 480, 490, 500);
|
||||
const ParamGenerator<int> gen = Values(
|
||||
10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
|
||||
110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
|
||||
210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
|
||||
310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
|
||||
410, 420, 430, 440, 450, 460, 470, 480, 490, 500);
|
||||
|
||||
const int expected_values[] = {
|
||||
10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130,
|
||||
140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260,
|
||||
270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390,
|
||||
400, 410, 420, 430, 440, 450, 460, 470, 480, 490, 500};
|
||||
10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
|
||||
110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
|
||||
210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
|
||||
310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
|
||||
410, 420, 430, 440, 450, 460, 470, 480, 490, 500};
|
||||
VerifyGenerator(gen, expected_values);
|
||||
}
|
||||
|
||||
|
@ -482,16 +490,17 @@ TEST(CombineTest, CombineWithMaxNumberOfParameters) {
|
|||
class NonDefaultConstructAssignString {
|
||||
public:
|
||||
NonDefaultConstructAssignString(const std::string& s) : str_(s) {}
|
||||
NonDefaultConstructAssignString() = delete;
|
||||
NonDefaultConstructAssignString(const NonDefaultConstructAssignString&) =
|
||||
default;
|
||||
NonDefaultConstructAssignString& operator=(
|
||||
const NonDefaultConstructAssignString&) = delete;
|
||||
~NonDefaultConstructAssignString() = default;
|
||||
|
||||
const std::string& str() const { return str_; }
|
||||
|
||||
private:
|
||||
std::string str_;
|
||||
|
||||
// Not default constructible
|
||||
NonDefaultConstructAssignString();
|
||||
// Not assignable
|
||||
void operator=(const NonDefaultConstructAssignString&);
|
||||
};
|
||||
|
||||
TEST(CombineTest, NonDefaultConstructAssign) {
|
||||
|
@ -521,6 +530,7 @@ TEST(CombineTest, NonDefaultConstructAssign) {
|
|||
EXPECT_TRUE(it == gen.end());
|
||||
}
|
||||
|
||||
|
||||
// Tests that an generator produces correct sequence after being
|
||||
// assigned from another generator.
|
||||
TEST(ParamGeneratorTest, AssignmentWorks) {
|
||||
|
@ -563,7 +573,7 @@ class TestGenerationEnvironment : public ::testing::Environment {
|
|||
Message msg;
|
||||
msg << "TestsExpandedAndRun/" << i;
|
||||
if (UnitTestOptions::FilterMatchesTest(
|
||||
"TestExpansionModule/MultipleTestGenerationTest",
|
||||
"TestExpansionModule/MultipleTestGenerationTest",
|
||||
msg.GetString().c_str())) {
|
||||
perform_check = true;
|
||||
}
|
||||
|
@ -585,11 +595,8 @@ class TestGenerationEnvironment : public ::testing::Environment {
|
|||
}
|
||||
|
||||
private:
|
||||
TestGenerationEnvironment()
|
||||
: fixture_constructor_count_(0),
|
||||
set_up_count_(0),
|
||||
tear_down_count_(0),
|
||||
test_body_count_(0) {}
|
||||
TestGenerationEnvironment() : fixture_constructor_count_(0), set_up_count_(0),
|
||||
tear_down_count_(0), test_body_count_(0) {}
|
||||
|
||||
int fixture_constructor_count_;
|
||||
int set_up_count_;
|
||||
|
@ -605,7 +612,7 @@ class TestGenerationTest : public TestWithParam<int> {
|
|||
public:
|
||||
enum {
|
||||
PARAMETER_COUNT =
|
||||
sizeof(test_generation_params) / sizeof(test_generation_params[0])
|
||||
sizeof(test_generation_params)/sizeof(test_generation_params[0])
|
||||
};
|
||||
|
||||
typedef TestGenerationEnvironment<PARAMETER_COUNT> Environment;
|
||||
|
@ -629,9 +636,9 @@ class TestGenerationTest : public TestWithParam<int> {
|
|||
for (int i = 0; i < PARAMETER_COUNT; ++i) {
|
||||
Message test_name;
|
||||
test_name << "TestsExpandedAndRun/" << i;
|
||||
if (!UnitTestOptions::FilterMatchesTest(
|
||||
"TestExpansionModule/MultipleTestGenerationTest",
|
||||
test_name.GetString())) {
|
||||
if ( !UnitTestOptions::FilterMatchesTest(
|
||||
"TestExpansionModule/MultipleTestGenerationTest",
|
||||
test_name.GetString())) {
|
||||
all_tests_in_test_case_selected = false;
|
||||
}
|
||||
}
|
||||
|
@ -722,7 +729,8 @@ TEST_P(ExternalInstantiationTest, IsMultipleOf33) {
|
|||
// Tests that a parameterized test case can be instantiated with multiple
|
||||
// generators.
|
||||
class MultipleInstantiationTest : public TestWithParam<int> {};
|
||||
TEST_P(MultipleInstantiationTest, AllowsMultipleInstances) {}
|
||||
TEST_P(MultipleInstantiationTest, AllowsMultipleInstances) {
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(Sequence1, MultipleInstantiationTest, Values(1, 2));
|
||||
INSTANTIATE_TEST_SUITE_P(Sequence2, MultipleInstantiationTest, Range(3, 5));
|
||||
|
||||
|
@ -772,7 +780,7 @@ class NamingTest : public TestWithParam<int> {};
|
|||
|
||||
TEST_P(NamingTest, TestsReportCorrectNamesAndParameters) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
|
||||
EXPECT_STREQ("ZeroToFiveSequence/NamingTest", test_info->test_suite_name());
|
||||
|
||||
|
@ -793,10 +801,10 @@ class MacroNamingTest : public TestWithParam<int> {};
|
|||
|
||||
TEST_P(PREFIX_WITH_MACRO(NamingTest), PREFIX_WITH_FOO(SomeTestName)) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
|
||||
EXPECT_STREQ("FortyTwo/MacroNamingTest", test_info->test_suite_name());
|
||||
EXPECT_STREQ("FooSomeTestName", test_info->name());
|
||||
EXPECT_STREQ("FooSomeTestName/0", test_info->name());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(FortyTwo, MacroNamingTest, Values(42));
|
||||
|
@ -807,12 +815,42 @@ class MacroNamingTestNonParametrized : public ::testing::Test {};
|
|||
TEST_F(PREFIX_WITH_MACRO(NamingTestNonParametrized),
|
||||
PREFIX_WITH_FOO(SomeTestName)) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
|
||||
EXPECT_STREQ("MacroNamingTestNonParametrized", test_info->test_suite_name());
|
||||
EXPECT_STREQ("FooSomeTestName", test_info->name());
|
||||
}
|
||||
|
||||
TEST(MacroNameing, LookupNames) {
|
||||
std::set<std::string> know_suite_names, know_test_names;
|
||||
|
||||
auto ins = testing::UnitTest::GetInstance();
|
||||
int ts = 0;
|
||||
while (const testing::TestSuite* suite = ins->GetTestSuite(ts++)) {
|
||||
know_suite_names.insert(suite->name());
|
||||
|
||||
int ti = 0;
|
||||
while (const testing::TestInfo* info = suite->GetTestInfo(ti++)) {
|
||||
know_test_names.insert(std::string(suite->name()) + "." + info->name());
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the expected form of the test suit name actually exists.
|
||||
EXPECT_NE( //
|
||||
know_suite_names.find("FortyTwo/MacroNamingTest"),
|
||||
know_suite_names.end());
|
||||
EXPECT_NE(
|
||||
know_suite_names.find("MacroNamingTestNonParametrized"),
|
||||
know_suite_names.end());
|
||||
// Check that the expected form of the test name actually exists.
|
||||
EXPECT_NE( //
|
||||
know_test_names.find("FortyTwo/MacroNamingTest.FooSomeTestName/0"),
|
||||
know_test_names.end());
|
||||
EXPECT_NE(
|
||||
know_test_names.find("MacroNamingTestNonParametrized.FooSomeTestName"),
|
||||
know_test_names.end());
|
||||
}
|
||||
|
||||
// Tests that user supplied custom parameter names are working correctly.
|
||||
// Runs the test with a builtin helper method which uses PrintToString,
|
||||
// as well as a custom function and custom functor to ensure all possible
|
||||
|
@ -886,7 +924,7 @@ class CustomIntegerNamingTest : public TestWithParam<int> {};
|
|||
|
||||
TEST_P(CustomIntegerNamingTest, TestsReportCorrectNames) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
Message test_name_stream;
|
||||
test_name_stream << "TestsReportCorrectNames/" << GetParam();
|
||||
EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
|
||||
|
@ -911,7 +949,7 @@ class CustomStructNamingTest : public TestWithParam<CustomStruct> {};
|
|||
|
||||
TEST_P(CustomStructNamingTest, TestsReportCorrectNames) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
Message test_name_stream;
|
||||
test_name_stream << "TestsReportCorrectNames/" << GetParam();
|
||||
EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
|
||||
|
@ -941,7 +979,7 @@ class StatefulNamingTest : public ::testing::TestWithParam<int> {
|
|||
|
||||
TEST_P(StatefulNamingTest, TestsReportCorrectNames) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
sum_ += GetParam();
|
||||
Message test_name_stream;
|
||||
test_name_stream << "TestsReportCorrectNames/" << sum_;
|
||||
|
@ -969,7 +1007,7 @@ class CommentTest : public TestWithParam<Unstreamable> {};
|
|||
|
||||
TEST_P(CommentTest, TestsCorrectlyReportUnstreamableParams) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
|
||||
EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
|
||||
}
|
||||
|
@ -983,8 +1021,7 @@ INSTANTIATE_TEST_SUITE_P(InstantiationWithComments, CommentTest,
|
|||
// perform simple tests on both.
|
||||
class NonParameterizedBaseTest : public ::testing::Test {
|
||||
public:
|
||||
NonParameterizedBaseTest() : n_(17) {}
|
||||
|
||||
NonParameterizedBaseTest() : n_(17) { }
|
||||
protected:
|
||||
int n_;
|
||||
};
|
||||
|
@ -992,14 +1029,16 @@ class NonParameterizedBaseTest : public ::testing::Test {
|
|||
class ParameterizedDerivedTest : public NonParameterizedBaseTest,
|
||||
public ::testing::WithParamInterface<int> {
|
||||
protected:
|
||||
ParameterizedDerivedTest() : count_(0) {}
|
||||
ParameterizedDerivedTest() : count_(0) { }
|
||||
int count_;
|
||||
static int global_count_;
|
||||
};
|
||||
|
||||
int ParameterizedDerivedTest::global_count_ = 0;
|
||||
|
||||
TEST_F(NonParameterizedBaseTest, FixtureIsInitialized) { EXPECT_EQ(17, n_); }
|
||||
TEST_F(NonParameterizedBaseTest, FixtureIsInitialized) {
|
||||
EXPECT_EQ(17, n_);
|
||||
}
|
||||
|
||||
TEST_P(ParameterizedDerivedTest, SeesSequence) {
|
||||
EXPECT_EQ(17, n_);
|
||||
|
@ -1007,10 +1046,11 @@ TEST_P(ParameterizedDerivedTest, SeesSequence) {
|
|||
EXPECT_EQ(GetParam(), global_count_++);
|
||||
}
|
||||
|
||||
class ParameterizedDeathTest : public ::testing::TestWithParam<int> {};
|
||||
class ParameterizedDeathTest : public ::testing::TestWithParam<int> { };
|
||||
|
||||
TEST_F(ParameterizedDeathTest, GetParamDiesFromTestF) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(GetParam(), ".* value-parameterized test .*");
|
||||
EXPECT_DEATH_IF_SUPPORTED(GetParam(),
|
||||
".* value-parameterized test .*");
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(RangeZeroToFive, ParameterizedDerivedTest,
|
||||
|
@ -1029,7 +1069,39 @@ TEST_P(MyEnumTest, ChecksParamMoreThanZero) { EXPECT_GE(10, GetParam()); }
|
|||
INSTANTIATE_TEST_SUITE_P(MyEnumTests, MyEnumTest,
|
||||
::testing::Values(ENUM1, ENUM2, 0));
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
namespace works_here {
|
||||
// Never used not instantiated, this should work.
|
||||
class NotUsedTest : public testing::TestWithParam<int> {};
|
||||
|
||||
///////
|
||||
// Never used not instantiated, this should work.
|
||||
template <typename T>
|
||||
class NotUsedTypeTest : public testing::Test {};
|
||||
TYPED_TEST_SUITE_P(NotUsedTypeTest);
|
||||
|
||||
// Used but not instantiated, this would fail. but...
|
||||
class NotInstantiatedTest : public testing::TestWithParam<int> {};
|
||||
// ... we mark is as allowed.
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NotInstantiatedTest);
|
||||
|
||||
TEST_P(NotInstantiatedTest, Used) { }
|
||||
|
||||
using OtherName = NotInstantiatedTest;
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OtherName);
|
||||
TEST_P(OtherName, Used) { }
|
||||
|
||||
// Used but not instantiated, this would fail. but...
|
||||
template <typename T>
|
||||
class NotInstantiatedTypeTest : public testing::Test {};
|
||||
TYPED_TEST_SUITE_P(NotInstantiatedTypeTest);
|
||||
// ... we mark is as allowed.
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NotInstantiatedTypeTest);
|
||||
|
||||
TYPED_TEST_P(NotInstantiatedTypeTest, Used) { }
|
||||
REGISTER_TYPED_TEST_SUITE_P(NotInstantiatedTypeTest, Used);
|
||||
} // namespace works_here
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Used in TestGenerationTest test suite.
|
||||
AddGlobalTestEnvironment(TestGenerationTest::Environment::Instance());
|
||||
// Used in GeneratorEvaluationTest test suite. Tests that the updated value
|
||||
|
|
|
@ -32,18 +32,20 @@
|
|||
// This header file provides classes and functions used internally
|
||||
// for testing Google Test itself.
|
||||
|
||||
#ifndef GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
|
||||
#define GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
|
||||
#ifndef GOOGLETEST_TEST_GOOGLETEST_PARAM_TEST_TEST_H_
|
||||
#define GOOGLETEST_TEST_GOOGLETEST_PARAM_TEST_TEST_H_
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// Test fixture for testing definition and instantiation of a test
|
||||
// in separate translation units.
|
||||
class ExternalInstantiationTest : public ::testing::TestWithParam<int> {};
|
||||
class ExternalInstantiationTest : public ::testing::TestWithParam<int> {
|
||||
};
|
||||
|
||||
// Test fixture for testing instantiation of a test in multiple
|
||||
// translation units.
|
||||
class InstantiationInMultipleTranslationUnitsTest
|
||||
: public ::testing::TestWithParam<int> {};
|
||||
: public ::testing::TestWithParam<int> {
|
||||
};
|
||||
|
||||
#endif // GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
|
||||
#endif // GOOGLETEST_TEST_GOOGLETEST_PARAM_TEST_TEST_H_
|
||||
|
|
|
@ -46,7 +46,8 @@ ParamGenerator<int> extern_gen = Values(33);
|
|||
// and instantiated in another. The test is defined in
|
||||
// googletest-param-test-test.cc and ExternalInstantiationTest fixture class is
|
||||
// defined in gtest-param-test_test.h.
|
||||
INSTANTIATE_TEST_SUITE_P(MultiplesOf33, ExternalInstantiationTest,
|
||||
INSTANTIATE_TEST_SUITE_P(MultiplesOf33,
|
||||
ExternalInstantiationTest,
|
||||
Values(33, 66));
|
||||
|
||||
// Tests that a parameterized test case can be instantiated
|
||||
|
@ -54,5 +55,7 @@ INSTANTIATE_TEST_SUITE_P(MultiplesOf33, ExternalInstantiationTest,
|
|||
// in googletest-param-test-test.cc and
|
||||
// InstantiationInMultipleTranslationUnitsTest fixture is defined in
|
||||
// gtest-param-test_test.h
|
||||
INSTANTIATE_TEST_SUITE_P(Sequence2, InstantiationInMultipleTranslationUnitsTest,
|
||||
Values(42 * 3, 42 * 4, 42 * 5));
|
||||
INSTANTIATE_TEST_SUITE_P(Sequence2,
|
||||
InstantiationInMultipleTranslationUnitsTest,
|
||||
Values(42*3, 42*4, 42*5));
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
#if GTEST_OS_MAC
|
||||
#include <time.h>
|
||||
# include <time.h>
|
||||
#endif // GTEST_OS_MAC
|
||||
|
||||
#include <list>
|
||||
|
@ -90,10 +90,10 @@ TEST(IsXDigitTest, ReturnsFalseForWideNonAscii) {
|
|||
|
||||
class Base {
|
||||
public:
|
||||
// Copy constructor and assignment operator do exactly what we need, so we
|
||||
// use them.
|
||||
Base() : member_(0) {}
|
||||
explicit Base(int n) : member_(n) {}
|
||||
Base(const Base&) = default;
|
||||
Base& operator=(const Base&) = default;
|
||||
virtual ~Base() {}
|
||||
int member() { return member_; }
|
||||
|
||||
|
@ -201,6 +201,13 @@ TEST(ImplicitCastTest, CanUseImplicitConstructor) {
|
|||
EXPECT_TRUE(converted);
|
||||
}
|
||||
|
||||
// The following code intentionally tests a suboptimal syntax.
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdangling-else"
|
||||
#pragma GCC diagnostic ignored "-Wempty-body"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#endif
|
||||
TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) {
|
||||
if (AlwaysFalse())
|
||||
GTEST_CHECK_(false) << "This should never be executed; "
|
||||
|
@ -216,6 +223,9 @@ TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) {
|
|||
else
|
||||
GTEST_CHECK_(true) << "";
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
|
||||
switch (0) {
|
||||
|
@ -226,8 +236,8 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
|
|||
}
|
||||
|
||||
switch (0)
|
||||
case 0:
|
||||
GTEST_CHECK_(true) << "Check failed in switch case";
|
||||
case 0:
|
||||
GTEST_CHECK_(true) << "Check failed in switch case";
|
||||
}
|
||||
|
||||
// Verifies behavior of FormatFileLocation.
|
||||
|
@ -269,7 +279,7 @@ TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
|
|||
}
|
||||
|
||||
#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA || \
|
||||
GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
|
||||
GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
|
||||
GTEST_OS_NETBSD || GTEST_OS_OPENBSD
|
||||
void* ThreadFunc(void* data) {
|
||||
internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
|
||||
|
@ -280,12 +290,12 @@ void* ThreadFunc(void* data) {
|
|||
|
||||
TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
||||
const size_t starting_count = GetThreadCount();
|
||||
pthread_t thread_id;
|
||||
pthread_t thread_id;
|
||||
|
||||
internal::Mutex mutex;
|
||||
{
|
||||
internal::MutexLock lock(&mutex);
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_t attr;
|
||||
ASSERT_EQ(0, pthread_attr_init(&attr));
|
||||
ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
|
||||
|
||||
|
@ -302,7 +312,8 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
|||
// joining a thread, causing flakiness in this test. To counter that, we
|
||||
// wait for up to .5 seconds for the OS to report the correct value.
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (GetThreadCount() == starting_count) break;
|
||||
if (GetThreadCount() == starting_count)
|
||||
break;
|
||||
|
||||
SleepMilliseconds(100);
|
||||
}
|
||||
|
@ -319,13 +330,13 @@ TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
|
|||
const bool a_false_condition = false;
|
||||
const char regex[] =
|
||||
#ifdef _MSC_VER
|
||||
"googletest-port-test\\.cc\\(\\d+\\):"
|
||||
"googletest-port-test\\.cc\\(\\d+\\):"
|
||||
#elif GTEST_USES_POSIX_RE
|
||||
"googletest-port-test\\.cc:[0-9]+"
|
||||
"googletest-port-test\\.cc:[0-9]+"
|
||||
#else
|
||||
"googletest-port-test\\.cc:\\d+"
|
||||
"googletest-port-test\\.cc:\\d+"
|
||||
#endif // _MSC_VER
|
||||
".*a_false_condition.*Extra info.*";
|
||||
".*a_false_condition.*Extra info.*";
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info",
|
||||
regex);
|
||||
|
@ -334,12 +345,10 @@ TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
|
|||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
|
||||
EXPECT_EXIT(
|
||||
{
|
||||
GTEST_CHECK_(true) << "Extra info";
|
||||
::std::cerr << "Success\n";
|
||||
exit(0);
|
||||
},
|
||||
EXPECT_EXIT({
|
||||
GTEST_CHECK_(true) << "Extra info";
|
||||
::std::cerr << "Success\n";
|
||||
exit(0); },
|
||||
::testing::ExitedWithCode(0), "Success");
|
||||
}
|
||||
|
||||
|
@ -350,22 +359,20 @@ TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
|
|||
// For simplicity, we only cover the most important platforms here.
|
||||
TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) {
|
||||
#if !GTEST_USES_PCRE
|
||||
#if GTEST_HAS_POSIX_RE
|
||||
# if GTEST_HAS_POSIX_RE
|
||||
|
||||
EXPECT_TRUE(GTEST_USES_POSIX_RE);
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
EXPECT_TRUE(GTEST_USES_SIMPLE_RE);
|
||||
|
||||
#endif
|
||||
# endif
|
||||
#endif // !GTEST_USES_PCRE
|
||||
}
|
||||
|
||||
#if GTEST_USES_POSIX_RE
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST
|
||||
|
||||
template <typename Str>
|
||||
class RETest : public ::testing::Test {};
|
||||
|
||||
|
@ -389,9 +396,9 @@ TYPED_TEST(RETest, ImplicitConstructorWorks) {
|
|||
|
||||
// Tests that RE's constructors reject invalid regular expressions.
|
||||
TYPED_TEST(RETest, RejectsInvalidRegex) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ const RE invalid(TypeParam("?")); },
|
||||
"\"?\" is not a valid POSIX Extended regular expression.");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
const RE invalid(TypeParam("?"));
|
||||
}, "\"?\" is not a valid POSIX Extended regular expression.");
|
||||
}
|
||||
|
||||
// Tests RE::FullMatch().
|
||||
|
@ -421,8 +428,6 @@ TYPED_TEST(RETest, PartialMatchWorks) {
|
|||
EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re));
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST
|
||||
|
||||
#elif GTEST_USES_SIMPLE_RE
|
||||
|
||||
TEST(IsInSetTest, NulCharIsNotInAnySet) {
|
||||
|
@ -787,7 +792,8 @@ TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) {
|
|||
EXPECT_TRUE(MatchRegexAtHead("a?b", "ab"));
|
||||
}
|
||||
|
||||
TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetionOfEscapeSequence) {
|
||||
TEST(MatchRegexAtHeadTest,
|
||||
WorksWhenRegexStartsWithRepetionOfEscapeSequence) {
|
||||
EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc"));
|
||||
EXPECT_FALSE(MatchRegexAtHead("\\s?b", " b"));
|
||||
|
||||
|
@ -843,14 +849,17 @@ TEST(RETest, ImplicitConstructorWorks) {
|
|||
|
||||
// Tests that RE's constructors reject invalid regular expressions.
|
||||
TEST(RETest, RejectsInvalidRegex) {
|
||||
EXPECT_NONFATAL_FAILURE({ const RE normal(NULL); },
|
||||
"NULL is not a valid simple regular expression");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
const RE normal(NULL);
|
||||
}, "NULL is not a valid simple regular expression");
|
||||
|
||||
EXPECT_NONFATAL_FAILURE({ const RE normal(".*(\\w+"); },
|
||||
"'(' is unsupported");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
const RE normal(".*(\\w+");
|
||||
}, "'(' is unsupported");
|
||||
|
||||
EXPECT_NONFATAL_FAILURE({ const RE invalid("^?"); },
|
||||
"'?' can only follow a repeatable token");
|
||||
EXPECT_NONFATAL_FAILURE({
|
||||
const RE invalid("^?");
|
||||
}, "'?' can only follow a repeatable token");
|
||||
}
|
||||
|
||||
// Tests RE::FullMatch().
|
||||
|
@ -992,13 +1001,12 @@ TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) {
|
|||
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");
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
Mutex m;
|
||||
{ MutexLock lock(&m); }
|
||||
m.AssertHeld();
|
||||
},
|
||||
"thread .*hold");
|
||||
}
|
||||
|
||||
TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
|
||||
|
@ -1009,16 +1017,16 @@ TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
|
|||
|
||||
class AtomicCounterWithMutex {
|
||||
public:
|
||||
explicit AtomicCounterWithMutex(Mutex* mutex)
|
||||
: value_(0), mutex_(mutex), random_(42) {}
|
||||
explicit AtomicCounterWithMutex(Mutex* mutex) :
|
||||
value_(0), mutex_(mutex), random_(42) {}
|
||||
|
||||
void Increment() {
|
||||
MutexLock lock(mutex_);
|
||||
int temp = value_;
|
||||
{
|
||||
// We need to put up a memory barrier to prevent reads and writes to
|
||||
// value_ rearranged with the call to SleepMilliseconds when observed
|
||||
// from other threads.
|
||||
// We need to put up a memory barrier to prevent reads and writes to
|
||||
// value_ rearranged with the call to SleepMilliseconds when observed
|
||||
// from other threads.
|
||||
#if GTEST_HAS_PTHREAD
|
||||
// On POSIX, locking a mutex puts up a memory barrier. We cannot use
|
||||
// Mutex and MutexLock here or rely on their memory barrier
|
||||
|
@ -1039,7 +1047,7 @@ class AtomicCounterWithMutex {
|
|||
SleepMilliseconds(static_cast<int>(random_.Generate(30)));
|
||||
::InterlockedIncrement(&dummy);
|
||||
#else
|
||||
#error "Memory barrier not implemented on this platform."
|
||||
# error "Memory barrier not implemented on this platform."
|
||||
#endif // GTEST_HAS_PTHREAD
|
||||
}
|
||||
value_ = temp + 1;
|
||||
|
@ -1049,11 +1057,12 @@ class AtomicCounterWithMutex {
|
|||
private:
|
||||
volatile int value_;
|
||||
Mutex* const mutex_; // Protects value_.
|
||||
Random random_;
|
||||
Random random_;
|
||||
};
|
||||
|
||||
void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
|
||||
for (int i = 0; i < param.second; ++i) param.first->Increment();
|
||||
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.
|
||||
|
@ -1069,12 +1078,14 @@ TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
|
|||
// 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));
|
||||
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();
|
||||
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
|
||||
|
@ -1084,7 +1095,7 @@ TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void RunFromThread(void(func)(T), T param) {
|
||||
void RunFromThread(void (func)(T), T param) {
|
||||
ThreadWithParam<T> thread(func, param, nullptr);
|
||||
thread.Join();
|
||||
}
|
||||
|
@ -1175,8 +1186,6 @@ class DestructorTracker {
|
|||
return DestructorCall::List().size() - 1;
|
||||
}
|
||||
const size_t index_;
|
||||
|
||||
GTEST_DISALLOW_ASSIGN_(DestructorTracker);
|
||||
};
|
||||
|
||||
typedef ThreadLocal<DestructorTracker>* ThreadParam;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче