Update to Google Test 1.10.0 (!117)
So far GParted includes Google Test 1.8.1 [1], which was the latest
release which supported pre-C++11 compilers [2]. Now that GParted
requires C++11 compilation, update to Google Test 1.10.0. Replace the
following files and directories from Google Test 1.10.0:
LICENSE
README.md
include/
src/
Note the LICENSE file is identical, where as the other files have
changed. This includes file additions and removals, hence the change
to Makefile.am too.
Even though Google Test releases up to and including 1.12.1 are
compilable with C++11 compilers [3], it is not possible to upgrade
beyond Google Test 1.10.0 at this time because later releases fail to
compile on on still supported RHEL / CentOS 7 with this error:
$ cd lib/gtest
$ make check
...
./include/gtest/gtest-matchers.h:414:12: error: 'is_trivially_copy_constructible' is not a member of 'std'
std::is_trivially_copy_constructible<M>::value &&
^
This failure turns out to be because GCC libstdc++ 4.8.5 doesn't include
is_trivially_copy_constructible et al [4][5].
[1] commit 2b222978f5
Update to Google Test 1.8.1
[2] Google Test release v1.8.1
https://github.com/google/googletest/releases/tag/release-1.8.1
"The 1.8.x is the last release supporting pre-C++11 compilers."
[3] Google Test release v1.12.1
https://github.com/google/googletest/releases/tag/release-1.12.1
"This will be the last release to support C++11. Future releases
will require at least C++14."
[4] 'is_trivially_copyable' is not a member of 'std'
https://stackoverflow.com/questions/25123458/is-trivially-copyable-is-not-a-member-of-std/25123551#25123551
"Some of them are not implemented. If we look at libstdc++'s C++11
status page:
Type properties are listed as partially implemented.
They list as missing:
...
is trivially_copy_constructible
"
[5] The GNU C++ Library, 1. Status, C++11
https://gcc.gnu.org/onlinedocs/gcc-4.8.3/libstdc++/manual/manual/status.html#status.iso.2011
"
| Section | Description | Status | Comments
...
| 20.9.4.3 | Type properties | Partial | Missing
is_trivially_copyable, is_trivially_constructible,
is_trivially_default_constructible, is_trivially_copy_constructible,
is_trivially_move_constructible, is_trivially_assignable,
is_trivially_default_assignable, is_trivially_copy_assignable,
is_trivially_move_assignable |
"
Closes !117 - Require C++11 compilation
This commit is contained in:
parent
3b469273de
commit
1ccb782156
|
@ -1,47 +1,48 @@
|
||||||
# Nonstandard package files for distribution
|
# Nonstandard package files for distribution
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
LICENSE \
|
LICENSE \
|
||||||
README.md \
|
README.md \
|
||||||
include/gtest/gtest-param-test.h.pump \
|
include/gtest/internal/custom/README.md \
|
||||||
include/gtest/internal/gtest-param-util-generated.h.pump \
|
include/gtest/internal/gtest-type-util.h.pump
|
||||||
include/gtest/internal/gtest-tuple.h.pump \
|
|
||||||
include/gtest/internal/gtest-type-util.h.pump
|
|
||||||
|
|
||||||
# gtest source files that we don't compile directly. They are
|
# Google Test source files that we don't compile directly. (Instead
|
||||||
# #included by gtest-all.cc.
|
# they are #included by gtest-all.cc).
|
||||||
GTEST_SRC = \
|
# List files with:
|
||||||
src/gtest-death-test.cc \
|
# cd lib/gtest/
|
||||||
src/gtest-filepath.cc \
|
# find src include '(' -name '*.h' -o -name '*.cc' ')' -print | \
|
||||||
src/gtest-internal-inl.h \
|
# egrep -v 'gtest-all.cc|gtest_main.cc' | sort
|
||||||
src/gtest-port.cc \
|
GTEST_SRC = \
|
||||||
src/gtest-printers.cc \
|
include/gtest/gtest-death-test.h \
|
||||||
src/gtest-test-part.cc \
|
include/gtest/gtest.h \
|
||||||
src/gtest-typed-test.cc \
|
include/gtest/gtest-matchers.h \
|
||||||
src/gtest.cc \
|
include/gtest/gtest-message.h \
|
||||||
include/gtest/gtest-death-test.h \
|
include/gtest/gtest-param-test.h \
|
||||||
include/gtest/gtest-message.h \
|
include/gtest/gtest_pred_impl.h \
|
||||||
include/gtest/gtest-param-test.h \
|
include/gtest/gtest-printers.h \
|
||||||
include/gtest/gtest-printers.h \
|
include/gtest/gtest_prod.h \
|
||||||
include/gtest/gtest-spi.h \
|
include/gtest/gtest-spi.h \
|
||||||
include/gtest/gtest-test-part.h \
|
include/gtest/gtest-test-part.h \
|
||||||
include/gtest/gtest-typed-test.h \
|
include/gtest/gtest-typed-test.h \
|
||||||
include/gtest/gtest.h \
|
include/gtest/internal/custom/gtest.h \
|
||||||
include/gtest/gtest_pred_impl.h \
|
include/gtest/internal/custom/gtest-port.h \
|
||||||
include/gtest/gtest_prod.h \
|
include/gtest/internal/custom/gtest-printers.h \
|
||||||
include/gtest/internal/gtest-death-test-internal.h \
|
include/gtest/internal/gtest-death-test-internal.h \
|
||||||
include/gtest/internal/gtest-filepath.h \
|
include/gtest/internal/gtest-filepath.h \
|
||||||
include/gtest/internal/gtest-internal.h \
|
include/gtest/internal/gtest-internal.h \
|
||||||
include/gtest/internal/gtest-linked_ptr.h \
|
include/gtest/internal/gtest-param-util.h \
|
||||||
include/gtest/internal/gtest-param-util-generated.h \
|
include/gtest/internal/gtest-port-arch.h \
|
||||||
include/gtest/internal/gtest-param-util.h \
|
include/gtest/internal/gtest-port.h \
|
||||||
include/gtest/internal/gtest-port.h \
|
include/gtest/internal/gtest-string.h \
|
||||||
include/gtest/internal/gtest-port-arch.h \
|
include/gtest/internal/gtest-type-util.h \
|
||||||
include/gtest/internal/gtest-string.h \
|
src/gtest.cc \
|
||||||
include/gtest/internal/gtest-tuple.h \
|
src/gtest-death-test.cc \
|
||||||
include/gtest/internal/gtest-type-util.h \
|
src/gtest-filepath.cc \
|
||||||
include/gtest/internal/custom/gtest.h \
|
src/gtest-internal-inl.h \
|
||||||
include/gtest/internal/custom/gtest-port.h \
|
src/gtest-matchers.cc \
|
||||||
include/gtest/internal/custom/gtest-printers.h
|
src/gtest-port.cc \
|
||||||
|
src/gtest-printers.cc \
|
||||||
|
src/gtest-test-part.cc \
|
||||||
|
src/gtest-typed-test.cc
|
||||||
|
|
||||||
EXTRA_DIST += $(GTEST_SRC)
|
EXTRA_DIST += $(GTEST_SRC)
|
||||||
|
|
||||||
|
|
|
@ -6,48 +6,7 @@ To build Google Test and your tests that use it, you need to tell your build
|
||||||
system where to find its headers and source files. The exact way to do it
|
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.
|
depends on which build system you use, and is usually straightforward.
|
||||||
|
|
||||||
#### Build
|
### Build with CMake
|
||||||
|
|
||||||
Suppose you put Google Test in directory `${GTEST_DIR}`. To build it, create a
|
|
||||||
library build target (or a project as called by Visual Studio and Xcode) to
|
|
||||||
compile
|
|
||||||
|
|
||||||
${GTEST_DIR}/src/gtest-all.cc
|
|
||||||
|
|
||||||
with `${GTEST_DIR}/include` in the system header search path and `${GTEST_DIR}`
|
|
||||||
in the normal header search path. Assuming a Linux-like system and gcc,
|
|
||||||
something like the following will do:
|
|
||||||
|
|
||||||
g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
|
|
||||||
-pthread -c ${GTEST_DIR}/src/gtest-all.cc
|
|
||||||
ar -rv libgtest.a gtest-all.o
|
|
||||||
|
|
||||||
(We need `-pthread` as Google Test uses threads.)
|
|
||||||
|
|
||||||
Next, you should compile your test source file with `${GTEST_DIR}/include` in
|
|
||||||
the system header search path, and link it with gtest and any other necessary
|
|
||||||
libraries:
|
|
||||||
|
|
||||||
g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \
|
|
||||||
-o your_test
|
|
||||||
|
|
||||||
As an example, the make/ directory contains a Makefile that you can use to build
|
|
||||||
Google Test on systems where GNU make is available (e.g. Linux, Mac OS X, and
|
|
||||||
Cygwin). It doesn't try to build Google Test's own tests. Instead, it just
|
|
||||||
builds the Google Test library and a sample test. You can use it as a starting
|
|
||||||
point for your own build script.
|
|
||||||
|
|
||||||
If the default settings are correct for your environment, the following commands
|
|
||||||
should succeed:
|
|
||||||
|
|
||||||
cd ${GTEST_DIR}/make
|
|
||||||
make
|
|
||||||
./sample1_unittest
|
|
||||||
|
|
||||||
If you see errors, try to tweak the contents of `make/Makefile` to make them go
|
|
||||||
away. There are instructions in `make/Makefile` on how to do it.
|
|
||||||
|
|
||||||
### Using CMake
|
|
||||||
|
|
||||||
Google Test comes with a CMake build script (
|
Google Test comes with a CMake build script (
|
||||||
[CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt))
|
[CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt))
|
||||||
|
@ -115,60 +74,64 @@ pulled into the main build with `add_subdirectory()`. For example:
|
||||||
|
|
||||||
New file `CMakeLists.txt.in`:
|
New file `CMakeLists.txt.in`:
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.2)
|
```cmake
|
||||||
|
cmake_minimum_required(VERSION 2.8.2)
|
||||||
|
|
||||||
project(googletest-download NONE)
|
project(googletest-download NONE)
|
||||||
|
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(googletest
|
ExternalProject_Add(googletest
|
||||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||||
GIT_TAG master
|
GIT_TAG master
|
||||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
|
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
|
||||||
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
|
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
TEST_COMMAND ""
|
TEST_COMMAND ""
|
||||||
)
|
)
|
||||||
|
```
|
||||||
|
|
||||||
Existing build's `CMakeLists.txt`:
|
Existing build's `CMakeLists.txt`:
|
||||||
|
|
||||||
# Download and unpack googletest at configure time
|
```cmake
|
||||||
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
|
# Download and unpack googletest at configure time
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
|
||||||
RESULT_VARIABLE result
|
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
|
RESULT_VARIABLE result
|
||||||
if(result)
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
|
||||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
if(result)
|
||||||
endif()
|
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
endif()
|
||||||
RESULT_VARIABLE result
|
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
|
RESULT_VARIABLE result
|
||||||
if(result)
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
|
||||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
if(result)
|
||||||
endif()
|
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Prevent overriding the parent project's compiler/linker
|
# Prevent overriding the parent project's compiler/linker
|
||||||
# settings on Windows
|
# settings on Windows
|
||||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
# Add googletest directly to our build. This defines
|
# Add googletest directly to our build. This defines
|
||||||
# the gtest and gtest_main targets.
|
# the gtest and gtest_main targets.
|
||||||
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
|
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
|
||||||
${CMAKE_BINARY_DIR}/googletest-build
|
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
|
||||||
EXCLUDE_FROM_ALL)
|
EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
# The gtest/gtest_main targets carry header search path
|
# The gtest/gtest_main targets carry header search path
|
||||||
# dependencies automatically when using CMake 2.8.11 or
|
# dependencies automatically when using CMake 2.8.11 or
|
||||||
# later. Otherwise we have to add them here ourselves.
|
# later. Otherwise we have to add them here ourselves.
|
||||||
if (CMAKE_VERSION VERSION_LESS 2.8.11)
|
if (CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||||
include_directories("${gtest_SOURCE_DIR}/include")
|
include_directories("${gtest_SOURCE_DIR}/include")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Now simply link against gtest or gtest_main as needed. Eg
|
# Now simply link against gtest or gtest_main as needed. Eg
|
||||||
add_executable(example example.cpp)
|
add_executable(example example.cpp)
|
||||||
target_link_libraries(example gtest_main)
|
target_link_libraries(example gtest_main)
|
||||||
add_test(NAME example_test COMMAND example)
|
add_test(NAME example_test COMMAND example)
|
||||||
|
```
|
||||||
|
|
||||||
Note that this approach requires CMake 2.8.2 or later due to its use of the
|
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
|
`ExternalProject_Add()` command. The above technique is discussed in more detail
|
||||||
|
@ -188,47 +151,14 @@ Google Test already has a CMake option for this: `gtest_force_shared_crt`
|
||||||
Enabling this option will make gtest link the runtimes dynamically too, and
|
Enabling this option will make gtest link the runtimes dynamically too, and
|
||||||
match the project in which it is included.
|
match the project in which it is included.
|
||||||
|
|
||||||
### Legacy Build Scripts
|
#### C++ Standard Version
|
||||||
|
|
||||||
Before settling on CMake, we have been providing hand-maintained build
|
An environment that supports C++11 is required in order to successfully build
|
||||||
projects/scripts for Visual Studio, Xcode, and Autotools. While we continue to
|
Google Test. One way to ensure this is to specify the standard in the top-level
|
||||||
provide them for convenience, they are not actively maintained any more. We
|
project, for example by using the `set(CMAKE_CXX_STANDARD 11)` command. If this
|
||||||
highly recommend that you follow the instructions in the above sections to
|
is not feasible, for example in a C project using Google Test for validation,
|
||||||
integrate Google Test with your existing build system.
|
then it can be specified by adding it to the options for cmake via the
|
||||||
|
`DCMAKE_CXX_FLAGS` option.
|
||||||
If you still need to use the legacy build scripts, here's how:
|
|
||||||
|
|
||||||
The msvc\ folder contains two solutions with Visual C++ projects. Open the
|
|
||||||
`gtest.sln` or `gtest-md.sln` file using Visual Studio, and you are ready to
|
|
||||||
build Google Test the same way you build any Visual Studio project. Files that
|
|
||||||
have names ending with -md use DLL versions of Microsoft runtime libraries (the
|
|
||||||
/MD or the /MDd compiler option). Files without that suffix use static versions
|
|
||||||
of the runtime libraries (the /MT or the /MTd option). Please note that one must
|
|
||||||
use the same option to compile both gtest and the test code. If you use Visual
|
|
||||||
Studio 2005 or above, we recommend the -md version as /MD is the default for new
|
|
||||||
projects in these versions of Visual Studio.
|
|
||||||
|
|
||||||
On Mac OS X, open the `gtest.xcodeproj` in the `xcode/` folder using Xcode.
|
|
||||||
Build the "gtest" target. The universal binary framework will end up in your
|
|
||||||
selected build directory (selected in the Xcode "Preferences..." -> "Building"
|
|
||||||
pane and defaults to xcode/build). Alternatively, at the command line, enter:
|
|
||||||
|
|
||||||
xcodebuild
|
|
||||||
|
|
||||||
This will build the "Release" configuration of gtest.framework in your default
|
|
||||||
build location. See the "xcodebuild" man page for more information about
|
|
||||||
building different configurations and building in different locations.
|
|
||||||
|
|
||||||
If you wish to use the Google Test Xcode project with Xcode 4.x and above, you
|
|
||||||
need to either:
|
|
||||||
|
|
||||||
* update the SDK configuration options in xcode/Config/General.xconfig.
|
|
||||||
Comment options `SDKROOT`, `MACOS_DEPLOYMENT_TARGET`, and `GCC_VERSION`. If
|
|
||||||
you choose this route you lose the ability to target earlier versions of
|
|
||||||
MacOS X.
|
|
||||||
* Install an SDK for an earlier version. This doesn't appear to be supported
|
|
||||||
by Apple, but has been reported to work
|
|
||||||
(http://stackoverflow.com/questions/5378518).
|
|
||||||
|
|
||||||
### Tweaking Google Test
|
### Tweaking Google Test
|
||||||
|
|
||||||
|
@ -239,41 +169,14 @@ 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.
|
them to either 1 or 0 to enable or disable a certain feature.
|
||||||
|
|
||||||
We list the most frequently used macros below. For a complete list, see file
|
We list the most frequently used macros below. For a complete list, see file
|
||||||
[include/gtest/internal/gtest-port.h](https://github.com/google/googletest/blob/master/include/gtest/internal/gtest-port.h).
|
[include/gtest/internal/gtest-port.h](https://github.com/google/googletest/blob/master/googletest/include/gtest/internal/gtest-port.h).
|
||||||
|
|
||||||
### Choosing a TR1 Tuple Library
|
|
||||||
|
|
||||||
Some Google Test features require the C++ Technical Report 1 (TR1) tuple
|
|
||||||
library, which is not yet available with all compilers. The good news is that
|
|
||||||
Google Test implements a subset of TR1 tuple that's enough for its own need, and
|
|
||||||
will automatically use this when the compiler doesn't provide TR1 tuple.
|
|
||||||
|
|
||||||
Usually you don't need to care about which tuple library Google Test uses.
|
|
||||||
However, if your project already uses TR1 tuple, you need to tell Google Test to
|
|
||||||
use the same TR1 tuple library the rest of your project uses, or the two tuple
|
|
||||||
implementations will clash. To do that, add
|
|
||||||
|
|
||||||
-DGTEST_USE_OWN_TR1_TUPLE=0
|
|
||||||
|
|
||||||
to the compiler flags while compiling Google Test and your tests. If you want to
|
|
||||||
force Google Test to use its own tuple library, just add
|
|
||||||
|
|
||||||
-DGTEST_USE_OWN_TR1_TUPLE=1
|
|
||||||
|
|
||||||
to the compiler flags instead.
|
|
||||||
|
|
||||||
If you don't want Google Test to use tuple at all, add
|
|
||||||
|
|
||||||
-DGTEST_HAS_TR1_TUPLE=0
|
|
||||||
|
|
||||||
and all features using tuple will be disabled.
|
|
||||||
|
|
||||||
### Multi-threaded Tests
|
### Multi-threaded Tests
|
||||||
|
|
||||||
Google Test is thread-safe where the pthread library is available. After
|
Google Test is thread-safe where the pthread library is available. After
|
||||||
`#include "gtest/gtest.h"`, you can check the `GTEST_IS_THREADSAFE` macro to see
|
`#include "gtest/gtest.h"`, you can check the
|
||||||
whether this is the case (yes if the macro is `#defined` to 1, no if it's
|
`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
|
||||||
undefined.).
|
`#defined` to 1, no if it's undefined.).
|
||||||
|
|
||||||
If Google Test doesn't correctly detect whether pthread is available in your
|
If Google Test doesn't correctly detect whether pthread is available in your
|
||||||
environment, you can force it with
|
environment, you can force it with
|
||||||
|
|
|
@ -161,7 +161,6 @@ GTEST_API_ bool InDeathTestChild();
|
||||||
// is rarely a problem as people usually don't put the test binary
|
// is rarely a problem as people usually don't put the test binary
|
||||||
// directory in PATH.
|
// directory in PATH.
|
||||||
//
|
//
|
||||||
// FIXME: make thread-safe death tests search the PATH.
|
|
||||||
|
|
||||||
// Asserts that a given statement causes the program to exit, with an
|
// Asserts that a given statement causes the program to exit, with an
|
||||||
// integer exit status that satisfies predicate, and emitting error output
|
// integer exit status that satisfies predicate, and emitting error output
|
||||||
|
@ -170,7 +169,7 @@ GTEST_API_ bool InDeathTestChild();
|
||||||
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
|
GTEST_DEATH_TEST_(statement, predicate, regex, 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 case, if any:
|
// test suite, if any:
|
||||||
# define EXPECT_EXIT(statement, predicate, regex) \
|
# define EXPECT_EXIT(statement, predicate, regex) \
|
||||||
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
|
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
|
||||||
|
|
||||||
|
@ -181,7 +180,7 @@ GTEST_API_ bool InDeathTestChild();
|
||||||
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
||||||
|
|
||||||
// Like ASSERT_DEATH, but continues on to successive tests in the
|
// Like ASSERT_DEATH, but continues on to successive tests in the
|
||||||
// test case, if any:
|
// test suite, if any:
|
||||||
# define EXPECT_DEATH(statement, regex) \
|
# define EXPECT_DEATH(statement, regex) \
|
||||||
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
||||||
|
|
||||||
|
@ -228,7 +227,7 @@ class GTEST_API_ KilledBySignal {
|
||||||
// return 12;
|
// return 12;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
|
// TEST(TestSuite, TestDieOr12WorksInDgbAndOpt) {
|
||||||
// int sideeffect = 0;
|
// int sideeffect = 0;
|
||||||
// // Only asserts in dbg.
|
// // Only asserts in dbg.
|
||||||
// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
|
// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
|
||||||
|
@ -277,20 +276,20 @@ class GTEST_API_ KilledBySignal {
|
||||||
// This macro is used for implementing macros such as
|
// This macro is used for implementing macros such as
|
||||||
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
|
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
|
||||||
// death tests are not supported. Those macros must compile on such systems
|
// death tests are not supported. Those macros must compile on such systems
|
||||||
// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
|
// if and only if EXPECT_DEATH and ASSERT_DEATH compile with the same parameters
|
||||||
// systems that support death tests. This allows one to write such a macro
|
// on systems that support death tests. This allows one to write such a macro on
|
||||||
// on a system that does not support death tests and be sure that it will
|
// a system that does not support death tests and be sure that it will compile
|
||||||
// compile on a death-test supporting system. It is exposed publicly so that
|
// on a death-test supporting system. It is exposed publicly so that systems
|
||||||
// systems that have death-tests with stricter requirements than
|
// that have death-tests with stricter requirements than GTEST_HAS_DEATH_TEST
|
||||||
// GTEST_HAS_DEATH_TEST can write their own equivalent of
|
// can write their own equivalent of EXPECT_DEATH_IF_SUPPORTED and
|
||||||
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED.
|
// ASSERT_DEATH_IF_SUPPORTED.
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// statement - A statement that a macro such as EXPECT_DEATH would test
|
// statement - A statement that a macro such as EXPECT_DEATH would test
|
||||||
// for program termination. This macro has to make sure this
|
// for program termination. This macro has to make sure this
|
||||||
// statement is compiled but not executed, to ensure that
|
// statement is compiled but not executed, to ensure that
|
||||||
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
|
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
|
||||||
// parameter iff EXPECT_DEATH compiles with it.
|
// parameter if and only if EXPECT_DEATH compiles with it.
|
||||||
// regex - A regex that a macro such as EXPECT_DEATH would use to test
|
// regex - A regex that a macro such as EXPECT_DEATH would use to test
|
||||||
// the output of statement. This parameter has to be
|
// the output of statement. This parameter has to be
|
||||||
// compiled but not evaluated by this macro, to ensure that
|
// compiled but not evaluated by this macro, to ensure that
|
||||||
|
|
|
@ -0,0 +1,750 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
|
//
|
||||||
|
// 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_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "gtest/gtest-printers.h"
|
||||||
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
|
// MSVC warning C5046 is new as of VS2017 version 15.8.
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1915
|
||||||
|
#define GTEST_MAYBE_5046_ 5046
|
||||||
|
#else
|
||||||
|
#define GTEST_MAYBE_5046_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||||
|
4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by
|
||||||
|
clients of class B */
|
||||||
|
/* Symbol involving type with internal linkage not defined */)
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// To implement a matcher Foo for type T, define:
|
||||||
|
// 1. a class FooMatcherImpl that implements the
|
||||||
|
// MatcherInterface<T> interface, and
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// listener does not own the ostream, and does not dereference it
|
||||||
|
// in the constructor or destructor.
|
||||||
|
explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
|
||||||
|
virtual ~MatchResultListener() = 0; // Makes this class abstract.
|
||||||
|
|
||||||
|
// Streams x to the underlying ostream; does nothing if the ostream
|
||||||
|
// is NULL.
|
||||||
|
template <typename T>
|
||||||
|
MatchResultListener& operator<<(const T& x) {
|
||||||
|
if (stream_ != nullptr) *stream_ << x;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the underlying ostream.
|
||||||
|
::std::ostream* stream() { return stream_; }
|
||||||
|
|
||||||
|
// Returns true if and only if the listener is interested in an explanation
|
||||||
|
// of the match result. A matcher's MatchAndExplain() method can use
|
||||||
|
// this information to avoid generating the explanation when no one
|
||||||
|
// intends to hear it.
|
||||||
|
bool IsInterested() const { return stream_ != nullptr; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
::std::ostream* const stream_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline MatchResultListener::~MatchResultListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// An instance of a subclass of this knows how to describe itself as a
|
||||||
|
// matcher.
|
||||||
|
class MatcherDescriberInterface {
|
||||||
|
public:
|
||||||
|
virtual ~MatcherDescriberInterface() {}
|
||||||
|
|
||||||
|
// Describes this matcher to an ostream. The function should print
|
||||||
|
// a verb phrase that describes the property a value matching this
|
||||||
|
// matcher should have. The subject of the verb phrase is the value
|
||||||
|
// being matched. For example, the DescribeTo() method of the Gt(7)
|
||||||
|
// matcher prints "is greater than 7".
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const = 0;
|
||||||
|
|
||||||
|
// Describes the negation of this matcher to an ostream. For
|
||||||
|
// example, if the description of this matcher is "is greater than
|
||||||
|
// 7", the negated description could be "is not greater than 7".
|
||||||
|
// You are not required to override this when implementing
|
||||||
|
// MatcherInterface, but it is highly advised so that your matcher
|
||||||
|
// can produce good error messages.
|
||||||
|
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||||
|
*os << "not (";
|
||||||
|
DescribeTo(os);
|
||||||
|
*os << ")";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The implementation of a matcher.
|
||||||
|
template <typename T>
|
||||||
|
class MatcherInterface : public MatcherDescriberInterface {
|
||||||
|
public:
|
||||||
|
// Returns true if and only if the matcher matches x; also explains the
|
||||||
|
// match result to 'listener' if necessary (see the next paragraph), in
|
||||||
|
// the form of a non-restrictive relative clause ("which ...",
|
||||||
|
// "whose ...", etc) that describes x. For example, the
|
||||||
|
// MatchAndExplain() method of the Pointee(...) matcher should
|
||||||
|
// generate an explanation like "which points to ...".
|
||||||
|
//
|
||||||
|
// Implementations of MatchAndExplain() should add an explanation of
|
||||||
|
// the match result *if and only if* they can provide additional
|
||||||
|
// information that's not already present (or not obvious) in the
|
||||||
|
// print-out of x and the matcher's description. Whether the match
|
||||||
|
// succeeds is not a factor in deciding whether an explanation is
|
||||||
|
// needed, as sometimes the caller needs to print a failure message
|
||||||
|
// when the match succeeds (e.g. when the matcher is used inside
|
||||||
|
// Not()).
|
||||||
|
//
|
||||||
|
// For example, a "has at least 10 elements" matcher should explain
|
||||||
|
// what the actual element count is, regardless of the match result,
|
||||||
|
// as it is useful information to the reader; on the other hand, an
|
||||||
|
// "is empty" matcher probably only needs to explain what the actual
|
||||||
|
// size is when the match fails, as it's redundant to say that the
|
||||||
|
// size is 0 when the value is already known to be empty.
|
||||||
|
//
|
||||||
|
// You should override this method when defining a new matcher.
|
||||||
|
//
|
||||||
|
// It's the responsibility of the caller (Google Test) to guarantee
|
||||||
|
// that 'listener' is not NULL. This helps to simplify a matcher's
|
||||||
|
// implementation when it doesn't care about the performance, as it
|
||||||
|
// can talk to 'listener' without checking its validity first.
|
||||||
|
// However, in order to implement dummy listeners efficiently,
|
||||||
|
// listener->stream() may be NULL.
|
||||||
|
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
|
||||||
|
|
||||||
|
// Inherits these methods from MatcherDescriberInterface:
|
||||||
|
// virtual void DescribeTo(::std::ostream* os) const = 0;
|
||||||
|
// virtual void DescribeNegationTo(::std::ostream* os) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
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; }
|
||||||
|
};
|
||||||
|
struct AnyNe {
|
||||||
|
template <typename A, typename B>
|
||||||
|
bool operator()(const A& a, const B& b) const { return a != b; }
|
||||||
|
};
|
||||||
|
struct AnyLt {
|
||||||
|
template <typename A, typename B>
|
||||||
|
bool operator()(const A& a, const B& b) const { return a < b; }
|
||||||
|
};
|
||||||
|
struct AnyGt {
|
||||||
|
template <typename A, typename B>
|
||||||
|
bool operator()(const A& a, const B& b) const { return a > b; }
|
||||||
|
};
|
||||||
|
struct AnyLe {
|
||||||
|
template <typename A, typename B>
|
||||||
|
bool operator()(const A& a, const B& b) const { return a <= b; }
|
||||||
|
};
|
||||||
|
struct AnyGe {
|
||||||
|
template <typename A, typename B>
|
||||||
|
bool operator()(const A& a, const B& b) const { return a >= b; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// A match result listener that ignores the explanation.
|
||||||
|
class DummyMatchResultListener : public MatchResultListener {
|
||||||
|
public:
|
||||||
|
DummyMatchResultListener() : MatchResultListener(nullptr) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
|
||||||
|
};
|
||||||
|
|
||||||
|
// A match result listener that forwards the explanation to a given
|
||||||
|
// ostream. The difference between this and MatchResultListener is
|
||||||
|
// that the former is concrete.
|
||||||
|
class StreamMatchResultListener : public MatchResultListener {
|
||||||
|
public:
|
||||||
|
explicit StreamMatchResultListener(::std::ostream* os)
|
||||||
|
: MatchResultListener(os) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if and only if this matcher matches x.
|
||||||
|
bool Matches(const T& x) const {
|
||||||
|
DummyMatchResultListener dummy;
|
||||||
|
return MatchAndExplain(x, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes this matcher to an ostream.
|
||||||
|
void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
|
||||||
|
|
||||||
|
// Describes the negation of this matcher to an ostream.
|
||||||
|
void DescribeNegationTo(::std::ostream* os) const {
|
||||||
|
impl_->DescribeNegationTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explains why x matches, or doesn't match, the matcher.
|
||||||
|
void ExplainMatchResultTo(const T& x, ::std::ostream* os) const {
|
||||||
|
StreamMatchResultListener listener(os);
|
||||||
|
MatchAndExplain(x, &listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the describer for this matcher object; retains ownership
|
||||||
|
// of the describer, which is only guaranteed to be alive when
|
||||||
|
// this matcher object is alive.
|
||||||
|
const MatcherDescriberInterface* GetDescriber() const {
|
||||||
|
return impl_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MatcherBase() {}
|
||||||
|
|
||||||
|
// 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)) {}
|
||||||
|
|
||||||
|
MatcherBase(const MatcherBase&) = default;
|
||||||
|
MatcherBase& operator=(const MatcherBase&) = default;
|
||||||
|
MatcherBase(MatcherBase&&) = default;
|
||||||
|
MatcherBase& operator=(MatcherBase&&) = default;
|
||||||
|
|
||||||
|
virtual ~MatcherBase() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<const MatcherInterface<const T&>> impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
|
||||||
|
// object that can check whether a value of type T matches. The
|
||||||
|
// implementation of Matcher<T> is just a std::shared_ptr to const
|
||||||
|
// MatcherInterface<T>. Don't inherit from Matcher!
|
||||||
|
template <typename T>
|
||||||
|
class Matcher : public internal::MatcherBase<T> {
|
||||||
|
public:
|
||||||
|
// Constructs a null matcher. Needed for storing Matcher objects in STL
|
||||||
|
// containers. A default-constructed matcher is not yet initialized. You
|
||||||
|
// cannot use it until a valid value has been assigned to it.
|
||||||
|
explicit Matcher() {} // NOLINT
|
||||||
|
|
||||||
|
// Constructs a matcher from its implementation.
|
||||||
|
explicit Matcher(const MatcherInterface<const T&>* impl)
|
||||||
|
: internal::MatcherBase<T>(impl) {}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
explicit Matcher(
|
||||||
|
const MatcherInterface<U>* impl,
|
||||||
|
typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
|
||||||
|
nullptr)
|
||||||
|
: internal::MatcherBase<T>(impl) {}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following two specializations allow the user to write str
|
||||||
|
// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string
|
||||||
|
// matcher is expected.
|
||||||
|
template <>
|
||||||
|
class GTEST_API_ Matcher<const std::string&>
|
||||||
|
: public internal::MatcherBase<const std::string&> {
|
||||||
|
public:
|
||||||
|
Matcher() {}
|
||||||
|
|
||||||
|
explicit Matcher(const MatcherInterface<const std::string&>* impl)
|
||||||
|
: internal::MatcherBase<const std::string&>(impl) {}
|
||||||
|
|
||||||
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
|
// str is a std::string object.
|
||||||
|
Matcher(const std::string& s); // NOLINT
|
||||||
|
|
||||||
|
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||||
|
Matcher(const char* s); // NOLINT
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class GTEST_API_ Matcher<std::string>
|
||||||
|
: public internal::MatcherBase<std::string> {
|
||||||
|
public:
|
||||||
|
Matcher() {}
|
||||||
|
|
||||||
|
explicit Matcher(const MatcherInterface<const std::string&>* impl)
|
||||||
|
: internal::MatcherBase<std::string>(impl) {}
|
||||||
|
explicit Matcher(const MatcherInterface<std::string>* impl)
|
||||||
|
: internal::MatcherBase<std::string>(impl) {}
|
||||||
|
|
||||||
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
|
// str is a string object.
|
||||||
|
Matcher(const std::string& s); // NOLINT
|
||||||
|
|
||||||
|
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||||
|
Matcher(const char* s); // NOLINT
|
||||||
|
};
|
||||||
|
|
||||||
|
#if GTEST_HAS_ABSL
|
||||||
|
// 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&> {
|
||||||
|
public:
|
||||||
|
Matcher() {}
|
||||||
|
|
||||||
|
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
|
||||||
|
: internal::MatcherBase<const absl::string_view&>(impl) {}
|
||||||
|
|
||||||
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
|
// str is a std::string object.
|
||||||
|
Matcher(const std::string& s); // NOLINT
|
||||||
|
|
||||||
|
// 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
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class GTEST_API_ Matcher<absl::string_view>
|
||||||
|
: public internal::MatcherBase<absl::string_view> {
|
||||||
|
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) {}
|
||||||
|
|
||||||
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
|
// str is a std::string object.
|
||||||
|
Matcher(const std::string& s); // NOLINT
|
||||||
|
|
||||||
|
// 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
|
||||||
|
};
|
||||||
|
#endif // GTEST_HAS_ABSL
|
||||||
|
|
||||||
|
// Prints a matcher in a human-readable format.
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) {
|
||||||
|
matcher.DescribeTo(&os);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The PolymorphicMatcher class template makes it easy to implement a
|
||||||
|
// polymorphic matcher (i.e. a matcher that can match values of more
|
||||||
|
// than one type, e.g. Eq(n) and NotNull()).
|
||||||
|
//
|
||||||
|
// To define a polymorphic matcher, a user should provide an Impl
|
||||||
|
// class that has a DescribeTo() method and a DescribeNegationTo()
|
||||||
|
// method, and define a member function (or member function template)
|
||||||
|
//
|
||||||
|
// bool MatchAndExplain(const Value& value,
|
||||||
|
// MatchResultListener* listener) const;
|
||||||
|
//
|
||||||
|
// See the definition of NotNull() for a complete example.
|
||||||
|
template <class Impl>
|
||||||
|
class PolymorphicMatcher {
|
||||||
|
public:
|
||||||
|
explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
|
||||||
|
|
||||||
|
// Returns a mutable reference to the underlying matcher
|
||||||
|
// implementation object.
|
||||||
|
Impl& mutable_impl() { return impl_; }
|
||||||
|
|
||||||
|
// Returns an immutable reference to the underlying matcher
|
||||||
|
// implementation object.
|
||||||
|
const Impl& impl() const { return impl_; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
operator Matcher<T>() const {
|
||||||
|
return Matcher<T>(new MonomorphicImpl<const T&>(impl_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T>
|
||||||
|
class MonomorphicImpl : public MatcherInterface<T> {
|
||||||
|
public:
|
||||||
|
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
|
||||||
|
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); }
|
||||||
|
|
||||||
|
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||||
|
impl_.DescribeNegationTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
|
||||||
|
return impl_.MatchAndExplain(x, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Impl impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
Impl impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates a matcher from its implementation.
|
||||||
|
// DEPRECATED: Especially in the generic code, prefer:
|
||||||
|
// Matcher<T>(new MyMatcherImpl<const T&>(...));
|
||||||
|
//
|
||||||
|
// MakeMatcher may create a Matcher that accepts its argument by value, which
|
||||||
|
// leads to unnecessary copies & lack of support for non-copyable types.
|
||||||
|
template <typename T>
|
||||||
|
inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
|
||||||
|
return Matcher<T>(impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher from its implementation. This is
|
||||||
|
// easier to use than the PolymorphicMatcher<Impl> constructor as it
|
||||||
|
// doesn't require you to explicitly write the template argument, e.g.
|
||||||
|
//
|
||||||
|
// MakePolymorphicMatcher(foo);
|
||||||
|
// vs
|
||||||
|
// PolymorphicMatcher<TypeOfFoo>(foo);
|
||||||
|
template <class Impl>
|
||||||
|
inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
|
||||||
|
return PolymorphicMatcher<Impl>(impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
// Implements a matcher that compares a given value with a
|
||||||
|
// pre-supplied value using one of the ==, <=, <, etc, operators. The
|
||||||
|
// two values being compared don't have to have the same type.
|
||||||
|
//
|
||||||
|
// The matcher defined here is polymorphic (for example, Eq(5) can be
|
||||||
|
// used to match an int, a short, a double, etc). Therefore we use
|
||||||
|
// a template type conversion operator in the implementation.
|
||||||
|
//
|
||||||
|
// The following template definition assumes that the Rhs parameter is
|
||||||
|
// a "bare" type (i.e. neither 'const T' nor 'T&').
|
||||||
|
template <typename D, typename Rhs, typename Op>
|
||||||
|
class ComparisonBase {
|
||||||
|
public:
|
||||||
|
explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
|
||||||
|
template <typename Lhs>
|
||||||
|
operator Matcher<Lhs>() const {
|
||||||
|
return Matcher<Lhs>(new Impl<const Lhs&>(rhs_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T>
|
||||||
|
static const T& Unwrap(const T& v) { return v; }
|
||||||
|
template <typename T>
|
||||||
|
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_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Rhs>
|
||||||
|
class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
|
||||||
|
public:
|
||||||
|
explicit EqMatcher(const Rhs& rhs)
|
||||||
|
: ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { }
|
||||||
|
static const char* Desc() { return "is equal to"; }
|
||||||
|
static const char* NegatedDesc() { return "isn't equal to"; }
|
||||||
|
};
|
||||||
|
template <typename Rhs>
|
||||||
|
class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
|
||||||
|
public:
|
||||||
|
explicit NeMatcher(const Rhs& rhs)
|
||||||
|
: ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { }
|
||||||
|
static const char* Desc() { return "isn't equal to"; }
|
||||||
|
static const char* NegatedDesc() { return "is equal to"; }
|
||||||
|
};
|
||||||
|
template <typename Rhs>
|
||||||
|
class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
|
||||||
|
public:
|
||||||
|
explicit LtMatcher(const Rhs& rhs)
|
||||||
|
: ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { }
|
||||||
|
static const char* Desc() { return "is <"; }
|
||||||
|
static const char* NegatedDesc() { return "isn't <"; }
|
||||||
|
};
|
||||||
|
template <typename Rhs>
|
||||||
|
class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
|
||||||
|
public:
|
||||||
|
explicit GtMatcher(const Rhs& rhs)
|
||||||
|
: ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { }
|
||||||
|
static const char* Desc() { return "is >"; }
|
||||||
|
static const char* NegatedDesc() { return "isn't >"; }
|
||||||
|
};
|
||||||
|
template <typename Rhs>
|
||||||
|
class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
|
||||||
|
public:
|
||||||
|
explicit LeMatcher(const Rhs& rhs)
|
||||||
|
: ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { }
|
||||||
|
static const char* Desc() { return "is <="; }
|
||||||
|
static const char* NegatedDesc() { return "isn't <="; }
|
||||||
|
};
|
||||||
|
template <typename Rhs>
|
||||||
|
class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
|
||||||
|
public:
|
||||||
|
explicit GeMatcher(const Rhs& rhs)
|
||||||
|
: ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { }
|
||||||
|
static const char* Desc() { return "is >="; }
|
||||||
|
static const char* NegatedDesc() { return "isn'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.
|
||||||
|
class MatchesRegexMatcher {
|
||||||
|
public:
|
||||||
|
MatchesRegexMatcher(const RE* regex, bool full_match)
|
||||||
|
: regex_(regex), full_match_(full_match) {}
|
||||||
|
|
||||||
|
#if GTEST_HAS_ABSL
|
||||||
|
bool MatchAndExplain(const absl::string_view& s,
|
||||||
|
MatchResultListener* listener) const {
|
||||||
|
return MatchAndExplain(std::string(s), listener);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_ABSL
|
||||||
|
|
||||||
|
// Accepts pointer types, particularly:
|
||||||
|
// const char*
|
||||||
|
// char*
|
||||||
|
// const wchar_t*
|
||||||
|
// wchar_t*
|
||||||
|
template <typename CharType>
|
||||||
|
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
|
||||||
|
return s != nullptr && MatchAndExplain(std::string(s), listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches anything that can convert to std::string.
|
||||||
|
//
|
||||||
|
// This is a template, not just a plain function with const std::string&,
|
||||||
|
// because absl::string_view has some interfering non-explicit constructors.
|
||||||
|
template <class MatcheeStringType>
|
||||||
|
bool MatchAndExplain(const MatcheeStringType& s,
|
||||||
|
MatchResultListener* /* listener */) const {
|
||||||
|
const std::string& s2(s);
|
||||||
|
return full_match_ ? RE::FullMatch(s2, *regex_)
|
||||||
|
: RE::PartialMatch(s2, *regex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescribeTo(::std::ostream* os) const {
|
||||||
|
*os << (full_match_ ? "matches" : "contains") << " regular expression ";
|
||||||
|
UniversalPrinter<std::string>::Print(regex_->pattern(), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescribeNegationTo(::std::ostream* os) const {
|
||||||
|
*os << "doesn't " << (full_match_ ? "match" : "contain")
|
||||||
|
<< " regular expression ";
|
||||||
|
UniversalPrinter<std::string>::Print(regex_->pattern(), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::shared_ptr<const RE> regex_;
|
||||||
|
const bool full_match_;
|
||||||
|
};
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Matches a string that fully matches regular expression 'regex'.
|
||||||
|
// The matcher takes ownership of 'regex'.
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches a string that contains regular expression 'regex'.
|
||||||
|
// The matcher takes ownership of 'regex'.
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches anything equal to x.
|
||||||
|
// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
|
||||||
|
// wouldn't compile.
|
||||||
|
template <typename T>
|
||||||
|
inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
|
||||||
|
|
||||||
|
// Constructs a Matcher<T> from a 'value' of type T. The constructed
|
||||||
|
// matcher matches any value that's equal to 'value'.
|
||||||
|
template <typename T>
|
||||||
|
Matcher<T>::Matcher(T value) { *this = Eq(value); }
|
||||||
|
|
||||||
|
// Creates a monomorphic matcher that matches anything with type Lhs
|
||||||
|
// and equal to rhs. A user may need to use this instead of Eq(...)
|
||||||
|
// in order to resolve an overloading ambiguity.
|
||||||
|
//
|
||||||
|
// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x))
|
||||||
|
// or Matcher<T>(x), but more readable than the latter.
|
||||||
|
//
|
||||||
|
// We could define similar monomorphic matchers for other comparison
|
||||||
|
// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do
|
||||||
|
// it yet as those are used much less than Eq() in practice. A user
|
||||||
|
// can always write Matcher<T>(Lt(5)) to be explicit about the type,
|
||||||
|
// for example.
|
||||||
|
template <typename Lhs, typename Rhs>
|
||||||
|
inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches anything >= x.
|
||||||
|
template <typename Rhs>
|
||||||
|
inline internal::GeMatcher<Rhs> Ge(Rhs x) {
|
||||||
|
return internal::GeMatcher<Rhs>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches anything > x.
|
||||||
|
template <typename Rhs>
|
||||||
|
inline internal::GtMatcher<Rhs> Gt(Rhs x) {
|
||||||
|
return internal::GtMatcher<Rhs>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches anything <= x.
|
||||||
|
template <typename Rhs>
|
||||||
|
inline internal::LeMatcher<Rhs> Le(Rhs x) {
|
||||||
|
return internal::LeMatcher<Rhs>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches anything < x.
|
||||||
|
template <typename Rhs>
|
||||||
|
inline internal::LtMatcher<Rhs> Lt(Rhs x) {
|
||||||
|
return internal::LtMatcher<Rhs>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches anything != x.
|
||||||
|
template <typename Rhs>
|
||||||
|
inline internal::NeMatcher<Rhs> Ne(Rhs x) {
|
||||||
|
return internal::NeMatcher<Rhs>(x);
|
||||||
|
}
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
|
@ -48,6 +48,7 @@
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
|
@ -106,14 +107,6 @@ class GTEST_API_ Message {
|
||||||
*ss_ << str;
|
*ss_ << str;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_OS_SYMBIAN
|
|
||||||
// Streams a value (either a pointer or not) to this object.
|
|
||||||
template <typename T>
|
|
||||||
inline Message& operator <<(const T& value) {
|
|
||||||
StreamHelper(typename internal::is_pointer<T>::type(), value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Streams a non-pointer value to this object.
|
// Streams a non-pointer value to this object.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Message& operator <<(const T& val) {
|
inline Message& operator <<(const T& val) {
|
||||||
|
@ -151,14 +144,13 @@ class GTEST_API_ Message {
|
||||||
// as "(null)".
|
// as "(null)".
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Message& operator <<(T* const& pointer) { // NOLINT
|
inline Message& operator <<(T* const& pointer) { // NOLINT
|
||||||
if (pointer == NULL) {
|
if (pointer == nullptr) {
|
||||||
*ss_ << "(null)";
|
*ss_ << "(null)";
|
||||||
} else {
|
} else {
|
||||||
*ss_ << pointer;
|
*ss_ << pointer;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif // GTEST_OS_SYMBIAN
|
|
||||||
|
|
||||||
// Since the basic IO manipulators are overloaded for both narrow
|
// Since the basic IO manipulators are overloaded for both narrow
|
||||||
// and wide streams, we have to provide this specialized definition
|
// and wide streams, we have to provide this specialized definition
|
||||||
|
@ -187,12 +179,6 @@ class GTEST_API_ Message {
|
||||||
Message& operator <<(const ::std::wstring& wstr);
|
Message& operator <<(const ::std::wstring& wstr);
|
||||||
#endif // GTEST_HAS_STD_WSTRING
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
#if GTEST_HAS_GLOBAL_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 ::wstring& wstr);
|
|
||||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
|
||||||
|
|
||||||
// Gets the text streamed to this object so far as an std::string.
|
// Gets the text streamed to this object so far as an std::string.
|
||||||
// Each '\0' character in the buffer is replaced with "\\0".
|
// Each '\0' character in the buffer is replaced with "\\0".
|
||||||
//
|
//
|
||||||
|
@ -200,31 +186,8 @@ class GTEST_API_ Message {
|
||||||
std::string GetString() const;
|
std::string GetString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if GTEST_OS_SYMBIAN
|
|
||||||
// These are needed as the Nokia Symbian Compiler cannot decide between
|
|
||||||
// const T& and const T* in a function template. The Nokia compiler _can_
|
|
||||||
// decide between class template specializations for T and T*, so a
|
|
||||||
// tr1::type_traits-like is_pointer works, and we can overload on that.
|
|
||||||
template <typename T>
|
|
||||||
inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
|
|
||||||
if (pointer == NULL) {
|
|
||||||
*ss_ << "(null)";
|
|
||||||
} else {
|
|
||||||
*ss_ << pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
inline void StreamHelper(internal::false_type /*is_pointer*/,
|
|
||||||
const T& value) {
|
|
||||||
// See the comments in Message& operator <<(const T&) above for why
|
|
||||||
// we need this using statement.
|
|
||||||
using ::operator <<;
|
|
||||||
*ss_ << value;
|
|
||||||
}
|
|
||||||
#endif // GTEST_OS_SYMBIAN
|
|
||||||
|
|
||||||
// We'll hold the text streamed to this object here.
|
// We'll hold the text streamed to this object here.
|
||||||
const internal::scoped_ptr< ::std::stringstream> ss_;
|
const std::unique_ptr< ::std::stringstream> ss_;
|
||||||
|
|
||||||
// We declare (but don't implement) this to prevent the compiler
|
// We declare (but don't implement) this to prevent the compiler
|
||||||
// from implementing the assignment operator.
|
// from implementing the assignment operator.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,500 +0,0 @@
|
||||||
$$ -*- mode: c++; -*-
|
|
||||||
$var n = 50 $$ Maximum length of Values arguments we want to support.
|
|
||||||
$var maxtuple = 10 $$ Maximum number of Combine arguments 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.
|
|
||||||
//
|
|
||||||
// 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_
|
|
||||||
|
|
||||||
|
|
||||||
// Value-parameterized tests allow you to test your code with different
|
|
||||||
// parameters without writing multiple copies of the same test.
|
|
||||||
//
|
|
||||||
// Here is how you use value-parameterized tests:
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
// To write value-parameterized tests, first you should define a fixture
|
|
||||||
// class. It is usually derived from testing::TestWithParam<T> (see below for
|
|
||||||
// another inheritance scheme that's sometimes useful in more complicated
|
|
||||||
// class hierarchies), where the type of your parameter values.
|
|
||||||
// TestWithParam<T> is itself derived from testing::Test. T can be any
|
|
||||||
// copyable type. If it's a raw pointer, you are responsible for managing the
|
|
||||||
// lifespan of the pointed values.
|
|
||||||
|
|
||||||
class FooTest : public ::testing::TestWithParam<const char*> {
|
|
||||||
// You can implement all the usual class fixture members here.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Then, use the TEST_P macro to define as many parameterized tests
|
|
||||||
// for this fixture as you want. The _P suffix is for "parameterized"
|
|
||||||
// or "pattern", whichever you prefer to think.
|
|
||||||
|
|
||||||
TEST_P(FooTest, DoesBlah) {
|
|
||||||
// Inside a test, access the test parameter with the GetParam() method
|
|
||||||
// of the TestWithParam<T> class:
|
|
||||||
EXPECT_TRUE(foo.Blah(GetParam()));
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_P(FooTest, HasBlahBlah) {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
|
|
||||||
// case with any set of parameters you want. Google Test defines a number
|
|
||||||
// of functions for generating test parameters. They return what we call
|
|
||||||
// (surprise!) parameter generators. Here is a summary of them, which
|
|
||||||
// are all in the testing namespace:
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Range(begin, end [, step]) - Yields values {begin, begin+step,
|
|
||||||
// begin+step+step, ...}. The values do not
|
|
||||||
// include end. step defaults to 1.
|
|
||||||
// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
|
|
||||||
// ValuesIn(container) - Yields values from a C-style array, an STL
|
|
||||||
// ValuesIn(begin,end) container, or an iterator range [begin, end).
|
|
||||||
// Bool() - Yields sequence {false, true}.
|
|
||||||
// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
|
|
||||||
// for the math savvy) of the values generated
|
|
||||||
// by the N generators.
|
|
||||||
//
|
|
||||||
// For more details, see comments at the definitions of these functions below
|
|
||||||
// in this file.
|
|
||||||
//
|
|
||||||
// The following statement will instantiate tests from the FooTest test case
|
|
||||||
// each with parameter values "meeny", "miny", and "moe".
|
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(InstantiationName,
|
|
||||||
FooTest,
|
|
||||||
Values("meeny", "miny", "moe"));
|
|
||||||
|
|
||||||
// To distinguish different instances of the pattern, (yes, you
|
|
||||||
// can instantiate it more then once) the first argument to the
|
|
||||||
// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
|
|
||||||
// actual test case name. Remember to pick unique prefixes for different
|
|
||||||
// instantiations. The tests from the instantiation above will have
|
|
||||||
// these names:
|
|
||||||
//
|
|
||||||
// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
|
|
||||||
// * InstantiationName/FooTest.DoesBlah/1 for "miny"
|
|
||||||
// * InstantiationName/FooTest.DoesBlah/2 for "moe"
|
|
||||||
// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
|
|
||||||
// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
|
|
||||||
// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
|
|
||||||
//
|
|
||||||
// You can use these names in --gtest_filter.
|
|
||||||
//
|
|
||||||
// This statement will instantiate all tests from FooTest again, each
|
|
||||||
// with parameter values "cat" and "dog":
|
|
||||||
|
|
||||||
const char* pets[] = {"cat", "dog"};
|
|
||||||
INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
|
|
||||||
|
|
||||||
// The tests from the instantiation above will have these names:
|
|
||||||
//
|
|
||||||
// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
|
|
||||||
// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
|
|
||||||
// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
|
|
||||||
// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
|
|
||||||
//
|
|
||||||
// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
|
|
||||||
// in the given test case, whether their definitions come before or
|
|
||||||
// AFTER the INSTANTIATE_TEST_CASE_P statement.
|
|
||||||
//
|
|
||||||
// Please also note that generator expressions (including parameters to the
|
|
||||||
// generators) are evaluated in InitGoogleTest(), after main() has started.
|
|
||||||
// This allows the user on one hand, to adjust generator parameters in order
|
|
||||||
// to dynamically determine a set of tests to run and on the other hand,
|
|
||||||
// give the user a chance to inspect the generated tests with Google Test
|
|
||||||
// reflection API before RUN_ALL_TESTS() is executed.
|
|
||||||
//
|
|
||||||
// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
|
|
||||||
// for more examples.
|
|
||||||
//
|
|
||||||
// In the future, we plan to publish the API for defining new parameter
|
|
||||||
// generators. But for now this interface remains part of the internal
|
|
||||||
// implementation and is subject to change.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// A parameterized test fixture must be derived from testing::Test and from
|
|
||||||
// testing::WithParamInterface<T>, where T is the type of the parameter
|
|
||||||
// values. Inheriting from TestWithParam<T> satisfies that requirement because
|
|
||||||
// TestWithParam<T> inherits from both Test and WithParamInterface. In more
|
|
||||||
// complicated hierarchies, however, it is occasionally useful to inherit
|
|
||||||
// separately from Test and WithParamInterface. For example:
|
|
||||||
|
|
||||||
class BaseTest : public ::testing::Test {
|
|
||||||
// You can inherit all the usual members for a non-parameterized test
|
|
||||||
// fixture here.
|
|
||||||
};
|
|
||||||
|
|
||||||
class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
|
|
||||||
// The usual test fixture members go here too.
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(BaseTest, HasFoo) {
|
|
||||||
// This is an ordinary non-parameterized test.
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_P(DerivedTest, DoesBlah) {
|
|
||||||
// GetParam works just the same here as if you inherit from TestWithParam.
|
|
||||||
EXPECT_TRUE(foo.Blah(GetParam()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
|
|
||||||
#if !GTEST_OS_SYMBIAN
|
|
||||||
# include <utility>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gtest/internal/gtest-internal.h"
|
|
||||||
#include "gtest/internal/gtest-param-util.h"
|
|
||||||
#include "gtest/internal/gtest-param-util-generated.h"
|
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
|
|
||||||
// Functions producing parameter generators.
|
|
||||||
//
|
|
||||||
// Google Test uses these generators to produce parameters for value-
|
|
||||||
// parameterized tests. When a parameterized test case is instantiated
|
|
||||||
// with a particular generator, Google Test creates and runs tests
|
|
||||||
// for each element in the sequence produced by the generator.
|
|
||||||
//
|
|
||||||
// In the following sample, tests from test case FooTest are instantiated
|
|
||||||
// each three times with parameter values 3, 5, and 8:
|
|
||||||
//
|
|
||||||
// class FooTest : public TestWithParam<int> { ... };
|
|
||||||
//
|
|
||||||
// TEST_P(FooTest, TestThis) {
|
|
||||||
// }
|
|
||||||
// TEST_P(FooTest, TestThat) {
|
|
||||||
// }
|
|
||||||
// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
|
|
||||||
//
|
|
||||||
|
|
||||||
// Range() returns generators providing sequences of values in a range.
|
|
||||||
//
|
|
||||||
// Synopsis:
|
|
||||||
// Range(start, end)
|
|
||||||
// - returns a generator producing a sequence of values {start, start+1,
|
|
||||||
// start+2, ..., }.
|
|
||||||
// Range(start, end, step)
|
|
||||||
// - returns a generator producing a sequence of values {start, start+step,
|
|
||||||
// start+step+step, ..., }.
|
|
||||||
// Notes:
|
|
||||||
// * The generated sequences never include end. For example, Range(1, 5)
|
|
||||||
// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
|
|
||||||
// returns a generator producing {1, 3, 5, 7}.
|
|
||||||
// * start and end must have the same type. That type may be any integral or
|
|
||||||
// floating-point type or a user defined type satisfying these conditions:
|
|
||||||
// * It must be assignable (have operator=() defined).
|
|
||||||
// * It must have operator+() (operator+(int-compatible type) for
|
|
||||||
// two-operand version).
|
|
||||||
// * It must have operator<() defined.
|
|
||||||
// Elements in the resulting sequences will also have that type.
|
|
||||||
// * Condition start < end must be satisfied in order for resulting sequences
|
|
||||||
// to contain any elements.
|
|
||||||
//
|
|
||||||
template <typename T, typename IncrementT>
|
|
||||||
internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
|
|
||||||
return internal::ParamGenerator<T>(
|
|
||||||
new internal::RangeGenerator<T, IncrementT>(start, end, step));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
internal::ParamGenerator<T> Range(T start, T end) {
|
|
||||||
return Range(start, end, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValuesIn() function allows generation of tests with parameters coming from
|
|
||||||
// a container.
|
|
||||||
//
|
|
||||||
// Synopsis:
|
|
||||||
// ValuesIn(const T (&array)[N])
|
|
||||||
// - returns a generator producing sequences with elements from
|
|
||||||
// a C-style array.
|
|
||||||
// ValuesIn(const Container& container)
|
|
||||||
// - returns a generator producing sequences with elements from
|
|
||||||
// an STL-style container.
|
|
||||||
// ValuesIn(Iterator begin, Iterator end)
|
|
||||||
// - returns a generator producing sequences with elements from
|
|
||||||
// a range [begin, end) defined by a pair of STL-style iterators. These
|
|
||||||
// iterators can also be plain C pointers.
|
|
||||||
//
|
|
||||||
// Please note that ValuesIn copies the values from the containers
|
|
||||||
// passed in and keeps them to generate tests in RUN_ALL_TESTS().
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
//
|
|
||||||
// This instantiates tests from test case StringTest
|
|
||||||
// each with C-string values of "foo", "bar", and "baz":
|
|
||||||
//
|
|
||||||
// const char* strings[] = {"foo", "bar", "baz"};
|
|
||||||
// INSTANTIATE_TEST_CASE_P(StringSequence, StringTest, ValuesIn(strings));
|
|
||||||
//
|
|
||||||
// This instantiates tests from test case StlStringTest
|
|
||||||
// each with STL strings with values "a" and "b":
|
|
||||||
//
|
|
||||||
// ::std::vector< ::std::string> GetParameterStrings() {
|
|
||||||
// ::std::vector< ::std::string> v;
|
|
||||||
// v.push_back("a");
|
|
||||||
// v.push_back("b");
|
|
||||||
// return v;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// INSTANTIATE_TEST_CASE_P(CharSequence,
|
|
||||||
// StlStringTest,
|
|
||||||
// ValuesIn(GetParameterStrings()));
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// This will also instantiate tests from CharTest
|
|
||||||
// each with parameter values 'a' and 'b':
|
|
||||||
//
|
|
||||||
// ::std::list<char> GetParameterChars() {
|
|
||||||
// ::std::list<char> list;
|
|
||||||
// list.push_back('a');
|
|
||||||
// list.push_back('b');
|
|
||||||
// return list;
|
|
||||||
// }
|
|
||||||
// ::std::list<char> l = GetParameterChars();
|
|
||||||
// INSTANTIATE_TEST_CASE_P(CharSequence2,
|
|
||||||
// CharTest,
|
|
||||||
// ValuesIn(l.begin(), l.end()));
|
|
||||||
//
|
|
||||||
template <typename ForwardIterator>
|
|
||||||
internal::ParamGenerator<
|
|
||||||
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
|
|
||||||
ValuesIn(ForwardIterator begin, ForwardIterator end) {
|
|
||||||
typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
|
|
||||||
::value_type ParamType;
|
|
||||||
return internal::ParamGenerator<ParamType>(
|
|
||||||
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t N>
|
|
||||||
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
|
|
||||||
return ValuesIn(array, array + N);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Container>
|
|
||||||
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
|
||||||
const Container& container) {
|
|
||||||
return ValuesIn(container.begin(), container.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values() allows generating tests from explicitly specified list of
|
|
||||||
// parameters.
|
|
||||||
//
|
|
||||||
// Synopsis:
|
|
||||||
// Values(T v1, T v2, ..., T vN)
|
|
||||||
// - returns a generator producing sequences with elements v1, v2, ..., vN.
|
|
||||||
//
|
|
||||||
// For example, this instantiates tests from test case BarTest each
|
|
||||||
// with values "one", "two", and "three":
|
|
||||||
//
|
|
||||||
// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
|
|
||||||
//
|
|
||||||
// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
|
|
||||||
// The exact type of values will depend on the type of parameter in BazTest.
|
|
||||||
//
|
|
||||||
// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
|
|
||||||
//
|
|
||||||
// Currently, Values() supports from 1 to $n parameters.
|
|
||||||
//
|
|
||||||
$range i 1..n
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
|
|
||||||
template <$for j, [[typename T$j]]>
|
|
||||||
internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) {
|
|
||||||
return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// Bool() allows generating tests with parameters in a set of (false, true).
|
|
||||||
//
|
|
||||||
// Synopsis:
|
|
||||||
// Bool()
|
|
||||||
// - returns a generator producing sequences with elements {false, true}.
|
|
||||||
//
|
|
||||||
// It is useful when testing code that depends on Boolean flags. Combinations
|
|
||||||
// of multiple flags can be tested when several Bool()'s are combined using
|
|
||||||
// Combine() function.
|
|
||||||
//
|
|
||||||
// In the following example all tests in the test case FlagDependentTest
|
|
||||||
// will be instantiated twice with parameters false and true.
|
|
||||||
//
|
|
||||||
// class FlagDependentTest : public testing::TestWithParam<bool> {
|
|
||||||
// virtual void SetUp() {
|
|
||||||
// external_flag = GetParam();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
|
|
||||||
//
|
|
||||||
inline internal::ParamGenerator<bool> Bool() {
|
|
||||||
return Values(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
# if GTEST_HAS_COMBINE
|
|
||||||
// Combine() allows the user to combine two or more sequences to produce
|
|
||||||
// values of a Cartesian product of those sequences' elements.
|
|
||||||
//
|
|
||||||
// Synopsis:
|
|
||||||
// Combine(gen1, gen2, ..., genN)
|
|
||||||
// - returns a generator producing sequences with elements coming from
|
|
||||||
// the Cartesian product of elements from the sequences generated by
|
|
||||||
// gen1, gen2, ..., genN. The sequence elements will have a type of
|
|
||||||
// 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 $maxtuple arguments. This number is currently limited
|
|
||||||
// by the maximum number of elements in the tuple implementation used by Google
|
|
||||||
// Test.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// This will instantiate tests in test case AnimalTest each one with
|
|
||||||
// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
|
|
||||||
// tuple("dog", BLACK), and tuple("dog", WHITE):
|
|
||||||
//
|
|
||||||
// enum Color { BLACK, GRAY, WHITE };
|
|
||||||
// class AnimalTest
|
|
||||||
// : public testing::TestWithParam<tuple<const char*, Color> > {...};
|
|
||||||
//
|
|
||||||
// TEST_P(AnimalTest, AnimalLooksNice) {...}
|
|
||||||
//
|
|
||||||
// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
|
|
||||||
// Combine(Values("cat", "dog"),
|
|
||||||
// Values(BLACK, WHITE)));
|
|
||||||
//
|
|
||||||
// This will instantiate tests in FlagDependentTest with all variations of two
|
|
||||||
// Boolean flags:
|
|
||||||
//
|
|
||||||
// class FlagDependentTest
|
|
||||||
// : public testing::TestWithParam<tuple<bool, bool> > {
|
|
||||||
// virtual void SetUp() {
|
|
||||||
// // Assigns external_flag_1 and external_flag_2 values from the tuple.
|
|
||||||
// tie(external_flag_1, external_flag_2) = GetParam();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// TEST_P(FlagDependentTest, TestFeature1) {
|
|
||||||
// // Test your code using external_flag_1 and external_flag_2 here.
|
|
||||||
// }
|
|
||||||
// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
|
|
||||||
// Combine(Bool(), Bool()));
|
|
||||||
//
|
|
||||||
$range i 2..maxtuple
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
|
|
||||||
template <$for j, [[typename Generator$j]]>
|
|
||||||
internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
|
|
||||||
$for j, [[const Generator$j& g$j]]) {
|
|
||||||
return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>(
|
|
||||||
$for j, [[g$j]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
# endif // GTEST_HAS_COMBINE
|
|
||||||
|
|
||||||
# define TEST_P(test_case_name, test_name) \
|
|
||||||
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
|
|
||||||
: public test_case_name { \
|
|
||||||
public: \
|
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
|
|
||||||
virtual void TestBody(); \
|
|
||||||
private: \
|
|
||||||
static int AddToRegistry() { \
|
|
||||||
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
|
|
||||||
GetTestCasePatternHolder<test_case_name>(\
|
|
||||||
#test_case_name, \
|
|
||||||
::testing::internal::CodeLocation(\
|
|
||||||
__FILE__, __LINE__))->AddTestPattern(\
|
|
||||||
GTEST_STRINGIFY_(test_case_name), \
|
|
||||||
GTEST_STRINGIFY_(test_name), \
|
|
||||||
new ::testing::internal::TestMetaFactory< \
|
|
||||||
GTEST_TEST_CLASS_NAME_(\
|
|
||||||
test_case_name, test_name)>()); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
|
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
|
|
||||||
}; \
|
|
||||||
int GTEST_TEST_CLASS_NAME_(test_case_name, \
|
|
||||||
test_name)::gtest_registering_dummy_ = \
|
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
|
|
||||||
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
|
|
||||||
|
|
||||||
// The optional last argument to INSTANTIATE_TEST_CASE_P allows the user
|
|
||||||
// to specify a function or functor that generates custom test name suffixes
|
|
||||||
// based on the test parameters. The function should accept one argument of
|
|
||||||
// type testing::TestParamInfo<class ParamType>, and return std::string.
|
|
||||||
//
|
|
||||||
// testing::PrintToStringParamName is a builtin test suffix generator that
|
|
||||||
// returns the value of testing::PrintToString(GetParam()).
|
|
||||||
//
|
|
||||||
// Note: test names must be non-empty, unique, and may only contain ASCII
|
|
||||||
// alphanumeric characters or underscore. Because PrintToString adds quotes
|
|
||||||
// to std::string and C strings, it won't work for these types.
|
|
||||||
|
|
||||||
# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \
|
|
||||||
static ::testing::internal::ParamGenerator<test_case_name::ParamType> \
|
|
||||||
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
|
|
||||||
static ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \
|
|
||||||
const ::testing::TestParamInfo<test_case_name::ParamType>& info) { \
|
|
||||||
return ::testing::internal::GetParamNameGen<test_case_name::ParamType> \
|
|
||||||
(__VA_ARGS__)(info); \
|
|
||||||
} \
|
|
||||||
static int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \
|
|
||||||
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
|
|
||||||
GetTestCasePatternHolder<test_case_name>(\
|
|
||||||
#test_case_name, \
|
|
||||||
::testing::internal::CodeLocation(\
|
|
||||||
__FILE__, __LINE__))->AddTestCaseInstantiation(\
|
|
||||||
#prefix, \
|
|
||||||
>est_##prefix##test_case_name##_EvalGenerator_, \
|
|
||||||
>est_##prefix##test_case_name##_EvalGenerateName_, \
|
|
||||||
__FILE__, __LINE__)
|
|
||||||
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
|
|
@ -100,17 +100,16 @@
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
#if GTEST_HAS_STD_TUPLE_
|
|
||||||
# include <tuple>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GTEST_HAS_ABSL
|
#if GTEST_HAS_ABSL
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
|
@ -152,9 +151,10 @@ class TypeWithoutFormatter {
|
||||||
public:
|
public:
|
||||||
// This default version is called when kTypeKind is kOtherType.
|
// This default version is called when kTypeKind is kOtherType.
|
||||||
static void PrintValue(const T& value, ::std::ostream* os) {
|
static void PrintValue(const T& value, ::std::ostream* os) {
|
||||||
PrintBytesInObjectTo(static_cast<const unsigned char*>(
|
PrintBytesInObjectTo(
|
||||||
reinterpret_cast<const void*>(&value)),
|
static_cast<const unsigned char*>(
|
||||||
sizeof(value), os);
|
reinterpret_cast<const void*>(std::addressof(value))),
|
||||||
|
sizeof(value), os);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -233,12 +233,12 @@ template <typename Char, typename CharTraits, typename T>
|
||||||
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
|
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
|
||||||
TypeWithoutFormatter<T, (internal::IsAProtocolMessage<T>::value
|
TypeWithoutFormatter<T, (internal::IsAProtocolMessage<T>::value
|
||||||
? kProtobuf
|
? kProtobuf
|
||||||
: internal::ImplicitlyConvertible<
|
: std::is_convertible<
|
||||||
const T&, internal::BiggestInt>::value
|
const T&, internal::BiggestInt>::value
|
||||||
? kConvertibleToInteger
|
? kConvertibleToInteger
|
||||||
:
|
:
|
||||||
#if GTEST_HAS_ABSL
|
#if GTEST_HAS_ABSL
|
||||||
internal::ImplicitlyConvertible<
|
std::is_convertible<
|
||||||
const T&, absl::string_view>::value
|
const T&, absl::string_view>::value
|
||||||
? kConvertibleToStringView
|
? kConvertibleToStringView
|
||||||
:
|
:
|
||||||
|
@ -358,16 +358,6 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
|
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
|
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
|
||||||
|
|
||||||
#if GTEST_HAS_GLOBAL_STRING
|
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string);
|
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GTEST_HAS_GLOBAL_WSTRING
|
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring);
|
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
|
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
|
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
|
||||||
|
@ -448,7 +438,7 @@ void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */,
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */,
|
void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */,
|
||||||
T* p, ::std::ostream* os) {
|
T* p, ::std::ostream* os) {
|
||||||
if (p == NULL) {
|
if (p == nullptr) {
|
||||||
*os << "NULL";
|
*os << "NULL";
|
||||||
} else {
|
} else {
|
||||||
// T is not a function type. We just call << to print p,
|
// T is not a function type. We just call << to print p,
|
||||||
|
@ -460,7 +450,7 @@ void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */,
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */,
|
void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */,
|
||||||
T* p, ::std::ostream* os) {
|
T* p, ::std::ostream* os) {
|
||||||
if (p == NULL) {
|
if (p == nullptr) {
|
||||||
*os << "NULL";
|
*os << "NULL";
|
||||||
} else {
|
} else {
|
||||||
// T is a function type, so '*os << p' doesn't do what we want
|
// T is a function type, so '*os << p' doesn't do what we want
|
||||||
|
@ -515,13 +505,9 @@ void PrintTo(const T& value, ::std::ostream* os) {
|
||||||
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
|
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
|
||||||
!IsRecursiveContainer<T>::value
|
!IsRecursiveContainer<T>::value
|
||||||
? kPrintContainer
|
? kPrintContainer
|
||||||
: !is_pointer<T>::value
|
: !std::is_pointer<T>::value
|
||||||
? kPrintOther
|
? kPrintOther
|
||||||
#if GTEST_LANG_CXX11
|
|
||||||
: std::is_function<typename std::remove_pointer<T>::type>::value
|
: std::is_function<typename std::remove_pointer<T>::type>::value
|
||||||
#else
|
|
||||||
: !internal::ImplicitlyConvertible<T, const void*>::value
|
|
||||||
#endif
|
|
||||||
? kPrintFunctionPointer
|
? kPrintFunctionPointer
|
||||||
: kPrintPointer > (),
|
: kPrintPointer > (),
|
||||||
value, os);
|
value, os);
|
||||||
|
@ -603,27 +589,13 @@ void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overloads for ::string and ::std::string.
|
// Overloads for ::std::string.
|
||||||
#if GTEST_HAS_GLOBAL_STRING
|
|
||||||
GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
|
|
||||||
inline void PrintTo(const ::string& s, ::std::ostream* os) {
|
|
||||||
PrintStringTo(s, os);
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_GLOBAL_STRING
|
|
||||||
|
|
||||||
GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
|
GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
|
||||||
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
|
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
|
||||||
PrintStringTo(s, os);
|
PrintStringTo(s, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overloads for ::wstring and ::std::wstring.
|
// Overloads for ::std::wstring.
|
||||||
#if GTEST_HAS_GLOBAL_WSTRING
|
|
||||||
GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
|
|
||||||
inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
|
|
||||||
PrintWideStringTo(s, os);
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#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) {
|
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
||||||
|
@ -638,99 +610,38 @@ inline void PrintTo(absl::string_view sp, ::std::ostream* os) {
|
||||||
}
|
}
|
||||||
#endif // GTEST_HAS_ABSL
|
#endif // GTEST_HAS_ABSL
|
||||||
|
|
||||||
#if GTEST_LANG_CXX11
|
|
||||||
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
|
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
|
||||||
#endif // GTEST_LANG_CXX11
|
|
||||||
|
|
||||||
#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
|
template <typename T>
|
||||||
|
void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) {
|
||||||
|
UniversalPrinter<T&>::Print(ref.get(), os);
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function for printing a tuple. T must be instantiated with
|
// Helper function for printing a tuple. T must be instantiated with
|
||||||
// a tuple type.
|
// a tuple type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void PrintTupleTo(const T& t, ::std::ostream* os);
|
void PrintTupleTo(const T&, std::integral_constant<size_t, 0>,
|
||||||
#endif // GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
|
::std::ostream*) {}
|
||||||
|
|
||||||
#if GTEST_HAS_TR1_TUPLE
|
template <typename T, size_t I>
|
||||||
// Overload for ::std::tr1::tuple. Needed for printing function arguments,
|
void PrintTupleTo(const T& t, std::integral_constant<size_t, I>,
|
||||||
// which are packed as tuples.
|
::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, std::integral_constant<size_t, I - 1>(), os);
|
||||||
// Overloaded PrintTo() for tuples of various arities. We support
|
GTEST_INTENTIONAL_CONST_COND_PUSH_()
|
||||||
// tuples of up-to 10 fields. The following implementation works
|
if (I > 1) {
|
||||||
// regardless of whether tr1::tuple is implemented using the
|
GTEST_INTENTIONAL_CONST_COND_POP_()
|
||||||
// non-standard variadic template feature or not.
|
*os << ", ";
|
||||||
|
}
|
||||||
inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
|
UniversalPrinter<typename std::tuple_element<I - 1, T>::type>::Print(
|
||||||
PrintTupleTo(t, os);
|
std::get<I - 1>(t), os);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
|
|
||||||
::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
|
||||||
typename T6>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
|
|
||||||
::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
|
||||||
typename T6, typename T7>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
|
|
||||||
::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
|
||||||
typename T6, typename T7, typename T8>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
|
|
||||||
::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
|
||||||
typename T6, typename T7, typename T8, typename T9>
|
|
||||||
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
|
|
||||||
::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
|
||||||
typename T6, typename T7, typename T8, typename T9, typename T10>
|
|
||||||
void PrintTo(
|
|
||||||
const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
|
|
||||||
::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_TR1_TUPLE
|
|
||||||
|
|
||||||
#if GTEST_HAS_STD_TUPLE_
|
|
||||||
template <typename... Types>
|
template <typename... Types>
|
||||||
void PrintTo(const ::std::tuple<Types...>& t, ::std::ostream* os) {
|
void PrintTo(const ::std::tuple<Types...>& t, ::std::ostream* os) {
|
||||||
PrintTupleTo(t, os);
|
*os << "(";
|
||||||
|
PrintTupleTo(t, std::integral_constant<size_t, sizeof...(Types)>(), os);
|
||||||
|
*os << ")";
|
||||||
}
|
}
|
||||||
#endif // GTEST_HAS_STD_TUPLE_
|
|
||||||
|
|
||||||
// Overload for std::pair.
|
// Overload for std::pair.
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
|
@ -826,7 +737,6 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
|
||||||
// If the array has more than kThreshold elements, we'll have to
|
// If the array has more than kThreshold elements, we'll have to
|
||||||
// omit some details by printing only the first and the last
|
// omit some details by printing only the first and the last
|
||||||
// kChunkSize elements.
|
// kChunkSize elements.
|
||||||
// FIXME: let the user control the threshold using a flag.
|
|
||||||
if (len <= kThreshold) {
|
if (len <= kThreshold) {
|
||||||
PrintRawArrayTo(begin, len, os);
|
PrintRawArrayTo(begin, len, os);
|
||||||
} else {
|
} else {
|
||||||
|
@ -905,7 +815,7 @@ template <>
|
||||||
class UniversalTersePrinter<const char*> {
|
class UniversalTersePrinter<const char*> {
|
||||||
public:
|
public:
|
||||||
static void Print(const char* str, ::std::ostream* os) {
|
static void Print(const char* str, ::std::ostream* os) {
|
||||||
if (str == NULL) {
|
if (str == nullptr) {
|
||||||
*os << "NULL";
|
*os << "NULL";
|
||||||
} else {
|
} else {
|
||||||
UniversalPrint(std::string(str), os);
|
UniversalPrint(std::string(str), os);
|
||||||
|
@ -925,7 +835,7 @@ template <>
|
||||||
class UniversalTersePrinter<const wchar_t*> {
|
class UniversalTersePrinter<const wchar_t*> {
|
||||||
public:
|
public:
|
||||||
static void Print(const wchar_t* str, ::std::ostream* os) {
|
static void Print(const wchar_t* str, ::std::ostream* os) {
|
||||||
if (str == NULL) {
|
if (str == nullptr) {
|
||||||
*os << "NULL";
|
*os << "NULL";
|
||||||
} else {
|
} else {
|
||||||
UniversalPrint(::std::wstring(str), os);
|
UniversalPrint(::std::wstring(str), os);
|
||||||
|
@ -961,109 +871,20 @@ void UniversalPrint(const T& value, ::std::ostream* os) {
|
||||||
|
|
||||||
typedef ::std::vector< ::std::string> Strings;
|
typedef ::std::vector< ::std::string> Strings;
|
||||||
|
|
||||||
// TuplePolicy<TupleT> must provide:
|
|
||||||
// - tuple_size
|
|
||||||
// size of tuple TupleT.
|
|
||||||
// - get<size_t I>(const TupleT& t)
|
|
||||||
// static function extracting element I of tuple TupleT.
|
|
||||||
// - tuple_element<size_t I>::type
|
|
||||||
// type of element I of tuple TupleT.
|
|
||||||
template <typename TupleT>
|
|
||||||
struct TuplePolicy;
|
|
||||||
|
|
||||||
#if GTEST_HAS_TR1_TUPLE
|
|
||||||
template <typename TupleT>
|
|
||||||
struct TuplePolicy {
|
|
||||||
typedef TupleT Tuple;
|
|
||||||
static const size_t tuple_size = ::std::tr1::tuple_size<Tuple>::value;
|
|
||||||
|
|
||||||
template <size_t I>
|
|
||||||
struct tuple_element : ::std::tr1::tuple_element<static_cast<int>(I), Tuple> {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t I>
|
|
||||||
static typename AddReference<const typename ::std::tr1::tuple_element<
|
|
||||||
static_cast<int>(I), Tuple>::type>::type
|
|
||||||
get(const Tuple& tuple) {
|
|
||||||
return ::std::tr1::get<I>(tuple);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename TupleT>
|
|
||||||
const size_t TuplePolicy<TupleT>::tuple_size;
|
|
||||||
#endif // GTEST_HAS_TR1_TUPLE
|
|
||||||
|
|
||||||
#if GTEST_HAS_STD_TUPLE_
|
|
||||||
template <typename... Types>
|
|
||||||
struct TuplePolicy< ::std::tuple<Types...> > {
|
|
||||||
typedef ::std::tuple<Types...> Tuple;
|
|
||||||
static const size_t tuple_size = ::std::tuple_size<Tuple>::value;
|
|
||||||
|
|
||||||
template <size_t I>
|
|
||||||
struct tuple_element : ::std::tuple_element<I, Tuple> {};
|
|
||||||
|
|
||||||
template <size_t I>
|
|
||||||
static const typename ::std::tuple_element<I, Tuple>::type& get(
|
|
||||||
const Tuple& tuple) {
|
|
||||||
return ::std::get<I>(tuple);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename... Types>
|
|
||||||
const size_t TuplePolicy< ::std::tuple<Types...> >::tuple_size;
|
|
||||||
#endif // GTEST_HAS_STD_TUPLE_
|
|
||||||
|
|
||||||
#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
|
|
||||||
// This helper template allows PrintTo() for tuples and
|
|
||||||
// UniversalTersePrintTupleFieldsToStrings() to be defined by
|
|
||||||
// induction on the number of tuple fields. The idea is that
|
|
||||||
// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
|
|
||||||
// fields in tuple t, and can be defined in terms of
|
|
||||||
// TuplePrefixPrinter<N - 1>.
|
|
||||||
//
|
|
||||||
// The inductive case.
|
|
||||||
template <size_t N>
|
|
||||||
struct TuplePrefixPrinter {
|
|
||||||
// Prints the first N fields of a tuple.
|
|
||||||
template <typename Tuple>
|
|
||||||
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
|
|
||||||
TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
|
|
||||||
GTEST_INTENTIONAL_CONST_COND_PUSH_()
|
|
||||||
if (N > 1) {
|
|
||||||
GTEST_INTENTIONAL_CONST_COND_POP_()
|
|
||||||
*os << ", ";
|
|
||||||
}
|
|
||||||
UniversalPrinter<
|
|
||||||
typename TuplePolicy<Tuple>::template tuple_element<N - 1>::type>
|
|
||||||
::Print(TuplePolicy<Tuple>::template get<N - 1>(t), os);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tersely prints the first N fields of a tuple to a string vector,
|
// Tersely prints the first N fields of a tuple to a string vector,
|
||||||
// one element for each field.
|
// one element for each field.
|
||||||
template <typename Tuple>
|
|
||||||
static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
|
|
||||||
TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
|
|
||||||
::std::stringstream ss;
|
|
||||||
UniversalTersePrint(TuplePolicy<Tuple>::template get<N - 1>(t), &ss);
|
|
||||||
strings->push_back(ss.str());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base case.
|
|
||||||
template <>
|
|
||||||
struct TuplePrefixPrinter<0> {
|
|
||||||
template <typename Tuple>
|
|
||||||
static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
|
|
||||||
|
|
||||||
template <typename Tuple>
|
|
||||||
static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper function for printing a tuple.
|
|
||||||
// Tuple must be either std::tr1::tuple or std::tuple type.
|
|
||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
void PrintTupleTo(const Tuple& t, ::std::ostream* os) {
|
void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>,
|
||||||
*os << "(";
|
Strings*) {}
|
||||||
TuplePrefixPrinter<TuplePolicy<Tuple>::tuple_size>::PrintPrefixTo(t, os);
|
template <typename Tuple, size_t I>
|
||||||
*os << ")";
|
void TersePrintPrefixToStrings(const Tuple& t,
|
||||||
|
std::integral_constant<size_t, I>,
|
||||||
|
Strings* strings) {
|
||||||
|
TersePrintPrefixToStrings(t, std::integral_constant<size_t, I - 1>(),
|
||||||
|
strings);
|
||||||
|
::std::stringstream ss;
|
||||||
|
UniversalTersePrint(std::get<I - 1>(t), &ss);
|
||||||
|
strings->push_back(ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints the fields of a tuple tersely to a string vector, one
|
// Prints the fields of a tuple tersely to a string vector, one
|
||||||
|
@ -1072,11 +893,11 @@ void PrintTupleTo(const Tuple& t, ::std::ostream* os) {
|
||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
||||||
Strings result;
|
Strings result;
|
||||||
TuplePrefixPrinter<TuplePolicy<Tuple>::tuple_size>::
|
TersePrintPrefixToStrings(
|
||||||
TersePrintPrefixToStrings(value, &result);
|
value, std::integral_constant<size_t, std::tuple_size<Tuple>::value>(),
|
||||||
|
&result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif // GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
|
|
@ -72,14 +72,15 @@ class GTEST_API_ ScopedFakeTestPartResultReporter
|
||||||
TestPartResultArray* result);
|
TestPartResultArray* result);
|
||||||
|
|
||||||
// The d'tor restores the previous test part result reporter.
|
// The d'tor restores the previous test part result reporter.
|
||||||
virtual ~ScopedFakeTestPartResultReporter();
|
~ScopedFakeTestPartResultReporter() override;
|
||||||
|
|
||||||
// Appends the TestPartResult object to the TestPartResultArray
|
// Appends the TestPartResult object to the TestPartResultArray
|
||||||
// received in the constructor.
|
// received in the constructor.
|
||||||
//
|
//
|
||||||
// This method is from the TestPartResultReporterInterface
|
// This method is from the TestPartResultReporterInterface
|
||||||
// interface.
|
// interface.
|
||||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
void ReportTestPartResult(const TestPartResult& result) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
|
|
@ -53,22 +53,20 @@ class GTEST_API_ TestPartResult {
|
||||||
enum Type {
|
enum Type {
|
||||||
kSuccess, // Succeeded.
|
kSuccess, // Succeeded.
|
||||||
kNonFatalFailure, // Failed but the test can continue.
|
kNonFatalFailure, // Failed but the test can continue.
|
||||||
kFatalFailure // Failed and the test should be terminated.
|
kFatalFailure, // Failed and the test should be terminated.
|
||||||
|
kSkip // Skipped.
|
||||||
};
|
};
|
||||||
|
|
||||||
// C'tor. TestPartResult does NOT have a default constructor.
|
// C'tor. TestPartResult does NOT have a default constructor.
|
||||||
// Always use this constructor (with parameters) to create a
|
// Always use this constructor (with parameters) to create a
|
||||||
// TestPartResult object.
|
// TestPartResult object.
|
||||||
TestPartResult(Type a_type,
|
TestPartResult(Type a_type, const char* a_file_name, int a_line_number,
|
||||||
const char* a_file_name,
|
|
||||||
int a_line_number,
|
|
||||||
const char* a_message)
|
const char* a_message)
|
||||||
: type_(a_type),
|
: type_(a_type),
|
||||||
file_name_(a_file_name == NULL ? "" : a_file_name),
|
file_name_(a_file_name == nullptr ? "" : a_file_name),
|
||||||
line_number_(a_line_number),
|
line_number_(a_line_number),
|
||||||
summary_(ExtractSummary(a_message)),
|
summary_(ExtractSummary(a_message)),
|
||||||
message_(a_message) {
|
message_(a_message) {}
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the outcome of the test part.
|
// Gets the outcome of the test part.
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
|
@ -76,7 +74,7 @@ class GTEST_API_ TestPartResult {
|
||||||
// Gets the name of the source file where the test part took place, or
|
// Gets the name of the source file where the test part took place, or
|
||||||
// NULL if it's unknown.
|
// NULL if it's unknown.
|
||||||
const char* file_name() const {
|
const char* file_name() const {
|
||||||
return file_name_.empty() ? NULL : file_name_.c_str();
|
return file_name_.empty() ? nullptr : file_name_.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the line in the source file where the test part took place,
|
// Gets the line in the source file where the test part took place,
|
||||||
|
@ -89,18 +87,21 @@ class GTEST_API_ TestPartResult {
|
||||||
// Gets the message associated with the test part.
|
// Gets the message associated with the test part.
|
||||||
const char* message() const { return message_.c_str(); }
|
const char* message() const { return message_.c_str(); }
|
||||||
|
|
||||||
// Returns true iff the test part passed.
|
// Returns true if and only if the test part was skipped.
|
||||||
|
bool skipped() const { return type_ == kSkip; }
|
||||||
|
|
||||||
|
// Returns true if and only if the test part passed.
|
||||||
bool passed() const { return type_ == kSuccess; }
|
bool passed() const { return type_ == kSuccess; }
|
||||||
|
|
||||||
// Returns true iff the test part failed.
|
// Returns true if and only if the test part non-fatally failed.
|
||||||
bool failed() const { return type_ != kSuccess; }
|
|
||||||
|
|
||||||
// Returns true iff the test part non-fatally failed.
|
|
||||||
bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
|
bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
|
||||||
|
|
||||||
// Returns true iff the test part fatally failed.
|
// Returns true if and only if the test part fatally failed.
|
||||||
bool fatally_failed() const { return type_ == kFatalFailure; }
|
bool fatally_failed() const { return type_ == kFatalFailure; }
|
||||||
|
|
||||||
|
// Returns true if and only if the test part failed.
|
||||||
|
bool failed() const { return fatally_failed() || nonfatally_failed(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
Type type_;
|
||||||
|
|
||||||
|
@ -164,8 +165,8 @@ class GTEST_API_ HasNewFatalFailureHelper
|
||||||
: public TestPartResultReporterInterface {
|
: public TestPartResultReporterInterface {
|
||||||
public:
|
public:
|
||||||
HasNewFatalFailureHelper();
|
HasNewFatalFailureHelper();
|
||||||
virtual ~HasNewFatalFailureHelper();
|
~HasNewFatalFailureHelper() override;
|
||||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
void ReportTestPartResult(const TestPartResult& result) override;
|
||||||
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
||||||
private:
|
private:
|
||||||
bool has_new_fatal_failure_;
|
bool has_new_fatal_failure_;
|
||||||
|
|
|
@ -52,22 +52,22 @@ class FooTest : public testing::Test {
|
||||||
T value_;
|
T value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Next, associate a list of types with the test case, which will be
|
// Next, associate a list of types with the test suite, which will be
|
||||||
// repeated for each type in the list. The typedef is necessary for
|
// repeated for each type in the list. The typedef is necessary for
|
||||||
// the macro to parse correctly.
|
// the macro to parse correctly.
|
||||||
typedef testing::Types<char, int, unsigned int> MyTypes;
|
typedef testing::Types<char, int, unsigned int> MyTypes;
|
||||||
TYPED_TEST_CASE(FooTest, MyTypes);
|
TYPED_TEST_SUITE(FooTest, MyTypes);
|
||||||
|
|
||||||
// If the type list contains only one type, you can write that type
|
// If the type list contains only one type, you can write that type
|
||||||
// directly without Types<...>:
|
// directly without Types<...>:
|
||||||
// TYPED_TEST_CASE(FooTest, int);
|
// TYPED_TEST_SUITE(FooTest, int);
|
||||||
|
|
||||||
// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
|
// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
|
||||||
// tests for this test case as you want.
|
// tests for this test suite as you want.
|
||||||
TYPED_TEST(FooTest, DoesBlah) {
|
TYPED_TEST(FooTest, DoesBlah) {
|
||||||
// Inside a test, refer to TypeParam to get the type parameter.
|
// Inside a test, refer to the special name TypeParam to get the type
|
||||||
// Since we are inside a derived class template, C++ requires use to
|
// parameter. Since we are inside a derived class template, C++ requires
|
||||||
// visit the members of FooTest via 'this'.
|
// us to visit the members of FooTest via 'this'.
|
||||||
TypeParam n = this->value_;
|
TypeParam n = this->value_;
|
||||||
|
|
||||||
// To visit static members of the fixture, add the TestFixture::
|
// To visit static members of the fixture, add the TestFixture::
|
||||||
|
@ -83,7 +83,7 @@ TYPED_TEST(FooTest, DoesBlah) {
|
||||||
|
|
||||||
TYPED_TEST(FooTest, HasPropertyA) { ... }
|
TYPED_TEST(FooTest, HasPropertyA) { ... }
|
||||||
|
|
||||||
// TYPED_TEST_CASE takes an optional third argument which allows to specify a
|
// TYPED_TEST_SUITE takes an optional third argument which allows to specify a
|
||||||
// class that generates custom test name suffixes based on the type. This should
|
// class that generates custom test name suffixes based on the type. This should
|
||||||
// be a class which has a static template function GetName(int index) returning
|
// be a class which has a static template function GetName(int index) returning
|
||||||
// a string for each type. The provided integer index equals the index of the
|
// a string for each type. The provided integer index equals the index of the
|
||||||
|
@ -99,7 +99,7 @@ TYPED_TEST(FooTest, HasPropertyA) { ... }
|
||||||
// if (std::is_same<T, unsigned int>()) return "unsignedInt";
|
// if (std::is_same<T, unsigned int>()) return "unsignedInt";
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
// TYPED_TEST_CASE(FooTest, MyTypes, MyTypeNames);
|
// TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames);
|
||||||
|
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
|
@ -126,13 +126,13 @@ class FooTest : public testing::Test {
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
|
|
||||||
// Next, declare that you will define a type-parameterized test case
|
// Next, declare that you will define a type-parameterized test suite
|
||||||
// (the _P suffix is for "parameterized" or "pattern", whichever you
|
// (the _P suffix is for "parameterized" or "pattern", whichever you
|
||||||
// prefer):
|
// prefer):
|
||||||
TYPED_TEST_CASE_P(FooTest);
|
TYPED_TEST_SUITE_P(FooTest);
|
||||||
|
|
||||||
// Then, use TYPED_TEST_P() to define as many type-parameterized tests
|
// Then, use TYPED_TEST_P() to define as many type-parameterized tests
|
||||||
// for this type-parameterized test case as you want.
|
// for this type-parameterized test suite as you want.
|
||||||
TYPED_TEST_P(FooTest, DoesBlah) {
|
TYPED_TEST_P(FooTest, DoesBlah) {
|
||||||
// Inside a test, refer to TypeParam to get the type parameter.
|
// Inside a test, refer to TypeParam to get the type parameter.
|
||||||
TypeParam n = 0;
|
TypeParam n = 0;
|
||||||
|
@ -143,10 +143,10 @@ TYPED_TEST_P(FooTest, HasPropertyA) { ... }
|
||||||
|
|
||||||
// Now the tricky part: you need to register all test patterns before
|
// Now the tricky part: you need to register all test patterns before
|
||||||
// you can instantiate them. The first argument of the macro is the
|
// you can instantiate them. The first argument of the macro is the
|
||||||
// test case name; the rest are the names of the tests in this test
|
// test suite name; the rest are the names of the tests in this test
|
||||||
// case.
|
// case.
|
||||||
REGISTER_TYPED_TEST_CASE_P(FooTest,
|
REGISTER_TYPED_TEST_SUITE_P(FooTest,
|
||||||
DoesBlah, HasPropertyA);
|
DoesBlah, HasPropertyA);
|
||||||
|
|
||||||
// Finally, you are free to instantiate the pattern with the types you
|
// Finally, you are free to instantiate the pattern with the types you
|
||||||
// want. If you put the above code in a header file, you can #include
|
// want. If you put the above code in a header file, you can #include
|
||||||
|
@ -154,19 +154,19 @@ REGISTER_TYPED_TEST_CASE_P(FooTest,
|
||||||
//
|
//
|
||||||
// To distinguish different instances of the pattern, the first
|
// To distinguish different instances of the pattern, the first
|
||||||
// argument to the INSTANTIATE_* macro is a prefix that will be added
|
// argument to the INSTANTIATE_* macro is a prefix that will be added
|
||||||
// to the actual test case name. Remember to pick unique prefixes for
|
// to the actual test suite name. Remember to pick unique prefixes for
|
||||||
// different instances.
|
// different instances.
|
||||||
typedef testing::Types<char, int, unsigned int> MyTypes;
|
typedef testing::Types<char, int, unsigned int> MyTypes;
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||||
|
|
||||||
// If the type list contains only one type, you can write that type
|
// If the type list contains only one type, you can write that type
|
||||||
// directly without Types<...>:
|
// directly without Types<...>:
|
||||||
// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
|
// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
|
||||||
//
|
//
|
||||||
// Similar to the optional argument of TYPED_TEST_CASE above,
|
// Similar to the optional argument of TYPED_TEST_SUITE above,
|
||||||
// INSTANTIATE_TEST_CASE_P takes an optional fourth argument which allows to
|
// INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to
|
||||||
// generate custom names.
|
// generate custom names.
|
||||||
// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes, MyTypeNames);
|
// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames);
|
||||||
|
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
|
@ -180,21 +180,18 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// Expands to the name of the typedef for the type parameters of the
|
// Expands to the name of the typedef for the type parameters of the
|
||||||
// given test case.
|
// given test suite.
|
||||||
# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
|
#define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_
|
||||||
|
|
||||||
// Expands to the name of the typedef for the NameGenerator, responsible for
|
// Expands to the name of the typedef for the NameGenerator, responsible for
|
||||||
// creating the suffixes of the name.
|
// creating the suffixes of the name.
|
||||||
#define GTEST_NAME_GENERATOR_(TestCaseName) \
|
#define GTEST_NAME_GENERATOR_(TestSuiteName) \
|
||||||
gtest_type_params_##TestCaseName##_NameGenerator
|
gtest_type_params_##TestSuiteName##_NameGenerator
|
||||||
|
|
||||||
// The 'Types' template argument below must have spaces around it
|
#define TYPED_TEST_SUITE(CaseName, Types, ...) \
|
||||||
// since some compilers may choke on '>>' when passing a template
|
typedef ::testing::internal::TypeList<Types>::type GTEST_TYPE_PARAMS_( \
|
||||||
// instance (e.g. Types<int>)
|
CaseName); \
|
||||||
# define TYPED_TEST_CASE(CaseName, Types, ...) \
|
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
|
||||||
typedef ::testing::internal::TypeList< Types >::type GTEST_TYPE_PARAMS_( \
|
|
||||||
CaseName); \
|
|
||||||
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
|
|
||||||
GTEST_NAME_GENERATOR_(CaseName)
|
GTEST_NAME_GENERATOR_(CaseName)
|
||||||
|
|
||||||
# define TYPED_TEST(CaseName, TestName) \
|
# define TYPED_TEST(CaseName, TestName) \
|
||||||
|
@ -224,6 +221,13 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
||||||
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||||
TestName)<gtest_TypeParam_>::TestBody()
|
TestName)<gtest_TypeParam_>::TestBody()
|
||||||
|
|
||||||
|
// Legacy API is deprecated but still available
|
||||||
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
#define TYPED_TEST_CASE \
|
||||||
|
static_assert(::testing::internal::TypedTestCaseIsDeprecated(), ""); \
|
||||||
|
TYPED_TEST_SUITE
|
||||||
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
#endif // GTEST_HAS_TYPED_TEST
|
#endif // GTEST_HAS_TYPED_TEST
|
||||||
|
|
||||||
// Implements type-parameterized tests.
|
// Implements type-parameterized tests.
|
||||||
|
@ -233,73 +237,93 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// Expands to the namespace name that the type-parameterized tests for
|
// Expands to the namespace name that the type-parameterized tests for
|
||||||
// the given type-parameterized test case are defined in. The exact
|
// the given type-parameterized test suite are defined in. The exact
|
||||||
// name of the namespace is subject to change without notice.
|
// name of the namespace is subject to change without notice.
|
||||||
# define GTEST_CASE_NAMESPACE_(TestCaseName) \
|
#define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_
|
||||||
gtest_case_##TestCaseName##_
|
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// Expands to the name of the variable used to remember the names of
|
// Expands to the name of the variable used to remember the names of
|
||||||
// the defined tests in the given test case.
|
// the defined tests in the given test suite.
|
||||||
# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
|
#define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \
|
||||||
gtest_typed_test_case_p_state_##TestCaseName##_
|
gtest_typed_test_suite_p_state_##TestSuiteName##_
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
|
||||||
//
|
//
|
||||||
// Expands to the name of the variable used to remember the names of
|
// Expands to the name of the variable used to remember the names of
|
||||||
// the registered tests in the given test case.
|
// the registered tests in the given test suite.
|
||||||
# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
|
#define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \
|
||||||
gtest_registered_test_names_##TestCaseName##_
|
gtest_registered_test_names_##TestSuiteName##_
|
||||||
|
|
||||||
// The variables defined in the type-parameterized test macros are
|
// The variables defined in the type-parameterized test macros are
|
||||||
// static as typically these macros are used in a .h file that can be
|
// static as typically these macros are used in a .h file that can be
|
||||||
// #included in multiple translation units linked together.
|
// #included in multiple translation units linked together.
|
||||||
# define TYPED_TEST_CASE_P(CaseName) \
|
#define TYPED_TEST_SUITE_P(SuiteName) \
|
||||||
static ::testing::internal::TypedTestCasePState \
|
static ::testing::internal::TypedTestSuitePState \
|
||||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
|
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName)
|
||||||
|
|
||||||
# define TYPED_TEST_P(CaseName, TestName) \
|
// Legacy API is deprecated but still available
|
||||||
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
template <typename gtest_TypeParam_> \
|
#define TYPED_TEST_CASE_P \
|
||||||
class TestName : public CaseName<gtest_TypeParam_> { \
|
static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \
|
||||||
private: \
|
TYPED_TEST_SUITE_P
|
||||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
typedef gtest_TypeParam_ TypeParam; \
|
|
||||||
virtual void TestBody(); \
|
|
||||||
}; \
|
|
||||||
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
|
|
||||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
|
|
||||||
__FILE__, __LINE__, #CaseName, #TestName); \
|
|
||||||
} \
|
|
||||||
template <typename gtest_TypeParam_> \
|
|
||||||
void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
|
|
||||||
|
|
||||||
# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
|
#define TYPED_TEST_P(SuiteName, TestName) \
|
||||||
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||||
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
|
template <typename gtest_TypeParam_> \
|
||||||
} \
|
class TestName : public SuiteName<gtest_TypeParam_> { \
|
||||||
static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) \
|
private: \
|
||||||
GTEST_ATTRIBUTE_UNUSED_ = \
|
typedef SuiteName<gtest_TypeParam_> TestFixture; \
|
||||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames( \
|
typedef gtest_TypeParam_ TypeParam; \
|
||||||
__FILE__, __LINE__, #__VA_ARGS__)
|
virtual void TestBody(); \
|
||||||
|
}; \
|
||||||
|
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
|
||||||
|
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
||||||
|
__FILE__, __LINE__, #SuiteName, #TestName); \
|
||||||
|
} \
|
||||||
|
template <typename gtest_TypeParam_> \
|
||||||
|
void GTEST_SUITE_NAMESPACE_( \
|
||||||
|
SuiteName)::TestName<gtest_TypeParam_>::TestBody()
|
||||||
|
|
||||||
// The 'Types' template argument below must have spaces around it
|
#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \
|
||||||
// since some compilers may choke on '>>' when passing a template
|
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||||
// instance (e.g. Types<int>)
|
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
|
||||||
# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types, ...) \
|
} \
|
||||||
static bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
|
static const char* const GTEST_REGISTERED_TEST_NAMES_( \
|
||||||
::testing::internal::TypeParameterizedTestCase< \
|
SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \
|
||||||
CaseName, GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
|
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
|
||||||
::testing::internal::TypeList< Types >::type>:: \
|
__FILE__, __LINE__, #__VA_ARGS__)
|
||||||
Register(#Prefix, \
|
|
||||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
// Legacy API is deprecated but still available
|
||||||
>EST_TYPED_TEST_CASE_P_STATE_(CaseName), #CaseName, \
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
GTEST_REGISTERED_TEST_NAMES_(CaseName), \
|
#define REGISTER_TYPED_TEST_CASE_P \
|
||||||
::testing::internal::GenerateNames< \
|
static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \
|
||||||
::testing::internal::NameGeneratorSelector< \
|
""); \
|
||||||
__VA_ARGS__>::type, \
|
REGISTER_TYPED_TEST_SUITE_P
|
||||||
::testing::internal::TypeList< Types >::type>())
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
|
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
||||||
|
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::CodeLocation(__FILE__, __LINE__), \
|
||||||
|
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), #SuiteName, \
|
||||||
|
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
|
||||||
|
::testing::internal::GenerateNames< \
|
||||||
|
::testing::internal::NameGeneratorSelector< \
|
||||||
|
__VA_ARGS__>::type, \
|
||||||
|
::testing::internal::TypeList<Types>::type>())
|
||||||
|
|
||||||
|
// Legacy API is deprecated but still available
|
||||||
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
#define INSTANTIATE_TYPED_TEST_CASE_P \
|
||||||
|
static_assert( \
|
||||||
|
::testing::internal::InstantiateTypedTestCase_P_IsDeprecated(), ""); \
|
||||||
|
INSTANTIATE_TYPED_TEST_SUITE_P
|
||||||
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
#endif // GTEST_HAS_TYPED_TEST_P
|
#endif // GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,11 +27,10 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// This file is AUTOMATICALLY GENERATED on 01/02/2018 by command
|
// This file is AUTOMATICALLY GENERATED on 01/02/2019 by command
|
||||||
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
|
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
|
||||||
//
|
//
|
||||||
// Implements a family of generic predicate assertion macros.
|
// Implements a family of generic predicate assertion macros.
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
|
@ -67,6 +66,8 @@ namespace testing {
|
||||||
// We also define the EXPECT_* variations.
|
// We also define the EXPECT_* variations.
|
||||||
//
|
//
|
||||||
// For now we only support predicates whose arity is at most 5.
|
// For now we only support predicates whose arity is at most 5.
|
||||||
|
// Please email googletestframework@googlegroups.com if you need
|
||||||
|
// support for higher arities.
|
||||||
|
|
||||||
// GTEST_ASSERT_ is the basic statement to which all of the assertions
|
// GTEST_ASSERT_ is the basic statement to which all of the assertions
|
||||||
// in this file reduce. Don't use this in your code.
|
// in this file reduce. Don't use this in your code.
|
||||||
|
@ -89,9 +90,10 @@ AssertionResult AssertPred1Helper(const char* pred_text,
|
||||||
const T1& v1) {
|
const T1& v1) {
|
||||||
if (pred(v1)) return AssertionSuccess();
|
if (pred(v1)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure()
|
||||||
<< e1 << ") evaluates to false, where"
|
<< pred_text << "(" << e1 << ") evaluates to false, where"
|
||||||
<< "\n" << e1 << " evaluates to " << v1;
|
<< "\n"
|
||||||
|
<< e1 << " evaluates to " << ::testing::PrintToString(v1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
||||||
|
@ -133,11 +135,12 @@ AssertionResult AssertPred2Helper(const char* pred_text,
|
||||||
const T2& v2) {
|
const T2& v2) {
|
||||||
if (pred(v1, v2)) return AssertionSuccess();
|
if (pred(v1, v2)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure()
|
||||||
<< e1 << ", "
|
<< pred_text << "(" << e1 << ", " << e2
|
||||||
<< e2 << ") evaluates to false, where"
|
<< ") evaluates to false, where"
|
||||||
<< "\n" << e1 << " evaluates to " << v1
|
<< "\n"
|
||||||
<< "\n" << e2 << " evaluates to " << v2;
|
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
|
||||||
|
<< e2 << " evaluates to " << ::testing::PrintToString(v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
||||||
|
@ -184,13 +187,13 @@ AssertionResult AssertPred3Helper(const char* pred_text,
|
||||||
const T3& v3) {
|
const T3& v3) {
|
||||||
if (pred(v1, v2, v3)) return AssertionSuccess();
|
if (pred(v1, v2, v3)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure()
|
||||||
<< e1 << ", "
|
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3
|
||||||
<< e2 << ", "
|
<< ") evaluates to false, where"
|
||||||
<< e3 << ") evaluates to false, where"
|
<< "\n"
|
||||||
<< "\n" << e1 << " evaluates to " << v1
|
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
|
||||||
<< "\n" << e2 << " evaluates to " << v2
|
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
|
||||||
<< "\n" << e3 << " evaluates to " << v3;
|
<< e3 << " evaluates to " << ::testing::PrintToString(v3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
||||||
|
@ -242,15 +245,14 @@ AssertionResult AssertPred4Helper(const char* pred_text,
|
||||||
const T4& v4) {
|
const T4& v4) {
|
||||||
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
|
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure()
|
||||||
<< e1 << ", "
|
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
|
||||||
<< e2 << ", "
|
<< ") evaluates to false, where"
|
||||||
<< e3 << ", "
|
<< "\n"
|
||||||
<< e4 << ") evaluates to false, where"
|
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
|
||||||
<< "\n" << e1 << " evaluates to " << v1
|
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
|
||||||
<< "\n" << e2 << " evaluates to " << v2
|
<< e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
|
||||||
<< "\n" << e3 << " evaluates to " << v3
|
<< e4 << " evaluates to " << ::testing::PrintToString(v4);
|
||||||
<< "\n" << e4 << " evaluates to " << v4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
||||||
|
@ -307,17 +309,15 @@ AssertionResult AssertPred5Helper(const char* pred_text,
|
||||||
const T5& v5) {
|
const T5& v5) {
|
||||||
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
|
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure()
|
||||||
<< e1 << ", "
|
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
|
||||||
<< e2 << ", "
|
<< ", " << e5 << ") evaluates to false, where"
|
||||||
<< e3 << ", "
|
<< "\n"
|
||||||
<< e4 << ", "
|
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
|
||||||
<< e5 << ") evaluates to false, where"
|
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
|
||||||
<< "\n" << e1 << " evaluates to " << v1
|
<< e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
|
||||||
<< "\n" << e2 << " evaluates to " << v2
|
<< e4 << " evaluates to " << ::testing::PrintToString(v4) << "\n"
|
||||||
<< "\n" << e3 << " evaluates to " << v3
|
<< e5 << " evaluates to " << ::testing::PrintToString(v5);
|
||||||
<< "\n" << e4 << " evaluates to " << v4
|
|
||||||
<< "\n" << e5 << " evaluates to " << v5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
# Customization Points
|
||||||
|
|
||||||
|
The custom directory is an injection point for custom user configurations.
|
||||||
|
|
||||||
|
## Header `gtest.h`
|
||||||
|
|
||||||
|
### The following macros can be defined:
|
||||||
|
|
||||||
|
* `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of
|
||||||
|
`OsStackTraceGetterInterface`.
|
||||||
|
* `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See
|
||||||
|
`testing::TempDir` for semantics and signature.
|
||||||
|
|
||||||
|
## Header `gtest-port.h`
|
||||||
|
|
||||||
|
The following macros can be defined:
|
||||||
|
|
||||||
|
### Flag related macros:
|
||||||
|
|
||||||
|
* `GTEST_FLAG(flag_name)`
|
||||||
|
* `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its
|
||||||
|
own flagfile flag parsing.
|
||||||
|
* `GTEST_DECLARE_bool_(name)`
|
||||||
|
* `GTEST_DECLARE_int32_(name)`
|
||||||
|
* `GTEST_DECLARE_string_(name)`
|
||||||
|
* `GTEST_DEFINE_bool_(name, default_val, doc)`
|
||||||
|
* `GTEST_DEFINE_int32_(name, default_val, doc)`
|
||||||
|
* `GTEST_DEFINE_string_(name, default_val, doc)`
|
||||||
|
|
||||||
|
### Logging:
|
||||||
|
|
||||||
|
* `GTEST_LOG_(severity)`
|
||||||
|
* `GTEST_CHECK_(condition)`
|
||||||
|
* Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too.
|
||||||
|
|
||||||
|
### Threading:
|
||||||
|
|
||||||
|
* `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided.
|
||||||
|
* `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal`
|
||||||
|
are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)`
|
||||||
|
and `GTEST_DEFINE_STATIC_MUTEX_(mutex)`
|
||||||
|
* `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)`
|
||||||
|
* `GTEST_LOCK_EXCLUDED_(locks)`
|
||||||
|
|
||||||
|
### Underlying library support features
|
||||||
|
|
||||||
|
* `GTEST_HAS_CXXABI_H_`
|
||||||
|
|
||||||
|
### Exporting API symbols:
|
||||||
|
|
||||||
|
* `GTEST_API_` - Specifier for exported symbols.
|
||||||
|
|
||||||
|
## Header `gtest-printers.h`
|
||||||
|
|
||||||
|
* See documentation at `gtest/gtest-printers.h` for details on how to define a
|
||||||
|
custom printer.
|
|
@ -36,9 +36,11 @@
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
|
|
||||||
|
#include "gtest/gtest-matchers.h"
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -78,7 +80,7 @@ class GTEST_API_ DeathTest {
|
||||||
// argument is set. If the death test should be skipped, the pointer
|
// argument is set. If the death test should be skipped, the pointer
|
||||||
// is set to NULL; otherwise, it is set to the address of a new concrete
|
// is set to NULL; otherwise, it is set to the address of a new concrete
|
||||||
// DeathTest object that controls the execution of the current test.
|
// DeathTest object that controls the execution of the current test.
|
||||||
static bool Create(const char* statement, const RE* regex,
|
static bool Create(const char* statement, Matcher<const std::string&> matcher,
|
||||||
const char* file, int line, DeathTest** test);
|
const char* file, int line, DeathTest** test);
|
||||||
DeathTest();
|
DeathTest();
|
||||||
virtual ~DeathTest() { }
|
virtual ~DeathTest() { }
|
||||||
|
@ -144,21 +146,44 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
class DeathTestFactory {
|
class DeathTestFactory {
|
||||||
public:
|
public:
|
||||||
virtual ~DeathTestFactory() { }
|
virtual ~DeathTestFactory() { }
|
||||||
virtual bool Create(const char* statement, const RE* regex,
|
virtual bool Create(const char* statement,
|
||||||
const char* file, int line, DeathTest** test) = 0;
|
Matcher<const std::string&> matcher, const char* file,
|
||||||
|
int line, DeathTest** test) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A concrete DeathTestFactory implementation for normal use.
|
// A concrete DeathTestFactory implementation for normal use.
|
||||||
class DefaultDeathTestFactory : public DeathTestFactory {
|
class DefaultDeathTestFactory : public DeathTestFactory {
|
||||||
public:
|
public:
|
||||||
virtual bool Create(const char* statement, const RE* regex,
|
bool Create(const char* statement, Matcher<const std::string&> matcher,
|
||||||
const char* file, int line, DeathTest** test);
|
const char* file, int line, DeathTest** test) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns true if exit_status describes a process that was terminated
|
// Returns true if exit_status describes a process that was terminated
|
||||||
// by a signal, or exited normally with a nonzero exit code.
|
// by a signal, or exited normally with a nonzero exit code.
|
||||||
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
||||||
|
|
||||||
|
// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
|
||||||
|
// and interpreted as a regex (rather than an Eq matcher) for legacy
|
||||||
|
// compatibility.
|
||||||
|
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||||
|
::testing::internal::RE regex) {
|
||||||
|
return ContainsRegex(regex.pattern());
|
||||||
|
}
|
||||||
|
inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
|
||||||
|
return ContainsRegex(regex);
|
||||||
|
}
|
||||||
|
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||||
|
const ::std::string& regex) {
|
||||||
|
return ContainsRegex(regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
|
||||||
|
// used directly.
|
||||||
|
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||||
|
Matcher<const ::std::string&> matcher) {
|
||||||
|
return matcher;
|
||||||
|
}
|
||||||
|
|
||||||
// Traps C++ exceptions escaping statement and reports them as test
|
// Traps C++ exceptions escaping statement and reports them as test
|
||||||
// failures. Note that trapping SEH exceptions is not implemented here.
|
// failures. Note that trapping SEH exceptions is not implemented here.
|
||||||
# if GTEST_HAS_EXCEPTIONS
|
# if GTEST_HAS_EXCEPTIONS
|
||||||
|
@ -186,38 +211,38 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
||||||
|
|
||||||
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
||||||
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
||||||
# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
|
#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
if (::testing::internal::AlwaysTrue()) { \
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
const ::testing::internal::RE& gtest_regex = (regex); \
|
::testing::internal::DeathTest* gtest_dt; \
|
||||||
::testing::internal::DeathTest* gtest_dt; \
|
if (!::testing::internal::DeathTest::Create( \
|
||||||
if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \
|
#statement, \
|
||||||
__FILE__, __LINE__, >est_dt)) { \
|
::testing::internal::MakeDeathTestMatcher(regex_or_matcher), \
|
||||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
__FILE__, __LINE__, >est_dt)) { \
|
||||||
} \
|
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||||
if (gtest_dt != NULL) { \
|
} \
|
||||||
::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
|
if (gtest_dt != nullptr) { \
|
||||||
gtest_dt_ptr(gtest_dt); \
|
std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
|
||||||
switch (gtest_dt->AssumeRole()) { \
|
switch (gtest_dt->AssumeRole()) { \
|
||||||
case ::testing::internal::DeathTest::OVERSEE_TEST: \
|
case ::testing::internal::DeathTest::OVERSEE_TEST: \
|
||||||
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
|
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
|
||||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||||
} \
|
} \
|
||||||
break; \
|
break; \
|
||||||
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
|
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
|
||||||
::testing::internal::DeathTest::ReturnSentinel \
|
::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \
|
||||||
gtest_sentinel(gtest_dt); \
|
gtest_dt); \
|
||||||
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
|
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
|
||||||
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
default: \
|
default: \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} else \
|
} else \
|
||||||
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
|
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \
|
||||||
fail(::testing::internal::DeathTest::LastMessage())
|
: fail(::testing::internal::DeathTest::LastMessage())
|
||||||
// The symbol "fail" here expands to something into which a message
|
// The symbol "fail" here expands to something into which a message
|
||||||
// can be streamed.
|
// can be streamed.
|
||||||
|
|
||||||
|
@ -226,14 +251,13 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
||||||
// must accept a streamed message even though the message is never printed.
|
// must accept a streamed message even though the message is never printed.
|
||||||
// The regex object is not evaluated, but it is used to prevent "unused"
|
// The regex object is not evaluated, but it is used to prevent "unused"
|
||||||
// warnings and to avoid an expression that doesn't compile in debug mode.
|
// warnings and to avoid an expression that doesn't compile in debug mode.
|
||||||
#define GTEST_EXECUTE_STATEMENT_(statement, regex) \
|
#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
if (::testing::internal::AlwaysTrue()) { \
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
} else if (!::testing::internal::AlwaysTrue()) { \
|
} else if (!::testing::internal::AlwaysTrue()) { \
|
||||||
const ::testing::internal::RE& gtest_regex = (regex); \
|
::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
|
||||||
static_cast<void>(gtest_regex); \
|
} else \
|
||||||
} else \
|
|
||||||
::testing::Message()
|
::testing::Message()
|
||||||
|
|
||||||
// A class representing the parsed contents of the
|
// A class representing the parsed contents of the
|
||||||
|
|
|
@ -110,7 +110,7 @@ class GTEST_API_ FilePath {
|
||||||
const FilePath& base_name,
|
const FilePath& base_name,
|
||||||
const char* extension);
|
const char* extension);
|
||||||
|
|
||||||
// Returns true iff the path is "".
|
// Returns true if and only if the path is "".
|
||||||
bool IsEmpty() const { return pathname_.empty(); }
|
bool IsEmpty() const { return pathname_.empty(); }
|
||||||
|
|
||||||
// If input name has a trailing separator character, removes it and returns
|
// If input name has a trailing separator character, removes it and returns
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "gtest/gtest-message.h"
|
#include "gtest/gtest-message.h"
|
||||||
|
@ -79,7 +80,6 @@
|
||||||
// Stringifies its argument.
|
// Stringifies its argument.
|
||||||
#define GTEST_STRINGIFY_(name) #name
|
#define GTEST_STRINGIFY_(name) #name
|
||||||
|
|
||||||
class ProtocolMessage;
|
|
||||||
namespace proto2 { class Message; }
|
namespace proto2 { class Message; }
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
@ -91,7 +91,7 @@ class Message; // Represents a failure message.
|
||||||
class Test; // Represents a test.
|
class Test; // Represents a test.
|
||||||
class TestInfo; // Information about a test.
|
class TestInfo; // Information about a test.
|
||||||
class TestPartResult; // Result of a test part.
|
class TestPartResult; // Result of a test part.
|
||||||
class UnitTest; // A collection of test cases.
|
class UnitTest; // A collection of test suites.
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
::std::string PrintToString(const T& value);
|
::std::string PrintToString(const T& value);
|
||||||
|
@ -106,34 +106,22 @@ class UnitTestImpl; // Opaque implementation of UnitTest
|
||||||
// stack trace.
|
// stack trace.
|
||||||
GTEST_API_ extern const char kStackTraceMarker[];
|
GTEST_API_ extern const char kStackTraceMarker[];
|
||||||
|
|
||||||
// Two overloaded helpers for checking at compile time whether an
|
// An IgnoredValue object can be implicitly constructed from ANY value.
|
||||||
// expression is a null pointer literal (i.e. NULL or any 0-valued
|
class IgnoredValue {
|
||||||
// compile-time integral constant). Their return values have
|
struct Sink {};
|
||||||
// different sizes, so we can use sizeof() to test which version is
|
public:
|
||||||
// picked by the compiler. These helpers have no implementations, as
|
// This constructor template allows any value to be implicitly
|
||||||
// we only need their signatures.
|
// converted to IgnoredValue. The object has no data member and
|
||||||
//
|
// doesn't try to remember anything about the argument. We
|
||||||
// Given IsNullLiteralHelper(x), the compiler will pick the first
|
// deliberately omit the 'explicit' keyword in order to allow the
|
||||||
// version if x can be implicitly converted to Secret*, and pick the
|
// conversion to be implicit.
|
||||||
// second version otherwise. Since Secret is a secret and incomplete
|
// Disable the conversion if T already has a magical conversion operator.
|
||||||
// type, the only expression a user can write that has type Secret* is
|
// Otherwise we get ambiguity.
|
||||||
// a null pointer literal. Therefore, we know that x is a null
|
template <typename T,
|
||||||
// pointer literal if and only if the first version is picked by the
|
typename std::enable_if<!std::is_convertible<T, Sink>::value,
|
||||||
// compiler.
|
int>::type = 0>
|
||||||
char IsNullLiteralHelper(Secret* p);
|
IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit)
|
||||||
char (&IsNullLiteralHelper(...))[2]; // NOLINT
|
};
|
||||||
|
|
||||||
// A compile-time bool constant that is true if and only if x is a
|
|
||||||
// null pointer literal (i.e. NULL or any 0-valued compile-time
|
|
||||||
// integral constant).
|
|
||||||
#ifdef GTEST_ELLIPSIS_NEEDS_POD_
|
|
||||||
// We lose support for NULL detection where the compiler doesn't like
|
|
||||||
// passing non-POD classes through ellipsis (...).
|
|
||||||
# define GTEST_IS_NULL_LITERAL_(x) false
|
|
||||||
#else
|
|
||||||
# define GTEST_IS_NULL_LITERAL_(x) \
|
|
||||||
(sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
|
|
||||||
#endif // GTEST_ELLIPSIS_NEEDS_POD_
|
|
||||||
|
|
||||||
// Appends the user-supplied message to the Google-Test-generated message.
|
// Appends the user-supplied message to the Google-Test-generated message.
|
||||||
GTEST_API_ std::string AppendUserMessage(
|
GTEST_API_ std::string AppendUserMessage(
|
||||||
|
@ -201,7 +189,7 @@ GTEST_API_ std::string DiffStrings(const std::string& left,
|
||||||
// expected_value: "5"
|
// expected_value: "5"
|
||||||
// actual_value: "6"
|
// actual_value: "6"
|
||||||
//
|
//
|
||||||
// The ignoring_case parameter is true iff the assertion is a
|
// The ignoring_case parameter is true if and only if the assertion is a
|
||||||
// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
|
// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
|
||||||
// be inserted into the message.
|
// be inserted into the message.
|
||||||
GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
|
GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
|
||||||
|
@ -330,15 +318,15 @@ class FloatingPoint {
|
||||||
// Returns the sign bit of this number.
|
// Returns the sign bit of this number.
|
||||||
Bits sign_bit() const { return kSignBitMask & u_.bits_; }
|
Bits sign_bit() const { return kSignBitMask & u_.bits_; }
|
||||||
|
|
||||||
// Returns true iff this is NAN (not a number).
|
// Returns true if and only if this is NAN (not a number).
|
||||||
bool is_nan() const {
|
bool is_nan() const {
|
||||||
// It's a NAN if the exponent bits are all ones and the fraction
|
// It's a NAN if the exponent bits are all ones and the fraction
|
||||||
// bits are not entirely zeros.
|
// bits are not entirely zeros.
|
||||||
return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
|
return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff this number is at most kMaxUlps ULP's away from
|
// Returns true if and only if this number is at most kMaxUlps ULP's away
|
||||||
// rhs. In particular, this function:
|
// from rhs. In particular, this function:
|
||||||
//
|
//
|
||||||
// - returns false if either number is (or both are) NAN.
|
// - returns false if either number is (or both are) NAN.
|
||||||
// - treats really large numbers as almost equal to infinity.
|
// - treats really large numbers as almost equal to infinity.
|
||||||
|
@ -409,7 +397,7 @@ typedef FloatingPoint<float> Float;
|
||||||
typedef FloatingPoint<double> Double;
|
typedef FloatingPoint<double> Double;
|
||||||
|
|
||||||
// In order to catch the mistake of putting tests that use different
|
// In order to catch the mistake of putting tests that use different
|
||||||
// test fixture classes in the same test case, we need to assign
|
// test fixture classes in the same test suite, we need to assign
|
||||||
// unique IDs to fixture classes and compare them. The TypeId type is
|
// unique IDs to fixture classes and compare them. The TypeId type is
|
||||||
// used to hold such IDs. The user should treat TypeId as an opaque
|
// used to hold such IDs. The user should treat TypeId as an opaque
|
||||||
// type: the only operation allowed on TypeId values is to compare
|
// type: the only operation allowed on TypeId values is to compare
|
||||||
|
@ -469,7 +457,7 @@ class TestFactoryBase {
|
||||||
template <class TestClass>
|
template <class TestClass>
|
||||||
class TestFactoryImpl : public TestFactoryBase {
|
class TestFactoryImpl : public TestFactoryBase {
|
||||||
public:
|
public:
|
||||||
virtual Test* CreateTest() { return new TestClass; }
|
Test* CreateTest() override { return new TestClass; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
|
@ -485,9 +473,9 @@ GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
|
||||||
|
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// Types of SetUpTestCase() and TearDownTestCase() functions.
|
// Types of SetUpTestSuite() and TearDownTestSuite() functions.
|
||||||
typedef void (*SetUpTestCaseFunc)();
|
using SetUpTestSuiteFunc = void (*)();
|
||||||
typedef void (*TearDownTestCaseFunc)();
|
using TearDownTestSuiteFunc = void (*)();
|
||||||
|
|
||||||
struct CodeLocation {
|
struct CodeLocation {
|
||||||
CodeLocation(const std::string& a_file, int a_line)
|
CodeLocation(const std::string& a_file, int a_line)
|
||||||
|
@ -497,12 +485,64 @@ struct CodeLocation {
|
||||||
int line;
|
int line;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper to identify which setup function for TestCase / TestSuite to call.
|
||||||
|
// Only one function is allowed, either TestCase or TestSute but not both.
|
||||||
|
|
||||||
|
// Utility functions to help SuiteApiResolver
|
||||||
|
using SetUpTearDownSuiteFuncType = void (*)();
|
||||||
|
|
||||||
|
inline SetUpTearDownSuiteFuncType GetNotDefaultOrNull(
|
||||||
|
SetUpTearDownSuiteFuncType a, SetUpTearDownSuiteFuncType def) {
|
||||||
|
return a == def ? nullptr : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
// Note that SuiteApiResolver inherits from T because
|
||||||
|
// SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way
|
||||||
|
// SuiteApiResolver can access them.
|
||||||
|
struct SuiteApiResolver : T {
|
||||||
|
// testing::Test is only forward declared at this point. So we make it a
|
||||||
|
// dependend class for the compiler to be OK with it.
|
||||||
|
using Test =
|
||||||
|
typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type;
|
||||||
|
|
||||||
|
static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename,
|
||||||
|
int line_num) {
|
||||||
|
SetUpTearDownSuiteFuncType test_case_fp =
|
||||||
|
GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase);
|
||||||
|
SetUpTearDownSuiteFuncType test_suite_fp =
|
||||||
|
GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite);
|
||||||
|
|
||||||
|
GTEST_CHECK_(!test_case_fp || !test_suite_fp)
|
||||||
|
<< "Test can not provide both SetUpTestSuite and SetUpTestCase, please "
|
||||||
|
"make sure there is only one present at "
|
||||||
|
<< filename << ":" << line_num;
|
||||||
|
|
||||||
|
return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename,
|
||||||
|
int line_num) {
|
||||||
|
SetUpTearDownSuiteFuncType test_case_fp =
|
||||||
|
GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase);
|
||||||
|
SetUpTearDownSuiteFuncType test_suite_fp =
|
||||||
|
GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite);
|
||||||
|
|
||||||
|
GTEST_CHECK_(!test_case_fp || !test_suite_fp)
|
||||||
|
<< "Test can not provide both TearDownTestSuite and TearDownTestCase,"
|
||||||
|
" please make sure there is only one present at"
|
||||||
|
<< filename << ":" << line_num;
|
||||||
|
|
||||||
|
return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Creates a new TestInfo object and registers it with Google Test;
|
// Creates a new TestInfo object and registers it with Google Test;
|
||||||
// returns the created object.
|
// returns the created object.
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
//
|
//
|
||||||
// test_case_name: name of the test case
|
// test_suite_name: name of the test suite
|
||||||
// name: name of the test
|
// 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.
|
// this is not a typed or a type-parameterized test.
|
||||||
|
@ -510,21 +550,16 @@ struct CodeLocation {
|
||||||
// or NULL if this is not a type-parameterized test.
|
// or NULL if this is not a type-parameterized test.
|
||||||
// code_location: code location where the test is defined
|
// code_location: code location where the test is defined
|
||||||
// fixture_class_id: ID of the test fixture class
|
// fixture_class_id: ID of the test fixture class
|
||||||
// set_up_tc: pointer to the function that sets up the test case
|
// 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 case
|
// tear_down_tc: pointer to the function that tears down the test suite
|
||||||
// factory: pointer to the factory that creates a test object.
|
// factory: pointer to the factory that creates a test object.
|
||||||
// The newly created TestInfo instance will assume
|
// The newly created TestInfo instance will assume
|
||||||
// ownership of the factory object.
|
// ownership of the factory object.
|
||||||
GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
|
GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
|
||||||
const char* test_case_name,
|
const char* test_suite_name, const char* name, const char* type_param,
|
||||||
const char* name,
|
const char* value_param, CodeLocation code_location,
|
||||||
const char* type_param,
|
TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
|
||||||
const char* value_param,
|
TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory);
|
||||||
CodeLocation code_location,
|
|
||||||
TypeId fixture_class_id,
|
|
||||||
SetUpTestCaseFunc set_up_tc,
|
|
||||||
TearDownTestCaseFunc tear_down_tc,
|
|
||||||
TestFactoryBase* factory);
|
|
||||||
|
|
||||||
// If *pstr starts with the given prefix, modifies *pstr to be right
|
// If *pstr starts with the given prefix, modifies *pstr to be right
|
||||||
// past the prefix and returns true; otherwise leaves *pstr unchanged
|
// past the prefix and returns true; otherwise leaves *pstr unchanged
|
||||||
|
@ -536,19 +571,20 @@ GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||||
|
|
||||||
// State of the definition of a type-parameterized test case.
|
// State of the definition of a type-parameterized test suite.
|
||||||
class GTEST_API_ TypedTestCasePState {
|
class GTEST_API_ TypedTestSuitePState {
|
||||||
public:
|
public:
|
||||||
TypedTestCasePState() : registered_(false) {}
|
TypedTestSuitePState() : registered_(false) {}
|
||||||
|
|
||||||
// Adds the given test name to defined_test_names_ and return true
|
// Adds the given test name to defined_test_names_ and return true
|
||||||
// if the test case hasn't been registered; otherwise aborts the
|
// if the test suite hasn't been registered; otherwise aborts the
|
||||||
// program.
|
// program.
|
||||||
bool AddTestName(const char* file, int line, const char* case_name,
|
bool AddTestName(const char* file, int line, const char* case_name,
|
||||||
const char* test_name) {
|
const char* test_name) {
|
||||||
if (registered_) {
|
if (registered_) {
|
||||||
fprintf(stderr, "%s Test %s must be defined before "
|
fprintf(stderr,
|
||||||
"REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
|
"%s Test %s must be defined before "
|
||||||
|
"REGISTER_TYPED_TEST_SUITE_P(%s, ...).\n",
|
||||||
FormatFileLocation(file, line).c_str(), test_name, case_name);
|
FormatFileLocation(file, line).c_str(), test_name, case_name);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
posix::Abort();
|
posix::Abort();
|
||||||
|
@ -581,14 +617,19 @@ class GTEST_API_ TypedTestCasePState {
|
||||||
RegisteredTestsMap registered_tests_;
|
RegisteredTestsMap registered_tests_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Legacy API is deprecated but still available
|
||||||
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
using TypedTestCasePState = TypedTestSuitePState;
|
||||||
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
|
|
||||||
// Skips to the first non-space char after the first comma in 'str';
|
// Skips to the first non-space char after the first comma in 'str';
|
||||||
// returns NULL if no comma is found in 'str'.
|
// returns NULL if no comma is found in 'str'.
|
||||||
inline const char* SkipComma(const char* str) {
|
inline const char* SkipComma(const char* str) {
|
||||||
const char* comma = strchr(str, ',');
|
const char* comma = strchr(str, ',');
|
||||||
if (comma == NULL) {
|
if (comma == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
while (IsSpace(*(++comma))) {}
|
while (IsSpace(*(++comma))) {}
|
||||||
return comma;
|
return comma;
|
||||||
|
@ -598,7 +639,7 @@ inline const char* SkipComma(const char* str) {
|
||||||
// the entire string if it contains no comma.
|
// the entire string if it contains no comma.
|
||||||
inline std::string GetPrefixUntilComma(const char* str) {
|
inline std::string GetPrefixUntilComma(const char* str) {
|
||||||
const char* comma = strchr(str, ',');
|
const char* comma = strchr(str, ',');
|
||||||
return comma == NULL ? str : std::string(str, comma);
|
return comma == nullptr ? str : std::string(str, comma);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Splits a given string on a given delimiter, populating a given
|
// Splits a given string on a given delimiter, populating a given
|
||||||
|
@ -648,7 +689,7 @@ template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
|
||||||
class TypeParameterizedTest {
|
class TypeParameterizedTest {
|
||||||
public:
|
public:
|
||||||
// 'index' is the index of the test in the type list 'Types'
|
// 'index' is the index of the test in the type list 'Types'
|
||||||
// specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
|
// specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
|
||||||
// Types). Valid values for 'index' are [0, N - 1] where N is the
|
// Types). Valid values for 'index' are [0, N - 1] where N is the
|
||||||
// length of Types.
|
// length of Types.
|
||||||
static bool Register(const char* prefix, const CodeLocation& code_location,
|
static bool Register(const char* prefix, const CodeLocation& code_location,
|
||||||
|
@ -663,13 +704,17 @@ class TypeParameterizedTest {
|
||||||
// list.
|
// list.
|
||||||
MakeAndRegisterTestInfo(
|
MakeAndRegisterTestInfo(
|
||||||
(std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
|
(std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
|
||||||
"/" + type_names[index])
|
"/" + type_names[static_cast<size_t>(index)])
|
||||||
.c_str(),
|
.c_str(),
|
||||||
StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
|
StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
|
||||||
GetTypeName<Type>().c_str(),
|
GetTypeName<Type>().c_str(),
|
||||||
NULL, // No value parameter.
|
nullptr, // No value parameter.
|
||||||
code_location, GetTypeId<FixtureClass>(), TestClass::SetUpTestCase,
|
code_location, GetTypeId<FixtureClass>(),
|
||||||
TestClass::TearDownTestCase, new TestFactoryImpl<TestClass>);
|
SuiteApiResolver<TestClass>::GetSetUpCaseOrSuite(
|
||||||
|
code_location.file.c_str(), code_location.line),
|
||||||
|
SuiteApiResolver<TestClass>::GetTearDownCaseOrSuite(
|
||||||
|
code_location.file.c_str(), code_location.line),
|
||||||
|
new TestFactoryImpl<TestClass>);
|
||||||
|
|
||||||
// Next, recurses (at compile time) with the tail of the type list.
|
// Next, recurses (at compile time) with the tail of the type list.
|
||||||
return TypeParameterizedTest<Fixture, TestSel,
|
return TypeParameterizedTest<Fixture, TestSel,
|
||||||
|
@ -695,15 +740,15 @@ class TypeParameterizedTest<Fixture, TestSel, Types0> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
|
// TypeParameterizedTestSuite<Fixture, Tests, Types>::Register()
|
||||||
// registers *all combinations* of 'Tests' and 'Types' with Google
|
// registers *all combinations* of 'Tests' and 'Types' with Google
|
||||||
// Test. The return value is insignificant - we just need to return
|
// Test. The return value is insignificant - we just need to return
|
||||||
// something such that we can call this function in a namespace scope.
|
// something such that we can call this function in a namespace scope.
|
||||||
template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
|
template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
|
||||||
class TypeParameterizedTestCase {
|
class TypeParameterizedTestSuite {
|
||||||
public:
|
public:
|
||||||
static bool Register(const char* prefix, CodeLocation code_location,
|
static bool Register(const char* prefix, CodeLocation code_location,
|
||||||
const TypedTestCasePState* state, const char* case_name,
|
const TypedTestSuitePState* state, const char* case_name,
|
||||||
const char* test_names,
|
const char* test_names,
|
||||||
const std::vector<std::string>& type_names =
|
const std::vector<std::string>& type_names =
|
||||||
GenerateNames<DefaultNameGenerator, Types>()) {
|
GenerateNames<DefaultNameGenerator, Types>()) {
|
||||||
|
@ -726,20 +771,20 @@ class TypeParameterizedTestCase {
|
||||||
prefix, test_location, case_name, test_names, 0, type_names);
|
prefix, test_location, case_name, test_names, 0, type_names);
|
||||||
|
|
||||||
// Next, recurses (at compile time) with the tail of the test list.
|
// Next, recurses (at compile time) with the tail of the test list.
|
||||||
return TypeParameterizedTestCase<Fixture, typename Tests::Tail,
|
return TypeParameterizedTestSuite<Fixture, typename Tests::Tail,
|
||||||
Types>::Register(prefix, code_location,
|
Types>::Register(prefix, code_location,
|
||||||
state, case_name,
|
state, case_name,
|
||||||
SkipComma(test_names),
|
SkipComma(test_names),
|
||||||
type_names);
|
type_names);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// The base case for the compile time recursion.
|
// The base case for the compile time recursion.
|
||||||
template <GTEST_TEMPLATE_ Fixture, typename Types>
|
template <GTEST_TEMPLATE_ Fixture, typename Types>
|
||||||
class TypeParameterizedTestCase<Fixture, Templates0, Types> {
|
class TypeParameterizedTestSuite<Fixture, Templates0, Types> {
|
||||||
public:
|
public:
|
||||||
static bool Register(const char* /*prefix*/, const CodeLocation&,
|
static bool Register(const char* /*prefix*/, const CodeLocation&,
|
||||||
const TypedTestCasePState* /*state*/,
|
const TypedTestSuitePState* /*state*/,
|
||||||
const char* /*case_name*/, const char* /*test_names*/,
|
const char* /*case_name*/, const char* /*test_names*/,
|
||||||
const std::vector<std::string>& =
|
const std::vector<std::string>& =
|
||||||
std::vector<std::string>() /*type_names*/) {
|
std::vector<std::string>() /*type_names*/) {
|
||||||
|
@ -802,120 +847,16 @@ class GTEST_API_ Random {
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
|
|
||||||
// compiler error iff T1 and T2 are different types.
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
struct CompileAssertTypesEqual;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct CompileAssertTypesEqual<T, T> {
|
|
||||||
};
|
|
||||||
|
|
||||||
// Removes the reference from a type if it is a reference type,
|
|
||||||
// otherwise leaves it unchanged. This is the same as
|
|
||||||
// tr1::remove_reference, which is not widely available yet.
|
|
||||||
template <typename T>
|
|
||||||
struct RemoveReference { typedef T type; }; // NOLINT
|
|
||||||
template <typename T>
|
|
||||||
struct RemoveReference<T&> { typedef T type; }; // NOLINT
|
|
||||||
|
|
||||||
// A handy wrapper around RemoveReference that works when the argument
|
|
||||||
// T depends on template parameters.
|
|
||||||
#define GTEST_REMOVE_REFERENCE_(T) \
|
|
||||||
typename ::testing::internal::RemoveReference<T>::type
|
|
||||||
|
|
||||||
// Removes const from a type if it is a const type, otherwise leaves
|
|
||||||
// it unchanged. This is the same as tr1::remove_const, which is not
|
|
||||||
// widely available yet.
|
|
||||||
template <typename T>
|
|
||||||
struct RemoveConst { typedef T type; }; // NOLINT
|
|
||||||
template <typename T>
|
|
||||||
struct RemoveConst<const T> { typedef T type; }; // NOLINT
|
|
||||||
|
|
||||||
// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
|
|
||||||
// definition to fail to remove the const in 'const int[3]' and 'const
|
|
||||||
// char[3][4]'. The following specialization works around the bug.
|
|
||||||
template <typename T, size_t N>
|
|
||||||
struct RemoveConst<const T[N]> {
|
|
||||||
typedef typename RemoveConst<T>::type type[N];
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1400
|
|
||||||
// This is the only specialization that allows VC++ 7.1 to remove const in
|
|
||||||
// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC
|
|
||||||
// and thus needs to be conditionally compiled.
|
|
||||||
template <typename T, size_t N>
|
|
||||||
struct RemoveConst<T[N]> {
|
|
||||||
typedef typename RemoveConst<T>::type type[N];
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// A handy wrapper around RemoveConst that works when the argument
|
|
||||||
// T depends on template parameters.
|
|
||||||
#define GTEST_REMOVE_CONST_(T) \
|
|
||||||
typename ::testing::internal::RemoveConst<T>::type
|
|
||||||
|
|
||||||
// Turns const U&, U&, const U, and U all into U.
|
// Turns const U&, U&, const U, and U all into U.
|
||||||
#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
|
#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
|
||||||
GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
|
typename std::remove_const<typename std::remove_reference<T>::type>::type
|
||||||
|
|
||||||
// ImplicitlyConvertible<From, To>::value is a compile-time bool
|
|
||||||
// constant that's true iff type From can be implicitly converted to
|
|
||||||
// type To.
|
|
||||||
template <typename From, typename To>
|
|
||||||
class ImplicitlyConvertible {
|
|
||||||
private:
|
|
||||||
// We need the following helper functions only for their types.
|
|
||||||
// They have no implementations.
|
|
||||||
|
|
||||||
// MakeFrom() is an expression whose type is From. We cannot simply
|
|
||||||
// use From(), as the type From may not have a public default
|
|
||||||
// constructor.
|
|
||||||
static typename AddReference<From>::type MakeFrom();
|
|
||||||
|
|
||||||
// These two functions are overloaded. Given an expression
|
|
||||||
// Helper(x), the compiler will pick the first version if x can be
|
|
||||||
// implicitly converted to type To; otherwise it will pick the
|
|
||||||
// second version.
|
|
||||||
//
|
|
||||||
// The first version returns a value of size 1, and the second
|
|
||||||
// version returns a value of size 2. Therefore, by checking the
|
|
||||||
// size of Helper(x), which can be done at compile time, we can tell
|
|
||||||
// which version of Helper() is used, and hence whether x can be
|
|
||||||
// implicitly converted to type To.
|
|
||||||
static char Helper(To);
|
|
||||||
static char (&Helper(...))[2]; // NOLINT
|
|
||||||
|
|
||||||
// We have to put the 'public' section after the 'private' section,
|
|
||||||
// or MSVC refuses to compile the code.
|
|
||||||
public:
|
|
||||||
#if defined(__BORLANDC__)
|
|
||||||
// C++Builder cannot use member overload resolution during template
|
|
||||||
// instantiation. The simplest workaround is to use its C++0x type traits
|
|
||||||
// functions (C++Builder 2009 and above only).
|
|
||||||
static const bool value = __is_convertible(From, To);
|
|
||||||
#else
|
|
||||||
// MSVC warns about implicitly converting from double to int for
|
|
||||||
// possible loss of data, so we need to temporarily disable the
|
|
||||||
// warning.
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244)
|
|
||||||
static const bool value =
|
|
||||||
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
|
||||||
#endif // __BORLANDC__
|
|
||||||
};
|
|
||||||
template <typename From, typename To>
|
|
||||||
const bool ImplicitlyConvertible<From, To>::value;
|
|
||||||
|
|
||||||
// IsAProtocolMessage<T>::value is a compile-time bool constant that's
|
// IsAProtocolMessage<T>::value is a compile-time bool constant that's
|
||||||
// true iff T is type ProtocolMessage, proto2::Message, or a subclass
|
// true if and only if T is type proto2::Message or a subclass of it.
|
||||||
// of those.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsAProtocolMessage
|
struct IsAProtocolMessage
|
||||||
: public bool_constant<
|
: public bool_constant<
|
||||||
ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
|
std::is_convertible<const T*, const ::proto2::Message*>::value> {};
|
||||||
ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
|
|
||||||
};
|
|
||||||
|
|
||||||
// When the compiler sees expression IsContainerTest<C>(0), if C is an
|
// When the compiler sees expression IsContainerTest<C>(0), if C is an
|
||||||
// STL-style container class, the first overload of IsContainerTest
|
// STL-style container class, the first overload of IsContainerTest
|
||||||
|
@ -942,7 +883,6 @@ struct IsAProtocolMessage
|
||||||
// IsContainerTest(typename C::const_iterator*) and
|
// IsContainerTest(typename C::const_iterator*) and
|
||||||
// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
|
// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
|
||||||
typedef int IsContainer;
|
typedef int IsContainer;
|
||||||
#if GTEST_LANG_CXX11
|
|
||||||
template <class C,
|
template <class C,
|
||||||
class Iterator = decltype(::std::declval<const C&>().begin()),
|
class Iterator = decltype(::std::declval<const C&>().begin()),
|
||||||
class = decltype(::std::declval<const C&>().end()),
|
class = decltype(::std::declval<const C&>().end()),
|
||||||
|
@ -952,14 +892,6 @@ template <class C,
|
||||||
IsContainer IsContainerTest(int /* dummy */) {
|
IsContainer IsContainerTest(int /* dummy */) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
template <class C>
|
|
||||||
IsContainer IsContainerTest(int /* dummy */,
|
|
||||||
typename C::iterator* /* it */ = NULL,
|
|
||||||
typename C::const_iterator* /* const_it */ = NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif // GTEST_LANG_CXX11
|
|
||||||
|
|
||||||
typedef char IsNotContainer;
|
typedef char IsNotContainer;
|
||||||
template <class C>
|
template <class C>
|
||||||
|
@ -980,47 +912,30 @@ struct IsHashTable {
|
||||||
static char test(...);
|
static char test(...);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const bool value = sizeof(test<T>(0, 0)) == sizeof(int);
|
static const bool value = sizeof(test<T>(nullptr, nullptr)) == sizeof(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const bool IsHashTable<T>::value;
|
const bool IsHashTable<T>::value;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct VoidT {
|
|
||||||
typedef void value_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename = void>
|
|
||||||
struct HasValueType : false_type {};
|
|
||||||
template <typename T>
|
|
||||||
struct HasValueType<T, VoidT<typename T::value_type> > : true_type {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename C,
|
template <typename C,
|
||||||
bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer),
|
bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)>
|
||||||
bool = HasValueType<C>::value>
|
|
||||||
struct IsRecursiveContainerImpl;
|
struct IsRecursiveContainerImpl;
|
||||||
|
|
||||||
template <typename C, bool HV>
|
template <typename C>
|
||||||
struct IsRecursiveContainerImpl<C, false, HV> : public false_type {};
|
struct IsRecursiveContainerImpl<C, false> : public std::false_type {};
|
||||||
|
|
||||||
// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to
|
// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to
|
||||||
// obey the same inconsistencies as the IsContainerTest, namely check if
|
// obey the same inconsistencies as the IsContainerTest, namely check if
|
||||||
// something is a container is relying on only const_iterator in C++11 and
|
// something is a container is relying on only const_iterator in C++11 and
|
||||||
// is relying on both const_iterator and iterator otherwise
|
// is relying on both const_iterator and iterator otherwise
|
||||||
template <typename C>
|
template <typename C>
|
||||||
struct IsRecursiveContainerImpl<C, true, false> : public false_type {};
|
struct IsRecursiveContainerImpl<C, true> {
|
||||||
|
using value_type = decltype(*std::declval<typename C::const_iterator>());
|
||||||
template <typename C>
|
using type =
|
||||||
struct IsRecursiveContainerImpl<C, true, true> {
|
std::is_same<typename std::remove_const<
|
||||||
#if GTEST_LANG_CXX11
|
typename std::remove_reference<value_type>::type>::type,
|
||||||
typedef typename IteratorTraits<typename C::const_iterator>::value_type
|
C>;
|
||||||
value_type;
|
|
||||||
#else
|
|
||||||
typedef typename IteratorTraits<typename C::iterator>::value_type value_type;
|
|
||||||
#endif
|
|
||||||
typedef is_same<value_type, C> type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// IsRecursiveContainer<Type> is a unary compile-time predicate that
|
// IsRecursiveContainer<Type> is a unary compile-time predicate that
|
||||||
|
@ -1032,13 +947,6 @@ struct IsRecursiveContainerImpl<C, true, true> {
|
||||||
template <typename C>
|
template <typename C>
|
||||||
struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
|
struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
|
||||||
|
|
||||||
// EnableIf<condition>::type is void when 'Cond' is true, and
|
|
||||||
// undefined when 'Cond' is false. To use SFINAE to make a function
|
|
||||||
// overload only apply when a particular expression is true, add
|
|
||||||
// "typename EnableIf<expression>::type* = 0" as the last parameter.
|
|
||||||
template<bool> struct EnableIf;
|
|
||||||
template<> struct EnableIf<true> { typedef void type; }; // NOLINT
|
|
||||||
|
|
||||||
// Utilities for native arrays.
|
// Utilities for native arrays.
|
||||||
|
|
||||||
// ArrayEq() compares two k-dimensional native arrays using the
|
// ArrayEq() compares two k-dimensional native arrays using the
|
||||||
|
@ -1161,10 +1069,9 @@ class NativeArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
static_assert(!std::is_const<Element>::value, "Type must not be const");
|
||||||
kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper<
|
static_assert(!std::is_reference<Element>::value,
|
||||||
Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value
|
"Type must not be a reference");
|
||||||
};
|
|
||||||
|
|
||||||
// Initializes this object with a copy of the input.
|
// Initializes this object with a copy of the input.
|
||||||
void InitCopy(const Element* array, size_t a_size) {
|
void InitCopy(const Element* array, size_t a_size) {
|
||||||
|
@ -1189,6 +1096,139 @@ class NativeArray {
|
||||||
GTEST_DISALLOW_ASSIGN_(NativeArray);
|
GTEST_DISALLOW_ASSIGN_(NativeArray);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Backport of std::index_sequence.
|
||||||
|
template <size_t... Is>
|
||||||
|
struct IndexSequence {
|
||||||
|
using type = IndexSequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Double the IndexSequence, and one if plus_one is true.
|
||||||
|
template <bool plus_one, typename T, size_t sizeofT>
|
||||||
|
struct DoubleSequence;
|
||||||
|
template <size_t... I, size_t sizeofT>
|
||||||
|
struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
|
||||||
|
using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
|
||||||
|
};
|
||||||
|
template <size_t... I, size_t sizeofT>
|
||||||
|
struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
|
||||||
|
using type = IndexSequence<I..., (sizeofT + I)...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
N / 2>::type {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MakeIndexSequence<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 <typename T, size_t I>
|
||||||
|
struct ElemFromListImpl<T, I, I> {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the Nth element from T...
|
||||||
|
// It uses O(1) instantiation depth.
|
||||||
|
template <size_t N, typename I, typename... T>
|
||||||
|
struct ElemFromList;
|
||||||
|
|
||||||
|
template <size_t N, size_t... I, typename... T>
|
||||||
|
struct ElemFromList<N, IndexSequence<I...>, T...>
|
||||||
|
: ElemFromListImpl<T, N, I>... {};
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
class FlatTuple;
|
||||||
|
|
||||||
|
template <typename Derived, size_t I>
|
||||||
|
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;
|
||||||
|
FlatTupleElemBase() = default;
|
||||||
|
explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
|
||||||
|
value_type value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Derived, typename Idx>
|
||||||
|
struct FlatTupleBase;
|
||||||
|
|
||||||
|
template <size_t... Idx, typename... T>
|
||||||
|
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))... {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// instantiation depth of more than 10x the number of elements in some
|
||||||
|
// implementations.
|
||||||
|
// FlatTuple and ElemFromList are not recursive and have a fixed depth
|
||||||
|
// regardless of T...
|
||||||
|
// MakeIndexSequence, on the other hand, it is recursive but with an
|
||||||
|
// instantiation depth of O(ln(N)).
|
||||||
|
template <typename... T>
|
||||||
|
class FlatTuple
|
||||||
|
: private FlatTupleBase<FlatTuple<T...>,
|
||||||
|
typename MakeIndexSequence<sizeof...(T)>::type> {
|
||||||
|
using Indices = typename FlatTuple::FlatTupleBase::Indices;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FlatTuple() = default;
|
||||||
|
explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Utility functions to be called with static_assert to induce deprecation
|
||||||
|
// warnings.
|
||||||
|
GTEST_INTERNAL_DEPRECATED(
|
||||||
|
"INSTANTIATE_TEST_CASE_P is deprecated, please use "
|
||||||
|
"INSTANTIATE_TEST_SUITE_P")
|
||||||
|
constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
|
||||||
|
|
||||||
|
GTEST_INTERNAL_DEPRECATED(
|
||||||
|
"TYPED_TEST_CASE_P is deprecated, please use "
|
||||||
|
"TYPED_TEST_SUITE_P")
|
||||||
|
constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
|
||||||
|
|
||||||
|
GTEST_INTERNAL_DEPRECATED(
|
||||||
|
"TYPED_TEST_CASE is deprecated, please use "
|
||||||
|
"TYPED_TEST_SUITE")
|
||||||
|
constexpr bool TypedTestCaseIsDeprecated() { return true; }
|
||||||
|
|
||||||
|
GTEST_INTERNAL_DEPRECATED(
|
||||||
|
"REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
|
||||||
|
"REGISTER_TYPED_TEST_SUITE_P")
|
||||||
|
constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
|
||||||
|
|
||||||
|
GTEST_INTERNAL_DEPRECATED(
|
||||||
|
"INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
|
||||||
|
"INSTANTIATE_TYPED_TEST_SUITE_P")
|
||||||
|
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
|
@ -1208,7 +1248,10 @@ class NativeArray {
|
||||||
#define GTEST_SUCCESS_(message) \
|
#define GTEST_SUCCESS_(message) \
|
||||||
GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
|
GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
|
||||||
|
|
||||||
// Suppress MSVC warning 4702 (unreachable code) for the code following
|
#define GTEST_SKIP_(message) \
|
||||||
|
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip)
|
||||||
|
|
||||||
|
// Suppress MSVC warning 4072 (unreachable code) for the code following
|
||||||
// statement if it returns or throws (or doesn't return or throw in some
|
// statement if it returns or throws (or doesn't return or throw in some
|
||||||
// situations).
|
// situations).
|
||||||
#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
|
#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
|
||||||
|
@ -1300,31 +1343,38 @@ class NativeArray {
|
||||||
" Actual: it does.")
|
" Actual: it does.")
|
||||||
|
|
||||||
// Expands to the name of the class that implements the given test.
|
// Expands to the name of the class that implements the given test.
|
||||||
#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
|
#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
|
||||||
test_case_name##_##test_name##_Test
|
test_suite_name##_##test_name##_Test
|
||||||
|
|
||||||
// Helper macro for defining tests.
|
// Helper macro for defining tests.
|
||||||
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
|
#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \
|
||||||
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
|
static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \
|
||||||
public:\
|
"test_suite_name must not be empty"); \
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
|
static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \
|
||||||
private:\
|
"test_name must not be empty"); \
|
||||||
virtual void TestBody();\
|
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
|
||||||
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
|
: public parent_class { \
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
|
public: \
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
|
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \
|
||||||
};\
|
\
|
||||||
\
|
private: \
|
||||||
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
|
virtual void TestBody(); \
|
||||||
::test_info_ =\
|
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \
|
||||||
::testing::internal::MakeAndRegisterTestInfo(\
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||||
#test_case_name, #test_name, NULL, NULL, \
|
test_name)); \
|
||||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
}; \
|
||||||
(parent_id), \
|
\
|
||||||
parent_class::SetUpTestCase, \
|
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||||
parent_class::TearDownTestCase, \
|
test_name)::test_info_ = \
|
||||||
new ::testing::internal::TestFactoryImpl<\
|
::testing::internal::MakeAndRegisterTestInfo( \
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
|
#test_suite_name, #test_name, nullptr, nullptr, \
|
||||||
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
|
::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \
|
||||||
|
::testing::internal::SuiteApiResolver< \
|
||||||
|
parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \
|
||||||
|
::testing::internal::SuiteApiResolver< \
|
||||||
|
parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \
|
||||||
|
new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \
|
||||||
|
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 // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||||
|
|
|
@ -1,243 +0,0 @@
|
||||||
// Copyright 2003 Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// A "smart" pointer type with reference tracking. Every pointer to a
|
|
||||||
// particular object is kept on a circular linked list. When the last pointer
|
|
||||||
// to an object is destroyed or reassigned, the object is deleted.
|
|
||||||
//
|
|
||||||
// Used properly, this deletes the object when the last reference goes away.
|
|
||||||
// There are several caveats:
|
|
||||||
// - Like all reference counting schemes, cycles lead to leaks.
|
|
||||||
// - Each smart pointer is actually two pointers (8 bytes instead of 4).
|
|
||||||
// - Every time a pointer is assigned, the entire list of pointers to that
|
|
||||||
// object is traversed. This class is therefore NOT SUITABLE when there
|
|
||||||
// will often be more than two or three pointers to a particular object.
|
|
||||||
// - References are only tracked as long as linked_ptr<> objects are copied.
|
|
||||||
// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
|
|
||||||
// will happen (double deletion).
|
|
||||||
//
|
|
||||||
// A good use of this class is storing object references in STL containers.
|
|
||||||
// You can safely put linked_ptr<> in a vector<>.
|
|
||||||
// Other uses may not be as good.
|
|
||||||
//
|
|
||||||
// Note: If you use an incomplete type with linked_ptr<>, the class
|
|
||||||
// *containing* linked_ptr<> must have a constructor and destructor (even
|
|
||||||
// if they do nothing!).
|
|
||||||
//
|
|
||||||
// Bill Gibbons suggested we use something like this.
|
|
||||||
//
|
|
||||||
// Thread Safety:
|
|
||||||
// Unlike other linked_ptr implementations, in this implementation
|
|
||||||
// a linked_ptr object is thread-safe in the sense that:
|
|
||||||
// - it's safe to copy linked_ptr objects concurrently,
|
|
||||||
// - it's safe to copy *from* a linked_ptr and read its underlying
|
|
||||||
// raw pointer (e.g. via get()) concurrently, and
|
|
||||||
// - it's safe to write to two linked_ptrs that point to the same
|
|
||||||
// shared object concurrently.
|
|
||||||
// FIXME: rename this to safe_linked_ptr to avoid
|
|
||||||
// confusion with normal linked_ptr.
|
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// Protects copying of all linked_ptr objects.
|
|
||||||
GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
|
||||||
|
|
||||||
// This is used internally by all instances of linked_ptr<>. It needs to be
|
|
||||||
// a non-template class because different types of linked_ptr<> can refer to
|
|
||||||
// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
|
|
||||||
// So, it needs to be possible for different types of linked_ptr to participate
|
|
||||||
// in the same circular linked list, so we need a single class type here.
|
|
||||||
//
|
|
||||||
// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>.
|
|
||||||
class linked_ptr_internal {
|
|
||||||
public:
|
|
||||||
// Create a new circle that includes only this instance.
|
|
||||||
void join_new() {
|
|
||||||
next_ = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Many linked_ptr operations may change p.link_ for some linked_ptr
|
|
||||||
// variable p in the same circle as this object. Therefore we need
|
|
||||||
// to prevent two such operations from occurring concurrently.
|
|
||||||
//
|
|
||||||
// Note that different types of linked_ptr objects can coexist in a
|
|
||||||
// circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
|
|
||||||
// linked_ptr<Derived2>). Therefore we must use a single mutex to
|
|
||||||
// protect all linked_ptr objects. This can create serious
|
|
||||||
// contention in production code, but is acceptable in a testing
|
|
||||||
// framework.
|
|
||||||
|
|
||||||
// Join an existing circle.
|
|
||||||
void join(linked_ptr_internal const* ptr)
|
|
||||||
GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
|
|
||||||
MutexLock lock(&g_linked_ptr_mutex);
|
|
||||||
|
|
||||||
linked_ptr_internal const* p = ptr;
|
|
||||||
while (p->next_ != ptr) {
|
|
||||||
assert(p->next_ != this &&
|
|
||||||
"Trying to join() a linked ring we are already in. "
|
|
||||||
"Is GMock thread safety enabled?");
|
|
||||||
p = p->next_;
|
|
||||||
}
|
|
||||||
p->next_ = this;
|
|
||||||
next_ = ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leave whatever circle we're part of. Returns true if we were the
|
|
||||||
// last member of the circle. Once this is done, you can join() another.
|
|
||||||
bool depart()
|
|
||||||
GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
|
|
||||||
MutexLock lock(&g_linked_ptr_mutex);
|
|
||||||
|
|
||||||
if (next_ == this) return true;
|
|
||||||
linked_ptr_internal const* p = next_;
|
|
||||||
while (p->next_ != this) {
|
|
||||||
assert(p->next_ != next_ &&
|
|
||||||
"Trying to depart() a linked ring we are not in. "
|
|
||||||
"Is GMock thread safety enabled?");
|
|
||||||
p = p->next_;
|
|
||||||
}
|
|
||||||
p->next_ = next_;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable linked_ptr_internal const* next_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class linked_ptr {
|
|
||||||
public:
|
|
||||||
typedef T element_type;
|
|
||||||
|
|
||||||
// Take over ownership of a raw pointer. This should happen as soon as
|
|
||||||
// possible after the object is created.
|
|
||||||
explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
|
|
||||||
~linked_ptr() { depart(); }
|
|
||||||
|
|
||||||
// Copy an existing linked_ptr<>, adding ourselves to the list of references.
|
|
||||||
template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
|
|
||||||
linked_ptr(linked_ptr const& ptr) { // NOLINT
|
|
||||||
assert(&ptr != this);
|
|
||||||
copy(&ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assignment releases the old value and acquires the new.
|
|
||||||
template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
|
|
||||||
depart();
|
|
||||||
copy(&ptr);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
linked_ptr& operator=(linked_ptr const& ptr) {
|
|
||||||
if (&ptr != this) {
|
|
||||||
depart();
|
|
||||||
copy(&ptr);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smart pointer members.
|
|
||||||
void reset(T* ptr = NULL) {
|
|
||||||
depart();
|
|
||||||
capture(ptr);
|
|
||||||
}
|
|
||||||
T* get() const { return value_; }
|
|
||||||
T* operator->() const { return value_; }
|
|
||||||
T& operator*() const { return *value_; }
|
|
||||||
|
|
||||||
bool operator==(T* p) const { return value_ == p; }
|
|
||||||
bool operator!=(T* p) const { return value_ != p; }
|
|
||||||
template <typename U>
|
|
||||||
bool operator==(linked_ptr<U> const& ptr) const {
|
|
||||||
return value_ == ptr.get();
|
|
||||||
}
|
|
||||||
template <typename U>
|
|
||||||
bool operator!=(linked_ptr<U> const& ptr) const {
|
|
||||||
return value_ != ptr.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename U>
|
|
||||||
friend class linked_ptr;
|
|
||||||
|
|
||||||
T* value_;
|
|
||||||
linked_ptr_internal link_;
|
|
||||||
|
|
||||||
void depart() {
|
|
||||||
if (link_.depart()) delete value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void capture(T* ptr) {
|
|
||||||
value_ = ptr;
|
|
||||||
link_.join_new();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U> void copy(linked_ptr<U> const* ptr) {
|
|
||||||
value_ = ptr->get();
|
|
||||||
if (value_)
|
|
||||||
link_.join(&ptr->link_);
|
|
||||||
else
|
|
||||||
link_.join_new();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> inline
|
|
||||||
bool operator==(T* ptr, const linked_ptr<T>& x) {
|
|
||||||
return ptr == x.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> inline
|
|
||||||
bool operator!=(T* ptr, const linked_ptr<T>& x) {
|
|
||||||
return ptr != x.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// A function to convert T* into linked_ptr<T>
|
|
||||||
// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
|
|
||||||
// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
|
|
||||||
template <typename T>
|
|
||||||
linked_ptr<T> make_linked_ptr(T* ptr) {
|
|
||||||
return linked_ptr<T>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,282 +0,0 @@
|
||||||
$$ -*- mode: c++; -*-
|
|
||||||
$var n = 50 $$ Maximum length of Values arguments we want to support.
|
|
||||||
$var maxtuple = 10 $$ Maximum number of Combine arguments 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 and function utilities for implementing parameterized tests.
|
|
||||||
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
|
||||||
//
|
|
||||||
// Currently Google Test supports at most $n arguments in Values,
|
|
||||||
// and at most $maxtuple arguments in Combine. Please contact
|
|
||||||
// googletestframework@googlegroups.com if you need more.
|
|
||||||
// Please note that the number of arguments to Combine is limited
|
|
||||||
// by the maximum arity of the implementation of tuple which is
|
|
||||||
// currently set at $maxtuple.
|
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
|
||||||
|
|
||||||
#include "gtest/internal/gtest-param-util.h"
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
|
|
||||||
// Forward declarations of ValuesIn(), which is implemented in
|
|
||||||
// include/gtest/gtest-param-test.h.
|
|
||||||
template <typename ForwardIterator>
|
|
||||||
internal::ParamGenerator<
|
|
||||||
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
|
|
||||||
ValuesIn(ForwardIterator begin, ForwardIterator end);
|
|
||||||
|
|
||||||
template <typename T, size_t N>
|
|
||||||
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
|
|
||||||
|
|
||||||
template <class Container>
|
|
||||||
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
|
||||||
const Container& container);
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// Used in the Values() function to provide polymorphic capabilities.
|
|
||||||
$range i 1..n
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
|
|
||||||
template <$for j, [[typename T$j]]>
|
|
||||||
class ValueArray$i {
|
|
||||||
public:
|
|
||||||
$if i==1 [[explicit ]]ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
operator ParamGenerator<T>() const {
|
|
||||||
const T array[] = {$for j, [[static_cast<T>(v$(j)_)]]};
|
|
||||||
return ValuesIn(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueArray$i(const ValueArray$i& other) : $for j, [[v$(j)_(other.v$(j)_)]] {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// No implementation - assignment is unsupported.
|
|
||||||
void operator=(const ValueArray$i& other);
|
|
||||||
|
|
||||||
$for j [[
|
|
||||||
|
|
||||||
const T$j v$(j)_;
|
|
||||||
]]
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
# if GTEST_HAS_COMBINE
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
|
||||||
//
|
|
||||||
// Generates values from the Cartesian product of values produced
|
|
||||||
// by the argument generators.
|
|
||||||
//
|
|
||||||
$range i 2..maxtuple
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
$range k 2..i
|
|
||||||
|
|
||||||
template <$for j, [[typename T$j]]>
|
|
||||||
class CartesianProductGenerator$i
|
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > {
|
|
||||||
public:
|
|
||||||
typedef ::testing::tuple<$for j, [[T$j]]> ParamType;
|
|
||||||
|
|
||||||
CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
|
|
||||||
: $for j, [[g$(j)_(g$j)]] {}
|
|
||||||
virtual ~CartesianProductGenerator$i() {}
|
|
||||||
|
|
||||||
virtual ParamIteratorInterface<ParamType>* Begin() const {
|
|
||||||
return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]);
|
|
||||||
}
|
|
||||||
virtual ParamIteratorInterface<ParamType>* End() const {
|
|
||||||
return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Iterator : public ParamIteratorInterface<ParamType> {
|
|
||||||
public:
|
|
||||||
Iterator(const ParamGeneratorInterface<ParamType>* base, $for j, [[
|
|
||||||
|
|
||||||
const ParamGenerator<T$j>& g$j,
|
|
||||||
const typename ParamGenerator<T$j>::iterator& current$(j)]])
|
|
||||||
: base_(base),
|
|
||||||
$for j, [[
|
|
||||||
|
|
||||||
begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j)
|
|
||||||
]] {
|
|
||||||
ComputeCurrentValue();
|
|
||||||
}
|
|
||||||
virtual ~Iterator() {}
|
|
||||||
|
|
||||||
virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
|
|
||||||
return base_;
|
|
||||||
}
|
|
||||||
// Advance should not be called on beyond-of-range iterators
|
|
||||||
// so no component iterators must be beyond end of range, either.
|
|
||||||
virtual void Advance() {
|
|
||||||
assert(!AtEnd());
|
|
||||||
++current$(i)_;
|
|
||||||
|
|
||||||
$for k [[
|
|
||||||
if (current$(i+2-k)_ == end$(i+2-k)_) {
|
|
||||||
current$(i+2-k)_ = begin$(i+2-k)_;
|
|
||||||
++current$(i+2-k-1)_;
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
ComputeCurrentValue();
|
|
||||||
}
|
|
||||||
virtual ParamIteratorInterface<ParamType>* Clone() const {
|
|
||||||
return new Iterator(*this);
|
|
||||||
}
|
|
||||||
virtual const ParamType* Current() const { return current_value_.get(); }
|
|
||||||
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
|
|
||||||
// Having the same base generator guarantees that the other
|
|
||||||
// iterator is of the same type and we can downcast.
|
|
||||||
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
|
||||||
<< "The program attempted to compare iterators "
|
|
||||||
<< "from different generators." << std::endl;
|
|
||||||
const Iterator* typed_other =
|
|
||||||
CheckedDowncastToActualType<const Iterator>(&other);
|
|
||||||
// We must report iterators equal if they both point beyond their
|
|
||||||
// respective ranges. That can happen in a variety of fashions,
|
|
||||||
// so we have to consult AtEnd().
|
|
||||||
return (AtEnd() && typed_other->AtEnd()) ||
|
|
||||||
($for j && [[
|
|
||||||
|
|
||||||
current$(j)_ == typed_other->current$(j)_
|
|
||||||
]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Iterator(const Iterator& other)
|
|
||||||
: base_(other.base_), $for j, [[
|
|
||||||
|
|
||||||
begin$(j)_(other.begin$(j)_),
|
|
||||||
end$(j)_(other.end$(j)_),
|
|
||||||
current$(j)_(other.current$(j)_)
|
|
||||||
]] {
|
|
||||||
ComputeCurrentValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComputeCurrentValue() {
|
|
||||||
if (!AtEnd())
|
|
||||||
current_value_.reset(new ParamType($for j, [[*current$(j)_]]));
|
|
||||||
}
|
|
||||||
bool AtEnd() const {
|
|
||||||
// We must report iterator past the end of the range when either of the
|
|
||||||
// component iterators has reached the end of its range.
|
|
||||||
return
|
|
||||||
$for j || [[
|
|
||||||
|
|
||||||
current$(j)_ == end$(j)_
|
|
||||||
]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// No implementation - assignment is unsupported.
|
|
||||||
void operator=(const Iterator& other);
|
|
||||||
|
|
||||||
const ParamGeneratorInterface<ParamType>* const base_;
|
|
||||||
// begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
|
|
||||||
// current[i]_ is the actual traversing iterator.
|
|
||||||
$for j [[
|
|
||||||
|
|
||||||
const typename ParamGenerator<T$j>::iterator begin$(j)_;
|
|
||||||
const typename ParamGenerator<T$j>::iterator end$(j)_;
|
|
||||||
typename ParamGenerator<T$j>::iterator current$(j)_;
|
|
||||||
]]
|
|
||||||
|
|
||||||
linked_ptr<ParamType> current_value_;
|
|
||||||
}; // class CartesianProductGenerator$i::Iterator
|
|
||||||
|
|
||||||
// No implementation - assignment is unsupported.
|
|
||||||
void operator=(const CartesianProductGenerator$i& other);
|
|
||||||
|
|
||||||
|
|
||||||
$for j [[
|
|
||||||
const ParamGenerator<T$j> g$(j)_;
|
|
||||||
|
|
||||||
]]
|
|
||||||
}; // class CartesianProductGenerator$i
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
|
||||||
//
|
|
||||||
// Helper classes providing Combine() with polymorphic features. They allow
|
|
||||||
// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
|
|
||||||
// convertible to U.
|
|
||||||
//
|
|
||||||
$range i 2..maxtuple
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
|
|
||||||
template <$for j, [[class Generator$j]]>
|
|
||||||
class CartesianProductHolder$i {
|
|
||||||
public:
|
|
||||||
CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
|
|
||||||
: $for j, [[g$(j)_(g$j)]] {}
|
|
||||||
template <$for j, [[typename T$j]]>
|
|
||||||
operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const {
|
|
||||||
return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >(
|
|
||||||
new CartesianProductGenerator$i<$for j, [[T$j]]>(
|
|
||||||
$for j,[[
|
|
||||||
|
|
||||||
static_cast<ParamGenerator<T$j> >(g$(j)_)
|
|
||||||
]]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// No implementation - assignment is unsupported.
|
|
||||||
void operator=(const CartesianProductHolder$i& other);
|
|
||||||
|
|
||||||
|
|
||||||
$for j [[
|
|
||||||
const Generator$j g$(j)_;
|
|
||||||
|
|
||||||
]]
|
|
||||||
}; // class CartesianProductHolder$i
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
# endif // GTEST_HAS_COMBINE
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
|
|
@ -37,18 +37,19 @@
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
#include "gtest/internal/gtest-linked_ptr.h"
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
#include "gtest/gtest-printers.h"
|
#include "gtest/gtest-printers.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// Input to a parameterized test name generator, describing a test parameter.
|
// Input to a parameterized test name generator, describing a test parameter.
|
||||||
// Consists of the parameter value and the integer parameter index.
|
// Consists of the parameter value and the integer parameter index.
|
||||||
template <class ParamType>
|
template <class ParamType>
|
||||||
|
@ -72,13 +73,14 @@ struct PrintToStringParamName {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
// Utility Functions
|
||||||
|
|
||||||
// Outputs a message explaining invalid registration of different
|
// Outputs a message explaining invalid registration of different
|
||||||
// fixture class for the same test case. This may happen when
|
// fixture class for the same test suite. This may happen when
|
||||||
// TEST_P macro is used to define two tests with the same name
|
// TEST_P macro is used to define two tests with the same name
|
||||||
// but in different namespaces.
|
// but in different namespaces.
|
||||||
GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
|
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
|
||||||
CodeLocation code_location);
|
CodeLocation code_location);
|
||||||
|
|
||||||
template <typename> class ParamGeneratorInterface;
|
template <typename> class ParamGeneratorInterface;
|
||||||
template <typename> class ParamGenerator;
|
template <typename> class ParamGenerator;
|
||||||
|
@ -153,7 +155,7 @@ class ParamIterator {
|
||||||
private:
|
private:
|
||||||
friend class ParamGenerator<T>;
|
friend class ParamGenerator<T>;
|
||||||
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
|
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
|
||||||
scoped_ptr<ParamIteratorInterface<T> > impl_;
|
std::unique_ptr<ParamIteratorInterface<T> > impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ParamGeneratorInterface<T> is the binary interface to access generators
|
// ParamGeneratorInterface<T> is the binary interface to access generators
|
||||||
|
@ -192,7 +194,7 @@ class ParamGenerator {
|
||||||
iterator end() const { return iterator(impl_->End()); }
|
iterator end() const { return iterator(impl_->End()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
linked_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
|
// Generates values from a range of two comparable values. Can be used to
|
||||||
|
@ -205,12 +207,12 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
RangeGenerator(T begin, T end, IncrementT step)
|
RangeGenerator(T begin, T end, IncrementT step)
|
||||||
: begin_(begin), end_(end),
|
: begin_(begin), end_(end),
|
||||||
step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
|
step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
|
||||||
virtual ~RangeGenerator() {}
|
~RangeGenerator() override {}
|
||||||
|
|
||||||
virtual ParamIteratorInterface<T>* Begin() const {
|
ParamIteratorInterface<T>* Begin() const override {
|
||||||
return new Iterator(this, begin_, 0, step_);
|
return new Iterator(this, begin_, 0, step_);
|
||||||
}
|
}
|
||||||
virtual ParamIteratorInterface<T>* End() const {
|
ParamIteratorInterface<T>* End() const override {
|
||||||
return new Iterator(this, end_, end_index_, step_);
|
return new Iterator(this, end_, end_index_, step_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,20 +222,20 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
|
Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
|
||||||
IncrementT step)
|
IncrementT step)
|
||||||
: base_(base), value_(value), index_(index), step_(step) {}
|
: base_(base), value_(value), index_(index), step_(step) {}
|
||||||
virtual ~Iterator() {}
|
~Iterator() override {}
|
||||||
|
|
||||||
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
|
const ParamGeneratorInterface<T>* BaseGenerator() const override {
|
||||||
return base_;
|
return base_;
|
||||||
}
|
}
|
||||||
virtual void Advance() {
|
void Advance() override {
|
||||||
value_ = static_cast<T>(value_ + step_);
|
value_ = static_cast<T>(value_ + step_);
|
||||||
index_++;
|
index_++;
|
||||||
}
|
}
|
||||||
virtual ParamIteratorInterface<T>* Clone() const {
|
ParamIteratorInterface<T>* Clone() const override {
|
||||||
return new Iterator(*this);
|
return new Iterator(*this);
|
||||||
}
|
}
|
||||||
virtual const T* Current() const { return &value_; }
|
const T* Current() const override { return &value_; }
|
||||||
virtual bool Equals(const ParamIteratorInterface<T>& other) const {
|
bool Equals(const ParamIteratorInterface<T>& other) const override {
|
||||||
// Having the same base generator guarantees that the other
|
// Having the same base generator guarantees that the other
|
||||||
// iterator is of the same type and we can downcast.
|
// iterator is of the same type and we can downcast.
|
||||||
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
||||||
|
@ -290,12 +292,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
template <typename ForwardIterator>
|
template <typename ForwardIterator>
|
||||||
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
|
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
|
||||||
: container_(begin, end) {}
|
: container_(begin, end) {}
|
||||||
virtual ~ValuesInIteratorRangeGenerator() {}
|
~ValuesInIteratorRangeGenerator() override {}
|
||||||
|
|
||||||
virtual ParamIteratorInterface<T>* Begin() const {
|
ParamIteratorInterface<T>* Begin() const override {
|
||||||
return new Iterator(this, container_.begin());
|
return new Iterator(this, container_.begin());
|
||||||
}
|
}
|
||||||
virtual ParamIteratorInterface<T>* End() const {
|
ParamIteratorInterface<T>* End() const override {
|
||||||
return new Iterator(this, container_.end());
|
return new Iterator(this, container_.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,16 +309,16 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
Iterator(const ParamGeneratorInterface<T>* base,
|
Iterator(const ParamGeneratorInterface<T>* base,
|
||||||
typename ContainerType::const_iterator iterator)
|
typename ContainerType::const_iterator iterator)
|
||||||
: base_(base), iterator_(iterator) {}
|
: base_(base), iterator_(iterator) {}
|
||||||
virtual ~Iterator() {}
|
~Iterator() override {}
|
||||||
|
|
||||||
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
|
const ParamGeneratorInterface<T>* BaseGenerator() const override {
|
||||||
return base_;
|
return base_;
|
||||||
}
|
}
|
||||||
virtual void Advance() {
|
void Advance() override {
|
||||||
++iterator_;
|
++iterator_;
|
||||||
value_.reset();
|
value_.reset();
|
||||||
}
|
}
|
||||||
virtual ParamIteratorInterface<T>* Clone() const {
|
ParamIteratorInterface<T>* Clone() const override {
|
||||||
return new Iterator(*this);
|
return new Iterator(*this);
|
||||||
}
|
}
|
||||||
// We need to use cached value referenced by iterator_ because *iterator_
|
// We need to use cached value referenced by iterator_ because *iterator_
|
||||||
|
@ -326,12 +328,11 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
// can advance iterator_ beyond the end of the range, and we cannot
|
// can advance iterator_ beyond the end of the range, and we cannot
|
||||||
// detect that fact. The client code, on the other hand, is
|
// detect that fact. The client code, on the other hand, is
|
||||||
// responsible for not calling Current() on an out-of-range iterator.
|
// responsible for not calling Current() on an out-of-range iterator.
|
||||||
virtual const T* Current() const {
|
const T* Current() const override {
|
||||||
if (value_.get() == NULL)
|
if (value_.get() == nullptr) value_.reset(new T(*iterator_));
|
||||||
value_.reset(new T(*iterator_));
|
|
||||||
return value_.get();
|
return value_.get();
|
||||||
}
|
}
|
||||||
virtual bool Equals(const ParamIteratorInterface<T>& other) const {
|
bool Equals(const ParamIteratorInterface<T>& other) const override {
|
||||||
// Having the same base generator guarantees that the other
|
// Having the same base generator guarantees that the other
|
||||||
// iterator is of the same type and we can downcast.
|
// iterator is of the same type and we can downcast.
|
||||||
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
||||||
|
@ -354,9 +355,9 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
// A cached value of *iterator_. We keep it here to allow access by
|
// A cached value of *iterator_. We keep it here to allow access by
|
||||||
// pointer in the wrapping iterator's operator->().
|
// pointer in the wrapping iterator's operator->().
|
||||||
// value_ needs to be mutable to be accessed in Current().
|
// value_ needs to be mutable to be accessed in Current().
|
||||||
// Use of scoped_ptr helps manage cached value's lifetime,
|
// Use of std::unique_ptr helps manage cached value's lifetime,
|
||||||
// which is bound by the lifespan of the iterator itself.
|
// which is bound by the lifespan of the iterator itself.
|
||||||
mutable scoped_ptr<const T> value_;
|
mutable std::unique_ptr<const T> value_;
|
||||||
}; // class ValuesInIteratorRangeGenerator::Iterator
|
}; // class ValuesInIteratorRangeGenerator::Iterator
|
||||||
|
|
||||||
// No implementation - assignment is unsupported.
|
// No implementation - assignment is unsupported.
|
||||||
|
@ -376,25 +377,12 @@ std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
|
||||||
return name_stream.GetString();
|
return name_stream.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
template <typename T = int>
|
||||||
//
|
void TestNotEmpty() {
|
||||||
// Parameterized test name overload helpers, which help the
|
static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
|
||||||
// INSTANTIATE_TEST_CASE_P macro choose between the default parameterized
|
|
||||||
// test name generator and user param name generator.
|
|
||||||
template <class ParamType, class ParamNameGenFunctor>
|
|
||||||
ParamNameGenFunctor GetParamNameGen(ParamNameGenFunctor func) {
|
|
||||||
return func;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ParamType>
|
|
||||||
struct ParamNameGenFunc {
|
|
||||||
typedef std::string Type(const TestParamInfo<ParamType>&);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class ParamType>
|
|
||||||
typename ParamNameGenFunc<ParamType>::Type *GetParamNameGen() {
|
|
||||||
return DefaultParamName;
|
|
||||||
}
|
}
|
||||||
|
template <typename T = int>
|
||||||
|
void TestNotEmpty(const T&) {}
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
|
@ -406,7 +394,7 @@ class ParameterizedTestFactory : public TestFactoryBase {
|
||||||
typedef typename TestClass::ParamType ParamType;
|
typedef typename TestClass::ParamType ParamType;
|
||||||
explicit ParameterizedTestFactory(ParamType parameter) :
|
explicit ParameterizedTestFactory(ParamType parameter) :
|
||||||
parameter_(parameter) {}
|
parameter_(parameter) {}
|
||||||
virtual Test* CreateTest() {
|
Test* CreateTest() override {
|
||||||
TestClass::SetParam(¶meter_);
|
TestClass::SetParam(¶meter_);
|
||||||
return new TestClass();
|
return new TestClass();
|
||||||
}
|
}
|
||||||
|
@ -434,19 +422,19 @@ class TestMetaFactoryBase {
|
||||||
// TestMetaFactory creates test factories for passing into
|
// TestMetaFactory creates test factories for passing into
|
||||||
// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
|
// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
|
||||||
// ownership of test factory pointer, same factory object cannot be passed
|
// ownership of test factory pointer, same factory object cannot be passed
|
||||||
// into that method twice. But ParameterizedTestCaseInfo is going to call
|
// into that method twice. But ParameterizedTestSuiteInfo is going to call
|
||||||
// it for each Test/Parameter value combination. Thus it needs meta factory
|
// it for each Test/Parameter value combination. Thus it needs meta factory
|
||||||
// creator class.
|
// creator class.
|
||||||
template <class TestCase>
|
template <class TestSuite>
|
||||||
class TestMetaFactory
|
class TestMetaFactory
|
||||||
: public TestMetaFactoryBase<typename TestCase::ParamType> {
|
: public TestMetaFactoryBase<typename TestSuite::ParamType> {
|
||||||
public:
|
public:
|
||||||
typedef typename TestCase::ParamType ParamType;
|
using ParamType = typename TestSuite::ParamType;
|
||||||
|
|
||||||
TestMetaFactory() {}
|
TestMetaFactory() {}
|
||||||
|
|
||||||
virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
|
TestFactoryBase* CreateTestFactory(ParamType parameter) override {
|
||||||
return new ParameterizedTestFactory<TestCase>(parameter);
|
return new ParameterizedTestFactory<TestSuite>(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -455,93 +443,93 @@ class TestMetaFactory
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// ParameterizedTestCaseInfoBase is a generic interface
|
// ParameterizedTestSuiteInfoBase is a generic interface
|
||||||
// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
|
// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase
|
||||||
// accumulates test information provided by TEST_P macro invocations
|
// accumulates test information provided by TEST_P macro invocations
|
||||||
// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
|
// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations
|
||||||
// and uses that information to register all resulting test instances
|
// and uses that information to register all resulting test instances
|
||||||
// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
|
// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
|
||||||
// a collection of pointers to the ParameterizedTestCaseInfo objects
|
// a collection of pointers to the ParameterizedTestSuiteInfo objects
|
||||||
// and calls RegisterTests() on each of them when asked.
|
// and calls RegisterTests() on each of them when asked.
|
||||||
class ParameterizedTestCaseInfoBase {
|
class ParameterizedTestSuiteInfoBase {
|
||||||
public:
|
public:
|
||||||
virtual ~ParameterizedTestCaseInfoBase() {}
|
virtual ~ParameterizedTestSuiteInfoBase() {}
|
||||||
|
|
||||||
// Base part of test case name for display purposes.
|
// Base part of test suite name for display purposes.
|
||||||
virtual const std::string& GetTestCaseName() const = 0;
|
virtual const std::string& GetTestSuiteName() const = 0;
|
||||||
// Test case id to verify identity.
|
// Test case id to verify identity.
|
||||||
virtual TypeId GetTestCaseTypeId() const = 0;
|
virtual TypeId GetTestSuiteTypeId() const = 0;
|
||||||
// UnitTest class invokes this method to register tests in this
|
// UnitTest class invokes this method to register tests in this
|
||||||
// test case right before running them in RUN_ALL_TESTS macro.
|
// test suite right before running them in RUN_ALL_TESTS macro.
|
||||||
// This method should not be called more then once on any single
|
// This method should not be called more than once on any single
|
||||||
// instance of a ParameterizedTestCaseInfoBase derived class.
|
// instance of a ParameterizedTestSuiteInfoBase derived class.
|
||||||
virtual void RegisterTests() = 0;
|
virtual void RegisterTests() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ParameterizedTestCaseInfoBase() {}
|
ParameterizedTestSuiteInfoBase() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
|
||||||
};
|
};
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
|
// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
|
||||||
// macro invocations for a particular test case and generators
|
// macro invocations for a particular test suite and generators
|
||||||
// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
|
// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that
|
||||||
// test case. It registers tests with all values generated by all
|
// test suite. It registers tests with all values generated by all
|
||||||
// generators when asked.
|
// generators when asked.
|
||||||
template <class TestCase>
|
template <class TestSuite>
|
||||||
class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||||
public:
|
public:
|
||||||
// ParamType and GeneratorCreationFunc are private types but are required
|
// ParamType and GeneratorCreationFunc are private types but are required
|
||||||
// for declarations of public methods AddTestPattern() and
|
// for declarations of public methods AddTestPattern() and
|
||||||
// AddTestCaseInstantiation().
|
// AddTestSuiteInstantiation().
|
||||||
typedef typename TestCase::ParamType ParamType;
|
using ParamType = typename TestSuite::ParamType;
|
||||||
// A function that returns an instance of appropriate generator type.
|
// A function that returns an instance of appropriate generator type.
|
||||||
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
|
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
|
||||||
typedef typename ParamNameGenFunc<ParamType>::Type ParamNameGeneratorFunc;
|
using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
|
||||||
|
|
||||||
explicit ParameterizedTestCaseInfo(
|
explicit ParameterizedTestSuiteInfo(const char* name,
|
||||||
const char* name, CodeLocation code_location)
|
CodeLocation code_location)
|
||||||
: test_case_name_(name), code_location_(code_location) {}
|
: test_suite_name_(name), code_location_(code_location) {}
|
||||||
|
|
||||||
// Test case base name for display purposes.
|
// Test case base name for display purposes.
|
||||||
virtual const std::string& GetTestCaseName() const { return test_case_name_; }
|
const std::string& GetTestSuiteName() const override {
|
||||||
|
return test_suite_name_;
|
||||||
|
}
|
||||||
// Test case id to verify identity.
|
// Test case id to verify identity.
|
||||||
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
|
TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
|
||||||
// TEST_P macro uses AddTestPattern() to record information
|
// TEST_P macro uses AddTestPattern() to record information
|
||||||
// about a single test in a LocalTestInfo structure.
|
// about a single test in a LocalTestInfo structure.
|
||||||
// test_case_name is the base name of the test case (without invocation
|
// test_suite_name is the base name of the test suite (without invocation
|
||||||
// prefix). test_base_name is the name of an individual test without
|
// prefix). test_base_name is the name of an individual test without
|
||||||
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
|
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
|
||||||
// test case base name and DoBar is test base name.
|
// test suite base name and DoBar is test base name.
|
||||||
void AddTestPattern(const char* test_case_name,
|
void AddTestPattern(const char* test_suite_name, const char* test_base_name,
|
||||||
const char* test_base_name,
|
|
||||||
TestMetaFactoryBase<ParamType>* meta_factory) {
|
TestMetaFactoryBase<ParamType>* meta_factory) {
|
||||||
tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
|
tests_.push_back(std::shared_ptr<TestInfo>(
|
||||||
test_base_name,
|
new TestInfo(test_suite_name, test_base_name, meta_factory)));
|
||||||
meta_factory)));
|
|
||||||
}
|
}
|
||||||
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
|
// INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
|
||||||
// about a generator.
|
// about a generator.
|
||||||
int AddTestCaseInstantiation(const std::string& instantiation_name,
|
int AddTestSuiteInstantiation(const std::string& instantiation_name,
|
||||||
GeneratorCreationFunc* func,
|
GeneratorCreationFunc* func,
|
||||||
ParamNameGeneratorFunc* name_func,
|
ParamNameGeneratorFunc* name_func,
|
||||||
const char* file, int line) {
|
const char* file, int line) {
|
||||||
instantiations_.push_back(
|
instantiations_.push_back(
|
||||||
InstantiationInfo(instantiation_name, func, name_func, file, line));
|
InstantiationInfo(instantiation_name, func, name_func, file, line));
|
||||||
return 0; // Return value used only to run this method in namespace scope.
|
return 0; // Return value used only to run this method in namespace scope.
|
||||||
}
|
}
|
||||||
// UnitTest class invokes this method to register tests in this test case
|
// UnitTest class invokes this method to register tests in this test suite
|
||||||
// test cases right before running tests in RUN_ALL_TESTS macro.
|
// test suites right before running tests in RUN_ALL_TESTS macro.
|
||||||
// This method should not be called more then once on any single
|
// This method should not be called more than once on any single
|
||||||
// instance of a ParameterizedTestCaseInfoBase derived class.
|
// instance of a ParameterizedTestSuiteInfoBase derived class.
|
||||||
// UnitTest has a guard to prevent from calling this method more then once.
|
// UnitTest has a guard to prevent from calling this method more than once.
|
||||||
virtual void RegisterTests() {
|
void RegisterTests() override {
|
||||||
for (typename TestInfoContainer::iterator test_it = tests_.begin();
|
for (typename TestInfoContainer::iterator test_it = tests_.begin();
|
||||||
test_it != tests_.end(); ++test_it) {
|
test_it != tests_.end(); ++test_it) {
|
||||||
linked_ptr<TestInfo> test_info = *test_it;
|
std::shared_ptr<TestInfo> test_info = *test_it;
|
||||||
for (typename InstantiationContainer::iterator gen_it =
|
for (typename InstantiationContainer::iterator gen_it =
|
||||||
instantiations_.begin(); gen_it != instantiations_.end();
|
instantiations_.begin(); gen_it != instantiations_.end();
|
||||||
++gen_it) {
|
++gen_it) {
|
||||||
|
@ -551,10 +539,10 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||||
const char* file = gen_it->file;
|
const char* file = gen_it->file;
|
||||||
int line = gen_it->line;
|
int line = gen_it->line;
|
||||||
|
|
||||||
std::string test_case_name;
|
std::string test_suite_name;
|
||||||
if ( !instantiation_name.empty() )
|
if ( !instantiation_name.empty() )
|
||||||
test_case_name = instantiation_name + "/";
|
test_suite_name = instantiation_name + "/";
|
||||||
test_case_name += test_info->test_case_base_name;
|
test_suite_name += test_info->test_suite_base_name;
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
std::set<std::string> test_param_names;
|
std::set<std::string> test_param_names;
|
||||||
|
@ -577,39 +565,39 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||||
|
|
||||||
test_param_names.insert(param_name);
|
test_param_names.insert(param_name);
|
||||||
|
|
||||||
test_name_stream << test_info->test_base_name << "/" << param_name;
|
if (!test_info->test_base_name.empty()) {
|
||||||
|
test_name_stream << test_info->test_base_name << "/";
|
||||||
|
}
|
||||||
|
test_name_stream << param_name;
|
||||||
MakeAndRegisterTestInfo(
|
MakeAndRegisterTestInfo(
|
||||||
test_case_name.c_str(),
|
test_suite_name.c_str(), test_name_stream.GetString().c_str(),
|
||||||
test_name_stream.GetString().c_str(),
|
nullptr, // No type parameter.
|
||||||
NULL, // No type parameter.
|
PrintToString(*param_it).c_str(), code_location_,
|
||||||
PrintToString(*param_it).c_str(),
|
GetTestSuiteTypeId(),
|
||||||
code_location_,
|
SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
|
||||||
GetTestCaseTypeId(),
|
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
|
||||||
TestCase::SetUpTestCase,
|
|
||||||
TestCase::TearDownTestCase,
|
|
||||||
test_info->test_meta_factory->CreateTestFactory(*param_it));
|
test_info->test_meta_factory->CreateTestFactory(*param_it));
|
||||||
} // for param_it
|
} // for param_it
|
||||||
} // for gen_it
|
} // for gen_it
|
||||||
} // for test_it
|
} // for test_it
|
||||||
} // RegisterTests
|
} // RegisterTests
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// LocalTestInfo structure keeps information about a single test registered
|
// LocalTestInfo structure keeps information about a single test registered
|
||||||
// with TEST_P macro.
|
// with TEST_P macro.
|
||||||
struct TestInfo {
|
struct TestInfo {
|
||||||
TestInfo(const char* a_test_case_base_name,
|
TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
|
||||||
const char* a_test_base_name,
|
TestMetaFactoryBase<ParamType>* a_test_meta_factory)
|
||||||
TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
|
: test_suite_base_name(a_test_suite_base_name),
|
||||||
test_case_base_name(a_test_case_base_name),
|
test_base_name(a_test_base_name),
|
||||||
test_base_name(a_test_base_name),
|
test_meta_factory(a_test_meta_factory) {}
|
||||||
test_meta_factory(a_test_meta_factory) {}
|
|
||||||
|
|
||||||
const std::string test_case_base_name;
|
const std::string test_suite_base_name;
|
||||||
const std::string test_base_name;
|
const std::string test_base_name;
|
||||||
const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
|
const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
|
||||||
};
|
};
|
||||||
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
|
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
|
||||||
// Records data received from INSTANTIATE_TEST_CASE_P macros:
|
// Records data received from INSTANTIATE_TEST_SUITE_P macros:
|
||||||
// <Instantiation name, Sequence generator creation function,
|
// <Instantiation name, Sequence generator creation function,
|
||||||
// Name generator function, Source file, Source line>
|
// Name generator function, Source file, Source line>
|
||||||
struct InstantiationInfo {
|
struct InstantiationInfo {
|
||||||
|
@ -646,76 +634,247 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string test_case_name_;
|
const std::string test_suite_name_;
|
||||||
CodeLocation code_location_;
|
CodeLocation code_location_;
|
||||||
TestInfoContainer tests_;
|
TestInfoContainer tests_;
|
||||||
InstantiationContainer instantiations_;
|
InstantiationContainer instantiations_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo);
|
||||||
}; // class ParameterizedTestCaseInfo
|
}; // class ParameterizedTestSuiteInfo
|
||||||
|
|
||||||
|
// Legacy API is deprecated but still available
|
||||||
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
template <class TestCase>
|
||||||
|
using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
|
||||||
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
|
// ParameterizedTestSuiteRegistry contains a map of
|
||||||
// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
|
// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
|
||||||
// macros use it to locate their corresponding ParameterizedTestCaseInfo
|
// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
|
||||||
// descriptors.
|
// ParameterizedTestSuiteInfo descriptors.
|
||||||
class ParameterizedTestCaseRegistry {
|
class ParameterizedTestSuiteRegistry {
|
||||||
public:
|
public:
|
||||||
ParameterizedTestCaseRegistry() {}
|
ParameterizedTestSuiteRegistry() {}
|
||||||
~ParameterizedTestCaseRegistry() {
|
~ParameterizedTestSuiteRegistry() {
|
||||||
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
|
for (auto& test_suite_info : test_suite_infos_) {
|
||||||
it != test_case_infos_.end(); ++it) {
|
delete test_suite_info;
|
||||||
delete *it;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Looks up or creates and returns a structure containing information about
|
// Looks up or creates and returns a structure containing information about
|
||||||
// tests and instantiations of a particular test case.
|
// tests and instantiations of a particular test suite.
|
||||||
template <class TestCase>
|
template <class TestSuite>
|
||||||
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
|
ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
|
||||||
const char* test_case_name,
|
const char* test_suite_name, CodeLocation code_location) {
|
||||||
CodeLocation code_location) {
|
ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
|
||||||
ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
|
for (auto& test_suite_info : test_suite_infos_) {
|
||||||
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
|
if (test_suite_info->GetTestSuiteName() == test_suite_name) {
|
||||||
it != test_case_infos_.end(); ++it) {
|
if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
|
||||||
if ((*it)->GetTestCaseName() == test_case_name) {
|
|
||||||
if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
|
|
||||||
// Complain about incorrect usage of Google Test facilities
|
// Complain about incorrect usage of Google Test facilities
|
||||||
// and terminate the program since we cannot guaranty correct
|
// and terminate the program since we cannot guaranty correct
|
||||||
// test case setup and tear-down in this case.
|
// test suite setup and tear-down in this case.
|
||||||
ReportInvalidTestCaseType(test_case_name, code_location);
|
ReportInvalidTestSuiteType(test_suite_name, code_location);
|
||||||
posix::Abort();
|
posix::Abort();
|
||||||
} else {
|
} else {
|
||||||
// At this point we are sure that the object we found is of the same
|
// At this point we are sure that the object we found is of the same
|
||||||
// type we are looking for, so we downcast it to that type
|
// type we are looking for, so we downcast it to that type
|
||||||
// without further checks.
|
// without further checks.
|
||||||
typed_test_info = CheckedDowncastToActualType<
|
typed_test_info = CheckedDowncastToActualType<
|
||||||
ParameterizedTestCaseInfo<TestCase> >(*it);
|
ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typed_test_info == NULL) {
|
if (typed_test_info == nullptr) {
|
||||||
typed_test_info = new ParameterizedTestCaseInfo<TestCase>(
|
typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
|
||||||
test_case_name, code_location);
|
test_suite_name, code_location);
|
||||||
test_case_infos_.push_back(typed_test_info);
|
test_suite_infos_.push_back(typed_test_info);
|
||||||
}
|
}
|
||||||
return typed_test_info;
|
return typed_test_info;
|
||||||
}
|
}
|
||||||
void RegisterTests() {
|
void RegisterTests() {
|
||||||
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
|
for (auto& test_suite_info : test_suite_infos_) {
|
||||||
it != test_case_infos_.end(); ++it) {
|
test_suite_info->RegisterTests();
|
||||||
(*it)->RegisterTests();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Legacy API is deprecated but still available
|
||||||
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
template <class TestCase>
|
||||||
|
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
|
||||||
|
const char* test_case_name, CodeLocation code_location) {
|
||||||
|
return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
|
private:
|
||||||
|
using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
|
||||||
|
|
||||||
|
TestSuiteInfoContainer test_suite_infos_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Forward declarations of ValuesIn(), which is implemented in
|
||||||
|
// include/gtest/gtest-param-test.h.
|
||||||
|
template <class Container>
|
||||||
|
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
||||||
|
const Container& container);
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
// Used in the Values() function to provide polymorphic capabilities.
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
class ValueArray {
|
||||||
|
public:
|
||||||
|
ValueArray(Ts... v) : v_{std::move(v)...} {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
operator ParamGenerator<T>() const { // NOLINT
|
||||||
|
return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
|
template <typename T, size_t... I>
|
||||||
|
std::vector<T> MakeVector(IndexSequence<I...>) const {
|
||||||
|
return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
|
||||||
|
}
|
||||||
|
|
||||||
TestCaseInfoContainer test_case_infos_;
|
FlatTuple<Ts...> v_;
|
||||||
|
};
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
|
template <typename... T>
|
||||||
|
class CartesianProductGenerator
|
||||||
|
: public ParamGeneratorInterface<::std::tuple<T...>> {
|
||||||
|
public:
|
||||||
|
typedef ::std::tuple<T...> ParamType;
|
||||||
|
|
||||||
|
CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g)
|
||||||
|
: generators_(g) {}
|
||||||
|
~CartesianProductGenerator() override {}
|
||||||
|
|
||||||
|
ParamIteratorInterface<ParamType>* Begin() const override {
|
||||||
|
return new Iterator(this, generators_, false);
|
||||||
|
}
|
||||||
|
ParamIteratorInterface<ParamType>* End() const override {
|
||||||
|
return new Iterator(this, generators_, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <class I>
|
||||||
|
class IteratorImpl;
|
||||||
|
template <size_t... I>
|
||||||
|
class IteratorImpl<IndexSequence<I...>>
|
||||||
|
: public ParamIteratorInterface<ParamType> {
|
||||||
|
public:
|
||||||
|
IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
|
||||||
|
const std::tuple<ParamGenerator<T>...>& generators, bool is_end)
|
||||||
|
: base_(base),
|
||||||
|
begin_(std::get<I>(generators).begin()...),
|
||||||
|
end_(std::get<I>(generators).end()...),
|
||||||
|
current_(is_end ? end_ : begin_) {
|
||||||
|
ComputeCurrentValue();
|
||||||
|
}
|
||||||
|
~IteratorImpl() override {}
|
||||||
|
|
||||||
|
const ParamGeneratorInterface<ParamType>* BaseGenerator() const override {
|
||||||
|
return base_;
|
||||||
|
}
|
||||||
|
// Advance should not be called on beyond-of-range iterators
|
||||||
|
// so no component iterators must be beyond end of range, either.
|
||||||
|
void Advance() override {
|
||||||
|
assert(!AtEnd());
|
||||||
|
// Advance the last iterator.
|
||||||
|
++std::get<sizeof...(T) - 1>(current_);
|
||||||
|
// if that reaches end, propagate that up.
|
||||||
|
AdvanceIfEnd<sizeof...(T) - 1>();
|
||||||
|
ComputeCurrentValue();
|
||||||
|
}
|
||||||
|
ParamIteratorInterface<ParamType>* Clone() const override {
|
||||||
|
return new IteratorImpl(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ParamType* Current() const override { return current_value_.get(); }
|
||||||
|
|
||||||
|
bool Equals(const ParamIteratorInterface<ParamType>& other) const override {
|
||||||
|
// Having the same base generator guarantees that the other
|
||||||
|
// iterator is of the same type and we can downcast.
|
||||||
|
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
||||||
|
<< "The program attempted to compare iterators "
|
||||||
|
<< "from different generators." << std::endl;
|
||||||
|
const IteratorImpl* typed_other =
|
||||||
|
CheckedDowncastToActualType<const IteratorImpl>(&other);
|
||||||
|
|
||||||
|
// We must report iterators equal if they both point beyond their
|
||||||
|
// respective ranges. That can happen in a variety of fashions,
|
||||||
|
// so we have to consult AtEnd().
|
||||||
|
if (AtEnd() && typed_other->AtEnd()) return true;
|
||||||
|
|
||||||
|
bool same = true;
|
||||||
|
bool dummy[] = {
|
||||||
|
(same = same && std::get<I>(current_) ==
|
||||||
|
std::get<I>(typed_other->current_))...};
|
||||||
|
(void)dummy;
|
||||||
|
return same;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <size_t ThisI>
|
||||||
|
void AdvanceIfEnd() {
|
||||||
|
if (std::get<ThisI>(current_) != std::get<ThisI>(end_)) return;
|
||||||
|
|
||||||
|
bool last = ThisI == 0;
|
||||||
|
if (last) {
|
||||||
|
// We are done. Nothing else to propagate.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t NextI = ThisI - (ThisI != 0);
|
||||||
|
std::get<ThisI>(current_) = std::get<ThisI>(begin_);
|
||||||
|
++std::get<NextI>(current_);
|
||||||
|
AdvanceIfEnd<NextI>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeCurrentValue() {
|
||||||
|
if (!AtEnd())
|
||||||
|
current_value_ = std::make_shared<ParamType>(*std::get<I>(current_)...);
|
||||||
|
}
|
||||||
|
bool AtEnd() const {
|
||||||
|
bool at_end = false;
|
||||||
|
bool dummy[] = {
|
||||||
|
(at_end = at_end || std::get<I>(current_) == std::get<I>(end_))...};
|
||||||
|
(void)dummy;
|
||||||
|
return at_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ParamGeneratorInterface<ParamType>* const base_;
|
||||||
|
std::tuple<typename ParamGenerator<T>::iterator...> begin_;
|
||||||
|
std::tuple<typename ParamGenerator<T>::iterator...> end_;
|
||||||
|
std::tuple<typename ParamGenerator<T>::iterator...> current_;
|
||||||
|
std::shared_ptr<ParamType> current_value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;
|
||||||
|
|
||||||
|
std::tuple<ParamGenerator<T>...> generators_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class... Gen>
|
||||||
|
class CartesianProductHolder {
|
||||||
|
public:
|
||||||
|
CartesianProductHolder(const Gen&... g) : generators_(g...) {}
|
||||||
|
template <typename... T>
|
||||||
|
operator ParamGenerator<::std::tuple<T...>>() const {
|
||||||
|
return ParamGenerator<::std::tuple<T...>>(
|
||||||
|
new CartesianProductGenerator<T...>(generators_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::tuple<Gen...> generators_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
|
@ -38,14 +38,13 @@
|
||||||
// Determines the platform on which Google Test is compiled.
|
// Determines the platform on which Google Test is compiled.
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
# define GTEST_OS_CYGWIN 1
|
# define GTEST_OS_CYGWIN 1
|
||||||
#elif defined __SYMBIAN32__
|
# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
# define GTEST_OS_SYMBIAN 1
|
# define GTEST_OS_WINDOWS_MINGW 1
|
||||||
|
# define GTEST_OS_WINDOWS 1
|
||||||
#elif defined _WIN32
|
#elif defined _WIN32
|
||||||
# define GTEST_OS_WINDOWS 1
|
# define GTEST_OS_WINDOWS 1
|
||||||
# ifdef _WIN32_WCE
|
# ifdef _WIN32_WCE
|
||||||
# define GTEST_OS_WINDOWS_MOBILE 1
|
# define GTEST_OS_WINDOWS_MOBILE 1
|
||||||
# elif defined(__MINGW__) || defined(__MINGW32__)
|
|
||||||
# define GTEST_OS_WINDOWS_MINGW 1
|
|
||||||
# elif defined(WINAPI_FAMILY)
|
# elif defined(WINAPI_FAMILY)
|
||||||
# include <winapifamily.h>
|
# include <winapifamily.h>
|
||||||
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
|
@ -65,15 +64,21 @@
|
||||||
# else
|
# else
|
||||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
# define GTEST_OS_WINDOWS_DESKTOP 1
|
||||||
# endif // _WIN32_WCE
|
# endif // _WIN32_WCE
|
||||||
|
#elif defined __OS2__
|
||||||
|
# define GTEST_OS_OS2 1
|
||||||
#elif defined __APPLE__
|
#elif defined __APPLE__
|
||||||
# define GTEST_OS_MAC 1
|
# define GTEST_OS_MAC 1
|
||||||
# if TARGET_OS_IPHONE
|
# if TARGET_OS_IPHONE
|
||||||
# define GTEST_OS_IOS 1
|
# define GTEST_OS_IOS 1
|
||||||
# endif
|
# endif
|
||||||
|
#elif defined __DragonFly__
|
||||||
|
# define GTEST_OS_DRAGONFLY 1
|
||||||
#elif defined __FreeBSD__
|
#elif defined __FreeBSD__
|
||||||
# define GTEST_OS_FREEBSD 1
|
# define GTEST_OS_FREEBSD 1
|
||||||
#elif defined __Fuchsia__
|
#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
|
||||||
#elif defined __linux__
|
#elif defined __linux__
|
||||||
# define GTEST_OS_LINUX 1
|
# define GTEST_OS_LINUX 1
|
||||||
# if defined __ANDROID__
|
# if defined __ANDROID__
|
||||||
|
@ -95,6 +100,8 @@
|
||||||
# define GTEST_OS_OPENBSD 1
|
# define GTEST_OS_OPENBSD 1
|
||||||
#elif defined __QNX__
|
#elif defined __QNX__
|
||||||
# define GTEST_OS_QNX 1
|
# define GTEST_OS_QNX 1
|
||||||
|
#elif defined(__HAIKU__)
|
||||||
|
#define GTEST_OS_HAIKU 1
|
||||||
#endif // __CYGWIN__
|
#endif // __CYGWIN__
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -94,7 +94,8 @@ class GTEST_API_ String {
|
||||||
static const char* Utf16ToAnsi(LPCWSTR utf16_str);
|
static const char* Utf16ToAnsi(LPCWSTR utf16_str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compares two C strings. Returns true iff they have the same content.
|
// Compares two C strings. Returns true if and only if they have the same
|
||||||
|
// content.
|
||||||
//
|
//
|
||||||
// Unlike strcmp(), this function can handle NULL argument(s). A
|
// Unlike strcmp(), this function can handle NULL argument(s). A
|
||||||
// NULL C string is considered different to any non-NULL C string,
|
// NULL C string is considered different to any non-NULL C string,
|
||||||
|
@ -107,16 +108,16 @@ class GTEST_API_ String {
|
||||||
// returned.
|
// returned.
|
||||||
static std::string ShowWideCString(const wchar_t* wide_c_str);
|
static std::string ShowWideCString(const wchar_t* wide_c_str);
|
||||||
|
|
||||||
// Compares two wide C strings. Returns true iff they have the same
|
// Compares two wide C strings. Returns true if and only if they have the
|
||||||
// content.
|
// same content.
|
||||||
//
|
//
|
||||||
// Unlike wcscmp(), this function can handle NULL argument(s). A
|
// Unlike wcscmp(), this function can handle NULL argument(s). A
|
||||||
// NULL C string is considered different to any non-NULL C string,
|
// NULL C string is considered different to any non-NULL C string,
|
||||||
// including the empty string.
|
// including the empty string.
|
||||||
static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
|
static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
|
||||||
|
|
||||||
// Compares two C strings, ignoring case. Returns true iff they
|
// Compares two C strings, ignoring case. Returns true if and only if
|
||||||
// have the same content.
|
// they have the same content.
|
||||||
//
|
//
|
||||||
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
||||||
// A NULL C string is considered different to any non-NULL C string,
|
// A NULL C string is considered different to any non-NULL C string,
|
||||||
|
@ -124,8 +125,8 @@ class GTEST_API_ String {
|
||||||
static bool CaseInsensitiveCStringEquals(const char* lhs,
|
static bool CaseInsensitiveCStringEquals(const char* lhs,
|
||||||
const char* rhs);
|
const char* rhs);
|
||||||
|
|
||||||
// Compares two wide C strings, ignoring case. Returns true iff they
|
// Compares two wide C strings, ignoring case. Returns true if and only if
|
||||||
// have the same content.
|
// they have the same content.
|
||||||
//
|
//
|
||||||
// Unlike wcscasecmp(), this function can handle NULL argument(s).
|
// Unlike wcscasecmp(), this function can handle NULL argument(s).
|
||||||
// A NULL C string is considered different to any non-NULL wide C string,
|
// A NULL C string is considered different to any non-NULL wide C string,
|
||||||
|
@ -139,8 +140,8 @@ class GTEST_API_ String {
|
||||||
static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
|
static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
|
||||||
const wchar_t* rhs);
|
const wchar_t* rhs);
|
||||||
|
|
||||||
// Returns true iff the given string ends with the given suffix, ignoring
|
// Returns true if and only if the given string ends with the given suffix,
|
||||||
// case. Any string is considered to end with an empty suffix.
|
// ignoring case. Any string is considered to end with an empty suffix.
|
||||||
static bool EndsWithCaseInsensitive(
|
static bool EndsWithCaseInsensitive(
|
||||||
const std::string& str, const std::string& suffix);
|
const std::string& str, const std::string& suffix);
|
||||||
|
|
||||||
|
@ -150,6 +151,9 @@ class GTEST_API_ String {
|
||||||
// Formats an int value as "%X".
|
// Formats an int value as "%X".
|
||||||
static std::string FormatHexInt(int value);
|
static std::string FormatHexInt(int value);
|
||||||
|
|
||||||
|
// Formats an int value as "%X".
|
||||||
|
static std::string FormatHexUInt32(UInt32 value);
|
||||||
|
|
||||||
// Formats a byte as "%02X".
|
// Formats a byte as "%02X".
|
||||||
static std::string FormatByte(unsigned char value);
|
static std::string FormatByte(unsigned char value);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,348 +0,0 @@
|
||||||
$$ -*- mode: c++; -*-
|
|
||||||
$var n = 10 $$ Maximum number of tuple fields we want to support.
|
|
||||||
$$ This meta comment fixes auto-indentation in Emacs. }}
|
|
||||||
// Copyright 2009 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.
|
|
||||||
|
|
||||||
|
|
||||||
// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
|
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
|
||||||
|
|
||||||
#include <utility> // For ::std::pair.
|
|
||||||
|
|
||||||
// The compiler used in Symbian has a bug that prevents us from declaring the
|
|
||||||
// tuple template as a friend (it complains that tuple is redefined). This
|
|
||||||
// bypasses the bug by declaring the members that should otherwise be
|
|
||||||
// private as public.
|
|
||||||
// Sun Studio versions < 12 also have the above bug.
|
|
||||||
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
|
|
||||||
# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
|
|
||||||
#else
|
|
||||||
# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
|
|
||||||
template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
|
|
||||||
private:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict
|
|
||||||
// with our own definitions. Therefore using our own tuple does not work on
|
|
||||||
// those compilers.
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */
|
|
||||||
# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \
|
|
||||||
GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
$range i 0..n-1
|
|
||||||
$range j 0..n
|
|
||||||
$range k 1..n
|
|
||||||
// GTEST_n_TUPLE_(T) is the type of an n-tuple.
|
|
||||||
#define GTEST_0_TUPLE_(T) tuple<>
|
|
||||||
|
|
||||||
$for k [[
|
|
||||||
$range m 0..k-1
|
|
||||||
$range m2 k..n-1
|
|
||||||
#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
|
|
||||||
|
|
||||||
$for j [[
|
|
||||||
$range m 0..j-1
|
|
||||||
#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// In theory, defining stuff in the ::std namespace is undefined
|
|
||||||
// behavior. We can do this as we are playing the role of a standard
|
|
||||||
// library vendor.
|
|
||||||
namespace std {
|
|
||||||
namespace tr1 {
|
|
||||||
|
|
||||||
template <$for i, [[typename T$i = void]]>
|
|
||||||
class tuple;
|
|
||||||
|
|
||||||
// Anything in namespace gtest_internal is Google Test's INTERNAL
|
|
||||||
// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
|
|
||||||
namespace gtest_internal {
|
|
||||||
|
|
||||||
// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
|
|
||||||
template <typename T>
|
|
||||||
struct ByRef { typedef const T& type; }; // NOLINT
|
|
||||||
template <typename T>
|
|
||||||
struct ByRef<T&> { typedef T& type; }; // NOLINT
|
|
||||||
|
|
||||||
// A handy wrapper for ByRef.
|
|
||||||
#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
|
|
||||||
|
|
||||||
// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
|
|
||||||
// is the same as tr1::add_reference<T>::type.
|
|
||||||
template <typename T>
|
|
||||||
struct AddRef { typedef T& type; }; // NOLINT
|
|
||||||
template <typename T>
|
|
||||||
struct AddRef<T&> { typedef T& type; }; // NOLINT
|
|
||||||
|
|
||||||
// A handy wrapper for AddRef.
|
|
||||||
#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
|
|
||||||
|
|
||||||
// A helper for implementing get<k>().
|
|
||||||
template <int k> class Get;
|
|
||||||
|
|
||||||
// A helper for implementing tuple_element<k, T>. kIndexValid is true
|
|
||||||
// iff k < the number of fields in tuple type T.
|
|
||||||
template <bool kIndexValid, int kIndex, class Tuple>
|
|
||||||
struct TupleElement;
|
|
||||||
|
|
||||||
|
|
||||||
$for i [[
|
|
||||||
template <GTEST_$(n)_TYPENAMES_(T)>
|
|
||||||
struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > {
|
|
||||||
typedef T$i type;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
} // namespace gtest_internal
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class tuple<> {
|
|
||||||
public:
|
|
||||||
tuple() {}
|
|
||||||
tuple(const tuple& /* t */) {}
|
|
||||||
tuple& operator=(const tuple& /* t */) { return *this; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
$for k [[
|
|
||||||
$range m 0..k-1
|
|
||||||
template <GTEST_$(k)_TYPENAMES_(T)>
|
|
||||||
class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
|
|
||||||
public:
|
|
||||||
template <int k> friend class gtest_internal::Get;
|
|
||||||
|
|
||||||
tuple() : $for m, [[f$(m)_()]] {}
|
|
||||||
|
|
||||||
explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
|
|
||||||
$for m, [[f$(m)_(f$m)]] {}
|
|
||||||
|
|
||||||
tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
|
|
||||||
|
|
||||||
template <GTEST_$(k)_TYPENAMES_(U)>
|
|
||||||
tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
|
|
||||||
|
|
||||||
$if k == 2 [[
|
|
||||||
template <typename U0, typename U1>
|
|
||||||
tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
|
||||||
|
|
||||||
template <GTEST_$(k)_TYPENAMES_(U)>
|
|
||||||
tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
|
|
||||||
return CopyFrom(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
$if k == 2 [[
|
|
||||||
template <typename U0, typename U1>
|
|
||||||
tuple& operator=(const ::std::pair<U0, U1>& p) {
|
|
||||||
f0_ = p.first;
|
|
||||||
f1_ = p.second;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
|
||||||
|
|
||||||
template <GTEST_$(k)_TYPENAMES_(U)>
|
|
||||||
tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
|
|
||||||
|
|
||||||
$for m [[
|
|
||||||
f$(m)_ = t.f$(m)_;
|
|
||||||
|
|
||||||
]]
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$for m [[
|
|
||||||
T$m f$(m)_;
|
|
||||||
|
|
||||||
]]
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
// 6.1.3.2 Tuple creation functions.
|
|
||||||
|
|
||||||
// Known limitations: we don't support passing an
|
|
||||||
// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
|
|
||||||
// implement tie().
|
|
||||||
|
|
||||||
inline tuple<> make_tuple() { return tuple<>(); }
|
|
||||||
|
|
||||||
$for k [[
|
|
||||||
$range m 0..k-1
|
|
||||||
|
|
||||||
template <GTEST_$(k)_TYPENAMES_(T)>
|
|
||||||
inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
|
|
||||||
return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// 6.1.3.3 Tuple helper classes.
|
|
||||||
|
|
||||||
template <typename Tuple> struct tuple_size;
|
|
||||||
|
|
||||||
|
|
||||||
$for j [[
|
|
||||||
template <GTEST_$(j)_TYPENAMES_(T)>
|
|
||||||
struct tuple_size<GTEST_$(j)_TUPLE_(T) > {
|
|
||||||
static const int value = $j;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
template <int k, class Tuple>
|
|
||||||
struct tuple_element {
|
|
||||||
typedef typename gtest_internal::TupleElement<
|
|
||||||
k < (tuple_size<Tuple>::value), k, Tuple>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
|
|
||||||
|
|
||||||
// 6.1.3.4 Element access.
|
|
||||||
|
|
||||||
namespace gtest_internal {
|
|
||||||
|
|
||||||
|
|
||||||
$for i [[
|
|
||||||
template <>
|
|
||||||
class Get<$i> {
|
|
||||||
public:
|
|
||||||
template <class Tuple>
|
|
||||||
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
|
|
||||||
Field(Tuple& t) { return t.f$(i)_; } // NOLINT
|
|
||||||
|
|
||||||
template <class Tuple>
|
|
||||||
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
|
|
||||||
ConstField(const Tuple& t) { return t.f$(i)_; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
} // namespace gtest_internal
|
|
||||||
|
|
||||||
template <int k, GTEST_$(n)_TYPENAMES_(T)>
|
|
||||||
GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
|
|
||||||
get(GTEST_$(n)_TUPLE_(T)& t) {
|
|
||||||
return gtest_internal::Get<k>::Field(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int k, GTEST_$(n)_TYPENAMES_(T)>
|
|
||||||
GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
|
|
||||||
get(const GTEST_$(n)_TUPLE_(T)& t) {
|
|
||||||
return gtest_internal::Get<k>::ConstField(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6.1.3.5 Relational operators
|
|
||||||
|
|
||||||
// We only implement == and !=, as we don't have a need for the rest yet.
|
|
||||||
|
|
||||||
namespace gtest_internal {
|
|
||||||
|
|
||||||
// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
|
|
||||||
// first k fields of t1 equals the first k fields of t2.
|
|
||||||
// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
|
|
||||||
// k1 != k2.
|
|
||||||
template <int kSize1, int kSize2>
|
|
||||||
struct SameSizeTuplePrefixComparator;
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct SameSizeTuplePrefixComparator<0, 0> {
|
|
||||||
template <class Tuple1, class Tuple2>
|
|
||||||
static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int k>
|
|
||||||
struct SameSizeTuplePrefixComparator<k, k> {
|
|
||||||
template <class Tuple1, class Tuple2>
|
|
||||||
static bool Eq(const Tuple1& t1, const Tuple2& t2) {
|
|
||||||
return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
|
|
||||||
::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace gtest_internal
|
|
||||||
|
|
||||||
template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
|
|
||||||
inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
|
|
||||||
const GTEST_$(n)_TUPLE_(U)& u) {
|
|
||||||
return gtest_internal::SameSizeTuplePrefixComparator<
|
|
||||||
tuple_size<GTEST_$(n)_TUPLE_(T) >::value,
|
|
||||||
tuple_size<GTEST_$(n)_TUPLE_(U) >::value>::Eq(t, u);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
|
|
||||||
inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
|
|
||||||
const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
|
|
||||||
|
|
||||||
// 6.1.4 Pairs.
|
|
||||||
// Unimplemented.
|
|
||||||
|
|
||||||
} // namespace tr1
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
|
|
||||||
$for j [[
|
|
||||||
#undef GTEST_$(j)_TUPLE_
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
|
|
||||||
$for j [[
|
|
||||||
#undef GTEST_$(j)_TYPENAMES_
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
|
|
||||||
#undef GTEST_BY_REF_
|
|
||||||
#undef GTEST_ADD_REF_
|
|
||||||
#undef GTEST_TUPLE_ELEMENT_
|
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
|
|
@ -31,12 +31,11 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// Type utilities needed for implementing typed and type-parameterized
|
// Type utilities needed for implementing typed and type-parameterized
|
||||||
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||||
//
|
//
|
||||||
// Currently we support at most 50 types in a list, and at most 50
|
// Currently we support at most 50 types in a list, and at most 50
|
||||||
// type-parameterized tests in one type-parameterized test case.
|
// type-parameterized tests in one type-parameterized test suite.
|
||||||
// Please contact googletestframework@googlegroups.com if you need
|
// Please contact googletestframework@googlegroups.com if you need
|
||||||
// more.
|
// more.
|
||||||
|
|
||||||
|
@ -89,7 +88,7 @@ std::string GetTypeName() {
|
||||||
# if GTEST_HAS_CXXABI_H_
|
# if GTEST_HAS_CXXABI_H_
|
||||||
using abi::__cxa_demangle;
|
using abi::__cxa_demangle;
|
||||||
# endif // GTEST_HAS_CXXABI_H_
|
# endif // GTEST_HAS_CXXABI_H_
|
||||||
char* const readable_name = __cxa_demangle(name, 0, 0, &status);
|
char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
|
||||||
const std::string name_str(status == 0 ? readable_name : name);
|
const std::string name_str(status == 0 ? readable_name : name);
|
||||||
free(readable_name);
|
free(readable_name);
|
||||||
return CanonicalizeForStdLibVersioning(name_str);
|
return CanonicalizeForStdLibVersioning(name_str);
|
||||||
|
@ -106,18 +105,6 @@ std::string GetTypeName() {
|
||||||
|
|
||||||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
|
|
||||||
// type. This can be used as a compile-time assertion to ensure that
|
|
||||||
// two types are equal.
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
struct AssertTypeEq;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct AssertTypeEq<T, T> {
|
|
||||||
typedef bool type;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A unique type used as the default value for the arguments of class
|
// A unique type used as the default value for the arguments of class
|
||||||
// template Types. This allows us to simulate variadic templates
|
// template Types. This allows us to simulate variadic templates
|
||||||
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
||||||
|
@ -3312,8 +3299,8 @@ struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
|
||||||
};
|
};
|
||||||
|
|
||||||
// The TypeList template makes it possible to use either a single type
|
// The TypeList template makes it possible to use either a single type
|
||||||
// or a Types<...> list in TYPED_TEST_CASE() and
|
// or a Types<...> list in TYPED_TEST_SUITE() and
|
||||||
// INSTANTIATE_TYPED_TEST_CASE_P().
|
// INSTANTIATE_TYPED_TEST_SUITE_P().
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct TypeList {
|
struct TypeList {
|
||||||
|
|
|
@ -34,7 +34,7 @@ $var n = 50 $$ Maximum length of type lists we want to support.
|
||||||
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
// 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
|
// Currently we support at most $n types in a list, and at most $n
|
||||||
// type-parameterized tests in one type-parameterized test case.
|
// type-parameterized tests in one type-parameterized test suite.
|
||||||
// Please contact googletestframework@googlegroups.com if you need
|
// Please contact googletestframework@googlegroups.com if you need
|
||||||
// more.
|
// more.
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ std::string GetTypeName() {
|
||||||
# if GTEST_HAS_CXXABI_H_
|
# if GTEST_HAS_CXXABI_H_
|
||||||
using abi::__cxa_demangle;
|
using abi::__cxa_demangle;
|
||||||
# endif // GTEST_HAS_CXXABI_H_
|
# endif // GTEST_HAS_CXXABI_H_
|
||||||
char* const readable_name = __cxa_demangle(name, 0, 0, &status);
|
char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
|
||||||
const std::string name_str(status == 0 ? readable_name : name);
|
const std::string name_str(status == 0 ? readable_name : name);
|
||||||
free(readable_name);
|
free(readable_name);
|
||||||
return CanonicalizeForStdLibVersioning(name_str);
|
return CanonicalizeForStdLibVersioning(name_str);
|
||||||
|
@ -104,18 +104,6 @@ std::string GetTypeName() {
|
||||||
|
|
||||||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
|
|
||||||
// type. This can be used as a compile-time assertion to ensure that
|
|
||||||
// two types are equal.
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
struct AssertTypeEq;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct AssertTypeEq<T, T> {
|
|
||||||
typedef bool type;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A unique type used as the default value for the arguments of class
|
// A unique type used as the default value for the arguments of class
|
||||||
// template Types. This allows us to simulate variadic templates
|
// template Types. This allows us to simulate variadic templates
|
||||||
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
||||||
|
@ -291,8 +279,8 @@ struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
|
||||||
]]
|
]]
|
||||||
|
|
||||||
// The TypeList template makes it possible to use either a single type
|
// The TypeList template makes it possible to use either a single type
|
||||||
// or a Types<...> list in TYPED_TEST_CASE() and
|
// or a Types<...> list in TYPED_TEST_SUITE() and
|
||||||
// INSTANTIATE_TYPED_TEST_CASE_P().
|
// INSTANTIATE_TYPED_TEST_SUITE_P().
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct TypeList {
|
struct TypeList {
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "src/gtest.cc"
|
#include "src/gtest.cc"
|
||||||
#include "src/gtest-death-test.cc"
|
#include "src/gtest-death-test.cc"
|
||||||
#include "src/gtest-filepath.cc"
|
#include "src/gtest-filepath.cc"
|
||||||
|
#include "src/gtest-matchers.cc"
|
||||||
#include "src/gtest-port.cc"
|
#include "src/gtest-port.cc"
|
||||||
#include "src/gtest-printers.cc"
|
#include "src/gtest-printers.cc"
|
||||||
#include "src/gtest-test-part.cc"
|
#include "src/gtest-test-part.cc"
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
// This file implements death tests.
|
// This file implements death tests.
|
||||||
|
|
||||||
#include "gtest/gtest-death-test.h"
|
#include "gtest/gtest-death-test.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
#include "gtest/internal/custom/gtest.h"
|
#include "gtest/internal/custom/gtest.h"
|
||||||
|
|
||||||
|
@ -62,10 +65,16 @@
|
||||||
# endif // GTEST_OS_QNX
|
# endif // GTEST_OS_QNX
|
||||||
|
|
||||||
# if GTEST_OS_FUCHSIA
|
# if GTEST_OS_FUCHSIA
|
||||||
|
# include <lib/fdio/fd.h>
|
||||||
# include <lib/fdio/io.h>
|
# include <lib/fdio/io.h>
|
||||||
# include <lib/fdio/spawn.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/processargs.h>
|
||||||
# include <zircon/syscalls.h>
|
# include <zircon/syscalls.h>
|
||||||
|
# include <zircon/syscalls/policy.h>
|
||||||
# include <zircon/syscalls/port.h>
|
# include <zircon/syscalls/port.h>
|
||||||
# endif // GTEST_OS_FUCHSIA
|
# endif // GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
|
@ -113,8 +122,8 @@ GTEST_DEFINE_string_(
|
||||||
"Indicates the file, line number, temporal index of "
|
"Indicates the file, line number, temporal index of "
|
||||||
"the single death test to run, and a file descriptor to "
|
"the single death test to run, and a file descriptor to "
|
||||||
"which a success code may be sent, all separated by "
|
"which a success code may be sent, all separated by "
|
||||||
"the '|' characters. This flag is specified if and only if the current "
|
"the '|' characters. This flag is specified if and only if the "
|
||||||
"process is a sub-process launched for running a thread-safe "
|
"current process is a sub-process launched for running a thread-safe "
|
||||||
"death test. FOR INTERNAL USE ONLY.");
|
"death test. FOR INTERNAL USE ONLY.");
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
@ -266,8 +275,6 @@ static const int kFuchsiaReadPipeFd = 3;
|
||||||
// statement, which is not allowed; THREW means that the test statement
|
// statement, which is not allowed; THREW means that the test statement
|
||||||
// returned control by throwing an exception. IN_PROGRESS means the test
|
// returned control by throwing an exception. IN_PROGRESS means the test
|
||||||
// has not yet concluded.
|
// has not yet concluded.
|
||||||
// FIXME: Unify names and possibly values for
|
|
||||||
// AbortReason, DeathTestOutcome, and flag characters above.
|
|
||||||
enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
|
enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
|
||||||
|
|
||||||
// Routine for aborting the program which is safe to call from an
|
// Routine for aborting the program which is safe to call from an
|
||||||
|
@ -281,7 +288,7 @@ static void DeathTestAbort(const std::string& message) {
|
||||||
// the heap for any additional non-minuscule memory requirements.
|
// the heap for any additional non-minuscule memory requirements.
|
||||||
const InternalRunDeathTestFlag* const flag =
|
const InternalRunDeathTestFlag* const flag =
|
||||||
GetUnitTestImpl()->internal_run_death_test_flag();
|
GetUnitTestImpl()->internal_run_death_test_flag();
|
||||||
if (flag != NULL) {
|
if (flag != nullptr) {
|
||||||
FILE* parent = posix::FDOpen(flag->write_fd(), "w");
|
FILE* parent = posix::FDOpen(flag->write_fd(), "w");
|
||||||
fputc(kDeathTestInternalError, parent);
|
fputc(kDeathTestInternalError, parent);
|
||||||
fprintf(parent, "%s", message.c_str());
|
fprintf(parent, "%s", message.c_str());
|
||||||
|
@ -361,7 +368,7 @@ static void FailFromInternalError(int fd) {
|
||||||
// for the current test.
|
// for the current test.
|
||||||
DeathTest::DeathTest() {
|
DeathTest::DeathTest() {
|
||||||
TestInfo* const info = GetUnitTestImpl()->current_test_info();
|
TestInfo* const info = GetUnitTestImpl()->current_test_info();
|
||||||
if (info == NULL) {
|
if (info == nullptr) {
|
||||||
DeathTestAbort("Cannot run a death test outside of a TEST or "
|
DeathTestAbort("Cannot run a death test outside of a TEST or "
|
||||||
"TEST_F construct");
|
"TEST_F construct");
|
||||||
}
|
}
|
||||||
|
@ -369,10 +376,11 @@ DeathTest::DeathTest() {
|
||||||
|
|
||||||
// Creates and returns a death test by dispatching to the current
|
// Creates and returns a death test by dispatching to the current
|
||||||
// death test factory.
|
// death test factory.
|
||||||
bool DeathTest::Create(const char* statement, const RE* regex,
|
bool DeathTest::Create(const char* statement,
|
||||||
const char* file, int line, DeathTest** test) {
|
Matcher<const std::string&> matcher, const char* file,
|
||||||
|
int line, DeathTest** test) {
|
||||||
return GetUnitTestImpl()->death_test_factory()->Create(
|
return GetUnitTestImpl()->death_test_factory()->Create(
|
||||||
statement, regex, file, line, test);
|
statement, std::move(matcher), file, line, test);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* DeathTest::LastMessage() {
|
const char* DeathTest::LastMessage() {
|
||||||
|
@ -388,9 +396,9 @@ std::string DeathTest::last_death_test_message_;
|
||||||
// Provides cross platform implementation for some death functionality.
|
// Provides cross platform implementation for some death functionality.
|
||||||
class DeathTestImpl : public DeathTest {
|
class DeathTestImpl : public DeathTest {
|
||||||
protected:
|
protected:
|
||||||
DeathTestImpl(const char* a_statement, const RE* a_regex)
|
DeathTestImpl(const char* a_statement, Matcher<const std::string&> matcher)
|
||||||
: statement_(a_statement),
|
: statement_(a_statement),
|
||||||
regex_(a_regex),
|
matcher_(std::move(matcher)),
|
||||||
spawned_(false),
|
spawned_(false),
|
||||||
status_(-1),
|
status_(-1),
|
||||||
outcome_(IN_PROGRESS),
|
outcome_(IN_PROGRESS),
|
||||||
|
@ -398,13 +406,12 @@ class DeathTestImpl : public DeathTest {
|
||||||
write_fd_(-1) {}
|
write_fd_(-1) {}
|
||||||
|
|
||||||
// read_fd_ is expected to be closed and cleared by a derived class.
|
// read_fd_ is expected to be closed and cleared by a derived class.
|
||||||
~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
|
~DeathTestImpl() override { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
|
||||||
|
|
||||||
void Abort(AbortReason reason);
|
void Abort(AbortReason reason) override;
|
||||||
virtual bool Passed(bool status_ok);
|
bool Passed(bool status_ok) override;
|
||||||
|
|
||||||
const char* statement() const { return statement_; }
|
const char* statement() const { return statement_; }
|
||||||
const RE* regex() const { return regex_; }
|
|
||||||
bool spawned() const { return spawned_; }
|
bool spawned() const { return spawned_; }
|
||||||
void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
|
void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
|
||||||
int status() const { return status_; }
|
int status() const { return status_; }
|
||||||
|
@ -422,13 +429,15 @@ class DeathTestImpl : public DeathTest {
|
||||||
// case of unexpected codes.
|
// case of unexpected codes.
|
||||||
void ReadAndInterpretStatusByte();
|
void ReadAndInterpretStatusByte();
|
||||||
|
|
||||||
|
// Returns stderr output from the child process.
|
||||||
|
virtual std::string GetErrorLogs();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The textual content of the code this object is testing. This class
|
// The textual content of the code this object is testing. This class
|
||||||
// doesn't own this string and should not attempt to delete it.
|
// doesn't own this string and should not attempt to delete it.
|
||||||
const char* const statement_;
|
const char* const statement_;
|
||||||
// The regular expression which test output must match. DeathTestImpl
|
// A matcher that's expected to match the stderr output by the child process.
|
||||||
// doesn't own this object and should not attempt to delete it.
|
Matcher<const std::string&> matcher_;
|
||||||
const RE* const regex_;
|
|
||||||
// True if the death test child process has been successfully spawned.
|
// True if the death test child process has been successfully spawned.
|
||||||
bool spawned_;
|
bool spawned_;
|
||||||
// The exit status of the child process.
|
// The exit status of the child process.
|
||||||
|
@ -490,6 +499,10 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
|
||||||
set_read_fd(-1);
|
set_read_fd(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DeathTestImpl::GetErrorLogs() {
|
||||||
|
return GetCapturedStderr();
|
||||||
|
}
|
||||||
|
|
||||||
// Signals that the death test code which should have exited, didn't.
|
// Signals that the death test code which should have exited, didn't.
|
||||||
// Should be called only in a death test child process.
|
// Should be called only in a death test child process.
|
||||||
// Writes a status byte to the child's status file descriptor, then
|
// Writes a status byte to the child's status file descriptor, then
|
||||||
|
@ -543,22 +556,21 @@ static ::std::string FormatDeathTestOutput(const ::std::string& output) {
|
||||||
// in the format specified by wait(2). On Windows, this is the
|
// in the format specified by wait(2). On Windows, this is the
|
||||||
// value supplied to the ExitProcess() API or a numeric code
|
// value supplied to the ExitProcess() API or a numeric code
|
||||||
// of the exception that terminated the program.
|
// of the exception that terminated the program.
|
||||||
// regex: A regular expression object to be applied to
|
// matcher_: A matcher that's expected to match the stderr output by the child
|
||||||
// the test's captured standard error output; the death test
|
// process.
|
||||||
// fails if it does not match.
|
|
||||||
//
|
//
|
||||||
// Argument:
|
// Argument:
|
||||||
// status_ok: true if exit_status is acceptable in the context of
|
// status_ok: true if exit_status is acceptable in the context of
|
||||||
// this particular death test, which fails if it is false
|
// this particular death test, which fails if it is false
|
||||||
//
|
//
|
||||||
// Returns true iff all of the above conditions are met. Otherwise, the
|
// Returns true if and only if all of the above conditions are met. Otherwise,
|
||||||
// first failing condition, in the order given above, is the one that is
|
// the first failing condition, in the order given above, is the one that is
|
||||||
// reported. Also sets the last death test message string.
|
// reported. Also sets the last death test message string.
|
||||||
bool DeathTestImpl::Passed(bool status_ok) {
|
bool DeathTestImpl::Passed(bool status_ok) {
|
||||||
if (!spawned())
|
if (!spawned())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const std::string error_message = GetCapturedStderr();
|
const std::string error_message = GetErrorLogs();
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
Message buffer;
|
Message buffer;
|
||||||
|
@ -579,18 +591,15 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
||||||
break;
|
break;
|
||||||
case DIED:
|
case DIED:
|
||||||
if (status_ok) {
|
if (status_ok) {
|
||||||
# if GTEST_USES_PCRE
|
if (matcher_.Matches(error_message)) {
|
||||||
// PCRE regexes support embedded NULs.
|
|
||||||
const bool matched = RE::PartialMatch(error_message, *regex());
|
|
||||||
# else
|
|
||||||
const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
|
|
||||||
# endif // GTEST_USES_PCRE
|
|
||||||
if (matched) {
|
|
||||||
success = true;
|
success = true;
|
||||||
} else {
|
} else {
|
||||||
|
std::ostringstream stream;
|
||||||
|
matcher_.DescribeTo(&stream);
|
||||||
buffer << " Result: died but not with expected error.\n"
|
buffer << " Result: died but not with expected error.\n"
|
||||||
<< " Expected: " << regex()->pattern() << "\n"
|
<< " Expected: " << stream.str() << "\n"
|
||||||
<< "Actual msg:\n" << FormatDeathTestOutput(error_message);
|
<< "Actual msg:\n"
|
||||||
|
<< FormatDeathTestOutput(error_message);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buffer << " Result: died but not with expected exit code:\n"
|
buffer << " Result: died but not with expected exit code:\n"
|
||||||
|
@ -639,11 +648,11 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
||||||
//
|
//
|
||||||
class WindowsDeathTest : public DeathTestImpl {
|
class WindowsDeathTest : public DeathTestImpl {
|
||||||
public:
|
public:
|
||||||
WindowsDeathTest(const char* a_statement,
|
WindowsDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
|
||||||
const RE* a_regex,
|
const char* file, int line)
|
||||||
const char* file,
|
: DeathTestImpl(a_statement, std::move(matcher)),
|
||||||
int line)
|
file_(file),
|
||||||
: DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
|
line_(line) {}
|
||||||
|
|
||||||
// All of these virtual functions are inherited from DeathTest.
|
// All of these virtual functions are inherited from DeathTest.
|
||||||
virtual int Wait();
|
virtual int Wait();
|
||||||
|
@ -720,7 +729,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
const TestInfo* const info = impl->current_test_info();
|
const TestInfo* const info = impl->current_test_info();
|
||||||
const int death_test_index = info->result()->death_test_count();
|
const int death_test_index = info->result()->death_test_count();
|
||||||
|
|
||||||
if (flag != NULL) {
|
if (flag != nullptr) {
|
||||||
// ParseInternalRunDeathTestFlag() has performed all the necessary
|
// ParseInternalRunDeathTestFlag() has performed all the necessary
|
||||||
// processing.
|
// processing.
|
||||||
set_write_fd(flag->write_fd());
|
set_write_fd(flag->write_fd());
|
||||||
|
@ -729,8 +738,8 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
|
|
||||||
// WindowsDeathTest uses an anonymous pipe to communicate results of
|
// WindowsDeathTest uses an anonymous pipe to communicate results of
|
||||||
// a death test.
|
// a death test.
|
||||||
SECURITY_ATTRIBUTES handles_are_inheritable = {
|
SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
|
||||||
sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
|
nullptr, TRUE};
|
||||||
HANDLE read_handle, write_handle;
|
HANDLE read_handle, write_handle;
|
||||||
GTEST_DEATH_TEST_CHECK_(
|
GTEST_DEATH_TEST_CHECK_(
|
||||||
::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
|
::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
|
||||||
|
@ -741,13 +750,13 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
write_handle_.Reset(write_handle);
|
write_handle_.Reset(write_handle);
|
||||||
event_handle_.Reset(::CreateEvent(
|
event_handle_.Reset(::CreateEvent(
|
||||||
&handles_are_inheritable,
|
&handles_are_inheritable,
|
||||||
TRUE, // The event will automatically reset to non-signaled state.
|
TRUE, // The event will automatically reset to non-signaled state.
|
||||||
FALSE, // The initial state is non-signalled.
|
FALSE, // The initial state is non-signalled.
|
||||||
NULL)); // The even is unnamed.
|
nullptr)); // The even is unnamed.
|
||||||
GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
|
GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
|
||||||
const std::string filter_flag =
|
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" +
|
kFilterFlag + "=" + info->test_suite_name() +
|
||||||
info->test_case_name() + "." + info->name();
|
"." + info->name();
|
||||||
const std::string internal_flag =
|
const std::string internal_flag =
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
|
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
|
||||||
"=" + file_ + "|" + StreamableToString(line_) + "|" +
|
"=" + file_ + "|" + StreamableToString(line_) + "|" +
|
||||||
|
@ -760,10 +769,9 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
"|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
|
"|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
|
||||||
|
|
||||||
char executable_path[_MAX_PATH + 1]; // NOLINT
|
char executable_path[_MAX_PATH + 1]; // NOLINT
|
||||||
GTEST_DEATH_TEST_CHECK_(
|
GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
|
||||||
_MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
|
executable_path,
|
||||||
executable_path,
|
_MAX_PATH));
|
||||||
_MAX_PATH));
|
|
||||||
|
|
||||||
std::string command_line =
|
std::string command_line =
|
||||||
std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
|
std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
|
||||||
|
@ -784,17 +792,16 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
|
startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
PROCESS_INFORMATION process_info;
|
PROCESS_INFORMATION process_info;
|
||||||
GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
|
GTEST_DEATH_TEST_CHECK_(
|
||||||
executable_path,
|
::CreateProcessA(
|
||||||
const_cast<char*>(command_line.c_str()),
|
executable_path, const_cast<char*>(command_line.c_str()),
|
||||||
NULL, // Retuned process handle is not inheritable.
|
nullptr, // Retuned process handle is not inheritable.
|
||||||
NULL, // Retuned thread handle is not inheritable.
|
nullptr, // Retuned thread handle is not inheritable.
|
||||||
TRUE, // Child inherits all inheritable handles (for write_handle_).
|
TRUE, // Child inherits all inheritable handles (for write_handle_).
|
||||||
0x0, // Default creation flags.
|
0x0, // Default creation flags.
|
||||||
NULL, // Inherit the parent's environment.
|
nullptr, // Inherit the parent's environment.
|
||||||
UnitTest::GetInstance()->original_working_dir(),
|
UnitTest::GetInstance()->original_working_dir(), &startup_info,
|
||||||
&startup_info,
|
&process_info) != FALSE);
|
||||||
&process_info) != FALSE);
|
|
||||||
child_handle_.Reset(process_info.hProcess);
|
child_handle_.Reset(process_info.hProcess);
|
||||||
::CloseHandle(process_info.hThread);
|
::CloseHandle(process_info.hThread);
|
||||||
set_spawned(true);
|
set_spawned(true);
|
||||||
|
@ -805,38 +812,34 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
|
|
||||||
class FuchsiaDeathTest : public DeathTestImpl {
|
class FuchsiaDeathTest : public DeathTestImpl {
|
||||||
public:
|
public:
|
||||||
FuchsiaDeathTest(const char* a_statement,
|
FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
|
||||||
const RE* a_regex,
|
const char* file, int line)
|
||||||
const char* file,
|
: DeathTestImpl(a_statement, std::move(matcher)),
|
||||||
int line)
|
file_(file),
|
||||||
: DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
|
line_(line) {}
|
||||||
virtual ~FuchsiaDeathTest() {
|
|
||||||
zx_status_t status = zx_handle_close(child_process_);
|
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
|
||||||
status = zx_handle_close(port_);
|
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
// All of these virtual functions are inherited from DeathTest.
|
// All of these virtual functions are inherited from DeathTest.
|
||||||
virtual int Wait();
|
int Wait() override;
|
||||||
virtual TestRole AssumeRole();
|
TestRole AssumeRole() override;
|
||||||
|
std::string GetErrorLogs() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The name of the file in which the death test is located.
|
// The name of the file in which the death test is located.
|
||||||
const char* const file_;
|
const char* const file_;
|
||||||
// The line number on which the death test is located.
|
// The line number on which the death test is located.
|
||||||
const int line_;
|
const int line_;
|
||||||
|
// The stderr data captured by the child process.
|
||||||
|
std::string captured_stderr_;
|
||||||
|
|
||||||
zx_handle_t child_process_ = ZX_HANDLE_INVALID;
|
zx::process child_process_;
|
||||||
zx_handle_t port_ = ZX_HANDLE_INVALID;
|
zx::channel exception_channel_;
|
||||||
|
zx::socket stderr_socket_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utility class for accumulating command-line arguments.
|
// Utility class for accumulating command-line arguments.
|
||||||
class Arguments {
|
class Arguments {
|
||||||
public:
|
public:
|
||||||
Arguments() {
|
Arguments() { args_.push_back(nullptr); }
|
||||||
args_.push_back(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Arguments() {
|
~Arguments() {
|
||||||
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
|
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
|
||||||
|
@ -872,51 +875,88 @@ class Arguments {
|
||||||
// status, or 0 if no child process exists. As a side effect, sets the
|
// status, or 0 if no child process exists. As a side effect, sets the
|
||||||
// outcome data member.
|
// outcome data member.
|
||||||
int FuchsiaDeathTest::Wait() {
|
int FuchsiaDeathTest::Wait() {
|
||||||
|
const int kProcessKey = 0;
|
||||||
|
const int kSocketKey = 1;
|
||||||
|
const int kExceptionKey = 2;
|
||||||
|
|
||||||
if (!spawned())
|
if (!spawned())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Register to wait for the child process to terminate.
|
// Create a port to wait for socket/task/exception events.
|
||||||
zx_status_t status_zx;
|
zx_status_t status_zx;
|
||||||
status_zx = zx_object_wait_async(child_process_,
|
zx::port port;
|
||||||
port_,
|
status_zx = zx::port::create(0, &port);
|
||||||
0 /* key */,
|
|
||||||
ZX_PROCESS_TERMINATED,
|
|
||||||
ZX_WAIT_ASYNC_ONCE);
|
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
// Wait for it to terminate, or an exception to be received.
|
// Register to wait for the child process to terminate.
|
||||||
zx_port_packet_t packet;
|
status_zx = child_process_.wait_async(
|
||||||
status_zx = zx_port_wait(port_, ZX_TIME_INFINITE, &packet);
|
port, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
if (ZX_PKT_IS_EXCEPTION(packet.type)) {
|
// Register to wait for the socket to be readable or closed.
|
||||||
// Process encountered an exception. Kill it directly rather than letting
|
status_zx = stderr_socket_.wait_async(
|
||||||
// other handlers process the event.
|
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
|
||||||
status_zx = zx_task_kill(child_process_);
|
ZX_WAIT_ASYNC_ONCE);
|
||||||
|
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);
|
||||||
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
|
bool process_terminated = false;
|
||||||
|
bool socket_closed = false;
|
||||||
|
do {
|
||||||
|
zx_port_packet_t packet = {};
|
||||||
|
status_zx = port.wait(zx::time::infinite(), &packet);
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
// Now wait for |child_process_| to terminate.
|
if (packet.key == kExceptionKey) {
|
||||||
zx_signals_t signals = 0;
|
// Process encountered an exception. Kill it directly rather than
|
||||||
status_zx = zx_object_wait_one(
|
// letting other handlers process the event. We will get a kProcessKey
|
||||||
child_process_, ZX_PROCESS_TERMINATED, ZX_TIME_INFINITE, &signals);
|
// event when the process actually terminates.
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
status_zx = child_process_.kill();
|
||||||
GTEST_DEATH_TEST_CHECK_(signals & ZX_PROCESS_TERMINATED);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
} else {
|
} else if (packet.key == kProcessKey) {
|
||||||
// Process terminated.
|
// Process terminated.
|
||||||
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
|
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
|
||||||
GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
|
GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
|
||||||
}
|
process_terminated = true;
|
||||||
|
} else if (packet.key == kSocketKey) {
|
||||||
|
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
|
||||||
|
if (packet.signal.observed & ZX_SOCKET_READABLE) {
|
||||||
|
// Read data from the socket.
|
||||||
|
constexpr size_t kBufferSize = 1024;
|
||||||
|
do {
|
||||||
|
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);
|
||||||
|
captured_stderr_.resize(old_length + bytes_read);
|
||||||
|
} while (status_zx == ZX_OK);
|
||||||
|
if (status_zx == ZX_ERR_PEER_CLOSED) {
|
||||||
|
socket_closed = true;
|
||||||
|
} 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);
|
||||||
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED);
|
||||||
|
socket_closed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!process_terminated && !socket_closed);
|
||||||
|
|
||||||
ReadAndInterpretStatusByte();
|
ReadAndInterpretStatusByte();
|
||||||
|
|
||||||
zx_info_process_t buffer;
|
zx_info_process_t buffer;
|
||||||
status_zx = zx_object_get_info(
|
status_zx = child_process_.get_info(
|
||||||
child_process_,
|
ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr);
|
||||||
ZX_INFO_PROCESS,
|
|
||||||
&buffer,
|
|
||||||
sizeof(buffer),
|
|
||||||
nullptr,
|
|
||||||
nullptr);
|
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
GTEST_DEATH_TEST_CHECK_(buffer.exited);
|
GTEST_DEATH_TEST_CHECK_(buffer.exited);
|
||||||
|
@ -936,21 +976,20 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||||
const TestInfo* const info = impl->current_test_info();
|
const TestInfo* const info = impl->current_test_info();
|
||||||
const int death_test_index = info->result()->death_test_count();
|
const int death_test_index = info->result()->death_test_count();
|
||||||
|
|
||||||
if (flag != NULL) {
|
if (flag != nullptr) {
|
||||||
// ParseInternalRunDeathTestFlag() has performed all the necessary
|
// ParseInternalRunDeathTestFlag() has performed all the necessary
|
||||||
// processing.
|
// processing.
|
||||||
set_write_fd(kFuchsiaReadPipeFd);
|
set_write_fd(kFuchsiaReadPipeFd);
|
||||||
return EXECUTE_TEST;
|
return EXECUTE_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
CaptureStderr();
|
|
||||||
// Flush the log buffers since the log streams are shared with the child.
|
// Flush the log buffers since the log streams are shared with the child.
|
||||||
FlushInfoLog();
|
FlushInfoLog();
|
||||||
|
|
||||||
// Build the child process command line.
|
// Build the child process command line.
|
||||||
const std::string filter_flag =
|
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
|
kFilterFlag + "=" + info->test_suite_name() +
|
||||||
+ info->test_case_name() + "." + info->name();
|
"." + info->name();
|
||||||
const std::string internal_flag =
|
const std::string internal_flag =
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
||||||
+ file_ + "|"
|
+ file_ + "|"
|
||||||
|
@ -964,35 +1003,68 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||||
// Build the pipe for communication with the child.
|
// Build the pipe for communication with the child.
|
||||||
zx_status_t status;
|
zx_status_t status;
|
||||||
zx_handle_t child_pipe_handle;
|
zx_handle_t child_pipe_handle;
|
||||||
uint32_t type;
|
int child_pipe_fd;
|
||||||
status = fdio_pipe_half(&child_pipe_handle, &type);
|
status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
|
||||||
GTEST_DEATH_TEST_CHECK_(status >= 0);
|
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||||
set_read_fd(status);
|
set_read_fd(child_pipe_fd);
|
||||||
|
|
||||||
// Set the pipe handle for the child.
|
// Set the pipe handle for the child.
|
||||||
fdio_spawn_action_t add_handle_action = {};
|
fdio_spawn_action_t spawn_actions[2] = {};
|
||||||
add_handle_action.action = FDIO_SPAWN_ACTION_ADD_HANDLE;
|
fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
|
||||||
add_handle_action.h.id = PA_HND(type, kFuchsiaReadPipeFd);
|
add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
|
||||||
add_handle_action.h.handle = child_pipe_handle;
|
add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd);
|
||||||
|
add_handle_action->h.handle = child_pipe_handle;
|
||||||
|
|
||||||
|
// 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_);
|
||||||
|
GTEST_DEATH_TEST_CHECK_(status >= 0);
|
||||||
|
int stderr_producer_fd = -1;
|
||||||
|
status =
|
||||||
|
fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd);
|
||||||
|
GTEST_DEATH_TEST_CHECK_(status >= 0);
|
||||||
|
|
||||||
|
// Make the stderr socket nonblocking.
|
||||||
|
GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
|
||||||
|
|
||||||
|
fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
|
||||||
|
add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
|
||||||
|
add_stderr_action->fd.local_fd = stderr_producer_fd;
|
||||||
|
add_stderr_action->fd.target_fd = STDERR_FILENO;
|
||||||
|
|
||||||
|
// Create a child job.
|
||||||
|
zx_handle_t child_job = ZX_HANDLE_INVALID;
|
||||||
|
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);
|
||||||
|
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());
|
||||||
|
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||||
|
|
||||||
// Spawn the child process.
|
// Spawn the child process.
|
||||||
status = fdio_spawn_etc(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL,
|
status = fdio_spawn_etc(
|
||||||
args.Argv()[0], args.Argv(), nullptr, 1,
|
child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
|
||||||
&add_handle_action, &child_process_, nullptr);
|
2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
|
||||||
|
|
||||||
// Create an exception port and attach it to the |child_process_|, to allow
|
|
||||||
// us to suppress the system default exception handler from firing.
|
|
||||||
status = zx_port_create(0, &port_);
|
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
|
||||||
status = zx_task_bind_exception_port(
|
|
||||||
child_process_, port_, 0 /* key */, 0 /*options */);
|
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||||
|
|
||||||
set_spawned(true);
|
set_spawned(true);
|
||||||
return OVERSEE_TEST;
|
return OVERSEE_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string FuchsiaDeathTest::GetErrorLogs() {
|
||||||
|
return captured_stderr_;
|
||||||
|
}
|
||||||
|
|
||||||
#else // We are neither on Windows, nor on Fuchsia.
|
#else // We are neither on Windows, nor on Fuchsia.
|
||||||
|
|
||||||
// ForkingDeathTest provides implementations for most of the abstract
|
// ForkingDeathTest provides implementations for most of the abstract
|
||||||
|
@ -1000,10 +1072,10 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||||
// left undefined.
|
// left undefined.
|
||||||
class ForkingDeathTest : public DeathTestImpl {
|
class ForkingDeathTest : public DeathTestImpl {
|
||||||
public:
|
public:
|
||||||
ForkingDeathTest(const char* statement, const RE* regex);
|
ForkingDeathTest(const char* statement, Matcher<const std::string&> matcher);
|
||||||
|
|
||||||
// All of these virtual functions are inherited from DeathTest.
|
// All of these virtual functions are inherited from DeathTest.
|
||||||
virtual int Wait();
|
int Wait() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
|
void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
|
||||||
|
@ -1014,9 +1086,9 @@ class ForkingDeathTest : public DeathTestImpl {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructs a ForkingDeathTest.
|
// Constructs a ForkingDeathTest.
|
||||||
ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
|
ForkingDeathTest::ForkingDeathTest(const char* a_statement,
|
||||||
: DeathTestImpl(a_statement, a_regex),
|
Matcher<const std::string&> matcher)
|
||||||
child_pid_(-1) {}
|
: DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {}
|
||||||
|
|
||||||
// Waits for the child in a death test to exit, returning its exit
|
// Waits for the child in a death test to exit, returning its exit
|
||||||
// status, or 0 if no child process exists. As a side effect, sets the
|
// status, or 0 if no child process exists. As a side effect, sets the
|
||||||
|
@ -1037,9 +1109,9 @@ int ForkingDeathTest::Wait() {
|
||||||
// in the child process.
|
// in the child process.
|
||||||
class NoExecDeathTest : public ForkingDeathTest {
|
class NoExecDeathTest : public ForkingDeathTest {
|
||||||
public:
|
public:
|
||||||
NoExecDeathTest(const char* a_statement, const RE* a_regex) :
|
NoExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher)
|
||||||
ForkingDeathTest(a_statement, a_regex) { }
|
: ForkingDeathTest(a_statement, std::move(matcher)) {}
|
||||||
virtual TestRole AssumeRole();
|
TestRole AssumeRole() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The AssumeRole process for a fork-and-run death test. It implements a
|
// The AssumeRole process for a fork-and-run death test. It implements a
|
||||||
|
@ -1092,10 +1164,13 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
|
||||||
// only this specific death test to be run.
|
// only this specific death test to be run.
|
||||||
class ExecDeathTest : public ForkingDeathTest {
|
class ExecDeathTest : public ForkingDeathTest {
|
||||||
public:
|
public:
|
||||||
ExecDeathTest(const char* a_statement, const RE* a_regex,
|
ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
|
||||||
const char* file, int line) :
|
const char* file, int line)
|
||||||
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
|
: ForkingDeathTest(a_statement, std::move(matcher)),
|
||||||
virtual TestRole AssumeRole();
|
file_(file),
|
||||||
|
line_(line) {}
|
||||||
|
TestRole AssumeRole() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
|
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
|
||||||
::std::vector<std::string> args = GetInjectableArgvs();
|
::std::vector<std::string> args = GetInjectableArgvs();
|
||||||
|
@ -1115,9 +1190,7 @@ class ExecDeathTest : public ForkingDeathTest {
|
||||||
// Utility class for accumulating command-line arguments.
|
// Utility class for accumulating command-line arguments.
|
||||||
class Arguments {
|
class Arguments {
|
||||||
public:
|
public:
|
||||||
Arguments() {
|
Arguments() { args_.push_back(nullptr); }
|
||||||
args_.push_back(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Arguments() {
|
~Arguments() {
|
||||||
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
|
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
|
||||||
|
@ -1211,6 +1284,9 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||||
// correct answer.
|
// correct answer.
|
||||||
static void StackLowerThanAddress(const void* ptr,
|
static void StackLowerThanAddress(const void* ptr,
|
||||||
bool* result) GTEST_NO_INLINE_;
|
bool* result) GTEST_NO_INLINE_;
|
||||||
|
// HWAddressSanitizer add a random tag to the MSB of the local variable address,
|
||||||
|
// making comparison result unpredictable.
|
||||||
|
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||||
static void StackLowerThanAddress(const void* ptr, bool* result) {
|
static void StackLowerThanAddress(const void* ptr, bool* result) {
|
||||||
int dummy;
|
int dummy;
|
||||||
*result = (&dummy < ptr);
|
*result = (&dummy < ptr);
|
||||||
|
@ -1218,6 +1294,7 @@ static void StackLowerThanAddress(const void* ptr, bool* result) {
|
||||||
|
|
||||||
// Make sure AddressSanitizer does not tamper with the stack here.
|
// Make sure AddressSanitizer does not tamper with the stack here.
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||||
|
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||||
static bool StackGrowsDown() {
|
static bool StackGrowsDown() {
|
||||||
int dummy;
|
int dummy;
|
||||||
bool result;
|
bool result;
|
||||||
|
@ -1262,7 +1339,8 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
fd_flags | FD_CLOEXEC));
|
fd_flags | FD_CLOEXEC));
|
||||||
struct inheritance inherit = {0};
|
struct inheritance inherit = {0};
|
||||||
// spawn is a system call.
|
// spawn is a system call.
|
||||||
child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
|
child_pid =
|
||||||
|
spawn(args.argv[0], 0, nullptr, &inherit, args.argv, GetEnviron());
|
||||||
// Restores the current working directory.
|
// Restores the current working directory.
|
||||||
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
||||||
|
@ -1286,9 +1364,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
|
|
||||||
if (!use_fork) {
|
if (!use_fork) {
|
||||||
static const bool stack_grows_down = StackGrowsDown();
|
static const bool stack_grows_down = StackGrowsDown();
|
||||||
const size_t stack_size = getpagesize();
|
const auto stack_size = static_cast<size_t>(getpagesize());
|
||||||
// MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
|
// MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
|
||||||
void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
|
void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE,
|
||||||
MAP_ANON | MAP_PRIVATE, -1, 0);
|
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||||
GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
|
GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
|
||||||
|
|
||||||
|
@ -1302,8 +1380,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
void* const stack_top =
|
void* const stack_top =
|
||||||
static_cast<char*>(stack) +
|
static_cast<char*>(stack) +
|
||||||
(stack_grows_down ? stack_size - kMaxStackAlignment : 0);
|
(stack_grows_down ? stack_size - kMaxStackAlignment : 0);
|
||||||
GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment &&
|
GTEST_DEATH_TEST_CHECK_(
|
||||||
reinterpret_cast<intptr_t>(stack_top) % kMaxStackAlignment == 0);
|
static_cast<size_t>(stack_size) > kMaxStackAlignment &&
|
||||||
|
reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0);
|
||||||
|
|
||||||
child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
|
child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
|
||||||
|
|
||||||
|
@ -1320,7 +1399,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
# endif // GTEST_OS_QNX
|
# endif // GTEST_OS_QNX
|
||||||
# if GTEST_OS_LINUX
|
# if GTEST_OS_LINUX
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||||
sigaction(SIGPROF, &saved_sigprof_action, NULL));
|
sigaction(SIGPROF, &saved_sigprof_action, nullptr));
|
||||||
# endif // GTEST_OS_LINUX
|
# endif // GTEST_OS_LINUX
|
||||||
|
|
||||||
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
||||||
|
@ -1338,7 +1417,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||||
const TestInfo* const info = impl->current_test_info();
|
const TestInfo* const info = impl->current_test_info();
|
||||||
const int death_test_index = info->result()->death_test_count();
|
const int death_test_index = info->result()->death_test_count();
|
||||||
|
|
||||||
if (flag != NULL) {
|
if (flag != nullptr) {
|
||||||
set_write_fd(flag->write_fd());
|
set_write_fd(flag->write_fd());
|
||||||
return EXECUTE_TEST;
|
return EXECUTE_TEST;
|
||||||
}
|
}
|
||||||
|
@ -1349,9 +1428,9 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||||
// it be closed when the child process does an exec:
|
// it be closed when the child process does an exec:
|
||||||
GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
|
GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
|
||||||
|
|
||||||
const std::string filter_flag =
|
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
|
kFilterFlag + "=" + info->test_suite_name() +
|
||||||
+ info->test_case_name() + "." + info->name();
|
"." + info->name();
|
||||||
const std::string internal_flag =
|
const std::string internal_flag =
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
||||||
+ file_ + "|" + StreamableToString(line_) + "|"
|
+ file_ + "|" + StreamableToString(line_) + "|"
|
||||||
|
@ -1384,7 +1463,8 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||||
// by the "test" argument to its address. If the test should be
|
// by the "test" argument to its address. If the test should be
|
||||||
// skipped, sets that pointer to NULL. Returns true, unless the
|
// skipped, sets that pointer to NULL. Returns true, unless the
|
||||||
// flag is set to an invalid value.
|
// flag is set to an invalid value.
|
||||||
bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
bool DefaultDeathTestFactory::Create(const char* statement,
|
||||||
|
Matcher<const std::string&> matcher,
|
||||||
const char* file, int line,
|
const char* file, int line,
|
||||||
DeathTest** test) {
|
DeathTest** test) {
|
||||||
UnitTestImpl* const impl = GetUnitTestImpl();
|
UnitTestImpl* const impl = GetUnitTestImpl();
|
||||||
|
@ -1393,7 +1473,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
||||||
const int death_test_index = impl->current_test_info()
|
const int death_test_index = impl->current_test_info()
|
||||||
->increment_death_test_count();
|
->increment_death_test_count();
|
||||||
|
|
||||||
if (flag != NULL) {
|
if (flag != nullptr) {
|
||||||
if (death_test_index > flag->index()) {
|
if (death_test_index > flag->index()) {
|
||||||
DeathTest::set_last_death_test_message(
|
DeathTest::set_last_death_test_message(
|
||||||
"Death test count (" + StreamableToString(death_test_index)
|
"Death test count (" + StreamableToString(death_test_index)
|
||||||
|
@ -1404,7 +1484,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
||||||
|
|
||||||
if (!(flag->file() == file && flag->line() == line &&
|
if (!(flag->file() == file && flag->line() == line &&
|
||||||
flag->index() == death_test_index)) {
|
flag->index() == death_test_index)) {
|
||||||
*test = NULL;
|
*test = nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1413,22 +1493,22 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
||||||
|
|
||||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
||||||
GTEST_FLAG(death_test_style) == "fast") {
|
GTEST_FLAG(death_test_style) == "fast") {
|
||||||
*test = new WindowsDeathTest(statement, regex, file, line);
|
*test = new WindowsDeathTest(statement, std::move(matcher), file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
# elif GTEST_OS_FUCHSIA
|
# elif GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
||||||
GTEST_FLAG(death_test_style) == "fast") {
|
GTEST_FLAG(death_test_style) == "fast") {
|
||||||
*test = new FuchsiaDeathTest(statement, regex, file, line);
|
*test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
# else
|
# else
|
||||||
|
|
||||||
if (GTEST_FLAG(death_test_style) == "threadsafe") {
|
if (GTEST_FLAG(death_test_style) == "threadsafe") {
|
||||||
*test = new ExecDeathTest(statement, regex, file, line);
|
*test = new ExecDeathTest(statement, std::move(matcher), file, line);
|
||||||
} else if (GTEST_FLAG(death_test_style) == "fast") {
|
} else if (GTEST_FLAG(death_test_style) == "fast") {
|
||||||
*test = new NoExecDeathTest(statement, regex);
|
*test = new NoExecDeathTest(statement, std::move(matcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
# endif // GTEST_OS_WINDOWS
|
# endif // GTEST_OS_WINDOWS
|
||||||
|
@ -1458,8 +1538,6 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||||
StreamableToString(parent_process_id));
|
StreamableToString(parent_process_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Replace the following check with a
|
|
||||||
// compile-time assertion when available.
|
|
||||||
GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
|
GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
|
||||||
|
|
||||||
const HANDLE write_handle =
|
const HANDLE write_handle =
|
||||||
|
@ -1515,7 +1593,7 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||||
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
||||||
// the flag is specified; otherwise returns NULL.
|
// the flag is specified; otherwise returns NULL.
|
||||||
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
|
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
|
||||||
if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
|
if (GTEST_FLAG(internal_run_death_test) == "") return nullptr;
|
||||||
|
|
||||||
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
|
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
|
||||||
// can use it here.
|
// can use it here.
|
||||||
|
|
|
@ -38,9 +38,6 @@
|
||||||
#elif GTEST_OS_WINDOWS
|
#elif GTEST_OS_WINDOWS
|
||||||
# include <direct.h>
|
# include <direct.h>
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
#elif GTEST_OS_SYMBIAN
|
|
||||||
// Symbian OpenC has PATH_MAX in sys/syslimits.h
|
|
||||||
# include <sys/syslimits.h>
|
|
||||||
#else
|
#else
|
||||||
# include <limits.h>
|
# include <limits.h>
|
||||||
# include <climits> // Some Linux distributions define PATH_MAX here.
|
# include <climits> // Some Linux distributions define PATH_MAX here.
|
||||||
|
@ -95,13 +92,14 @@ static bool IsPathSeparator(char c) {
|
||||||
|
|
||||||
// Returns the current working directory, or "" if unsuccessful.
|
// Returns the current working directory, or "" if unsuccessful.
|
||||||
FilePath FilePath::GetCurrentDir() {
|
FilePath FilePath::GetCurrentDir() {
|
||||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
|
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
|
||||||
// Windows CE doesn't have a current directory, so we just return
|
GTEST_OS_WINDOWS_RT || ARDUINO || defined(ESP_PLATFORM)
|
||||||
|
// These platforms do not have a current directory, so we just return
|
||||||
// something reasonable.
|
// something reasonable.
|
||||||
return FilePath(kCurrentDirectoryString);
|
return FilePath(kCurrentDirectoryString);
|
||||||
#elif GTEST_OS_WINDOWS
|
#elif GTEST_OS_WINDOWS
|
||||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||||
return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
|
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
|
||||||
#else
|
#else
|
||||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||||
char* result = getcwd(cwd, sizeof(cwd));
|
char* result = getcwd(cwd, sizeof(cwd));
|
||||||
|
@ -109,9 +107,9 @@ FilePath FilePath::GetCurrentDir() {
|
||||||
// getcwd will likely fail in NaCl due to the sandbox, so return something
|
// getcwd will likely fail in NaCl due to the sandbox, so return something
|
||||||
// reasonable. The user may have provided a shim implementation for getcwd,
|
// reasonable. The user may have provided a shim implementation for getcwd,
|
||||||
// however, so fallback only when failure is detected.
|
// however, so fallback only when failure is detected.
|
||||||
return FilePath(result == NULL ? kCurrentDirectoryString : cwd);
|
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
|
||||||
# endif // GTEST_OS_NACL
|
# endif // GTEST_OS_NACL
|
||||||
return FilePath(result == NULL ? "" : cwd);
|
return FilePath(result == nullptr ? "" : cwd);
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,8 +134,8 @@ const char* FilePath::FindLastPathSeparator() const {
|
||||||
#if GTEST_HAS_ALT_PATH_SEP_
|
#if GTEST_HAS_ALT_PATH_SEP_
|
||||||
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
||||||
// Comparing two pointers of which only one is NULL is undefined.
|
// Comparing two pointers of which only one is NULL is undefined.
|
||||||
if (last_alt_sep != NULL &&
|
if (last_alt_sep != nullptr &&
|
||||||
(last_sep == NULL || last_alt_sep > last_sep)) {
|
(last_sep == nullptr || last_alt_sep > last_sep)) {
|
||||||
return last_alt_sep;
|
return last_alt_sep;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -165,7 +163,7 @@ FilePath FilePath::RemoveFileName() const {
|
||||||
const char* const last_sep = FindLastPathSeparator();
|
const char* const last_sep = FindLastPathSeparator();
|
||||||
std::string dir;
|
std::string dir;
|
||||||
if (last_sep) {
|
if (last_sep) {
|
||||||
dir = std::string(c_str(), last_sep + 1 - c_str());
|
dir = std::string(c_str(), static_cast<size_t>(last_sep + 1 - c_str()));
|
||||||
} else {
|
} else {
|
||||||
dir = kCurrentDirectoryString;
|
dir = kCurrentDirectoryString;
|
||||||
}
|
}
|
||||||
|
@ -250,9 +248,6 @@ bool FilePath::DirectoryExists() const {
|
||||||
// root directory per disk drive.)
|
// root directory per disk drive.)
|
||||||
bool FilePath::IsRootDirectory() const {
|
bool FilePath::IsRootDirectory() const {
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
// FIXME: on Windows a network share like
|
|
||||||
// \\server\share can be a root directory, although it cannot be the
|
|
||||||
// current directory. Handle this properly.
|
|
||||||
return pathname_.length() == 3 && IsAbsolutePath();
|
return pathname_.length() == 3 && IsAbsolutePath();
|
||||||
#else
|
#else
|
||||||
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
|
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
|
||||||
|
@ -324,7 +319,7 @@ bool FilePath::CreateFolder() const {
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
||||||
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
||||||
int result = CreateDirectory(unicode, NULL) ? 0 : -1;
|
int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
|
||||||
delete [] unicode;
|
delete [] unicode;
|
||||||
#elif GTEST_OS_WINDOWS
|
#elif GTEST_OS_WINDOWS
|
||||||
int result = _mkdir(pathname_.c_str());
|
int result = _mkdir(pathname_.c_str());
|
||||||
|
@ -350,9 +345,8 @@ FilePath FilePath::RemoveTrailingPathSeparator() const {
|
||||||
// Removes any redundant separators that might be in the pathname.
|
// Removes any redundant separators that might be in the pathname.
|
||||||
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||||
// redundancies that might be in a pathname involving "." or "..".
|
// redundancies that might be in a pathname involving "." or "..".
|
||||||
// FIXME: handle Windows network shares (e.g. \\server\share).
|
|
||||||
void FilePath::Normalize() {
|
void FilePath::Normalize() {
|
||||||
if (pathname_.c_str() == NULL) {
|
if (pathname_.c_str() == nullptr) {
|
||||||
pathname_ = "";
|
pathname_ = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <string.h> // For memmove.
|
#include <string.h> // For memmove.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -98,14 +99,14 @@ const char kFlagfileFlag[] = "flagfile";
|
||||||
// A valid random seed must be in [1, kMaxRandomSeed].
|
// A valid random seed must be in [1, kMaxRandomSeed].
|
||||||
const int kMaxRandomSeed = 99999;
|
const int kMaxRandomSeed = 99999;
|
||||||
|
|
||||||
// g_help_flag is true iff the --help flag or an equivalent form is
|
// g_help_flag is true if and only if the --help flag or an equivalent form
|
||||||
// specified on the command line.
|
// is specified on the command line.
|
||||||
GTEST_API_ extern bool g_help_flag;
|
GTEST_API_ extern bool g_help_flag;
|
||||||
|
|
||||||
// Returns the current time in milliseconds.
|
// Returns the current time in milliseconds.
|
||||||
GTEST_API_ TimeInMillis GetTimeInMillis();
|
GTEST_API_ TimeInMillis GetTimeInMillis();
|
||||||
|
|
||||||
// Returns true iff Google Test should use colors in the output.
|
// Returns true if and only if Google Test should use colors in the output.
|
||||||
GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
|
GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
|
||||||
|
|
||||||
// Formats the given time in milliseconds as seconds.
|
// Formats the given time in milliseconds as seconds.
|
||||||
|
@ -230,7 +231,7 @@ GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
|
||||||
|
|
||||||
// Converts a wide string to a narrow string in UTF-8 encoding.
|
// Converts a wide string to a narrow string in UTF-8 encoding.
|
||||||
// The wide string is assumed to have the following encoding:
|
// The wide string is assumed to have the following encoding:
|
||||||
// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
|
// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin)
|
||||||
// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
|
// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
|
||||||
// Parameter str points to a null-terminated wide string.
|
// Parameter str points to a null-terminated wide string.
|
||||||
// Parameter num_chars may additionally limit the number
|
// Parameter num_chars may additionally limit the number
|
||||||
|
@ -265,8 +266,8 @@ GTEST_API_ bool ShouldShard(const char* total_shards_str,
|
||||||
GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
|
GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
|
||||||
|
|
||||||
// Given the total number of shards, the shard index, and the test id,
|
// Given the total number of shards, the shard index, and the test id,
|
||||||
// returns true iff the test should be run on this shard. The test id is
|
// returns true if and only if the test should be run on this shard. The test id
|
||||||
// some arbitrary but unique non-negative integer assigned to each test
|
// is some arbitrary but unique non-negative integer assigned to each test
|
||||||
// method. Assumes that 0 <= shard_index < total_shards.
|
// method. Assumes that 0 <= shard_index < total_shards.
|
||||||
GTEST_API_ bool ShouldRunTestOnShard(
|
GTEST_API_ bool ShouldRunTestOnShard(
|
||||||
int total_shards, int shard_index, int test_id);
|
int total_shards, int shard_index, int test_id);
|
||||||
|
@ -297,7 +298,8 @@ void ForEach(const Container& c, Functor functor) {
|
||||||
// in range [0, v.size()).
|
// in range [0, v.size()).
|
||||||
template <typename E>
|
template <typename E>
|
||||||
inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
|
inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
|
||||||
return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
|
return (i < 0 || i >= static_cast<int>(v.size())) ? default_value
|
||||||
|
: v[static_cast<size_t>(i)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performs an in-place shuffle of a range of the vector's elements.
|
// Performs an in-place shuffle of a range of the vector's elements.
|
||||||
|
@ -319,8 +321,11 @@ void ShuffleRange(internal::Random* random, int begin, int end,
|
||||||
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
|
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
|
||||||
for (int range_width = end - begin; range_width >= 2; range_width--) {
|
for (int range_width = end - begin; range_width >= 2; range_width--) {
|
||||||
const int last_in_range = begin + range_width - 1;
|
const int last_in_range = begin + range_width - 1;
|
||||||
const int selected = begin + random->Generate(range_width);
|
const int selected =
|
||||||
std::swap((*v)[selected], (*v)[last_in_range]);
|
begin +
|
||||||
|
static_cast<int>(random->Generate(static_cast<UInt32>(range_width)));
|
||||||
|
std::swap((*v)[static_cast<size_t>(selected)],
|
||||||
|
(*v)[static_cast<size_t>(last_in_range)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,7 +352,7 @@ class TestPropertyKeyIs {
|
||||||
// TestPropertyKeyIs has NO default constructor.
|
// TestPropertyKeyIs has NO default constructor.
|
||||||
explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
|
explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
|
||||||
|
|
||||||
// Returns true iff the test name of test property matches on key_.
|
// Returns true if and only if the test name of test property matches on key_.
|
||||||
bool operator()(const TestProperty& test_property) const {
|
bool operator()(const TestProperty& test_property) const {
|
||||||
return test_property.key() == key_;
|
return test_property.key() == key_;
|
||||||
}
|
}
|
||||||
|
@ -380,17 +385,17 @@ class GTEST_API_ UnitTestOptions {
|
||||||
|
|
||||||
// Functions for processing the gtest_filter flag.
|
// Functions for processing the gtest_filter flag.
|
||||||
|
|
||||||
// Returns true iff the wildcard pattern matches the string. The
|
// Returns true if and only if the wildcard pattern matches the string.
|
||||||
// first ':' or '\0' character in pattern marks the end of it.
|
// The first ':' or '\0' character in pattern marks the end of it.
|
||||||
//
|
//
|
||||||
// This recursive algorithm isn't very efficient, but is clear and
|
// This recursive algorithm isn't very efficient, but is clear and
|
||||||
// works well enough for matching test names, which are short.
|
// works well enough for matching test names, which are short.
|
||||||
static bool PatternMatchesString(const char *pattern, const char *str);
|
static bool PatternMatchesString(const char *pattern, const char *str);
|
||||||
|
|
||||||
// Returns true iff the user-specified filter matches the test case
|
// Returns true if and only if the user-specified filter matches the test
|
||||||
// name and the test name.
|
// suite name and the test name.
|
||||||
static bool FilterMatchesTest(const std::string &test_case_name,
|
static bool FilterMatchesTest(const std::string& test_suite_name,
|
||||||
const std::string &test_name);
|
const std::string& test_name);
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
// Function for supporting the gtest_catch_exception flag.
|
// Function for supporting the gtest_catch_exception flag.
|
||||||
|
@ -442,8 +447,8 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface {
|
||||||
public:
|
public:
|
||||||
OsStackTraceGetter() {}
|
OsStackTraceGetter() {}
|
||||||
|
|
||||||
virtual std::string CurrentStackTrace(int max_depth, int skip_count);
|
std::string CurrentStackTrace(int max_depth, int skip_count) override;
|
||||||
virtual void UponLeavingGTest();
|
void UponLeavingGTest() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if GTEST_HAS_ABSL
|
#if GTEST_HAS_ABSL
|
||||||
|
@ -474,7 +479,7 @@ class DefaultGlobalTestPartResultReporter
|
||||||
explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
|
explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
|
||||||
// Implements the TestPartResultReporterInterface. Reports the test part
|
// Implements the TestPartResultReporterInterface. Reports the test part
|
||||||
// result in the current test.
|
// result in the current test.
|
||||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
void ReportTestPartResult(const TestPartResult& result) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UnitTestImpl* const unit_test_;
|
UnitTestImpl* const unit_test_;
|
||||||
|
@ -490,7 +495,7 @@ class DefaultPerThreadTestPartResultReporter
|
||||||
explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
|
explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
|
||||||
// Implements the TestPartResultReporterInterface. The implementation just
|
// Implements the TestPartResultReporterInterface. The implementation just
|
||||||
// delegates to the current global test part result reporter of *unit_test_.
|
// delegates to the current global test part result reporter of *unit_test_.
|
||||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
void ReportTestPartResult(const TestPartResult& result) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UnitTestImpl* const unit_test_;
|
UnitTestImpl* const unit_test_;
|
||||||
|
@ -528,22 +533,25 @@ class GTEST_API_ UnitTestImpl {
|
||||||
void SetTestPartResultReporterForCurrentThread(
|
void SetTestPartResultReporterForCurrentThread(
|
||||||
TestPartResultReporterInterface* reporter);
|
TestPartResultReporterInterface* reporter);
|
||||||
|
|
||||||
// Gets the number of successful test cases.
|
// Gets the number of successful test suites.
|
||||||
int successful_test_case_count() const;
|
int successful_test_suite_count() const;
|
||||||
|
|
||||||
// Gets the number of failed test cases.
|
// Gets the number of failed test suites.
|
||||||
int failed_test_case_count() const;
|
int failed_test_suite_count() const;
|
||||||
|
|
||||||
// Gets the number of all test cases.
|
// Gets the number of all test suites.
|
||||||
int total_test_case_count() const;
|
int total_test_suite_count() const;
|
||||||
|
|
||||||
// Gets the number of all test cases that contain at least one test
|
// Gets the number of all test suites that contain at least one test
|
||||||
// that should run.
|
// that should run.
|
||||||
int test_case_to_run_count() const;
|
int test_suite_to_run_count() const;
|
||||||
|
|
||||||
// Gets the number of successful tests.
|
// Gets the number of successful tests.
|
||||||
int successful_test_count() const;
|
int successful_test_count() const;
|
||||||
|
|
||||||
|
// Gets the number of skipped tests.
|
||||||
|
int skipped_test_count() const;
|
||||||
|
|
||||||
// Gets the number of failed tests.
|
// Gets the number of failed tests.
|
||||||
int failed_test_count() const;
|
int failed_test_count() const;
|
||||||
|
|
||||||
|
@ -569,27 +577,33 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// Gets the elapsed time, in milliseconds.
|
// Gets the elapsed time, in milliseconds.
|
||||||
TimeInMillis elapsed_time() const { return elapsed_time_; }
|
TimeInMillis elapsed_time() const { return elapsed_time_; }
|
||||||
|
|
||||||
// Returns true iff the unit test passed (i.e. all test cases passed).
|
// Returns true if and only if the unit test passed (i.e. all test suites
|
||||||
|
// passed).
|
||||||
bool Passed() const { return !Failed(); }
|
bool Passed() const { return !Failed(); }
|
||||||
|
|
||||||
// Returns true iff the unit test failed (i.e. some test case failed
|
// Returns true if and only if the unit test failed (i.e. some test suite
|
||||||
// or something outside of all tests failed).
|
// failed or something outside of all tests failed).
|
||||||
bool Failed() const {
|
bool Failed() const {
|
||||||
return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
|
return failed_test_suite_count() > 0 || ad_hoc_test_result()->Failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the i-th test case among all the test cases. i can range from 0 to
|
// Gets the i-th test suite among all the test suites. i can range from 0 to
|
||||||
// total_test_case_count() - 1. If i is not in that range, returns NULL.
|
// total_test_suite_count() - 1. If i is not in that range, returns NULL.
|
||||||
const TestCase* GetTestCase(int i) const {
|
const TestSuite* GetTestSuite(int i) const {
|
||||||
const int index = GetElementOr(test_case_indices_, i, -1);
|
const int index = GetElementOr(test_suite_indices_, i, -1);
|
||||||
return index < 0 ? NULL : test_cases_[i];
|
return index < 0 ? nullptr : test_suites_[static_cast<size_t>(i)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the i-th test case among all the test cases. i can range from 0 to
|
// Legacy API is deprecated but still available
|
||||||
// total_test_case_count() - 1. If i is not in that range, returns NULL.
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
TestCase* GetMutableTestCase(int i) {
|
const TestCase* GetTestCase(int i) const { return GetTestSuite(i); }
|
||||||
const int index = GetElementOr(test_case_indices_, i, -1);
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
return index < 0 ? NULL : test_cases_[index];
|
|
||||||
|
// Gets the i-th test suite among all the test suites. i can range from 0 to
|
||||||
|
// total_test_suite_count() - 1. If i is not in that range, returns NULL.
|
||||||
|
TestSuite* GetMutableSuiteCase(int i) {
|
||||||
|
const int index = GetElementOr(test_suite_indices_, i, -1);
|
||||||
|
return index < 0 ? nullptr : test_suites_[static_cast<size_t>(index)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provides access to the event listener list.
|
// Provides access to the event listener list.
|
||||||
|
@ -626,30 +640,38 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
|
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
|
||||||
std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
|
std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
|
||||||
|
|
||||||
// Finds and returns a TestCase with the given name. If one doesn't
|
// Finds and returns a TestSuite with the given name. If one doesn't
|
||||||
// exist, creates one and returns it.
|
// exist, creates one and returns it.
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
//
|
//
|
||||||
// test_case_name: name of the test case
|
// test_suite_name: name of the test suite
|
||||||
// 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.
|
// this is not a typed or a type-parameterized test.
|
||||||
// set_up_tc: pointer to the function that sets up the test case
|
// 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 case
|
// tear_down_tc: pointer to the function that tears down the test suite
|
||||||
TestCase* GetTestCase(const char* test_case_name,
|
TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param,
|
||||||
const char* type_param,
|
internal::SetUpTestSuiteFunc set_up_tc,
|
||||||
Test::SetUpTestCaseFunc set_up_tc,
|
internal::TearDownTestSuiteFunc tear_down_tc);
|
||||||
Test::TearDownTestCaseFunc tear_down_tc);
|
|
||||||
|
// Legacy API is deprecated but still available
|
||||||
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
TestCase* GetTestCase(const char* test_case_name, const char* type_param,
|
||||||
|
internal::SetUpTestSuiteFunc set_up_tc,
|
||||||
|
internal::TearDownTestSuiteFunc tear_down_tc) {
|
||||||
|
return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc);
|
||||||
|
}
|
||||||
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
// Adds a TestInfo to the unit test.
|
// Adds a TestInfo to the unit test.
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
//
|
//
|
||||||
// set_up_tc: pointer to the function that sets up the test case
|
// 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 case
|
// tear_down_tc: pointer to the function that tears down the test suite
|
||||||
// test_info: the TestInfo object
|
// test_info: the TestInfo object
|
||||||
void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
|
void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
|
||||||
Test::TearDownTestCaseFunc tear_down_tc,
|
internal::TearDownTestSuiteFunc tear_down_tc,
|
||||||
TestInfo* test_info) {
|
TestInfo* test_info) {
|
||||||
// In order to support thread-safe death tests, we need to
|
// In order to support thread-safe death tests, we need to
|
||||||
// remember the original working directory when the test program
|
// remember the original working directory when the test program
|
||||||
|
@ -664,21 +686,20 @@ class GTEST_API_ UnitTestImpl {
|
||||||
<< "Failed to get the current working directory.";
|
<< "Failed to get the current working directory.";
|
||||||
}
|
}
|
||||||
|
|
||||||
GetTestCase(test_info->test_case_name(),
|
GetTestSuite(test_info->test_suite_name(), test_info->type_param(),
|
||||||
test_info->type_param(),
|
set_up_tc, tear_down_tc)
|
||||||
set_up_tc,
|
->AddTestInfo(test_info);
|
||||||
tear_down_tc)->AddTestInfo(test_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns ParameterizedTestCaseRegistry object used to keep track of
|
// Returns ParameterizedTestSuiteRegistry object used to keep track of
|
||||||
// value-parameterized tests and instantiate and register them.
|
// value-parameterized tests and instantiate and register them.
|
||||||
internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
|
internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() {
|
||||||
return parameterized_test_registry_;
|
return parameterized_test_registry_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the TestCase object for the test that's currently running.
|
// Sets the TestSuite object for the test that's currently running.
|
||||||
void set_current_test_case(TestCase* a_current_test_case) {
|
void set_current_test_suite(TestSuite* a_current_test_suite) {
|
||||||
current_test_case_ = a_current_test_case;
|
current_test_suite_ = a_current_test_suite;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the TestInfo object for the test that's currently running. If
|
// Sets the TestInfo object for the test that's currently running. If
|
||||||
|
@ -689,7 +710,7 @@ class GTEST_API_ UnitTestImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers all parameterized tests defined using TEST_P and
|
// Registers all parameterized tests defined using TEST_P and
|
||||||
// INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
|
// INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter
|
||||||
// combination. This method can be called more then once; it has guards
|
// combination. This method can be called more then once; it has guards
|
||||||
// protecting from registering the tests more then once. If
|
// protecting from registering the tests more then once. If
|
||||||
// value-parameterized tests are disabled, RegisterParameterizedTests is
|
// value-parameterized tests are disabled, RegisterParameterizedTests is
|
||||||
|
@ -704,7 +725,7 @@ class GTEST_API_ UnitTestImpl {
|
||||||
|
|
||||||
// Clears the results of all tests, except the ad hoc tests.
|
// Clears the results of all tests, except the ad hoc tests.
|
||||||
void ClearNonAdHocTestResult() {
|
void ClearNonAdHocTestResult() {
|
||||||
ForEach(test_cases_, TestCase::ClearTestCaseResult);
|
ForEach(test_suites_, TestSuite::ClearTestSuiteResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears the results of ad-hoc test assertions.
|
// Clears the results of ad-hoc test assertions.
|
||||||
|
@ -713,7 +734,7 @@ class GTEST_API_ UnitTestImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a TestProperty to the current TestResult object when invoked in a
|
// Adds a TestProperty to the current TestResult object when invoked in a
|
||||||
// context of a test or a test case, or to the global property set. If the
|
// context of a test or a test suite, or to the global property set. If the
|
||||||
// result already contains a property with the same key, the value will be
|
// result already contains a property with the same key, the value will be
|
||||||
// updated.
|
// updated.
|
||||||
void RecordProperty(const TestProperty& test_property);
|
void RecordProperty(const TestProperty& test_property);
|
||||||
|
@ -725,7 +746,7 @@ class GTEST_API_ UnitTestImpl {
|
||||||
|
|
||||||
// Matches the full name of each test against the user-specified
|
// Matches the full name of each test against the user-specified
|
||||||
// filter to decide whether the test should run, then records the
|
// filter to decide whether the test should run, then records the
|
||||||
// result in each TestCase and TestInfo object.
|
// result in each TestSuite and TestInfo object.
|
||||||
// If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
|
// If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
|
||||||
// based on sharding variables in the environment.
|
// based on sharding variables in the environment.
|
||||||
// Returns the number of tests that should run.
|
// Returns the number of tests that should run.
|
||||||
|
@ -734,7 +755,7 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// Prints the names of the tests matching the user-specified filter flag.
|
// Prints the names of the tests matching the user-specified filter flag.
|
||||||
void ListTestsMatchingFilter();
|
void ListTestsMatchingFilter();
|
||||||
|
|
||||||
const TestCase* current_test_case() const { return current_test_case_; }
|
const TestSuite* current_test_suite() const { return current_test_suite_; }
|
||||||
TestInfo* current_test_info() { return current_test_info_; }
|
TestInfo* current_test_info() { return current_test_info_; }
|
||||||
const TestInfo* current_test_info() const { return current_test_info_; }
|
const TestInfo* current_test_info() const { return current_test_info_; }
|
||||||
|
|
||||||
|
@ -795,11 +816,11 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// Gets the random number generator.
|
// Gets the random number generator.
|
||||||
internal::Random* random() { return &random_; }
|
internal::Random* random() { return &random_; }
|
||||||
|
|
||||||
// Shuffles all test cases, and the tests within each test case,
|
// Shuffles all test suites, and the tests within each test suite,
|
||||||
// making sure that death tests are still run first.
|
// making sure that death tests are still run first.
|
||||||
void ShuffleTests();
|
void ShuffleTests();
|
||||||
|
|
||||||
// Restores the test cases and tests to their order before the first shuffle.
|
// Restores the test suites and tests to their order before the first shuffle.
|
||||||
void UnshuffleTests();
|
void UnshuffleTests();
|
||||||
|
|
||||||
// Returns the value of GTEST_FLAG(catch_exceptions) at the moment
|
// Returns the value of GTEST_FLAG(catch_exceptions) at the moment
|
||||||
|
@ -839,31 +860,31 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// before/after the tests are run.
|
// before/after the tests are run.
|
||||||
std::vector<Environment*> environments_;
|
std::vector<Environment*> environments_;
|
||||||
|
|
||||||
// The vector of TestCases in their original order. It owns the
|
// The vector of TestSuites in their original order. It owns the
|
||||||
// elements in the vector.
|
// elements in the vector.
|
||||||
std::vector<TestCase*> test_cases_;
|
std::vector<TestSuite*> test_suites_;
|
||||||
|
|
||||||
// Provides a level of indirection for the test case list to allow
|
// Provides a level of indirection for the test suite list to allow
|
||||||
// easy shuffling and restoring the test case order. The i-th
|
// easy shuffling and restoring the test suite order. The i-th
|
||||||
// element of this vector is the index of the i-th test case in the
|
// element of this vector is the index of the i-th test suite in the
|
||||||
// shuffled order.
|
// shuffled order.
|
||||||
std::vector<int> test_case_indices_;
|
std::vector<int> test_suite_indices_;
|
||||||
|
|
||||||
// ParameterizedTestRegistry object used to register value-parameterized
|
// ParameterizedTestRegistry object used to register value-parameterized
|
||||||
// tests.
|
// tests.
|
||||||
internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
|
internal::ParameterizedTestSuiteRegistry parameterized_test_registry_;
|
||||||
|
|
||||||
// Indicates whether RegisterParameterizedTests() has been called already.
|
// Indicates whether RegisterParameterizedTests() has been called already.
|
||||||
bool parameterized_tests_registered_;
|
bool parameterized_tests_registered_;
|
||||||
|
|
||||||
// Index of the last death test case registered. Initially -1.
|
// Index of the last death test suite registered. Initially -1.
|
||||||
int last_death_test_case_;
|
int last_death_test_suite_;
|
||||||
|
|
||||||
// This points to the TestCase for the currently running test. It
|
// This points to the TestSuite for the currently running test. It
|
||||||
// changes as Google Test goes through one test case after another.
|
// changes as Google Test goes through one test suite after another.
|
||||||
// When no test is running, this is set to NULL and Google Test
|
// When no test is running, this is set to NULL and Google Test
|
||||||
// stores assertion results in ad_hoc_test_result_. Initially NULL.
|
// stores assertion results in ad_hoc_test_result_. Initially NULL.
|
||||||
TestCase* current_test_case_;
|
TestSuite* current_test_suite_;
|
||||||
|
|
||||||
// This points to the TestInfo for the currently running test. It
|
// This points to the TestInfo for the currently running test. It
|
||||||
// changes as Google Test goes through one test after another. When
|
// changes as Google Test goes through one test after another. When
|
||||||
|
@ -891,7 +912,7 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// desired.
|
// desired.
|
||||||
OsStackTraceGetterInterface* os_stack_trace_getter_;
|
OsStackTraceGetterInterface* os_stack_trace_getter_;
|
||||||
|
|
||||||
// True iff PostFlagParsingInit() has been called.
|
// True if and only if PostFlagParsingInit() has been called.
|
||||||
bool post_flag_parse_init_performed_;
|
bool post_flag_parse_init_performed_;
|
||||||
|
|
||||||
// The random number seed used at the beginning of the test run.
|
// The random number seed used at the beginning of the test run.
|
||||||
|
@ -910,8 +931,8 @@ class GTEST_API_ UnitTestImpl {
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
// The decomposed components of the gtest_internal_run_death_test flag,
|
// The decomposed components of the gtest_internal_run_death_test flag,
|
||||||
// parsed when RUN_ALL_TESTS is called.
|
// parsed when RUN_ALL_TESTS is called.
|
||||||
internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
|
std::unique_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
|
||||||
internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
|
std::unique_ptr<internal::DeathTestFactory> death_test_factory_;
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
// A per-thread stack of traces created by the SCOPED_TRACE() macro.
|
// A per-thread stack of traces created by the SCOPED_TRACE() macro.
|
||||||
|
@ -994,8 +1015,6 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
|
||||||
|
|
||||||
const bool parse_success = *end == '\0' && errno == 0;
|
const bool parse_success = *end == '\0' && errno == 0;
|
||||||
|
|
||||||
// FIXME: Convert this to compile time assertion when it is
|
|
||||||
// available.
|
|
||||||
GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
|
GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
|
||||||
|
|
||||||
const Integer result = static_cast<Integer>(parsed);
|
const Integer result = static_cast<Integer>(parsed);
|
||||||
|
@ -1059,18 +1078,18 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
MakeConnection();
|
MakeConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SocketWriter() {
|
~SocketWriter() override {
|
||||||
if (sockfd_ != -1)
|
if (sockfd_ != -1)
|
||||||
CloseConnection();
|
CloseConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends a string to the socket.
|
// Sends a string to the socket.
|
||||||
virtual void Send(const std::string& message) {
|
void Send(const std::string& message) override {
|
||||||
GTEST_CHECK_(sockfd_ != -1)
|
GTEST_CHECK_(sockfd_ != -1)
|
||||||
<< "Send() can be called only when there is a connection.";
|
<< "Send() can be called only when there is a connection.";
|
||||||
|
|
||||||
const int len = static_cast<int>(message.length());
|
const auto len = static_cast<size_t>(message.length());
|
||||||
if (write(sockfd_, message.c_str(), len) != len) {
|
if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
|
||||||
GTEST_LOG_(WARNING)
|
GTEST_LOG_(WARNING)
|
||||||
<< "stream_result_to: failed to stream to "
|
<< "stream_result_to: failed to stream to "
|
||||||
<< host_name_ << ":" << port_num_;
|
<< host_name_ << ":" << port_num_;
|
||||||
|
@ -1082,7 +1101,7 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
void MakeConnection();
|
void MakeConnection();
|
||||||
|
|
||||||
// Closes the socket.
|
// Closes the socket.
|
||||||
void CloseConnection() {
|
void CloseConnection() override {
|
||||||
GTEST_CHECK_(sockfd_ != -1)
|
GTEST_CHECK_(sockfd_ != -1)
|
||||||
<< "CloseConnection() can be called only when there is a connection.";
|
<< "CloseConnection() can be called only when there is a connection.";
|
||||||
|
|
||||||
|
@ -1108,11 +1127,11 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
explicit StreamingListener(AbstractSocketWriter* socket_writer)
|
explicit StreamingListener(AbstractSocketWriter* socket_writer)
|
||||||
: socket_writer_(socket_writer) { Start(); }
|
: socket_writer_(socket_writer) { Start(); }
|
||||||
|
|
||||||
void OnTestProgramStart(const UnitTest& /* unit_test */) {
|
void OnTestProgramStart(const UnitTest& /* unit_test */) override {
|
||||||
SendLn("event=TestProgramStart");
|
SendLn("event=TestProgramStart");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTestProgramEnd(const UnitTest& unit_test) {
|
void OnTestProgramEnd(const UnitTest& unit_test) override {
|
||||||
// Note that Google Test current only report elapsed time for each
|
// Note that Google Test current only report elapsed time for each
|
||||||
// test iteration, not for the entire test program.
|
// test iteration, not for the entire test program.
|
||||||
SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
|
SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
|
||||||
|
@ -1121,42 +1140,47 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
socket_writer_->CloseConnection();
|
socket_writer_->CloseConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
|
void OnTestIterationStart(const UnitTest& /* unit_test */,
|
||||||
|
int iteration) override {
|
||||||
SendLn("event=TestIterationStart&iteration=" +
|
SendLn("event=TestIterationStart&iteration=" +
|
||||||
StreamableToString(iteration));
|
StreamableToString(iteration));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
|
void OnTestIterationEnd(const UnitTest& unit_test,
|
||||||
|
int /* iteration */) override {
|
||||||
SendLn("event=TestIterationEnd&passed=" +
|
SendLn("event=TestIterationEnd&passed=" +
|
||||||
FormatBool(unit_test.Passed()) + "&elapsed_time=" +
|
FormatBool(unit_test.Passed()) + "&elapsed_time=" +
|
||||||
StreamableToString(unit_test.elapsed_time()) + "ms");
|
StreamableToString(unit_test.elapsed_time()) + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTestCaseStart(const TestCase& test_case) {
|
// Note that "event=TestCaseStart" is a wire format and has to remain
|
||||||
|
// "case" for compatibilty
|
||||||
|
void OnTestCaseStart(const TestCase& test_case) override {
|
||||||
SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
|
SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTestCaseEnd(const TestCase& test_case) {
|
// Note that "event=TestCaseEnd" is a wire format and has to remain
|
||||||
SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed())
|
// "case" for compatibilty
|
||||||
+ "&elapsed_time=" + StreamableToString(test_case.elapsed_time())
|
void OnTestCaseEnd(const TestCase& test_case) override {
|
||||||
+ "ms");
|
SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) +
|
||||||
|
"&elapsed_time=" + StreamableToString(test_case.elapsed_time()) +
|
||||||
|
"ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTestStart(const TestInfo& test_info) {
|
void OnTestStart(const TestInfo& test_info) override {
|
||||||
SendLn(std::string("event=TestStart&name=") + test_info.name());
|
SendLn(std::string("event=TestStart&name=") + test_info.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTestEnd(const TestInfo& test_info) {
|
void OnTestEnd(const TestInfo& test_info) override {
|
||||||
SendLn("event=TestEnd&passed=" +
|
SendLn("event=TestEnd&passed=" +
|
||||||
FormatBool((test_info.result())->Passed()) +
|
FormatBool((test_info.result())->Passed()) +
|
||||||
"&elapsed_time=" +
|
"&elapsed_time=" +
|
||||||
StreamableToString((test_info.result())->elapsed_time()) + "ms");
|
StreamableToString((test_info.result())->elapsed_time()) + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTestPartResult(const TestPartResult& test_part_result) {
|
void OnTestPartResult(const TestPartResult& test_part_result) override {
|
||||||
const char* file_name = test_part_result.file_name();
|
const char* file_name = test_part_result.file_name();
|
||||||
if (file_name == NULL)
|
if (file_name == nullptr) file_name = "";
|
||||||
file_name = "";
|
|
||||||
SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
|
SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
|
||||||
"&line=" + StreamableToString(test_part_result.line_number()) +
|
"&line=" + StreamableToString(test_part_result.line_number()) +
|
||||||
"&message=" + UrlEncode(test_part_result.message()));
|
"&message=" + UrlEncode(test_part_result.message()));
|
||||||
|
@ -1172,7 +1196,7 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
|
|
||||||
std::string FormatBool(bool value) { return value ? "1" : "0"; }
|
std::string FormatBool(bool value) { return value ? "1" : "0"; }
|
||||||
|
|
||||||
const scoped_ptr<AbstractSocketWriter> socket_writer_;
|
const std::unique_ptr<AbstractSocketWriter> socket_writer_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
|
||||||
}; // class StreamingListener
|
}; // class StreamingListener
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This file implements just enough of the matcher interface to allow
|
||||||
|
// EXPECT_DEATH and friends to accept a matcher argument.
|
||||||
|
|
||||||
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
#include "gtest/gtest-matchers.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const std::string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const std::string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const std::string&>::Matcher(const char* s) {
|
||||||
|
*this = Eq(std::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a std::string whose value is equal to
|
||||||
|
// s.
|
||||||
|
Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a std::string whose value is equal to
|
||||||
|
// 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
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const absl::string_view&>::Matcher(const std::string& s) {
|
||||||
|
*this = Eq(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const absl::string_view&>::Matcher(const char* s) {
|
||||||
|
*this = Eq(std::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const absl::string_view&>::Matcher(absl::string_view s) {
|
||||||
|
*this = Eq(std::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||||
|
// s.
|
||||||
|
Matcher<absl::string_view>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||||
|
// s.
|
||||||
|
Matcher<absl::string_view>::Matcher(const char* s) {
|
||||||
|
*this = Eq(std::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||||
|
// s.
|
||||||
|
Matcher<absl::string_view>::Matcher(absl::string_view s) {
|
||||||
|
*this = Eq(std::string(s));
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_ABSL
|
||||||
|
|
||||||
|
} // namespace testing
|
|
@ -31,16 +31,20 @@
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <map> // Used in ThreadLocal.
|
# include <map> // Used in ThreadLocal.
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# include <crtdbg.h>
|
||||||
|
# endif // _MSC_VER
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
@ -51,6 +55,14 @@
|
||||||
# include <mach/vm_map.h>
|
# include <mach/vm_map.h>
|
||||||
#endif // GTEST_OS_MAC
|
#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
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GTEST_OS_QNX
|
#if GTEST_OS_QNX
|
||||||
# include <devctl.h>
|
# include <devctl.h>
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
|
@ -105,7 +117,7 @@ T ReadProcFileField(const std::string& filename, int field) {
|
||||||
size_t GetThreadCount() {
|
size_t GetThreadCount() {
|
||||||
const std::string filename =
|
const std::string filename =
|
||||||
(Message() << "/proc/" << getpid() << "/stat").GetString();
|
(Message() << "/proc/" << getpid() << "/stat").GetString();
|
||||||
return ReadProcFileField<int>(filename, 19);
|
return ReadProcFileField<size_t>(filename, 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif GTEST_OS_MAC
|
#elif GTEST_OS_MAC
|
||||||
|
@ -127,6 +139,81 @@ size_t GetThreadCount() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
|
||||||
|
GTEST_OS_NETBSD
|
||||||
|
|
||||||
|
#if GTEST_OS_NETBSD
|
||||||
|
#undef KERN_PROC
|
||||||
|
#define KERN_PROC KERN_PROC2
|
||||||
|
#define kinfo_proc kinfo_proc2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GTEST_OS_DRAGONFLY
|
||||||
|
#define KP_NLWP(kp) (kp.kp_nthreads)
|
||||||
|
#elif GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
|
||||||
|
#define KP_NLWP(kp) (kp.ki_numthreads)
|
||||||
|
#elif GTEST_OS_NETBSD
|
||||||
|
#define KP_NLWP(kp) (kp.p_nlwps)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Returns the number of threads running in the process, or 0 to indicate that
|
||||||
|
// we cannot detect it.
|
||||||
|
size_t GetThreadCount() {
|
||||||
|
int mib[] = {
|
||||||
|
CTL_KERN,
|
||||||
|
KERN_PROC,
|
||||||
|
KERN_PROC_PID,
|
||||||
|
getpid(),
|
||||||
|
#if GTEST_OS_NETBSD
|
||||||
|
sizeof(struct kinfo_proc),
|
||||||
|
1,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
u_int miblen = sizeof(mib) / sizeof(mib[0]);
|
||||||
|
struct kinfo_proc info;
|
||||||
|
size_t size = sizeof(info);
|
||||||
|
if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<size_t>(KP_NLWP(info));
|
||||||
|
}
|
||||||
|
#elif GTEST_OS_OPENBSD
|
||||||
|
|
||||||
|
// Returns the number of threads running in the process, or 0 to indicate that
|
||||||
|
// 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,
|
||||||
|
};
|
||||||
|
u_int miblen = sizeof(mib) / sizeof(mib[0]);
|
||||||
|
|
||||||
|
// get number of structs
|
||||||
|
size_t size;
|
||||||
|
if (sysctl(mib, miblen, NULL, &size, NULL, 0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mib[5] = size / mib[4];
|
||||||
|
|
||||||
|
// populate array of structs
|
||||||
|
struct kinfo_proc info[mib[5]];
|
||||||
|
if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exclude empty members
|
||||||
|
int nthreads = 0;
|
||||||
|
for (int i = 0; i < size / mib[4]; i++) {
|
||||||
|
if (info[i].p_tid != -1)
|
||||||
|
nthreads++;
|
||||||
|
}
|
||||||
|
return nthreads;
|
||||||
|
}
|
||||||
|
|
||||||
#elif GTEST_OS_QNX
|
#elif GTEST_OS_QNX
|
||||||
|
|
||||||
// Returns the number of threads running in the process, or 0 to indicate that
|
// Returns the number of threads running in the process, or 0 to indicate that
|
||||||
|
@ -138,7 +225,7 @@ size_t GetThreadCount() {
|
||||||
}
|
}
|
||||||
procfs_info process_info;
|
procfs_info process_info;
|
||||||
const int status =
|
const int status =
|
||||||
devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
|
devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), nullptr);
|
||||||
close(fd);
|
close(fd);
|
||||||
if (status == EOK) {
|
if (status == EOK) {
|
||||||
return static_cast<size_t>(process_info.num_threads);
|
return static_cast<size_t>(process_info.num_threads);
|
||||||
|
@ -152,7 +239,7 @@ size_t GetThreadCount() {
|
||||||
size_t GetThreadCount() {
|
size_t GetThreadCount() {
|
||||||
struct procentry64 entry;
|
struct procentry64 entry;
|
||||||
pid_t pid = getpid();
|
pid_t pid = getpid();
|
||||||
int status = getprocs64(&entry, sizeof(entry), NULL, 0, &pid, 1);
|
int status = getprocs64(&entry, sizeof(entry), nullptr, 0, &pid, 1);
|
||||||
if (status == 1) {
|
if (status == 1) {
|
||||||
return entry.pi_thcount;
|
return entry.pi_thcount;
|
||||||
} else {
|
} else {
|
||||||
|
@ -192,7 +279,7 @@ size_t GetThreadCount() {
|
||||||
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
||||||
|
|
||||||
void SleepMilliseconds(int n) {
|
void SleepMilliseconds(int n) {
|
||||||
::Sleep(n);
|
::Sleep(static_cast<DWORD>(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoHandle::AutoHandle()
|
AutoHandle::AutoHandle()
|
||||||
|
@ -230,15 +317,15 @@ void AutoHandle::Reset(HANDLE handle) {
|
||||||
bool AutoHandle::IsCloseable() const {
|
bool AutoHandle::IsCloseable() const {
|
||||||
// Different Windows APIs may use either of these values to represent an
|
// Different Windows APIs may use either of these values to represent an
|
||||||
// invalid handle.
|
// invalid handle.
|
||||||
return handle_ != NULL && handle_ != INVALID_HANDLE_VALUE;
|
return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification::Notification()
|
Notification::Notification()
|
||||||
: event_(::CreateEvent(NULL, // Default security attributes.
|
: event_(::CreateEvent(nullptr, // Default security attributes.
|
||||||
TRUE, // Do not reset automatically.
|
TRUE, // Do not reset automatically.
|
||||||
FALSE, // Initially unset.
|
FALSE, // Initially unset.
|
||||||
NULL)) { // Anonymous event.
|
nullptr)) { // Anonymous event.
|
||||||
GTEST_CHECK_(event_.Get() != NULL);
|
GTEST_CHECK_(event_.Get() != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notification::Notify() {
|
void Notification::Notify() {
|
||||||
|
@ -261,13 +348,10 @@ Mutex::Mutex()
|
||||||
Mutex::~Mutex() {
|
Mutex::~Mutex() {
|
||||||
// Static mutexes are leaked intentionally. It is not thread-safe to try
|
// Static mutexes are leaked intentionally. It is not thread-safe to try
|
||||||
// to clean them up.
|
// to clean them up.
|
||||||
// FIXME: Switch to Slim Reader/Writer (SRW) Locks, which requires
|
|
||||||
// nothing to clean it up but is available only on Vista and later.
|
|
||||||
// https://docs.microsoft.com/en-us/windows/desktop/Sync/slim-reader-writer--srw--locks
|
|
||||||
if (type_ == kDynamic) {
|
if (type_ == kDynamic) {
|
||||||
::DeleteCriticalSection(critical_section_);
|
::DeleteCriticalSection(critical_section_);
|
||||||
delete critical_section_;
|
delete critical_section_;
|
||||||
critical_section_ = NULL;
|
critical_section_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,6 +380,7 @@ void Mutex::AssertHeld() {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
// Use the RAII idiom to flag mem allocs that are intentionally never
|
// Use the RAII idiom to flag mem allocs that are intentionally never
|
||||||
// deallocated. The motivation is to silence the false positive mem leaks
|
// deallocated. The motivation is to silence the false positive mem leaks
|
||||||
// that are reported by the debug version of MS's CRT which can only detect
|
// that are reported by the debug version of MS's CRT which can only detect
|
||||||
|
@ -308,19 +393,15 @@ class MemoryIsNotDeallocated
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
|
MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
|
||||||
#ifdef _MSC_VER
|
|
||||||
old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||||
// Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
|
// Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
|
||||||
// doesn't report mem leak if there's no matching deallocation.
|
// doesn't report mem leak if there's no matching deallocation.
|
||||||
_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
|
_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
|
||||||
#endif // _MSC_VER
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~MemoryIsNotDeallocated() {
|
~MemoryIsNotDeallocated() {
|
||||||
#ifdef _MSC_VER
|
|
||||||
// Restore the original _CRTDBG_ALLOC_MEM_DF flag
|
// Restore the original _CRTDBG_ALLOC_MEM_DF flag
|
||||||
_CrtSetDbgFlag(old_crtdbg_flag_);
|
_CrtSetDbgFlag(old_crtdbg_flag_);
|
||||||
#endif // _MSC_VER
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -328,6 +409,7 @@ class MemoryIsNotDeallocated
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
|
||||||
};
|
};
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -343,7 +425,9 @@ void Mutex::ThreadSafeLazyInit() {
|
||||||
owner_thread_id_ = 0;
|
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;
|
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||||
|
#endif // _MSC_VER
|
||||||
critical_section_ = new CRITICAL_SECTION;
|
critical_section_ = new CRITICAL_SECTION;
|
||||||
}
|
}
|
||||||
::InitializeCriticalSection(critical_section_);
|
::InitializeCriticalSection(critical_section_);
|
||||||
|
@ -384,17 +468,16 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
||||||
Notification* thread_can_start) {
|
Notification* thread_can_start) {
|
||||||
ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
|
ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
|
||||||
DWORD thread_id;
|
DWORD thread_id;
|
||||||
// FIXME: Consider to use _beginthreadex instead.
|
|
||||||
HANDLE thread_handle = ::CreateThread(
|
HANDLE thread_handle = ::CreateThread(
|
||||||
NULL, // Default security.
|
nullptr, // Default security.
|
||||||
0, // Default stack size.
|
0, // Default stack size.
|
||||||
&ThreadWithParamSupport::ThreadMain,
|
&ThreadWithParamSupport::ThreadMain,
|
||||||
param, // Parameter to ThreadMainStatic
|
param, // Parameter to ThreadMainStatic
|
||||||
0x0, // Default creation flags.
|
0x0, // Default creation flags.
|
||||||
&thread_id); // Need a valid pointer for the call to work under Win98.
|
&thread_id); // Need a valid pointer for the call to work under Win98.
|
||||||
GTEST_CHECK_(thread_handle != NULL) << "CreateThread failed with error "
|
GTEST_CHECK_(thread_handle != nullptr)
|
||||||
<< ::GetLastError() << ".";
|
<< "CreateThread failed with error " << ::GetLastError() << ".";
|
||||||
if (thread_handle == NULL) {
|
if (thread_handle == nullptr) {
|
||||||
delete param;
|
delete param;
|
||||||
}
|
}
|
||||||
return thread_handle;
|
return thread_handle;
|
||||||
|
@ -406,15 +489,15 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
||||||
: runnable_(runnable),
|
: runnable_(runnable),
|
||||||
thread_can_start_(thread_can_start) {
|
thread_can_start_(thread_can_start) {
|
||||||
}
|
}
|
||||||
scoped_ptr<Runnable> runnable_;
|
std::unique_ptr<Runnable> runnable_;
|
||||||
// Does not own.
|
// Does not own.
|
||||||
Notification* thread_can_start_;
|
Notification* thread_can_start_;
|
||||||
};
|
};
|
||||||
|
|
||||||
static DWORD WINAPI ThreadMain(void* ptr) {
|
static DWORD WINAPI ThreadMain(void* ptr) {
|
||||||
// Transfers ownership.
|
// Transfers ownership.
|
||||||
scoped_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
|
std::unique_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
|
||||||
if (param->thread_can_start_ != NULL)
|
if (param->thread_can_start_ != nullptr)
|
||||||
param->thread_can_start_->WaitForNotification();
|
param->thread_can_start_->WaitForNotification();
|
||||||
param->runnable_->Run();
|
param->runnable_->Run();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -472,7 +555,7 @@ class ThreadLocalRegistryImpl {
|
||||||
thread_local_values
|
thread_local_values
|
||||||
.insert(std::make_pair(
|
.insert(std::make_pair(
|
||||||
thread_local_instance,
|
thread_local_instance,
|
||||||
linked_ptr<ThreadLocalValueHolderBase>(
|
std::shared_ptr<ThreadLocalValueHolderBase>(
|
||||||
thread_local_instance->NewValueForCurrentThread())))
|
thread_local_instance->NewValueForCurrentThread())))
|
||||||
.first;
|
.first;
|
||||||
}
|
}
|
||||||
|
@ -481,7 +564,7 @@ class ThreadLocalRegistryImpl {
|
||||||
|
|
||||||
static void OnThreadLocalDestroyed(
|
static void OnThreadLocalDestroyed(
|
||||||
const ThreadLocalBase* thread_local_instance) {
|
const ThreadLocalBase* thread_local_instance) {
|
||||||
std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
|
std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
|
||||||
// Clean up the ThreadLocalValues data structure while holding the lock, but
|
// Clean up the ThreadLocalValues data structure while holding the lock, but
|
||||||
// defer the destruction of the ThreadLocalValueHolderBases.
|
// defer the destruction of the ThreadLocalValueHolderBases.
|
||||||
{
|
{
|
||||||
|
@ -509,7 +592,7 @@ class ThreadLocalRegistryImpl {
|
||||||
|
|
||||||
static void OnThreadExit(DWORD thread_id) {
|
static void OnThreadExit(DWORD thread_id) {
|
||||||
GTEST_CHECK_(thread_id != 0) << ::GetLastError();
|
GTEST_CHECK_(thread_id != 0) << ::GetLastError();
|
||||||
std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
|
std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
|
||||||
// Clean up the ThreadIdToThreadLocals data structure while holding the
|
// Clean up the ThreadIdToThreadLocals data structure while holding the
|
||||||
// lock, but defer the destruction of the ThreadLocalValueHolderBases.
|
// lock, but defer the destruction of the ThreadLocalValueHolderBases.
|
||||||
{
|
{
|
||||||
|
@ -536,7 +619,8 @@ class ThreadLocalRegistryImpl {
|
||||||
private:
|
private:
|
||||||
// In a particular thread, maps a ThreadLocal object to its value.
|
// In a particular thread, maps a ThreadLocal object to its value.
|
||||||
typedef std::map<const ThreadLocalBase*,
|
typedef std::map<const ThreadLocalBase*,
|
||||||
linked_ptr<ThreadLocalValueHolderBase> > ThreadLocalValues;
|
std::shared_ptr<ThreadLocalValueHolderBase> >
|
||||||
|
ThreadLocalValues;
|
||||||
// Stores all ThreadIdToThreadLocals having values in a thread, indexed by
|
// Stores all ThreadIdToThreadLocals having values in a thread, indexed by
|
||||||
// thread's ID.
|
// thread's ID.
|
||||||
typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
|
typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
|
||||||
|
@ -551,18 +635,17 @@ class ThreadLocalRegistryImpl {
|
||||||
HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
|
HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
|
||||||
FALSE,
|
FALSE,
|
||||||
thread_id);
|
thread_id);
|
||||||
GTEST_CHECK_(thread != NULL);
|
GTEST_CHECK_(thread != nullptr);
|
||||||
// We need to pass a valid thread ID pointer into CreateThread for it
|
// We need to pass a valid thread ID pointer into CreateThread for it
|
||||||
// to work correctly under Win98.
|
// to work correctly under Win98.
|
||||||
DWORD watcher_thread_id;
|
DWORD watcher_thread_id;
|
||||||
HANDLE watcher_thread = ::CreateThread(
|
HANDLE watcher_thread = ::CreateThread(
|
||||||
NULL, // Default security.
|
nullptr, // Default security.
|
||||||
0, // Default stack size
|
0, // Default stack size
|
||||||
&ThreadLocalRegistryImpl::WatcherThreadFunc,
|
&ThreadLocalRegistryImpl::WatcherThreadFunc,
|
||||||
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
|
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
|
||||||
CREATE_SUSPENDED,
|
CREATE_SUSPENDED, &watcher_thread_id);
|
||||||
&watcher_thread_id);
|
GTEST_CHECK_(watcher_thread != nullptr);
|
||||||
GTEST_CHECK_(watcher_thread != NULL);
|
|
||||||
// Give the watcher thread the same priority as ours to avoid being
|
// Give the watcher thread the same priority as ours to avoid being
|
||||||
// blocked by it.
|
// blocked by it.
|
||||||
::SetThreadPriority(watcher_thread,
|
::SetThreadPriority(watcher_thread,
|
||||||
|
@ -587,7 +670,9 @@ class ThreadLocalRegistryImpl {
|
||||||
// Returns map of thread local instances.
|
// Returns map of thread local instances.
|
||||||
static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
|
static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
|
||||||
mutex_.AssertHeld();
|
mutex_.AssertHeld();
|
||||||
|
#ifdef _MSC_VER
|
||||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||||
|
#endif // _MSC_VER
|
||||||
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
|
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
@ -630,7 +715,7 @@ RE::~RE() {
|
||||||
free(const_cast<char*>(pattern_));
|
free(const_cast<char*>(pattern_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff regular expression re matches the entire str.
|
// Returns true if and only if regular expression re matches the entire str.
|
||||||
bool RE::FullMatch(const char* str, const RE& re) {
|
bool RE::FullMatch(const char* str, const RE& re) {
|
||||||
if (!re.is_valid_) return false;
|
if (!re.is_valid_) return false;
|
||||||
|
|
||||||
|
@ -638,8 +723,8 @@ bool RE::FullMatch(const char* str, const RE& re) {
|
||||||
return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
|
return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff regular expression re matches a substring of str
|
// Returns true if and only if regular expression re matches a substring of
|
||||||
// (including str itself).
|
// str (including str itself).
|
||||||
bool RE::PartialMatch(const char* str, const RE& re) {
|
bool RE::PartialMatch(const char* str, const RE& re) {
|
||||||
if (!re.is_valid_) return false;
|
if (!re.is_valid_) return false;
|
||||||
|
|
||||||
|
@ -679,14 +764,14 @@ void RE::Init(const char* regex) {
|
||||||
|
|
||||||
#elif GTEST_USES_SIMPLE_RE
|
#elif GTEST_USES_SIMPLE_RE
|
||||||
|
|
||||||
// Returns true iff ch appears anywhere in str (excluding the
|
// Returns true if and only if ch appears anywhere in str (excluding the
|
||||||
// terminating '\0' character).
|
// terminating '\0' character).
|
||||||
bool IsInSet(char ch, const char* str) {
|
bool IsInSet(char ch, const char* str) {
|
||||||
return ch != '\0' && strchr(str, ch) != NULL;
|
return ch != '\0' && strchr(str, ch) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff ch belongs to the given classification. Unlike
|
// Returns true if and only if ch belongs to the given classification.
|
||||||
// similar functions in <ctype.h>, these aren't affected by the
|
// Unlike similar functions in <ctype.h>, these aren't affected by the
|
||||||
// current locale.
|
// current locale.
|
||||||
bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
|
bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
|
||||||
bool IsAsciiPunct(char ch) {
|
bool IsAsciiPunct(char ch) {
|
||||||
|
@ -699,13 +784,13 @@ bool IsAsciiWordChar(char ch) {
|
||||||
('0' <= ch && ch <= '9') || ch == '_';
|
('0' <= ch && ch <= '9') || ch == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff "\\c" is a supported escape sequence.
|
// Returns true if and only if "\\c" is a supported escape sequence.
|
||||||
bool IsValidEscape(char c) {
|
bool IsValidEscape(char c) {
|
||||||
return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
|
return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff the given atom (specified by escaped and pattern)
|
// Returns true if and only if the given atom (specified by escaped and
|
||||||
// matches ch. The result is undefined if the atom is invalid.
|
// pattern) matches ch. The result is undefined if the atom is invalid.
|
||||||
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
||||||
if (escaped) { // "\\p" where p is pattern_char.
|
if (escaped) { // "\\p" where p is pattern_char.
|
||||||
switch (pattern_char) {
|
switch (pattern_char) {
|
||||||
|
@ -736,17 +821,14 @@ static std::string FormatRegexSyntaxError(const char* regex, int index) {
|
||||||
// Generates non-fatal failures and returns false if regex is invalid;
|
// Generates non-fatal failures and returns false if regex is invalid;
|
||||||
// otherwise returns true.
|
// otherwise returns true.
|
||||||
bool ValidateRegex(const char* regex) {
|
bool ValidateRegex(const char* regex) {
|
||||||
if (regex == NULL) {
|
if (regex == nullptr) {
|
||||||
// FIXME: fix the source file location in the
|
|
||||||
// assertion failures to match where the regex is used in user
|
|
||||||
// code.
|
|
||||||
ADD_FAILURE() << "NULL is not a valid simple regular expression.";
|
ADD_FAILURE() << "NULL is not a valid simple regular expression.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_valid = true;
|
bool is_valid = true;
|
||||||
|
|
||||||
// True iff ?, *, or + can follow the previous atom.
|
// True if and only if ?, *, or + can follow the previous atom.
|
||||||
bool prev_repeatable = false;
|
bool prev_repeatable = false;
|
||||||
for (int i = 0; regex[i]; i++) {
|
for (int i = 0; regex[i]; i++) {
|
||||||
if (regex[i] == '\\') { // An escape sequence
|
if (regex[i] == '\\') { // An escape sequence
|
||||||
|
@ -822,8 +904,8 @@ bool MatchRepetitionAndRegexAtHead(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff regex matches a prefix of str. regex must be a
|
// Returns true if and only if regex matches a prefix of str. regex must
|
||||||
// valid simple regular expression and not start with "^", or the
|
// be a valid simple regular expression and not start with "^", or the
|
||||||
// result is undefined.
|
// result is undefined.
|
||||||
bool MatchRegexAtHead(const char* regex, const char* str) {
|
bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||||
if (*regex == '\0') // An empty regex matches a prefix of anything.
|
if (*regex == '\0') // An empty regex matches a prefix of anything.
|
||||||
|
@ -853,8 +935,8 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff regex matches any substring of str. regex must be
|
// Returns true if and only if regex matches any substring of str. regex must
|
||||||
// a valid simple regular expression, or the result is undefined.
|
// be a valid simple regular expression, or the result is undefined.
|
||||||
//
|
//
|
||||||
// The algorithm is recursive, but the recursion depth doesn't exceed
|
// The algorithm is recursive, but the recursion depth doesn't exceed
|
||||||
// the regex length, so we won't need to worry about running out of
|
// the regex length, so we won't need to worry about running out of
|
||||||
|
@ -862,8 +944,7 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||||
// exponential with respect to the regex length + the string length,
|
// exponential with respect to the regex length + the string length,
|
||||||
// but usually it's must faster (often close to linear).
|
// but usually it's must faster (often close to linear).
|
||||||
bool MatchRegexAnywhere(const char* regex, const char* str) {
|
bool MatchRegexAnywhere(const char* regex, const char* str) {
|
||||||
if (regex == NULL || str == NULL)
|
if (regex == nullptr || str == nullptr) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
if (*regex == '^')
|
if (*regex == '^')
|
||||||
return MatchRegexAtHead(regex + 1, str);
|
return MatchRegexAtHead(regex + 1, str);
|
||||||
|
@ -883,21 +964,21 @@ RE::~RE() {
|
||||||
free(const_cast<char*>(full_pattern_));
|
free(const_cast<char*>(full_pattern_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff regular expression re matches the entire str.
|
// Returns true if and only if regular expression re matches the entire str.
|
||||||
bool RE::FullMatch(const char* str, const RE& re) {
|
bool RE::FullMatch(const char* str, const RE& re) {
|
||||||
return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
|
return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff regular expression re matches a substring of str
|
// Returns true if and only if regular expression re matches a substring of
|
||||||
// (including str itself).
|
// str (including str itself).
|
||||||
bool RE::PartialMatch(const char* str, const RE& re) {
|
bool RE::PartialMatch(const char* str, const RE& re) {
|
||||||
return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
|
return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes an RE from its string representation.
|
// Initializes an RE from its string representation.
|
||||||
void RE::Init(const char* regex) {
|
void RE::Init(const char* regex) {
|
||||||
pattern_ = full_pattern_ = NULL;
|
pattern_ = full_pattern_ = nullptr;
|
||||||
if (regex != NULL) {
|
if (regex != nullptr) {
|
||||||
pattern_ = posix::StrDup(regex);
|
pattern_ = posix::StrDup(regex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,7 +1016,7 @@ const char kUnknownFile[] = "unknown file";
|
||||||
// Formats a source file path and a line number as they would appear
|
// 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.
|
// 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 == NULL ? kUnknownFile : file);
|
const std::string file_name(file == nullptr ? kUnknownFile : file);
|
||||||
|
|
||||||
if (line < 0) {
|
if (line < 0) {
|
||||||
return file_name + ":";
|
return file_name + ":";
|
||||||
|
@ -954,7 +1035,7 @@ GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
|
||||||
// to the file location it produces, unlike FormatFileLocation().
|
// to the file location it produces, unlike FormatFileLocation().
|
||||||
GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
|
GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
|
||||||
const char* file, int line) {
|
const char* file, int line) {
|
||||||
const std::string file_name(file == NULL ? kUnknownFile : file);
|
const std::string file_name(file == nullptr ? kUnknownFile : file);
|
||||||
|
|
||||||
if (line < 0)
|
if (line < 0)
|
||||||
return file_name;
|
return file_name;
|
||||||
|
@ -1021,20 +1102,22 @@ class CapturedStream {
|
||||||
// code as part of a regular standalone executable, which doesn't
|
// code as part of a regular standalone executable, which doesn't
|
||||||
// run in a Dalvik process (e.g. when running it through 'adb shell').
|
// run in a Dalvik process (e.g. when running it through 'adb shell').
|
||||||
//
|
//
|
||||||
// The location /sdcard is directly accessible from native code
|
// The location /data/local/tmp is directly accessible from native code.
|
||||||
// and is the only location (unofficially) supported by the Android
|
// '/sdcard' and other variants cannot be relied on, as they are not
|
||||||
// team. It's generally a symlink to the real SD Card mount point
|
// guaranteed to be mounted, or may have a delay in mounting.
|
||||||
// which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or
|
char name_template[] = "/data/local/tmp/gtest_captured_stream.XXXXXX";
|
||||||
// other OEM-customized locations. Never rely on these, and always
|
|
||||||
// use /sdcard.
|
|
||||||
char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
|
|
||||||
# else
|
# else
|
||||||
char name_template[] = "/tmp/captured_stream.XXXXXX";
|
char name_template[] = "/tmp/captured_stream.XXXXXX";
|
||||||
# endif // GTEST_OS_LINUX_ANDROID
|
# endif // GTEST_OS_LINUX_ANDROID
|
||||||
const int captured_fd = mkstemp(name_template);
|
const int captured_fd = mkstemp(name_template);
|
||||||
|
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;
|
filename_ = name_template;
|
||||||
# endif // GTEST_OS_WINDOWS
|
# endif // GTEST_OS_WINDOWS
|
||||||
fflush(NULL);
|
fflush(nullptr);
|
||||||
dup2(captured_fd, fd_);
|
dup2(captured_fd, fd_);
|
||||||
close(captured_fd);
|
close(captured_fd);
|
||||||
}
|
}
|
||||||
|
@ -1046,13 +1129,17 @@ class CapturedStream {
|
||||||
std::string GetCapturedString() {
|
std::string GetCapturedString() {
|
||||||
if (uncaptured_fd_ != -1) {
|
if (uncaptured_fd_ != -1) {
|
||||||
// Restores the original stream.
|
// Restores the original stream.
|
||||||
fflush(NULL);
|
fflush(nullptr);
|
||||||
dup2(uncaptured_fd_, fd_);
|
dup2(uncaptured_fd_, fd_);
|
||||||
close(uncaptured_fd_);
|
close(uncaptured_fd_);
|
||||||
uncaptured_fd_ = -1;
|
uncaptured_fd_ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* const file = posix::FOpen(filename_.c_str(), "r");
|
FILE* const file = posix::FOpen(filename_.c_str(), "r");
|
||||||
|
if (file == nullptr) {
|
||||||
|
GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_
|
||||||
|
<< " for capturing stream.";
|
||||||
|
}
|
||||||
const std::string content = ReadEntireFile(file);
|
const std::string content = ReadEntireFile(file);
|
||||||
posix::FClose(file);
|
posix::FClose(file);
|
||||||
return content;
|
return content;
|
||||||
|
@ -1069,13 +1156,13 @@ class CapturedStream {
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
||||||
|
|
||||||
static CapturedStream* g_captured_stderr = NULL;
|
static CapturedStream* g_captured_stderr = nullptr;
|
||||||
static CapturedStream* g_captured_stdout = NULL;
|
static CapturedStream* g_captured_stdout = nullptr;
|
||||||
|
|
||||||
// Starts capturing an output stream (stdout/stderr).
|
// Starts capturing an output stream (stdout/stderr).
|
||||||
static void CaptureStream(int fd, const char* stream_name,
|
static void CaptureStream(int fd, const char* stream_name,
|
||||||
CapturedStream** stream) {
|
CapturedStream** stream) {
|
||||||
if (*stream != NULL) {
|
if (*stream != nullptr) {
|
||||||
GTEST_LOG_(FATAL) << "Only one " << stream_name
|
GTEST_LOG_(FATAL) << "Only one " << stream_name
|
||||||
<< " capturer can exist at a time.";
|
<< " capturer can exist at a time.";
|
||||||
}
|
}
|
||||||
|
@ -1087,7 +1174,7 @@ static std::string GetCapturedStream(CapturedStream** captured_stream) {
|
||||||
const std::string content = (*captured_stream)->GetCapturedString();
|
const std::string content = (*captured_stream)->GetCapturedString();
|
||||||
|
|
||||||
delete *captured_stream;
|
delete *captured_stream;
|
||||||
*captured_stream = NULL;
|
*captured_stream = nullptr;
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
@ -1146,10 +1233,11 @@ std::string ReadEntireFile(FILE* file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
static const std::vector<std::string>* g_injected_test_argvs = NULL; // Owned.
|
static const std::vector<std::string>* g_injected_test_argvs =
|
||||||
|
nullptr; // Owned.
|
||||||
|
|
||||||
std::vector<std::string> GetInjectableArgvs() {
|
std::vector<std::string> GetInjectableArgvs() {
|
||||||
if (g_injected_test_argvs != NULL) {
|
if (g_injected_test_argvs != nullptr) {
|
||||||
return *g_injected_test_argvs;
|
return *g_injected_test_argvs;
|
||||||
}
|
}
|
||||||
return GetArgvs();
|
return GetArgvs();
|
||||||
|
@ -1165,16 +1253,9 @@ void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
|
||||||
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
|
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_GLOBAL_STRING
|
|
||||||
void SetInjectableArgvs(const std::vector< ::string>& new_argvs) {
|
|
||||||
SetInjectableArgvs(
|
|
||||||
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_GLOBAL_STRING
|
|
||||||
|
|
||||||
void ClearInjectableArgvs() {
|
void ClearInjectableArgvs() {
|
||||||
delete g_injected_test_argvs;
|
delete g_injected_test_argvs;
|
||||||
g_injected_test_argvs = NULL;
|
g_injected_test_argvs = nullptr;
|
||||||
}
|
}
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
@ -1207,7 +1288,7 @@ static std::string FlagToEnvVar(const char* flag) {
|
||||||
// unchanged and returns false.
|
// 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* value) {
|
||||||
// Parses the environment variable as a decimal integer.
|
// Parses the environment variable as a decimal integer.
|
||||||
char* end = NULL;
|
char* end = nullptr;
|
||||||
const long long_value = strtol(str, &end, 10); // NOLINT
|
const long long_value = strtol(str, &end, 10); // NOLINT
|
||||||
|
|
||||||
// Has strtol() consumed all characters in the string?
|
// Has strtol() consumed all characters in the string?
|
||||||
|
@ -1246,15 +1327,15 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
|
||||||
// Reads and returns the Boolean environment variable corresponding to
|
// Reads and returns the Boolean environment variable corresponding to
|
||||||
// the given flag; if it's not set, returns default_value.
|
// the given flag; if it's not set, returns default_value.
|
||||||
//
|
//
|
||||||
// The value is considered true iff it's not "0".
|
// The value is considered true if and only if it's not "0".
|
||||||
bool BoolFromGTestEnv(const char* flag, bool default_value) {
|
bool BoolFromGTestEnv(const char* flag, bool default_value) {
|
||||||
#if defined(GTEST_GET_BOOL_FROM_ENV_)
|
#if defined(GTEST_GET_BOOL_FROM_ENV_)
|
||||||
return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
|
return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
|
||||||
#else
|
#else
|
||||||
const std::string env_var = FlagToEnvVar(flag);
|
const std::string env_var = FlagToEnvVar(flag);
|
||||||
const char* const string_value = posix::GetEnv(env_var.c_str());
|
const char* const string_value = posix::GetEnv(env_var.c_str());
|
||||||
return string_value == NULL ?
|
return string_value == nullptr ? default_value
|
||||||
default_value : strcmp(string_value, "0") != 0;
|
: strcmp(string_value, "0") != 0;
|
||||||
#endif // defined(GTEST_GET_BOOL_FROM_ENV_)
|
#endif // defined(GTEST_GET_BOOL_FROM_ENV_)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,7 +1348,7 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
||||||
#else
|
#else
|
||||||
const std::string env_var = FlagToEnvVar(flag);
|
const std::string env_var = FlagToEnvVar(flag);
|
||||||
const char* const string_value = posix::GetEnv(env_var.c_str());
|
const char* const string_value = posix::GetEnv(env_var.c_str());
|
||||||
if (string_value == NULL) {
|
if (string_value == nullptr) {
|
||||||
// The environment variable is not set.
|
// The environment variable is not set.
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
@ -1296,7 +1377,7 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
||||||
std::string OutputFlagAlsoCheckEnvVar(){
|
std::string OutputFlagAlsoCheckEnvVar(){
|
||||||
std::string default_value_for_output_flag = "";
|
std::string default_value_for_output_flag = "";
|
||||||
const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
|
const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
|
||||||
if (NULL != xml_output_file_env) {
|
if (nullptr != xml_output_file_env) {
|
||||||
default_value_for_output_flag = std::string("xml:") + xml_output_file_env;
|
default_value_for_output_flag = std::string("xml:") + xml_output_file_env;
|
||||||
}
|
}
|
||||||
return default_value_for_output_flag;
|
return default_value_for_output_flag;
|
||||||
|
@ -1310,7 +1391,7 @@ const char* StringFromGTestEnv(const char* flag, const char* default_value) {
|
||||||
#else
|
#else
|
||||||
const std::string env_var = FlagToEnvVar(flag);
|
const std::string env_var = FlagToEnvVar(flag);
|
||||||
const char* const value = posix::GetEnv(env_var.c_str());
|
const char* const value = posix::GetEnv(env_var.c_str());
|
||||||
return value == NULL ? default_value : value;
|
return value == nullptr ? default_value : value;
|
||||||
#endif // defined(GTEST_GET_STRING_FROM_ENV_)
|
#endif // defined(GTEST_GET_STRING_FROM_ENV_)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ using ::std::ostream;
|
||||||
// Prints a segment of bytes in the given object.
|
// Prints a segment of bytes in the given object.
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||||
|
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||||
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||||
size_t count, ostream* os) {
|
size_t count, ostream* os) {
|
||||||
|
@ -89,7 +90,6 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
||||||
// If the object size is bigger than kThreshold, we'll have to omit
|
// If the object size is bigger than kThreshold, we'll have to omit
|
||||||
// some details by printing only the first and the last kChunkSize
|
// some details by printing only the first and the last kChunkSize
|
||||||
// bytes.
|
// bytes.
|
||||||
// FIXME: let the user control the threshold using a flag.
|
|
||||||
if (count < kThreshold) {
|
if (count < kThreshold) {
|
||||||
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
|
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
|
||||||
} else {
|
} else {
|
||||||
|
@ -144,7 +144,8 @@ inline bool IsPrintableAscii(wchar_t c) {
|
||||||
// which is the type of c.
|
// which is the type of c.
|
||||||
template <typename UnsignedChar, typename Char>
|
template <typename UnsignedChar, typename Char>
|
||||||
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||||
switch (static_cast<wchar_t>(c)) {
|
wchar_t w_c = static_cast<wchar_t>(c);
|
||||||
|
switch (w_c) {
|
||||||
case L'\0':
|
case L'\0':
|
||||||
*os << "\\0";
|
*os << "\\0";
|
||||||
break;
|
break;
|
||||||
|
@ -176,7 +177,7 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||||
*os << "\\v";
|
*os << "\\v";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (IsPrintableAscii(c)) {
|
if (IsPrintableAscii(w_c)) {
|
||||||
*os << static_cast<char>(c);
|
*os << static_cast<char>(c);
|
||||||
return kAsIs;
|
return kAsIs;
|
||||||
} else {
|
} else {
|
||||||
|
@ -236,7 +237,7 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
|
||||||
if (format == kHexEscape || (1 <= c && c <= 9)) {
|
if (format == kHexEscape || (1 <= c && c <= 9)) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else {
|
} else {
|
||||||
*os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
|
*os << ", 0x" << String::FormatHexInt(static_cast<int>(c));
|
||||||
}
|
}
|
||||||
*os << ")";
|
*os << ")";
|
||||||
}
|
}
|
||||||
|
@ -261,6 +262,7 @@ void PrintTo(wchar_t wc, ostream* os) {
|
||||||
template <typename CharType>
|
template <typename CharType>
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||||
|
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||||
static CharFormat PrintCharsAsStringTo(
|
static CharFormat PrintCharsAsStringTo(
|
||||||
const CharType* begin, size_t len, ostream* os) {
|
const CharType* begin, size_t len, ostream* os) {
|
||||||
|
@ -291,6 +293,7 @@ static CharFormat PrintCharsAsStringTo(
|
||||||
template <typename CharType>
|
template <typename CharType>
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||||
|
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||||
static void UniversalPrintCharArray(
|
static void UniversalPrintCharArray(
|
||||||
const CharType* begin, size_t len, ostream* os) {
|
const CharType* begin, size_t len, ostream* os) {
|
||||||
|
@ -327,7 +330,7 @@ void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
|
||||||
|
|
||||||
// Prints the given C string to the ostream.
|
// Prints the given C string to the ostream.
|
||||||
void PrintTo(const char* s, ostream* os) {
|
void PrintTo(const char* s, ostream* os) {
|
||||||
if (s == NULL) {
|
if (s == nullptr) {
|
||||||
*os << "NULL";
|
*os << "NULL";
|
||||||
} else {
|
} else {
|
||||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||||
|
@ -344,11 +347,11 @@ void PrintTo(const char* s, ostream* os) {
|
||||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||||
// Prints the given wide C string to the ostream.
|
// Prints the given wide C string to the ostream.
|
||||||
void PrintTo(const wchar_t* s, ostream* os) {
|
void PrintTo(const wchar_t* s, ostream* os) {
|
||||||
if (s == NULL) {
|
if (s == nullptr) {
|
||||||
*os << "NULL";
|
*os << "NULL";
|
||||||
} else {
|
} else {
|
||||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||||
PrintCharsAsStringTo(s, std::wcslen(s), os);
|
PrintCharsAsStringTo(s, wcslen(s), os);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // wchar_t is native
|
#endif // wchar_t is native
|
||||||
|
@ -420,17 +423,6 @@ void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
// Prints a ::string object.
|
|
||||||
#if GTEST_HAS_GLOBAL_STRING
|
|
||||||
void PrintStringTo(const ::string& s, ostream* os) {
|
|
||||||
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
|
||||||
if (GTEST_FLAG(print_utf8)) {
|
|
||||||
ConditionalPrintAsText(s.data(), s.size(), os);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_GLOBAL_STRING
|
|
||||||
|
|
||||||
void PrintStringTo(const ::std::string& s, ostream* os) {
|
void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||||
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
||||||
if (GTEST_FLAG(print_utf8)) {
|
if (GTEST_FLAG(print_utf8)) {
|
||||||
|
@ -439,13 +431,6 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints a ::wstring object.
|
|
||||||
#if GTEST_HAS_GLOBAL_WSTRING
|
|
||||||
void PrintWideStringTo(const ::wstring& s, ostream* os) {
|
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
|
|
|
@ -41,18 +41,21 @@ using internal::GetUnitTestImpl;
|
||||||
// in it.
|
// in it.
|
||||||
std::string TestPartResult::ExtractSummary(const char* message) {
|
std::string TestPartResult::ExtractSummary(const char* message) {
|
||||||
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
|
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
|
||||||
return stack_trace == NULL ? message :
|
return stack_trace == nullptr ? message : std::string(message, stack_trace);
|
||||||
std::string(message, stack_trace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints a TestPartResult object.
|
// Prints a TestPartResult object.
|
||||||
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
||||||
return os
|
return os << result.file_name() << ":" << result.line_number() << ": "
|
||||||
<< result.file_name() << ":" << result.line_number() << ": "
|
<< (result.type() == TestPartResult::kSuccess
|
||||||
<< (result.type() == TestPartResult::kSuccess ? "Success" :
|
? "Success"
|
||||||
result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
|
: result.type() == TestPartResult::kSkip
|
||||||
"Non-fatal failure") << ":\n"
|
? "Skipped"
|
||||||
<< result.message() << std::endl;
|
: result.type() == TestPartResult::kFatalFailure
|
||||||
|
? "Fatal failure"
|
||||||
|
: "Non-fatal failure")
|
||||||
|
<< ":\n"
|
||||||
|
<< result.message() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a TestPartResult to the array.
|
// Appends a TestPartResult to the array.
|
||||||
|
@ -67,7 +70,7 @@ const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
|
||||||
internal::posix::Abort();
|
internal::posix::Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_[index];
|
return array_[static_cast<size_t>(index)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of TestPartResult objects in the array.
|
// Returns the number of TestPartResult objects in the array.
|
||||||
|
|
|
@ -48,7 +48,7 @@ static const char* SkipSpaces(const char* str) {
|
||||||
static std::vector<std::string> SplitIntoTestNames(const char* src) {
|
static std::vector<std::string> SplitIntoTestNames(const char* src) {
|
||||||
std::vector<std::string> name_vec;
|
std::vector<std::string> name_vec;
|
||||||
src = SkipSpaces(src);
|
src = SkipSpaces(src);
|
||||||
for (; src != NULL; src = SkipComma(src)) {
|
for (; src != nullptr; src = SkipComma(src)) {
|
||||||
name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
|
name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
|
||||||
}
|
}
|
||||||
return name_vec;
|
return name_vec;
|
||||||
|
@ -57,7 +57,7 @@ static std::vector<std::string> SplitIntoTestNames(const char* src) {
|
||||||
// Verifies that registered_tests match the test names in
|
// Verifies that registered_tests match the test names in
|
||||||
// registered_tests_; returns registered_tests if successful, or
|
// registered_tests_; returns registered_tests if successful, or
|
||||||
// aborts the program otherwise.
|
// aborts the program otherwise.
|
||||||
const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
const char* TypedTestSuitePState::VerifyRegisteredTestNames(
|
||||||
const char* file, int line, const char* registered_tests) {
|
const char* file, int line, const char* registered_tests) {
|
||||||
typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
|
typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
|
||||||
registered_ = true;
|
registered_ = true;
|
||||||
|
@ -89,7 +89,7 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||||
tests.insert(name);
|
tests.insert(name);
|
||||||
} else {
|
} else {
|
||||||
errors << "No test named " << name
|
errors << "No test named " << name
|
||||||
<< " can be found in this test case.\n";
|
<< " can be found in this test suite.\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,11 +27,21 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
void setup() {
|
||||||
|
testing::InitGoogleTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() { RUN_ALL_TESTS(); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
GTEST_API_ int main(int argc, char **argv) {
|
GTEST_API_ int main(int argc, char **argv) {
|
||||||
printf("Running main() from %s\n", __FILE__);
|
printf("Running main() from %s\n", __FILE__);
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue