mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-14 21:38:34 +00:00
[libvpx] Update to v1.12.0
This commit is contained in:
1 parent
287a71dc66
commit
b5046d2a76
572 files changed
+52900
-29493
No files matched your search
+4
-11
@@ -1,5 +1,5 @@
|
||||
URL: https://github.com/google/googletest.git
|
||||
Version: release-1.8.1
|
||||
Version: release-1.11.0
|
||||
License: BSD
|
||||
License File: LICENSE
|
||||
|
||||
@@ -13,16 +13,9 @@ generation.
|
||||
|
||||
Local Modifications:
|
||||
- Remove everything but:
|
||||
googletest-release-1.8.1/googletest/
|
||||
CHANGES
|
||||
CONTRIBUTORS
|
||||
CONTRIBUTORS
|
||||
googletest/
|
||||
include
|
||||
LICENSE
|
||||
README.md
|
||||
src
|
||||
|
||||
- Make WithParamInterface<T>::GetParam static in order to avoid
|
||||
initialization issues
|
||||
https://github.com/google/googletest/pull/1830
|
||||
- Use wcslen() instead of std::wcslen()
|
||||
https://github.com/google/googletest/pull/1899
|
||||
LICENSE
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
Changes for 1.7.0:
|
||||
|
||||
* New feature: death tests are supported on OpenBSD and in iOS
|
||||
simulator now.
|
||||
* New feature: Google Test now implements a protocol to allow
|
||||
a test runner to detect that a test program has exited
|
||||
prematurely and report it as a failure (before it would be
|
||||
falsely reported as a success if the exit code is 0).
|
||||
* New feature: Test::RecordProperty() can now be used outside of the
|
||||
lifespan of a test method, in which case it will be attributed to
|
||||
the current test case or the test program in the XML report.
|
||||
* New feature (potentially breaking): --gtest_list_tests now prints
|
||||
the type parameters and value parameters for each test.
|
||||
* Improvement: char pointers and char arrays are now escaped properly
|
||||
in failure messages.
|
||||
* Improvement: failure summary in XML reports now includes file and
|
||||
line information.
|
||||
* Improvement: the <testsuites> XML element now has a timestamp attribute.
|
||||
* Improvement: When --gtest_filter is specified, XML report now doesn't
|
||||
contain information about tests that are filtered out.
|
||||
* Fixed the bug where long --gtest_filter flag values are truncated in
|
||||
death tests.
|
||||
* Potentially breaking change: RUN_ALL_TESTS() is now implemented as a
|
||||
function instead of a macro in order to work better with Clang.
|
||||
* Compatibility fixes with C++ 11 and various platforms.
|
||||
* Bug/warning fixes.
|
||||
|
||||
Changes for 1.6.0:
|
||||
|
||||
* New feature: ADD_FAILURE_AT() for reporting a test failure at the
|
||||
given source location -- useful for writing testing utilities.
|
||||
* New feature: the universal value printer is moved from Google Mock
|
||||
to Google Test.
|
||||
* New feature: type parameters and value parameters are reported in
|
||||
the XML report now.
|
||||
* A gtest_disable_pthreads CMake option.
|
||||
* Colored output works in GNU Screen sessions now.
|
||||
* Parameters of value-parameterized tests are now printed in the
|
||||
textual output.
|
||||
* Failures from ad hoc test assertions run before RUN_ALL_TESTS() are
|
||||
now correctly reported.
|
||||
* Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to
|
||||
ostream.
|
||||
* More complete handling of exceptions.
|
||||
* GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter
|
||||
name is already used by another library.
|
||||
* --gtest_catch_exceptions is now true by default, allowing a test
|
||||
program to continue after an exception is thrown.
|
||||
* Value-parameterized test fixtures can now derive from Test and
|
||||
WithParamInterface<T> separately, easing conversion of legacy tests.
|
||||
* Death test messages are clearly marked to make them more
|
||||
distinguishable from other messages.
|
||||
* Compatibility fixes for Android, Google Native Client, MinGW, HP UX,
|
||||
PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear),
|
||||
IBM XL C++ (Visual Age C++), and C++0x.
|
||||
* Bug fixes and implementation clean-ups.
|
||||
* Potentially incompatible changes: disables the harmful 'make install'
|
||||
command in autotools.
|
||||
|
||||
Changes for 1.5.0:
|
||||
|
||||
* New feature: assertions can be safely called in multiple threads
|
||||
where the pthreads library is available.
|
||||
* New feature: predicates used inside EXPECT_TRUE() and friends
|
||||
can now generate custom failure messages.
|
||||
* New feature: Google Test can now be compiled as a DLL.
|
||||
* New feature: fused source files are included.
|
||||
* New feature: prints help when encountering unrecognized Google Test flags.
|
||||
* Experimental feature: CMake build script (requires CMake 2.6.4+).
|
||||
* Experimental feature: the Pump script for meta programming.
|
||||
* double values streamed to an assertion are printed with enough precision
|
||||
to differentiate any two different values.
|
||||
* Google Test now works on Solaris and AIX.
|
||||
* Build and test script improvements.
|
||||
* Bug fixes and implementation clean-ups.
|
||||
|
||||
Potentially breaking changes:
|
||||
|
||||
* Stopped supporting VC++ 7.1 with exceptions disabled.
|
||||
* Dropped support for 'make install'.
|
||||
|
||||
Changes for 1.4.0:
|
||||
|
||||
* New feature: the event listener API
|
||||
* New feature: test shuffling
|
||||
* New feature: the XML report format is closer to junitreport and can
|
||||
be parsed by Hudson now.
|
||||
* New feature: when a test runs under Visual Studio, its failures are
|
||||
integrated in the IDE.
|
||||
* New feature: /MD(d) versions of VC++ projects.
|
||||
* New feature: elapsed time for the tests is printed by default.
|
||||
* New feature: comes with a TR1 tuple implementation such that Boost
|
||||
is no longer needed for Combine().
|
||||
* New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends.
|
||||
* New feature: the Xcode project can now produce static gtest
|
||||
libraries in addition to a framework.
|
||||
* Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile,
|
||||
Symbian, gcc, and C++Builder.
|
||||
* Bug fixes and implementation clean-ups.
|
||||
|
||||
Changes for 1.3.0:
|
||||
|
||||
* New feature: death tests on Windows, Cygwin, and Mac.
|
||||
* New feature: ability to use Google Test assertions in other testing
|
||||
frameworks.
|
||||
* New feature: ability to run disabled test via
|
||||
--gtest_also_run_disabled_tests.
|
||||
* New feature: the --help flag for printing the usage.
|
||||
* New feature: access to Google Test flag values in user code.
|
||||
* New feature: a script that packs Google Test into one .h and one
|
||||
.cc file for easy deployment.
|
||||
* New feature: support for distributing test functions to multiple
|
||||
machines (requires support from the test runner).
|
||||
* Bug fixes and implementation clean-ups.
|
||||
|
||||
Changes for 1.2.1:
|
||||
|
||||
* Compatibility fixes for Linux IA-64 and IBM z/OS.
|
||||
* Added support for using Boost and other TR1 implementations.
|
||||
* Changes to the build scripts to support upcoming release of Google C++
|
||||
Mocking Framework.
|
||||
* Added Makefile to the distribution package.
|
||||
* Improved build instructions in README.
|
||||
|
||||
Changes for 1.2.0:
|
||||
|
||||
* New feature: value-parameterized tests.
|
||||
* New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS)
|
||||
macros.
|
||||
* Changed the XML report format to match JUnit/Ant's.
|
||||
* Added tests to the Xcode project.
|
||||
* Added scons/SConscript for building with SCons.
|
||||
* Added src/gtest-all.cc for building Google Test from a single file.
|
||||
* Fixed compatibility with Solaris and z/OS.
|
||||
* Enabled running Python tests on systems with python 2.3 installed,
|
||||
e.g. Mac OS X 10.4.
|
||||
* Bug fixes.
|
||||
|
||||
Changes for 1.1.0:
|
||||
|
||||
* New feature: type-parameterized tests.
|
||||
* New feature: exception assertions.
|
||||
* New feature: printing elapsed time of tests.
|
||||
* Improved the robustness of death tests.
|
||||
* Added an Xcode project and samples.
|
||||
* Adjusted the output format on Windows to be understandable by Visual Studio.
|
||||
* Minor bug fixes.
|
||||
|
||||
Changes for 1.0.1:
|
||||
|
||||
* Added project files for Visual Studio 7.1.
|
||||
* Fixed issues with compiling on Mac OS X.
|
||||
* Fixed issues with compiling on Cygwin.
|
||||
|
||||
Changes for 1.0.0:
|
||||
|
||||
* Initial Open Source release of Google Test
|
||||
@@ -5,33 +5,59 @@
|
||||
|
||||
Ajay Joshi <jaj@google.com>
|
||||
Balázs Dán <balazs.dan@gmail.com>
|
||||
Benoit Sigoure <tsuna@google.com>
|
||||
Bharat Mediratta <bharat@menalto.com>
|
||||
Bogdan Piloca <boo@google.com>
|
||||
Chandler Carruth <chandlerc@google.com>
|
||||
Chris Prince <cprince@google.com>
|
||||
Chris Taylor <taylorc@google.com>
|
||||
Dan Egnor <egnor@google.com>
|
||||
Dave MacLachlan <dmaclach@gmail.com>
|
||||
David Anderson <danderson@google.com>
|
||||
Dean Sturtevant
|
||||
Eric Roman <eroman@chromium.org>
|
||||
Gene Volovich <gv@cite.com>
|
||||
Hady Zalek <hady.zalek@gmail.com>
|
||||
Hal Burch <gmock@hburch.com>
|
||||
Jeffrey Yasskin <jyasskin@google.com>
|
||||
Jim Keller <jimkeller@google.com>
|
||||
Joe Walnes <joe@truemesh.com>
|
||||
Jon Wray <jwray@google.com>
|
||||
Jói Sigurðsson <joi@google.com>
|
||||
Keir Mierle <mierle@gmail.com>
|
||||
Keith Ray <keith.ray@gmail.com>
|
||||
Kenton Varda <kenton@google.com>
|
||||
Kostya Serebryany <kcc@google.com>
|
||||
Krystian Kuzniarek <krystian.kuzniarek@gmail.com>
|
||||
Lev Makhlis
|
||||
Manuel Klimek <klimek@google.com>
|
||||
Mario Tanev <radix@google.com>
|
||||
Mark Paskin
|
||||
Markus Heule <markus.heule@gmail.com>
|
||||
Matthew Simmons <simmonmt@acm.org>
|
||||
Mika Raento <mikie@iki.fi>
|
||||
Mike Bland <mbland@google.com>
|
||||
Miklós Fazekas <mfazekas@szemafor.com>
|
||||
Neal Norwitz <nnorwitz@gmail.com>
|
||||
Nermin Ozkiranartli <nermin@google.com>
|
||||
Owen Carlsen <ocarlsen@google.com>
|
||||
Paneendra Ba <paneendra@google.com>
|
||||
Pasi Valminen <pasi.valminen@gmail.com>
|
||||
Patrick Hanna <phanna@google.com>
|
||||
Patrick Riley <pfr@google.com>
|
||||
Paul Menage <menage@google.com>
|
||||
Peter Kaminski <piotrk@google.com>
|
||||
Piotr Kaminski <piotrk@google.com>
|
||||
Preston Jackson <preston.a.jackson@gmail.com>
|
||||
Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
|
||||
Russ Cox <rsc@google.com>
|
||||
Russ Rufer <russ@pentad.com>
|
||||
Sean Mcafee <eefacm@gmail.com>
|
||||
Sigurður Ásgeirsson <siggi@google.com>
|
||||
Sverre Sundsdal <sundsdal@gmail.com>
|
||||
Takeshi Yoshino <tyoshino@google.com>
|
||||
Tracy Bialik <tracy@pentad.com>
|
||||
Vadim Berman <vadimb@google.com>
|
||||
Vlad Losev <vladl@google.com>
|
||||
Wolfgang Klier <wklier@google.com>
|
||||
Zhanyong Wan <wan@google.com>
|
||||
+90
-216
@@ -2,80 +2,51 @@
|
||||
|
||||
#### Setup
|
||||
|
||||
To build Google Test and your tests that use it, you need to tell your build
|
||||
To build GoogleTest and your tests that use it, you need to tell your build
|
||||
system where to find its headers and source files. The exact way to do it
|
||||
depends on which build system you use, and is usually straightforward.
|
||||
|
||||
#### Build
|
||||
### 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 (
|
||||
[CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt))
|
||||
GoogleTest comes with a CMake build script
|
||||
([CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt))
|
||||
that can be used on a wide range of platforms ("C" stands for cross-platform.).
|
||||
If you don't have CMake installed already, you can download it for free from
|
||||
<http://www.cmake.org/>.
|
||||
|
||||
CMake works by generating native makefiles or build projects that can be used in
|
||||
the compiler environment of your choice. You can either build Google Test as a
|
||||
the compiler environment of your choice. You can either build GoogleTest as a
|
||||
standalone project or it can be incorporated into an existing CMake build for
|
||||
another project.
|
||||
|
||||
#### Standalone CMake Project
|
||||
|
||||
When building Google Test as a standalone project, the typical workflow starts
|
||||
with:
|
||||
|
||||
mkdir mybuild # Create a directory to hold the build output.
|
||||
cd mybuild
|
||||
cmake ${GTEST_DIR} # Generate native build scripts.
|
||||
|
||||
If you want to build Google Test's samples, you should replace the last command
|
||||
When building GoogleTest as a standalone project, the typical workflow starts
|
||||
with
|
||||
|
||||
cmake -Dgtest_build_samples=ON ${GTEST_DIR}
|
||||
```
|
||||
git clone https://github.com/google/googletest.git -b release-1.10.0
|
||||
cd googletest # Main directory of the cloned repository.
|
||||
mkdir build # Create a directory to hold the build output.
|
||||
cd build
|
||||
cmake .. # Generate native build scripts for GoogleTest.
|
||||
```
|
||||
|
||||
The above command also includes GoogleMock by default. And so, if you want to
|
||||
build only GoogleTest, you should replace the last command with
|
||||
|
||||
```
|
||||
cmake .. -DBUILD_GMOCK=OFF
|
||||
```
|
||||
|
||||
If you are on a \*nix system, you should now see a Makefile in the current
|
||||
directory. Just type 'make' to build gtest.
|
||||
directory. Just type `make` to build GoogleTest. And then you can simply install
|
||||
GoogleTest if you are a system administrator.
|
||||
|
||||
```
|
||||
make
|
||||
sudo make install # Install in /usr/local/ by default
|
||||
```
|
||||
|
||||
If you use Windows and have Visual Studio installed, a `gtest.sln` file and
|
||||
several `.vcproj` files will be created. You can then build them using Visual
|
||||
@@ -85,13 +56,19 @@ On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated.
|
||||
|
||||
#### Incorporating Into An Existing CMake Project
|
||||
|
||||
If you want to use gtest in a project which already uses CMake, then a more
|
||||
robust and flexible approach is to build gtest as part of that project directly.
|
||||
This is done by making the GoogleTest source code available to the main build
|
||||
and adding it using CMake's `add_subdirectory()` command. This has the
|
||||
significant advantage that the same compiler and linker settings are used
|
||||
between gtest and the rest of your project, so issues associated with using
|
||||
incompatible libraries (eg debug/release), etc. are avoided. This is
|
||||
If you want to use GoogleTest in a project which already uses CMake, the easiest
|
||||
way is to get installed libraries and headers.
|
||||
|
||||
* Import GoogleTest by using `find_package` (or `pkg_check_modules`). For
|
||||
example, if `find_package(GTest CONFIG REQUIRED)` succeeds, you can use the
|
||||
libraries as `GTest::gtest`, `GTest::gmock`.
|
||||
|
||||
And a more robust and flexible approach is to build GoogleTest as part of that
|
||||
project directly. This is done by making the GoogleTest source code available to
|
||||
the main build and adding it using CMake's `add_subdirectory()` command. This
|
||||
has the significant advantage that the same compiler and linker settings are
|
||||
used between GoogleTest and the rest of your project, so issues associated with
|
||||
using incompatible libraries (eg debug/release), etc. are avoided. This is
|
||||
particularly useful on Windows. Making GoogleTest's source code available to the
|
||||
main build can be done a few different ways:
|
||||
|
||||
@@ -105,177 +82,74 @@ main build can be done a few different ways:
|
||||
possible or appropriate. Git submodules, for example, have their own set of
|
||||
advantages and drawbacks.
|
||||
* Use CMake to download GoogleTest as part of the build's configure step. This
|
||||
is just a little more complex, but doesn't have the limitations of the other
|
||||
methods.
|
||||
approach doesn't have the limitations of the other methods.
|
||||
|
||||
The last of the above methods is implemented with a small piece of CMake code in
|
||||
a separate file (e.g. `CMakeLists.txt.in`) which is copied to the build area and
|
||||
then invoked as a sub-build _during the CMake stage_. That directory is then
|
||||
pulled into the main build with `add_subdirectory()`. For example:
|
||||
The last of the above methods is implemented with a small piece of CMake code
|
||||
that downloads and pulls the GoogleTest code into the main build.
|
||||
|
||||
New file `CMakeLists.txt.in`:
|
||||
Just add to your `CMakeLists.txt`:
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
# Specify the commit you depend on and update it regularly.
|
||||
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
|
||||
)
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
project(googletest-download NONE)
|
||||
# Now simply link against gtest or gtest_main as needed. Eg
|
||||
add_executable(example example.cpp)
|
||||
target_link_libraries(example gtest_main)
|
||||
add_test(NAME example_test COMMAND example)
|
||||
```
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG master
|
||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
|
||||
Existing build's `CMakeLists.txt`:
|
||||
|
||||
# Download and unpack googletest at configure time
|
||||
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
|
||||
if(result)
|
||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
|
||||
if(result)
|
||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
# Prevent overriding the parent project's compiler/linker
|
||||
# settings on Windows
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Add googletest directly to our build. This defines
|
||||
# the gtest and gtest_main targets.
|
||||
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
|
||||
${CMAKE_BINARY_DIR}/googletest-build
|
||||
EXCLUDE_FROM_ALL)
|
||||
|
||||
# The gtest/gtest_main targets carry header search path
|
||||
# dependencies automatically when using CMake 2.8.11 or
|
||||
# later. Otherwise we have to add them here ourselves.
|
||||
if (CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
include_directories("${gtest_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
# Now simply link against gtest or gtest_main as needed. Eg
|
||||
add_executable(example example.cpp)
|
||||
target_link_libraries(example gtest_main)
|
||||
add_test(NAME example_test COMMAND example)
|
||||
|
||||
Note that this approach requires CMake 2.8.2 or later due to its use of the
|
||||
`ExternalProject_Add()` command. The above technique is discussed in more detail
|
||||
in [this separate article](http://crascit.com/2015/07/25/cmake-gtest/) which
|
||||
also contains a link to a fully generalized implementation of the technique.
|
||||
Note that this approach requires CMake 3.14 or later due to its use of the
|
||||
`FetchContent_MakeAvailable()` command.
|
||||
|
||||
##### Visual Studio Dynamic vs Static Runtimes
|
||||
|
||||
By default, new Visual Studio projects link the C runtimes dynamically but
|
||||
Google Test links them statically. This will generate an error that looks
|
||||
GoogleTest links them statically. This will generate an error that looks
|
||||
something like the following: gtest.lib(gtest-all.obj) : error LNK2038: mismatch
|
||||
detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value
|
||||
'MDd_DynamicDebug' in main.obj
|
||||
|
||||
Google Test already has a CMake option for this: `gtest_force_shared_crt`
|
||||
GoogleTest already has a CMake option for this: `gtest_force_shared_crt`
|
||||
|
||||
Enabling this option will make gtest link the runtimes dynamically too, and
|
||||
match the project in which it is included.
|
||||
|
||||
### Legacy Build Scripts
|
||||
#### C++ Standard Version
|
||||
|
||||
Before settling on CMake, we have been providing hand-maintained build
|
||||
projects/scripts for Visual Studio, Xcode, and Autotools. While we continue to
|
||||
provide them for convenience, they are not actively maintained any more. We
|
||||
highly recommend that you follow the instructions in the above sections to
|
||||
integrate Google Test with your existing build system.
|
||||
An environment that supports C++11 is required in order to successfully build
|
||||
GoogleTest. One way to ensure this is to specify the standard in the top-level
|
||||
project, for example by using the `set(CMAKE_CXX_STANDARD 11)` command. If this
|
||||
is not feasible, for example in a C project using GoogleTest for validation,
|
||||
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:
|
||||
### Tweaking GoogleTest
|
||||
|
||||
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
|
||||
|
||||
Google Test can be used in diverse environments. The default configuration may
|
||||
GoogleTest can be used in diverse environments. The default configuration may
|
||||
not work (or may not work well) out of the box in some environments. However,
|
||||
you can easily tweak Google Test by defining control macros on the compiler
|
||||
you can easily tweak GoogleTest by defining control macros on the compiler
|
||||
command line. Generally, these macros are named like `GTEST_XYZ` and you define
|
||||
them to either 1 or 0 to enable or disable a certain feature.
|
||||
|
||||
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).
|
||||
|
||||
### 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.
|
||||
[include/gtest/internal/gtest-port.h](https://github.com/google/googletest/blob/master/googletest/include/gtest/internal/gtest-port.h).
|
||||
|
||||
### Multi-threaded Tests
|
||||
|
||||
Google Test is thread-safe where the pthread library is available. After
|
||||
`#include "gtest/gtest.h"`, you can check the `GTEST_IS_THREADSAFE` macro to see
|
||||
whether this is the case (yes if the macro is `#defined` to 1, no if it's
|
||||
undefined.).
|
||||
GoogleTest is thread-safe where the pthread library is available. After
|
||||
`#include "gtest/gtest.h"`, you can check the
|
||||
`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
|
||||
`#defined` to 1, no if it's undefined.).
|
||||
|
||||
If Google Test doesn't correctly detect whether pthread is available in your
|
||||
If GoogleTest doesn't correctly detect whether pthread is available in your
|
||||
environment, you can force it with
|
||||
|
||||
-DGTEST_HAS_PTHREAD=1
|
||||
@@ -284,16 +158,16 @@ or
|
||||
|
||||
-DGTEST_HAS_PTHREAD=0
|
||||
|
||||
When Google Test uses pthread, you may need to add flags to your compiler and/or
|
||||
When GoogleTest uses pthread, you may need to add flags to your compiler and/or
|
||||
linker to select the pthread library, or you'll get link errors. If you use the
|
||||
CMake script or the deprecated Autotools script, this is taken care of for you.
|
||||
If you use your own build script, you'll need to read your compiler and linker's
|
||||
manual to figure out what flags to add.
|
||||
CMake script, this is taken care of for you. If you use your own build script,
|
||||
you'll need to read your compiler and linker's manual to figure out what flags
|
||||
to add.
|
||||
|
||||
### As a Shared Library (DLL)
|
||||
|
||||
Google Test is compact, so most users can build and link it as a static library
|
||||
for the simplicity. You can choose to use Google Test as a shared library (known
|
||||
GoogleTest is compact, so most users can build and link it as a static library
|
||||
for the simplicity. You can choose to use GoogleTest as a shared library (known
|
||||
as a DLL on Windows) if you prefer.
|
||||
|
||||
To compile *gtest* as a shared library, add
|
||||
@@ -313,22 +187,22 @@ Note: while the above steps aren't technically necessary today when using some
|
||||
compilers (e.g. GCC), they may become necessary in the future, if we decide to
|
||||
improve the speed of loading the library (see
|
||||
<http://gcc.gnu.org/wiki/Visibility> for details). Therefore you are recommended
|
||||
to always add the above flags when using Google Test as a shared library.
|
||||
Otherwise a future release of Google Test may break your build script.
|
||||
to always add the above flags when using GoogleTest as a shared library.
|
||||
Otherwise a future release of GoogleTest may break your build script.
|
||||
|
||||
### Avoiding Macro Name Clashes
|
||||
|
||||
In C++, macros don't obey namespaces. Therefore two libraries that both define a
|
||||
macro of the same name will clash if you `#include` both definitions. In case a
|
||||
Google Test macro clashes with another library, you can force Google Test to
|
||||
GoogleTest macro clashes with another library, you can force GoogleTest to
|
||||
rename its macro to avoid the conflict.
|
||||
|
||||
Specifically, if both Google Test and some other code define macro FOO, you can
|
||||
Specifically, if both GoogleTest and some other code define macro FOO, you can
|
||||
add
|
||||
|
||||
-DGTEST_DONT_DEFINE_FOO=1
|
||||
|
||||
to the compiler flags to tell Google Test to change the macro's name from `FOO`
|
||||
to the compiler flags to tell GoogleTest to change the macro's name from `FOO`
|
||||
to `GTEST_FOO`. Currently `FOO` can be `FAIL`, `SUCCEED`, or `TEST`. For
|
||||
example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
// directly.
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
|
||||
#include "gtest/internal/gtest-death-test-internal.h"
|
||||
|
||||
@@ -97,6 +97,10 @@ GTEST_API_ bool InDeathTestChild();
|
||||
//
|
||||
// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
|
||||
//
|
||||
// The final parameter to each of these macros is a matcher applied to any data
|
||||
// the sub-process wrote to stderr. For compatibility with existing tests, a
|
||||
// bare string is interpreted as a regular expression matcher.
|
||||
//
|
||||
// On the regular expressions used in death tests:
|
||||
//
|
||||
// GOOGLETEST_CM0005 DO NOT DELETE
|
||||
@@ -161,29 +165,28 @@ GTEST_API_ bool InDeathTestChild();
|
||||
// is rarely a problem as people usually don't put the test binary
|
||||
// directory in PATH.
|
||||
//
|
||||
// FIXME: make thread-safe death tests search the PATH.
|
||||
|
||||
// Asserts that a given statement causes the program to exit, with an
|
||||
// integer exit status that satisfies predicate, and emitting error output
|
||||
// that matches regex.
|
||||
# define ASSERT_EXIT(statement, predicate, regex) \
|
||||
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
|
||||
// Asserts that a given `statement` causes the program to exit, with an
|
||||
// integer exit status that satisfies `predicate`, and emitting error output
|
||||
// that matches `matcher`.
|
||||
# define ASSERT_EXIT(statement, predicate, matcher) \
|
||||
GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_FATAL_FAILURE_)
|
||||
|
||||
// Like ASSERT_EXIT, but continues on to successive tests in the
|
||||
// test case, if any:
|
||||
# define EXPECT_EXIT(statement, predicate, regex) \
|
||||
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
|
||||
// Like `ASSERT_EXIT`, but continues on to successive tests in the
|
||||
// test suite, if any:
|
||||
# define EXPECT_EXIT(statement, predicate, matcher) \
|
||||
GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_NONFATAL_FAILURE_)
|
||||
|
||||
// Asserts that a given statement causes the program to exit, either by
|
||||
// Asserts that a given `statement` causes the program to exit, either by
|
||||
// explicitly exiting with a nonzero exit code or being killed by a
|
||||
// signal, and emitting error output that matches regex.
|
||||
# define ASSERT_DEATH(statement, regex) \
|
||||
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
||||
// signal, and emitting error output that matches `matcher`.
|
||||
# define ASSERT_DEATH(statement, matcher) \
|
||||
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
|
||||
|
||||
// Like ASSERT_DEATH, but continues on to successive tests in the
|
||||
// test case, if any:
|
||||
# define EXPECT_DEATH(statement, regex) \
|
||||
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
||||
// Like `ASSERT_DEATH`, but continues on to successive tests in the
|
||||
// test suite, if any:
|
||||
# define EXPECT_DEATH(statement, matcher) \
|
||||
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
|
||||
|
||||
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
||||
|
||||
@@ -191,11 +194,10 @@ GTEST_API_ bool InDeathTestChild();
|
||||
class GTEST_API_ ExitedWithCode {
|
||||
public:
|
||||
explicit ExitedWithCode(int exit_code);
|
||||
ExitedWithCode(const ExitedWithCode&) = default;
|
||||
void operator=(const ExitedWithCode& other) = delete;
|
||||
bool operator()(int exit_status) const;
|
||||
private:
|
||||
// No implementation - assignment is unsupported.
|
||||
void operator=(const ExitedWithCode& other);
|
||||
|
||||
const int exit_code_;
|
||||
};
|
||||
|
||||
@@ -228,7 +230,7 @@ class GTEST_API_ KilledBySignal {
|
||||
// return 12;
|
||||
// }
|
||||
//
|
||||
// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
|
||||
// TEST(TestSuite, TestDieOr12WorksInDgbAndOpt) {
|
||||
// int sideeffect = 0;
|
||||
// // Only asserts in dbg.
|
||||
// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
|
||||
@@ -277,20 +279,20 @@ class GTEST_API_ KilledBySignal {
|
||||
// This macro is used for implementing macros such as
|
||||
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
|
||||
// death tests are not supported. Those macros must compile on such systems
|
||||
// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
|
||||
// systems that support death tests. This allows one to write such a macro
|
||||
// on a system that does not support death tests and be sure that it will
|
||||
// compile on a death-test supporting system. It is exposed publicly so that
|
||||
// systems that have death-tests with stricter requirements than
|
||||
// GTEST_HAS_DEATH_TEST can write their own equivalent of
|
||||
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED.
|
||||
// if and only if EXPECT_DEATH and ASSERT_DEATH compile with the same parameters
|
||||
// on systems that support death tests. This allows one to write such a macro on
|
||||
// a system that does not support death tests and be sure that it will compile
|
||||
// on a death-test supporting system. It is exposed publicly so that systems
|
||||
// that have death-tests with stricter requirements than GTEST_HAS_DEATH_TEST
|
||||
// can write their own equivalent of EXPECT_DEATH_IF_SUPPORTED and
|
||||
// ASSERT_DEATH_IF_SUPPORTED.
|
||||
//
|
||||
// Parameters:
|
||||
// statement - A statement that a macro such as EXPECT_DEATH would test
|
||||
// for program termination. This macro has to make sure this
|
||||
// statement is compiled but not executed, to ensure that
|
||||
// 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
|
||||
// the output of statement. This parameter has to be
|
||||
// compiled but not evaluated by this macro, to ensure that
|
||||
@@ -341,4 +343,4 @@ class GTEST_API_ KilledBySignal {
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||
@@ -0,0 +1,930 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
|
||||
#include <atomic>
|
||||
#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 FooMatcherMatcher that implements the matcher interface:
|
||||
// using is_gtest_matcher = void;
|
||||
// bool MatchAndExplain(const T&, std::ostream*);
|
||||
// (MatchResultListener* can also be used instead of std::ostream*)
|
||||
// void DescribeTo(std::ostream*);
|
||||
// void DescribeNegationTo(std::ostream*);
|
||||
//
|
||||
// 2. a factory function that creates a Matcher<T> object from a
|
||||
// FooMatcherMatcher.
|
||||
|
||||
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 GTEST_API_ 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 {
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
struct SharedPayloadBase {
|
||||
std::atomic<int> ref{1};
|
||||
void Ref() { ref.fetch_add(1, std::memory_order_relaxed); }
|
||||
bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SharedPayload : SharedPayloadBase {
|
||||
explicit SharedPayload(const T& v) : value(v) {}
|
||||
explicit SharedPayload(T&& v) : value(std::move(v)) {}
|
||||
|
||||
static void Destroy(SharedPayloadBase* shared) {
|
||||
delete static_cast<SharedPayload*>(shared);
|
||||
}
|
||||
|
||||
T value;
|
||||
};
|
||||
|
||||
// An internal class for implementing Matcher<T>, which will derive
|
||||
// from it. We put functionalities common to all Matcher<T>
|
||||
// specializations here to avoid code duplication.
|
||||
template <typename T>
|
||||
class MatcherBase : private MatcherDescriberInterface {
|
||||
public:
|
||||
// Returns true if and only if the matcher matches x; also explains the
|
||||
// match result to 'listener'.
|
||||
bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
|
||||
GTEST_CHECK_(vtable_ != nullptr);
|
||||
return vtable_->match_and_explain(*this, 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 final {
|
||||
GTEST_CHECK_(vtable_ != nullptr);
|
||||
vtable_->describe(*this, os, false);
|
||||
}
|
||||
|
||||
// Describes the negation of this matcher to an ostream.
|
||||
void DescribeNegationTo(::std::ostream* os) const final {
|
||||
GTEST_CHECK_(vtable_ != nullptr);
|
||||
vtable_->describe(*this, os, true);
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if (vtable_ == nullptr) return nullptr;
|
||||
return vtable_->get_describer(*this);
|
||||
}
|
||||
|
||||
protected:
|
||||
MatcherBase() : vtable_(nullptr) {}
|
||||
|
||||
// Constructs a matcher from its implementation.
|
||||
template <typename U>
|
||||
explicit MatcherBase(const MatcherInterface<U>* impl) {
|
||||
Init(impl);
|
||||
}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
MatcherBase(M&& m) { // NOLINT
|
||||
Init(std::forward<M>(m));
|
||||
}
|
||||
|
||||
MatcherBase(const MatcherBase& other)
|
||||
: vtable_(other.vtable_), buffer_(other.buffer_) {
|
||||
if (IsShared()) buffer_.shared->Ref();
|
||||
}
|
||||
|
||||
MatcherBase& operator=(const MatcherBase& other) {
|
||||
if (this == &other) return *this;
|
||||
Destroy();
|
||||
vtable_ = other.vtable_;
|
||||
buffer_ = other.buffer_;
|
||||
if (IsShared()) buffer_.shared->Ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
MatcherBase(MatcherBase&& other)
|
||||
: vtable_(other.vtable_), buffer_(other.buffer_) {
|
||||
other.vtable_ = nullptr;
|
||||
}
|
||||
|
||||
MatcherBase& operator=(MatcherBase&& other) {
|
||||
if (this == &other) return *this;
|
||||
Destroy();
|
||||
vtable_ = other.vtable_;
|
||||
buffer_ = other.buffer_;
|
||||
other.vtable_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MatcherBase() override { Destroy(); }
|
||||
|
||||
private:
|
||||
struct VTable {
|
||||
bool (*match_and_explain)(const MatcherBase&, const T&,
|
||||
MatchResultListener*);
|
||||
void (*describe)(const MatcherBase&, std::ostream*, bool negation);
|
||||
// Returns the captured object if it implements the interface, otherwise
|
||||
// returns the MatcherBase itself.
|
||||
const MatcherDescriberInterface* (*get_describer)(const MatcherBase&);
|
||||
// Called on shared instances when the reference count reaches 0.
|
||||
void (*shared_destroy)(SharedPayloadBase*);
|
||||
};
|
||||
|
||||
bool IsShared() const {
|
||||
return vtable_ != nullptr && vtable_->shared_destroy != nullptr;
|
||||
}
|
||||
|
||||
// If the implementation uses a listener, call that.
|
||||
template <typename P>
|
||||
static auto MatchAndExplainImpl(const MatcherBase& m, const T& value,
|
||||
MatchResultListener* listener)
|
||||
-> decltype(P::Get(m).MatchAndExplain(value, listener->stream())) {
|
||||
return P::Get(m).MatchAndExplain(value, listener->stream());
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
static auto MatchAndExplainImpl(const MatcherBase& m, const T& value,
|
||||
MatchResultListener* listener)
|
||||
-> decltype(P::Get(m).MatchAndExplain(value, listener)) {
|
||||
return P::Get(m).MatchAndExplain(value, listener);
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
static void DescribeImpl(const MatcherBase& m, std::ostream* os,
|
||||
bool negation) {
|
||||
if (negation) {
|
||||
P::Get(m).DescribeNegationTo(os);
|
||||
} else {
|
||||
P::Get(m).DescribeTo(os);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
static const MatcherDescriberInterface* GetDescriberImpl(
|
||||
const MatcherBase& m) {
|
||||
// If the impl is a MatcherDescriberInterface, then return it.
|
||||
// Otherwise use MatcherBase itself.
|
||||
// This allows us to implement the GetDescriber() function without support
|
||||
// from the impl, but some users really want to get their impl back when
|
||||
// they call GetDescriber().
|
||||
// We use std::get on a tuple as a workaround of not having `if constexpr`.
|
||||
return std::get<(
|
||||
std::is_convertible<decltype(&P::Get(m)),
|
||||
const MatcherDescriberInterface*>::value
|
||||
? 1
|
||||
: 0)>(std::make_tuple(&m, &P::Get(m)));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
const VTable* GetVTable() {
|
||||
static constexpr VTable kVTable = {&MatchAndExplainImpl<P>,
|
||||
&DescribeImpl<P>, &GetDescriberImpl<P>,
|
||||
P::shared_destroy};
|
||||
return &kVTable;
|
||||
}
|
||||
|
||||
union Buffer {
|
||||
// Add some types to give Buffer some common alignment/size use cases.
|
||||
void* ptr;
|
||||
double d;
|
||||
int64_t i;
|
||||
// And add one for the out-of-line cases.
|
||||
SharedPayloadBase* shared;
|
||||
};
|
||||
|
||||
void Destroy() {
|
||||
if (IsShared() && buffer_.shared->Unref()) {
|
||||
vtable_->shared_destroy(buffer_.shared);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
static constexpr bool IsInlined() {
|
||||
return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) &&
|
||||
std::is_trivially_copy_constructible<M>::value &&
|
||||
std::is_trivially_destructible<M>::value;
|
||||
}
|
||||
|
||||
template <typename M, bool = MatcherBase::IsInlined<M>()>
|
||||
struct ValuePolicy {
|
||||
static const M& Get(const MatcherBase& m) {
|
||||
// When inlined along with Init, need to be explicit to avoid violating
|
||||
// strict aliasing rules.
|
||||
const M *ptr = static_cast<const M*>(
|
||||
static_cast<const void*>(&m.buffer_));
|
||||
return *ptr;
|
||||
}
|
||||
static void Init(MatcherBase& m, M impl) {
|
||||
::new (static_cast<void*>(&m.buffer_)) M(impl);
|
||||
}
|
||||
static constexpr auto shared_destroy = nullptr;
|
||||
};
|
||||
|
||||
template <typename M>
|
||||
struct ValuePolicy<M, false> {
|
||||
using Shared = SharedPayload<M>;
|
||||
static const M& Get(const MatcherBase& m) {
|
||||
return static_cast<Shared*>(m.buffer_.shared)->value;
|
||||
}
|
||||
template <typename Arg>
|
||||
static void Init(MatcherBase& m, Arg&& arg) {
|
||||
m.buffer_.shared = new Shared(std::forward<Arg>(arg));
|
||||
}
|
||||
static constexpr auto shared_destroy = &Shared::Destroy;
|
||||
};
|
||||
|
||||
template <typename U, bool B>
|
||||
struct ValuePolicy<const MatcherInterface<U>*, B> {
|
||||
using M = const MatcherInterface<U>;
|
||||
using Shared = SharedPayload<std::unique_ptr<M>>;
|
||||
static const M& Get(const MatcherBase& m) {
|
||||
return *static_cast<Shared*>(m.buffer_.shared)->value;
|
||||
}
|
||||
static void Init(MatcherBase& m, M* impl) {
|
||||
m.buffer_.shared = new Shared(std::unique_ptr<M>(impl));
|
||||
}
|
||||
|
||||
static constexpr auto shared_destroy = &Shared::Destroy;
|
||||
};
|
||||
|
||||
template <typename M>
|
||||
void Init(M&& m) {
|
||||
using MM = typename std::decay<M>::type;
|
||||
using Policy = ValuePolicy<MM>;
|
||||
vtable_ = GetVTable<Policy>();
|
||||
Policy::Init(*this, std::forward<M>(m));
|
||||
}
|
||||
|
||||
const VTable* vtable_;
|
||||
Buffer buffer_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// 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) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) : internal::MatcherBase<T>(std::forward<M>(m)) {} // NOLINT
|
||||
|
||||
// Implicit constructor here allows people to write
|
||||
// EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
|
||||
Matcher(T value); // NOLINT
|
||||
};
|
||||
|
||||
// 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) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<const std::string&>(std::forward<M>(m)) {}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a std::string object.
|
||||
Matcher(const std::string& s); // NOLINT
|
||||
|
||||
// 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) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<std::string>(std::forward<M>(m)) {}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a string object.
|
||||
Matcher(const std::string& s); // NOLINT
|
||||
|
||||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||
Matcher(const char* s); // NOLINT
|
||||
};
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// The following two specializations allow the user to write str
|
||||
// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
|
||||
// matcher is expected.
|
||||
template <>
|
||||
class GTEST_API_ Matcher<const internal::StringView&>
|
||||
: public internal::MatcherBase<const internal::StringView&> {
|
||||
public:
|
||||
Matcher() {}
|
||||
|
||||
explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
|
||||
: internal::MatcherBase<const internal::StringView&>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<const internal::StringView&>(std::forward<M>(m)) {
|
||||
}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a std::string object.
|
||||
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 or std::string_views directly.
|
||||
Matcher(internal::StringView s); // NOLINT
|
||||
};
|
||||
|
||||
template <>
|
||||
class GTEST_API_ Matcher<internal::StringView>
|
||||
: public internal::MatcherBase<internal::StringView> {
|
||||
public:
|
||||
Matcher() {}
|
||||
|
||||
explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
|
||||
: internal::MatcherBase<internal::StringView>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<internal::StringView>* impl)
|
||||
: internal::MatcherBase<internal::StringView>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<internal::StringView>(std::forward<M>(m)) {}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a std::string object.
|
||||
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 or std::string_views directly.
|
||||
Matcher(internal::StringView s); // NOLINT
|
||||
};
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// 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) {}
|
||||
|
||||
void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); }
|
||||
|
||||
void DescribeNegationTo(::std::ostream* os) const override {
|
||||
impl_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
bool MatchAndExplain(T x, MatchResultListener* listener) const override {
|
||||
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) {}
|
||||
|
||||
using is_gtest_matcher = void;
|
||||
|
||||
template <typename Lhs>
|
||||
bool MatchAndExplain(const Lhs& lhs, std::ostream*) const {
|
||||
return Op()(lhs, Unwrap(rhs_));
|
||||
}
|
||||
void DescribeTo(std::ostream* os) const {
|
||||
*os << D::Desc() << " ";
|
||||
UniversalPrint(Unwrap(rhs_), os);
|
||||
}
|
||||
void DescribeNegationTo(std::ostream* os) const {
|
||||
*os << D::NegatedDesc() << " ";
|
||||
UniversalPrint(Unwrap(rhs_), os);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
static const T& Unwrap(const T& v) {
|
||||
return v;
|
||||
}
|
||||
template <typename T>
|
||||
static const T& Unwrap(std::reference_wrapper<T> v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
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 >="; }
|
||||
};
|
||||
|
||||
template <typename T, typename = typename std::enable_if<
|
||||
std::is_constructible<std::string, T>::value>::type>
|
||||
using StringLike = T;
|
||||
|
||||
// Implements polymorphic matchers MatchesRegex(regex) and
|
||||
// ContainsRegex(regex), which can be used as a Matcher<T> as long as
|
||||
// T can be converted to a string.
|
||||
class MatchesRegexMatcher {
|
||||
public:
|
||||
MatchesRegexMatcher(const RE* regex, bool full_match)
|
||||
: regex_(regex), full_match_(full_match) {}
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
bool MatchAndExplain(const internal::StringView& s,
|
||||
MatchResultListener* listener) const {
|
||||
return MatchAndExplain(std::string(s), listener);
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// 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));
|
||||
}
|
||||
template <typename T = std::string>
|
||||
PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
|
||||
const internal::StringLike<T>& regex) {
|
||||
return MatchesRegex(new internal::RE(std::string(regex)));
|
||||
}
|
||||
|
||||
// Matches a string that contains regular expression 'regex'.
|
||||
// The matcher takes ownership of 'regex'.
|
||||
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
||||
const internal::RE* regex) {
|
||||
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
|
||||
}
|
||||
template <typename T = std::string>
|
||||
PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
||||
const internal::StringLike<T>& regex) {
|
||||
return ContainsRegex(new internal::RE(std::string(regex)));
|
||||
}
|
||||
|
||||
// Creates a polymorphic matcher that matches anything equal to x.
|
||||
// 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 // GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
@@ -44,10 +44,12 @@
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
@@ -106,14 +108,6 @@ class GTEST_API_ Message {
|
||||
*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.
|
||||
template <typename T>
|
||||
inline Message& operator <<(const T& val) {
|
||||
@@ -151,14 +145,13 @@ class GTEST_API_ Message {
|
||||
// as "(null)".
|
||||
template <typename T>
|
||||
inline Message& operator <<(T* const& pointer) { // NOLINT
|
||||
if (pointer == NULL) {
|
||||
if (pointer == nullptr) {
|
||||
*ss_ << "(null)";
|
||||
} else {
|
||||
*ss_ << pointer;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif // GTEST_OS_SYMBIAN
|
||||
|
||||
// Since the basic IO manipulators are overloaded for both narrow
|
||||
// and wide streams, we have to provide this specialized definition
|
||||
@@ -187,12 +180,6 @@ class GTEST_API_ Message {
|
||||
Message& operator <<(const ::std::wstring& wstr);
|
||||
#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.
|
||||
// Each '\0' character in the buffer is replaced with "\\0".
|
||||
//
|
||||
@@ -200,31 +187,8 @@ class GTEST_API_ Message {
|
||||
std::string GetString() const;
|
||||
|
||||
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.
|
||||
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
|
||||
// from implementing the assignment operator.
|
||||
@@ -252,4 +216,4 @@ std::string StreamableToString(const T& streamable) {
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||
+142
-1069
File diff suppressed because it is too large.
Load diff
-500
@@ -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_
|
||||
+425
-503
File diff suppressed because it is too large.
Load diff
@@ -33,8 +33,8 @@
|
||||
|
||||
// GOOGLETEST_CM0004 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
@@ -72,14 +72,15 @@ class GTEST_API_ ScopedFakeTestPartResultReporter
|
||||
TestPartResultArray* result);
|
||||
|
||||
// The d'tor restores the previous test part result reporter.
|
||||
virtual ~ScopedFakeTestPartResultReporter();
|
||||
~ScopedFakeTestPartResultReporter() override;
|
||||
|
||||
// Appends the TestPartResult object to the TestPartResultArray
|
||||
// received in the constructor.
|
||||
//
|
||||
// This method is from the TestPartResultReporterInterface
|
||||
// interface.
|
||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
||||
void ReportTestPartResult(const TestPartResult& result) override;
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
||||
@@ -234,4 +235,4 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
}\
|
||||
} while (::testing::internal::AlwaysFalse())
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||
@@ -29,8 +29,8 @@
|
||||
//
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
@@ -53,22 +53,20 @@ class GTEST_API_ TestPartResult {
|
||||
enum Type {
|
||||
kSuccess, // Succeeded.
|
||||
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.
|
||||
// Always use this constructor (with parameters) to create a
|
||||
// TestPartResult object.
|
||||
TestPartResult(Type a_type,
|
||||
const char* a_file_name,
|
||||
int a_line_number,
|
||||
TestPartResult(Type a_type, const char* a_file_name, int a_line_number,
|
||||
const char* a_message)
|
||||
: type_(a_type),
|
||||
file_name_(a_file_name == NULL ? "" : a_file_name),
|
||||
file_name_(a_file_name == nullptr ? "" : a_file_name),
|
||||
line_number_(a_line_number),
|
||||
summary_(ExtractSummary(a_message)),
|
||||
message_(a_message) {
|
||||
}
|
||||
message_(a_message) {}
|
||||
|
||||
// Gets the outcome of the test part.
|
||||
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
|
||||
// NULL if it's unknown.
|
||||
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,
|
||||
@@ -89,18 +87,21 @@ class GTEST_API_ TestPartResult {
|
||||
// Gets the message associated with the test part.
|
||||
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; }
|
||||
|
||||
// Returns true iff the test part failed.
|
||||
bool failed() const { return type_ != kSuccess; }
|
||||
|
||||
// Returns true iff the test part non-fatally failed.
|
||||
// Returns true if and only if the test part non-fatally failed.
|
||||
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; }
|
||||
|
||||
// Returns true if and only if the test part failed.
|
||||
bool failed() const { return fatally_failed() || nonfatally_failed(); }
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
|
||||
@@ -164,8 +165,8 @@ class GTEST_API_ HasNewFatalFailureHelper
|
||||
: public TestPartResultReporterInterface {
|
||||
public:
|
||||
HasNewFatalFailureHelper();
|
||||
virtual ~HasNewFatalFailureHelper();
|
||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
||||
~HasNewFatalFailureHelper() override;
|
||||
void ReportTestPartResult(const TestPartResult& result) override;
|
||||
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
||||
private:
|
||||
bool has_new_fatal_failure_;
|
||||
@@ -180,4 +181,4 @@ class GTEST_API_ HasNewFatalFailureHelper
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||
@@ -27,11 +27,10 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
|
||||
// This header implements typed tests and type-parameterized tests.
|
||||
|
||||
@@ -52,22 +51,22 @@ class FooTest : public testing::Test {
|
||||
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
|
||||
// the macro to parse correctly.
|
||||
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
|
||||
// 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
|
||||
// tests for this test case as you want.
|
||||
// tests for this test suite as you want.
|
||||
TYPED_TEST(FooTest, DoesBlah) {
|
||||
// Inside a test, refer to TypeParam to get the type parameter.
|
||||
// Since we are inside a derived class template, C++ requires use to
|
||||
// visit the members of FooTest via 'this'.
|
||||
// Inside a test, refer to the special name TypeParam to get the type
|
||||
// parameter. Since we are inside a derived class template, C++ requires
|
||||
// us to visit the members of FooTest via 'this'.
|
||||
TypeParam n = this->value_;
|
||||
|
||||
// To visit static members of the fixture, add the TestFixture::
|
||||
@@ -83,7 +82,7 @@ TYPED_TEST(FooTest, DoesBlah) {
|
||||
|
||||
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
|
||||
// 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
|
||||
@@ -99,7 +98,7 @@ TYPED_TEST(FooTest, HasPropertyA) { ... }
|
||||
// if (std::is_same<T, unsigned int>()) return "unsignedInt";
|
||||
// }
|
||||
// };
|
||||
// TYPED_TEST_CASE(FooTest, MyTypes, MyTypeNames);
|
||||
// TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames);
|
||||
|
||||
#endif // 0
|
||||
|
||||
@@ -126,13 +125,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
|
||||
// prefer):
|
||||
TYPED_TEST_CASE_P(FooTest);
|
||||
TYPED_TEST_SUITE_P(FooTest);
|
||||
|
||||
// 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) {
|
||||
// Inside a test, refer to TypeParam to get the type parameter.
|
||||
TypeParam n = 0;
|
||||
@@ -143,10 +142,10 @@ TYPED_TEST_P(FooTest, HasPropertyA) { ... }
|
||||
|
||||
// Now the tricky part: you need to register all test patterns before
|
||||
// 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.
|
||||
REGISTER_TYPED_TEST_CASE_P(FooTest,
|
||||
DoesBlah, HasPropertyA);
|
||||
REGISTER_TYPED_TEST_SUITE_P(FooTest,
|
||||
DoesBlah, HasPropertyA);
|
||||
|
||||
// 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
|
||||
@@ -154,61 +153,58 @@ REGISTER_TYPED_TEST_CASE_P(FooTest,
|
||||
//
|
||||
// To distinguish different instances of the pattern, the first
|
||||
// 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.
|
||||
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
|
||||
// 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,
|
||||
// INSTANTIATE_TEST_CASE_P takes an optional fourth argument which allows to
|
||||
// Similar to the optional argument of TYPED_TEST_SUITE above,
|
||||
// INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to
|
||||
// generate custom names.
|
||||
// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes, MyTypeNames);
|
||||
// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames);
|
||||
|
||||
#endif // 0
|
||||
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/internal/gtest-type-util.h"
|
||||
|
||||
// Implements typed tests.
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Expands to the name of the typedef for the type parameters of the
|
||||
// given test case.
|
||||
# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
|
||||
// given test suite.
|
||||
#define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_
|
||||
|
||||
// Expands to the name of the typedef for the NameGenerator, responsible for
|
||||
// creating the suffixes of the name.
|
||||
#define GTEST_NAME_GENERATOR_(TestCaseName) \
|
||||
gtest_type_params_##TestCaseName##_NameGenerator
|
||||
#define GTEST_NAME_GENERATOR_(TestSuiteName) \
|
||||
gtest_type_params_##TestSuiteName##_NameGenerator
|
||||
|
||||
// The 'Types' template argument below must have spaces around it
|
||||
// since some compilers may choke on '>>' when passing a template
|
||||
// instance (e.g. Types<int>)
|
||||
# define TYPED_TEST_CASE(CaseName, Types, ...) \
|
||||
typedef ::testing::internal::TypeList< Types >::type GTEST_TYPE_PARAMS_( \
|
||||
CaseName); \
|
||||
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
|
||||
#define TYPED_TEST_SUITE(CaseName, Types, ...) \
|
||||
typedef ::testing::internal::GenerateTypeList<Types>::type \
|
||||
GTEST_TYPE_PARAMS_(CaseName); \
|
||||
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
|
||||
GTEST_NAME_GENERATOR_(CaseName)
|
||||
|
||||
# define TYPED_TEST(CaseName, TestName) \
|
||||
#define TYPED_TEST(CaseName, TestName) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
|
||||
"test-name must not be empty"); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||
: public CaseName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
virtual void TestBody(); \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
static bool gtest_##CaseName##_##TestName##_registered_ \
|
||||
GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
::testing::internal::TypeParameterizedTest< \
|
||||
GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest< \
|
||||
CaseName, \
|
||||
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
TestName)>, \
|
||||
@@ -216,7 +212,8 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
||||
CaseName)>::Register("", \
|
||||
::testing::internal::CodeLocation( \
|
||||
__FILE__, __LINE__), \
|
||||
#CaseName, #TestName, 0, \
|
||||
GTEST_STRINGIFY_(CaseName), \
|
||||
GTEST_STRINGIFY_(TestName), 0, \
|
||||
::testing::internal::GenerateNames< \
|
||||
GTEST_NAME_GENERATOR_(CaseName), \
|
||||
GTEST_TYPE_PARAMS_(CaseName)>()); \
|
||||
@@ -224,83 +221,109 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
||||
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
TestName)<gtest_TypeParam_>::TestBody()
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST
|
||||
// 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_
|
||||
|
||||
// Implements type-parameterized tests.
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Expands to the namespace name that the type-parameterized tests for
|
||||
// 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.
|
||||
# define GTEST_CASE_NAMESPACE_(TestCaseName) \
|
||||
gtest_case_##TestCaseName##_
|
||||
#define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Expands to the name of the variable used to remember the names of
|
||||
// the defined tests in the given test case.
|
||||
# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
|
||||
gtest_typed_test_case_p_state_##TestCaseName##_
|
||||
// the defined tests in the given test suite.
|
||||
#define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \
|
||||
gtest_typed_test_suite_p_state_##TestSuiteName##_
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
|
||||
//
|
||||
// Expands to the name of the variable used to remember the names of
|
||||
// the registered tests in the given test case.
|
||||
# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
|
||||
gtest_registered_test_names_##TestCaseName##_
|
||||
// the registered tests in the given test suite.
|
||||
#define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \
|
||||
gtest_registered_test_names_##TestSuiteName##_
|
||||
|
||||
// The variables defined in the type-parameterized test macros are
|
||||
// static as typically these macros are used in a .h file that can be
|
||||
// #included in multiple translation units linked together.
|
||||
# define TYPED_TEST_CASE_P(CaseName) \
|
||||
static ::testing::internal::TypedTestCasePState \
|
||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
|
||||
#define TYPED_TEST_SUITE_P(SuiteName) \
|
||||
static ::testing::internal::TypedTestSuitePState \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName)
|
||||
|
||||
# define TYPED_TEST_P(CaseName, TestName) \
|
||||
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class TestName : public CaseName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||
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()
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
#define TYPED_TEST_CASE_P \
|
||||
static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \
|
||||
TYPED_TEST_SUITE_P
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
|
||||
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
||||
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
|
||||
} \
|
||||
static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) \
|
||||
GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames( \
|
||||
__FILE__, __LINE__, #__VA_ARGS__)
|
||||
#define TYPED_TEST_P(SuiteName, TestName) \
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class TestName : public SuiteName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef SuiteName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
||||
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_STRINGIFY_(TestName)); \
|
||||
} \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_SUITE_NAMESPACE_( \
|
||||
SuiteName)::TestName<gtest_TypeParam_>::TestBody()
|
||||
|
||||
// The 'Types' template argument below must have spaces around it
|
||||
// since some compilers may choke on '>>' when passing a template
|
||||
// instance (e.g. Types<int>)
|
||||
# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types, ...) \
|
||||
static bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
::testing::internal::TypeParameterizedTestCase< \
|
||||
CaseName, GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
|
||||
::testing::internal::TypeList< Types >::type>:: \
|
||||
Register(#Prefix, \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
||||
>EST_TYPED_TEST_CASE_P_STATE_(CaseName), #CaseName, \
|
||||
GTEST_REGISTERED_TEST_NAMES_(CaseName), \
|
||||
::testing::internal::GenerateNames< \
|
||||
::testing::internal::NameGeneratorSelector< \
|
||||
__VA_ARGS__>::type, \
|
||||
::testing::internal::TypeList< Types >::type>())
|
||||
// Note: this won't work correctly if the trailing arguments are macros.
|
||||
#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
|
||||
} \
|
||||
static const char* const GTEST_REGISTERED_TEST_NAMES_( \
|
||||
SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
|
||||
GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST_P
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
#define REGISTER_TYPED_TEST_CASE_P \
|
||||
static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \
|
||||
""); \
|
||||
REGISTER_TYPED_TEST_SUITE_P
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
|
||||
"test-suit-prefix must not be empty"); \
|
||||
static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \
|
||||
::testing::internal::TypeParameterizedTestSuite< \
|
||||
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>:: \
|
||||
Register(GTEST_STRINGIFY_(Prefix), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
||||
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
|
||||
GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
|
||||
::testing::internal::GenerateNames< \
|
||||
::testing::internal::NameGeneratorSelector< \
|
||||
__VA_ARGS__>::type, \
|
||||
::testing::internal::GenerateTypeList<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 // GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||
+461
-309
File diff suppressed because it is too large.
Load diff
@@ -27,15 +27,14 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This 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!
|
||||
//
|
||||
// Implements a family of generic predicate assertion macros.
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
@@ -67,6 +66,8 @@ namespace testing {
|
||||
// We also define the EXPECT_* variations.
|
||||
//
|
||||
// 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
|
||||
// in this file reduce. Don't use this in your code.
|
||||
@@ -89,9 +90,10 @@ AssertionResult AssertPred1Helper(const char* pred_text,
|
||||
const T1& v1) {
|
||||
if (pred(v1)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure() << pred_text << "("
|
||||
<< e1 << ") evaluates to false, where"
|
||||
<< "\n" << e1 << " evaluates to " << v1;
|
||||
return AssertionFailure()
|
||||
<< pred_text << "(" << e1 << ") evaluates to false, where"
|
||||
<< "\n"
|
||||
<< e1 << " evaluates to " << ::testing::PrintToString(v1);
|
||||
}
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
||||
@@ -133,11 +135,12 @@ AssertionResult AssertPred2Helper(const char* pred_text,
|
||||
const T2& v2) {
|
||||
if (pred(v1, v2)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure() << pred_text << "("
|
||||
<< e1 << ", "
|
||||
<< e2 << ") evaluates to false, where"
|
||||
<< "\n" << e1 << " evaluates to " << v1
|
||||
<< "\n" << e2 << " evaluates to " << v2;
|
||||
return AssertionFailure()
|
||||
<< pred_text << "(" << e1 << ", " << e2
|
||||
<< ") evaluates to false, where"
|
||||
<< "\n"
|
||||
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
|
||||
<< e2 << " evaluates to " << ::testing::PrintToString(v2);
|
||||
}
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
||||
@@ -184,13 +187,13 @@ AssertionResult AssertPred3Helper(const char* pred_text,
|
||||
const T3& v3) {
|
||||
if (pred(v1, v2, v3)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure() << pred_text << "("
|
||||
<< e1 << ", "
|
||||
<< e2 << ", "
|
||||
<< e3 << ") evaluates to false, where"
|
||||
<< "\n" << e1 << " evaluates to " << v1
|
||||
<< "\n" << e2 << " evaluates to " << v2
|
||||
<< "\n" << e3 << " evaluates to " << v3;
|
||||
return AssertionFailure()
|
||||
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3
|
||||
<< ") evaluates to false, where"
|
||||
<< "\n"
|
||||
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
|
||||
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
|
||||
<< e3 << " evaluates to " << ::testing::PrintToString(v3);
|
||||
}
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
||||
@@ -242,15 +245,14 @@ AssertionResult AssertPred4Helper(const char* pred_text,
|
||||
const T4& v4) {
|
||||
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure() << pred_text << "("
|
||||
<< e1 << ", "
|
||||
<< e2 << ", "
|
||||
<< e3 << ", "
|
||||
<< e4 << ") evaluates to false, where"
|
||||
<< "\n" << e1 << " evaluates to " << v1
|
||||
<< "\n" << e2 << " evaluates to " << v2
|
||||
<< "\n" << e3 << " evaluates to " << v3
|
||||
<< "\n" << e4 << " evaluates to " << v4;
|
||||
return AssertionFailure()
|
||||
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
|
||||
<< ") evaluates to false, where"
|
||||
<< "\n"
|
||||
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
|
||||
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
|
||||
<< e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
|
||||
<< e4 << " evaluates to " << ::testing::PrintToString(v4);
|
||||
}
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
||||
@@ -307,17 +309,15 @@ AssertionResult AssertPred5Helper(const char* pred_text,
|
||||
const T5& v5) {
|
||||
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
|
||||
|
||||
return AssertionFailure() << pred_text << "("
|
||||
<< e1 << ", "
|
||||
<< e2 << ", "
|
||||
<< e3 << ", "
|
||||
<< e4 << ", "
|
||||
<< e5 << ") evaluates to false, where"
|
||||
<< "\n" << e1 << " evaluates to " << v1
|
||||
<< "\n" << e2 << " evaluates to " << v2
|
||||
<< "\n" << e3 << " evaluates to " << v3
|
||||
<< "\n" << e4 << " evaluates to " << v4
|
||||
<< "\n" << e5 << " evaluates to " << v5;
|
||||
return AssertionFailure()
|
||||
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
|
||||
<< ", " << e5 << ") evaluates to false, where"
|
||||
<< "\n"
|
||||
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
|
||||
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
|
||||
<< e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
|
||||
<< e4 << " evaluates to " << ::testing::PrintToString(v4) << "\n"
|
||||
<< e5 << " evaluates to " << ::testing::PrintToString(v5);
|
||||
}
|
||||
|
||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
||||
@@ -356,4 +356,4 @@ AssertionResult AssertPred5Helper(const char* pred_text,
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
@@ -31,8 +31,8 @@
|
||||
// Google C++ Testing and Mocking Framework definitions useful in production code.
|
||||
// GOOGLETEST_CM0003 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
|
||||
// When you need to test the private or protected members of a class,
|
||||
// use the FRIEND_TEST macro to declare your tests as friends of the
|
||||
@@ -58,4 +58,4 @@
|
||||
#define FRIEND_TEST(test_case_name, test_name)\
|
||||
friend class test_case_name##_##test_name##_Test
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||
+3
-3
@@ -31,7 +31,7 @@
|
||||
//
|
||||
// ** Custom implementation starts here **
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
|
||||
+3
-3
@@ -36,7 +36,7 @@
|
||||
//
|
||||
// ** Custom implementation starts here **
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
|
||||
+3
-3
@@ -31,7 +31,7 @@
|
||||
//
|
||||
// ** Custom implementation starts here **
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
|
||||
+72
-48
@@ -33,12 +33,14 @@
|
||||
// death tests. They are subject to change without notice.
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
|
||||
#include "gtest/gtest-matchers.h"
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <memory>
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
@@ -78,7 +80,7 @@ class GTEST_API_ DeathTest {
|
||||
// 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
|
||||
// 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);
|
||||
DeathTest();
|
||||
virtual ~DeathTest() { }
|
||||
@@ -144,21 +146,44 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
class DeathTestFactory {
|
||||
public:
|
||||
virtual ~DeathTestFactory() { }
|
||||
virtual bool Create(const char* statement, const RE* regex,
|
||||
const char* file, int line, DeathTest** test) = 0;
|
||||
virtual bool Create(const char* statement,
|
||||
Matcher<const std::string&> matcher, const char* file,
|
||||
int line, DeathTest** test) = 0;
|
||||
};
|
||||
|
||||
// A concrete DeathTestFactory implementation for normal use.
|
||||
class DefaultDeathTestFactory : public DeathTestFactory {
|
||||
public:
|
||||
virtual bool Create(const char* statement, const RE* regex,
|
||||
const char* file, int line, DeathTest** test);
|
||||
bool Create(const char* statement, Matcher<const std::string&> matcher,
|
||||
const char* file, int line, DeathTest** test) override;
|
||||
};
|
||||
|
||||
// Returns true if exit_status describes a process that was terminated
|
||||
// by a signal, or exited normally with a nonzero exit code.
|
||||
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
|
||||
// failures. Note that trapping SEH exceptions is not implemented here.
|
||||
# if GTEST_HAS_EXCEPTIONS
|
||||
@@ -186,38 +211,38 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
||||
|
||||
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
||||
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
||||
# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
const ::testing::internal::RE& gtest_regex = (regex); \
|
||||
::testing::internal::DeathTest* gtest_dt; \
|
||||
if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \
|
||||
__FILE__, __LINE__, >est_dt)) { \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||
} \
|
||||
if (gtest_dt != NULL) { \
|
||||
::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
|
||||
gtest_dt_ptr(gtest_dt); \
|
||||
switch (gtest_dt->AssumeRole()) { \
|
||||
case ::testing::internal::DeathTest::OVERSEE_TEST: \
|
||||
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||
} \
|
||||
break; \
|
||||
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
|
||||
::testing::internal::DeathTest::ReturnSentinel \
|
||||
gtest_sentinel(gtest_dt); \
|
||||
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
|
||||
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
||||
break; \
|
||||
} \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} else \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
|
||||
fail(::testing::internal::DeathTest::LastMessage())
|
||||
#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
::testing::internal::DeathTest* gtest_dt; \
|
||||
if (!::testing::internal::DeathTest::Create( \
|
||||
#statement, \
|
||||
::testing::internal::MakeDeathTestMatcher(regex_or_matcher), \
|
||||
__FILE__, __LINE__, >est_dt)) { \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||
} \
|
||||
if (gtest_dt != nullptr) { \
|
||||
std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
|
||||
switch (gtest_dt->AssumeRole()) { \
|
||||
case ::testing::internal::DeathTest::OVERSEE_TEST: \
|
||||
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||
} \
|
||||
break; \
|
||||
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
|
||||
::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \
|
||||
gtest_dt); \
|
||||
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
|
||||
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
||||
break; \
|
||||
} \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} else \
|
||||
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \
|
||||
: fail(::testing::internal::DeathTest::LastMessage())
|
||||
// The symbol "fail" here expands to something into which a message
|
||||
// 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.
|
||||
// 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.
|
||||
#define GTEST_EXECUTE_STATEMENT_(statement, regex) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} else if (!::testing::internal::AlwaysTrue()) { \
|
||||
const ::testing::internal::RE& gtest_regex = (regex); \
|
||||
static_cast<void>(gtest_regex); \
|
||||
} else \
|
||||
#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} else if (!::testing::internal::AlwaysTrue()) { \
|
||||
::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
|
||||
} else \
|
||||
::testing::Message()
|
||||
|
||||
// A class representing the parsed contents of the
|
||||
@@ -277,4 +301,4 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||
+5
-5
@@ -37,8 +37,8 @@
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
|
||||
@@ -110,7 +110,7 @@ class GTEST_API_ FilePath {
|
||||
const FilePath& base_name,
|
||||
const char* extension);
|
||||
|
||||
// Returns true iff the path is "".
|
||||
// Returns true if and only if the path is "".
|
||||
bool IsEmpty() const { return pathname_.empty(); }
|
||||
|
||||
// If input name has a trailing separator character, removes it and returns
|
||||
@@ -195,7 +195,7 @@ class GTEST_API_ FilePath {
|
||||
|
||||
void Normalize();
|
||||
|
||||
// Returns a pointer to the last occurence of a valid path separator in
|
||||
// Returns a pointer to the last occurrence of a valid path separator in
|
||||
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||
// separators. Returns NULL if no path separator was found.
|
||||
const char* FindLastPathSeparator() const;
|
||||
@@ -208,4 +208,4 @@ class GTEST_API_ FilePath {
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
+539
-309
File diff suppressed because it is too large.
Load diff
-243
@@ -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_
|
||||
-5552
File diff suppressed because it is too large.
Load diff
Vendored
-282
@@ -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_
|
||||
+393
-170
@@ -32,23 +32,26 @@
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-linked_ptr.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/gtest-printers.h"
|
||||
#include "gtest/gtest-test-part.h"
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Input to a parameterized test name generator, describing a test parameter.
|
||||
// Consists of the parameter value and the integer parameter index.
|
||||
template <class ParamType>
|
||||
@@ -72,13 +75,14 @@ struct PrintToStringParamName {
|
||||
namespace internal {
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Utility Functions
|
||||
|
||||
// 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
|
||||
// but in different namespaces.
|
||||
GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
|
||||
CodeLocation code_location);
|
||||
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
|
||||
CodeLocation code_location);
|
||||
|
||||
template <typename> class ParamGeneratorInterface;
|
||||
template <typename> class ParamGenerator;
|
||||
@@ -153,7 +157,7 @@ class ParamIterator {
|
||||
private:
|
||||
friend class ParamGenerator<T>;
|
||||
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
|
||||
@@ -192,7 +196,7 @@ class ParamGenerator {
|
||||
iterator end() const { return iterator(impl_->End()); }
|
||||
|
||||
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
|
||||
@@ -205,12 +209,12 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||
RangeGenerator(T begin, T end, IncrementT step)
|
||||
: begin_(begin), end_(end),
|
||||
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_);
|
||||
}
|
||||
virtual ParamIteratorInterface<T>* End() const {
|
||||
ParamIteratorInterface<T>* End() const override {
|
||||
return new Iterator(this, end_, end_index_, step_);
|
||||
}
|
||||
|
||||
@@ -220,20 +224,20 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||
Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
|
||||
IncrementT 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_;
|
||||
}
|
||||
virtual void Advance() {
|
||||
void Advance() override {
|
||||
value_ = static_cast<T>(value_ + step_);
|
||||
index_++;
|
||||
}
|
||||
virtual ParamIteratorInterface<T>* Clone() const {
|
||||
ParamIteratorInterface<T>* Clone() const override {
|
||||
return new Iterator(*this);
|
||||
}
|
||||
virtual const T* Current() const { return &value_; }
|
||||
virtual bool Equals(const ParamIteratorInterface<T>& other) const {
|
||||
const T* Current() const override { return &value_; }
|
||||
bool Equals(const ParamIteratorInterface<T>& 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())
|
||||
@@ -290,12 +294,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||
template <typename ForwardIterator>
|
||||
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
|
||||
: container_(begin, end) {}
|
||||
virtual ~ValuesInIteratorRangeGenerator() {}
|
||||
~ValuesInIteratorRangeGenerator() override {}
|
||||
|
||||
virtual ParamIteratorInterface<T>* Begin() const {
|
||||
ParamIteratorInterface<T>* Begin() const override {
|
||||
return new Iterator(this, container_.begin());
|
||||
}
|
||||
virtual ParamIteratorInterface<T>* End() const {
|
||||
ParamIteratorInterface<T>* End() const override {
|
||||
return new Iterator(this, container_.end());
|
||||
}
|
||||
|
||||
@@ -307,16 +311,16 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||
Iterator(const ParamGeneratorInterface<T>* base,
|
||||
typename ContainerType::const_iterator iterator)
|
||||
: base_(base), iterator_(iterator) {}
|
||||
virtual ~Iterator() {}
|
||||
~Iterator() override {}
|
||||
|
||||
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
|
||||
const ParamGeneratorInterface<T>* BaseGenerator() const override {
|
||||
return base_;
|
||||
}
|
||||
virtual void Advance() {
|
||||
void Advance() override {
|
||||
++iterator_;
|
||||
value_.reset();
|
||||
}
|
||||
virtual ParamIteratorInterface<T>* Clone() const {
|
||||
ParamIteratorInterface<T>* Clone() const override {
|
||||
return new Iterator(*this);
|
||||
}
|
||||
// We need to use cached value referenced by iterator_ because *iterator_
|
||||
@@ -326,12 +330,11 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||
// can advance iterator_ beyond the end of the range, and we cannot
|
||||
// detect that fact. The client code, on the other hand, is
|
||||
// responsible for not calling Current() on an out-of-range iterator.
|
||||
virtual const T* Current() const {
|
||||
if (value_.get() == NULL)
|
||||
value_.reset(new T(*iterator_));
|
||||
const T* Current() const override {
|
||||
if (value_.get() == nullptr) value_.reset(new T(*iterator_));
|
||||
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
|
||||
// iterator is of the same type and we can downcast.
|
||||
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
||||
@@ -354,9 +357,9 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||
// A cached value of *iterator_. We keep it here to allow access by
|
||||
// pointer in the wrapping iterator's operator->().
|
||||
// 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.
|
||||
mutable scoped_ptr<const T> value_;
|
||||
mutable std::unique_ptr<const T> value_;
|
||||
}; // class ValuesInIteratorRangeGenerator::Iterator
|
||||
|
||||
// No implementation - assignment is unsupported.
|
||||
@@ -376,25 +379,12 @@ std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
|
||||
return name_stream.GetString();
|
||||
}
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// Parameterized test name overload helpers, which help the
|
||||
// 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() {
|
||||
static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
|
||||
}
|
||||
template <typename T = int>
|
||||
void TestNotEmpty(const T&) {}
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
@@ -406,7 +396,7 @@ class ParameterizedTestFactory : public TestFactoryBase {
|
||||
typedef typename TestClass::ParamType ParamType;
|
||||
explicit ParameterizedTestFactory(ParamType parameter) :
|
||||
parameter_(parameter) {}
|
||||
virtual Test* CreateTest() {
|
||||
Test* CreateTest() override {
|
||||
TestClass::SetParam(¶meter_);
|
||||
return new TestClass();
|
||||
}
|
||||
@@ -434,19 +424,19 @@ class TestMetaFactoryBase {
|
||||
// TestMetaFactory creates test factories for passing into
|
||||
// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
|
||||
// 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
|
||||
// creator class.
|
||||
template <class TestCase>
|
||||
template <class TestSuite>
|
||||
class TestMetaFactory
|
||||
: public TestMetaFactoryBase<typename TestCase::ParamType> {
|
||||
: public TestMetaFactoryBase<typename TestSuite::ParamType> {
|
||||
public:
|
||||
typedef typename TestCase::ParamType ParamType;
|
||||
using ParamType = typename TestSuite::ParamType;
|
||||
|
||||
TestMetaFactory() {}
|
||||
|
||||
virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
|
||||
return new ParameterizedTestFactory<TestCase>(parameter);
|
||||
TestFactoryBase* CreateTestFactory(ParamType parameter) override {
|
||||
return new ParameterizedTestFactory<TestSuite>(parameter);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -455,93 +445,107 @@ class TestMetaFactory
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// ParameterizedTestCaseInfoBase is a generic interface
|
||||
// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
|
||||
// ParameterizedTestSuiteInfoBase is a generic interface
|
||||
// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase
|
||||
// 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
|
||||
// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
|
||||
// a collection of pointers to the ParameterizedTestCaseInfo objects
|
||||
// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
|
||||
// a collection of pointers to the ParameterizedTestSuiteInfo objects
|
||||
// and calls RegisterTests() on each of them when asked.
|
||||
class ParameterizedTestCaseInfoBase {
|
||||
class ParameterizedTestSuiteInfoBase {
|
||||
public:
|
||||
virtual ~ParameterizedTestCaseInfoBase() {}
|
||||
virtual ~ParameterizedTestSuiteInfoBase() {}
|
||||
|
||||
// Base part of test case name for display purposes.
|
||||
virtual const std::string& GetTestCaseName() const = 0;
|
||||
// Test case id to verify identity.
|
||||
virtual TypeId GetTestCaseTypeId() const = 0;
|
||||
// Base part of test suite name for display purposes.
|
||||
virtual const std::string& GetTestSuiteName() const = 0;
|
||||
// Test suite id to verify identity.
|
||||
virtual TypeId GetTestSuiteTypeId() const = 0;
|
||||
// UnitTest class invokes this method to register tests in this
|
||||
// test case right before running them in RUN_ALL_TESTS macro.
|
||||
// This method should not be called more then once on any single
|
||||
// instance of a ParameterizedTestCaseInfoBase derived class.
|
||||
// test suite right before running them in RUN_ALL_TESTS macro.
|
||||
// This method should not be called more than once on any single
|
||||
// instance of a ParameterizedTestSuiteInfoBase derived class.
|
||||
virtual void RegisterTests() = 0;
|
||||
|
||||
protected:
|
||||
ParameterizedTestCaseInfoBase() {}
|
||||
ParameterizedTestSuiteInfoBase() {}
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
|
||||
};
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
|
||||
// macro invocations for a particular test case and generators
|
||||
// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
|
||||
// test case. It registers tests with all values generated by all
|
||||
// Report a the name of a test_suit as safe to ignore
|
||||
// as the side effect of construction of this type.
|
||||
struct GTEST_API_ MarkAsIgnored {
|
||||
explicit MarkAsIgnored(const char* test_suite);
|
||||
};
|
||||
|
||||
GTEST_API_ void InsertSyntheticTestCase(const std::string& name,
|
||||
CodeLocation location, bool has_test_p);
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
//
|
||||
// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
|
||||
// macro invocations for a particular test suite and generators
|
||||
// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that
|
||||
// test suite. It registers tests with all values generated by all
|
||||
// generators when asked.
|
||||
template <class TestCase>
|
||||
class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||
template <class TestSuite>
|
||||
class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||
public:
|
||||
// ParamType and GeneratorCreationFunc are private types but are required
|
||||
// for declarations of public methods AddTestPattern() and
|
||||
// AddTestCaseInstantiation().
|
||||
typedef typename TestCase::ParamType ParamType;
|
||||
// AddTestSuiteInstantiation().
|
||||
using ParamType = typename TestSuite::ParamType;
|
||||
// A function that returns an instance of appropriate generator type.
|
||||
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
|
||||
typedef typename ParamNameGenFunc<ParamType>::Type ParamNameGeneratorFunc;
|
||||
using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
|
||||
|
||||
explicit ParameterizedTestCaseInfo(
|
||||
const char* name, CodeLocation code_location)
|
||||
: test_case_name_(name), code_location_(code_location) {}
|
||||
explicit ParameterizedTestSuiteInfo(const char* name,
|
||||
CodeLocation code_location)
|
||||
: test_suite_name_(name), code_location_(code_location) {}
|
||||
|
||||
// Test case base name for display purposes.
|
||||
virtual const std::string& GetTestCaseName() const { return test_case_name_; }
|
||||
// Test case id to verify identity.
|
||||
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
|
||||
// Test suite base name for display purposes.
|
||||
const std::string& GetTestSuiteName() const override {
|
||||
return test_suite_name_;
|
||||
}
|
||||
// Test suite id to verify identity.
|
||||
TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
|
||||
// TEST_P macro uses AddTestPattern() to record information
|
||||
// about a single test in a LocalTestInfo structure.
|
||||
// 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
|
||||
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
|
||||
// test case base name and DoBar is test base name.
|
||||
void AddTestPattern(const char* test_case_name,
|
||||
const char* test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* meta_factory) {
|
||||
tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
|
||||
test_base_name,
|
||||
meta_factory)));
|
||||
// test suite base name and DoBar is test base name.
|
||||
void AddTestPattern(const char* test_suite_name, const char* test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* meta_factory,
|
||||
CodeLocation code_location) {
|
||||
tests_.push_back(std::shared_ptr<TestInfo>(new TestInfo(
|
||||
test_suite_name, test_base_name, meta_factory, code_location)));
|
||||
}
|
||||
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
|
||||
// INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
|
||||
// about a generator.
|
||||
int AddTestCaseInstantiation(const std::string& instantiation_name,
|
||||
GeneratorCreationFunc* func,
|
||||
ParamNameGeneratorFunc* name_func,
|
||||
const char* file, int line) {
|
||||
int AddTestSuiteInstantiation(const std::string& instantiation_name,
|
||||
GeneratorCreationFunc* func,
|
||||
ParamNameGeneratorFunc* name_func,
|
||||
const char* file, int line) {
|
||||
instantiations_.push_back(
|
||||
InstantiationInfo(instantiation_name, func, name_func, file, line));
|
||||
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
|
||||
// test cases right before running tests in RUN_ALL_TESTS macro.
|
||||
// This method should not be called more then once on any single
|
||||
// instance of a ParameterizedTestCaseInfoBase derived class.
|
||||
// UnitTest has a guard to prevent from calling this method more then once.
|
||||
virtual void RegisterTests() {
|
||||
// UnitTest class invokes this method to register tests in this test suite
|
||||
// right before running tests in RUN_ALL_TESTS macro.
|
||||
// This method should not be called more than once on any single
|
||||
// instance of a ParameterizedTestSuiteInfoBase derived class.
|
||||
// UnitTest has a guard to prevent from calling this method more than once.
|
||||
void RegisterTests() override {
|
||||
bool generated_instantiations = false;
|
||||
|
||||
for (typename TestInfoContainer::iterator test_it = tests_.begin();
|
||||
test_it != tests_.end(); ++test_it) {
|
||||
linked_ptr<TestInfo> test_info = *test_it;
|
||||
std::shared_ptr<TestInfo> test_info = *test_it;
|
||||
for (typename InstantiationContainer::iterator gen_it =
|
||||
instantiations_.begin(); gen_it != instantiations_.end();
|
||||
++gen_it) {
|
||||
@@ -551,16 +555,18 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||
const char* file = gen_it->file;
|
||||
int line = gen_it->line;
|
||||
|
||||
std::string test_case_name;
|
||||
std::string test_suite_name;
|
||||
if ( !instantiation_name.empty() )
|
||||
test_case_name = instantiation_name + "/";
|
||||
test_case_name += test_info->test_case_base_name;
|
||||
test_suite_name = instantiation_name + "/";
|
||||
test_suite_name += test_info->test_suite_base_name;
|
||||
|
||||
size_t i = 0;
|
||||
std::set<std::string> test_param_names;
|
||||
for (typename ParamGenerator<ParamType>::iterator param_it =
|
||||
generator.begin();
|
||||
param_it != generator.end(); ++param_it, ++i) {
|
||||
generated_instantiations = true;
|
||||
|
||||
Message test_name_stream;
|
||||
|
||||
std::string param_name = name_func(
|
||||
@@ -577,39 +583,48 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||
|
||||
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(
|
||||
test_case_name.c_str(),
|
||||
test_name_stream.GetString().c_str(),
|
||||
NULL, // No type parameter.
|
||||
PrintToString(*param_it).c_str(),
|
||||
code_location_,
|
||||
GetTestCaseTypeId(),
|
||||
TestCase::SetUpTestCase,
|
||||
TestCase::TearDownTestCase,
|
||||
test_suite_name.c_str(), test_name_stream.GetString().c_str(),
|
||||
nullptr, // No type parameter.
|
||||
PrintToString(*param_it).c_str(), test_info->code_location,
|
||||
GetTestSuiteTypeId(),
|
||||
SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
|
||||
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
|
||||
test_info->test_meta_factory->CreateTestFactory(*param_it));
|
||||
} // for param_it
|
||||
} // for gen_it
|
||||
} // for test_it
|
||||
} // RegisterTests
|
||||
|
||||
if (!generated_instantiations) {
|
||||
// There are no generaotrs, or they all generate nothing ...
|
||||
InsertSyntheticTestCase(GetTestSuiteName(), code_location_,
|
||||
!tests_.empty());
|
||||
}
|
||||
} // RegisterTests
|
||||
|
||||
private:
|
||||
// LocalTestInfo structure keeps information about a single test registered
|
||||
// with TEST_P macro.
|
||||
struct TestInfo {
|
||||
TestInfo(const char* a_test_case_base_name,
|
||||
const char* a_test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
|
||||
test_case_base_name(a_test_case_base_name),
|
||||
test_base_name(a_test_base_name),
|
||||
test_meta_factory(a_test_meta_factory) {}
|
||||
TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* a_test_meta_factory,
|
||||
CodeLocation a_code_location)
|
||||
: test_suite_base_name(a_test_suite_base_name),
|
||||
test_base_name(a_test_base_name),
|
||||
test_meta_factory(a_test_meta_factory),
|
||||
code_location(a_code_location) {}
|
||||
|
||||
const std::string test_case_base_name;
|
||||
const std::string test_suite_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;
|
||||
const CodeLocation code_location;
|
||||
};
|
||||
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
|
||||
// Records data received from INSTANTIATE_TEST_CASE_P macros:
|
||||
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
|
||||
// Records data received from INSTANTIATE_TEST_SUITE_P macros:
|
||||
// <Instantiation name, Sequence generator creation function,
|
||||
// Name generator function, Source file, Source line>
|
||||
struct InstantiationInfo {
|
||||
@@ -639,86 +654,294 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||
|
||||
// Check for invalid characters
|
||||
for (std::string::size_type index = 0; index < name.size(); ++index) {
|
||||
if (!isalnum(name[index]) && name[index] != '_')
|
||||
if (!IsAlNum(name[index]) && name[index] != '_')
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string test_case_name_;
|
||||
const std::string test_suite_name_;
|
||||
CodeLocation code_location_;
|
||||
TestInfoContainer tests_;
|
||||
InstantiationContainer instantiations_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
|
||||
}; // class ParameterizedTestCaseInfo
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo);
|
||||
}; // 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.
|
||||
//
|
||||
// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
|
||||
// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
|
||||
// macros use it to locate their corresponding ParameterizedTestCaseInfo
|
||||
// descriptors.
|
||||
class ParameterizedTestCaseRegistry {
|
||||
// ParameterizedTestSuiteRegistry contains a map of
|
||||
// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
|
||||
// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
|
||||
// ParameterizedTestSuiteInfo descriptors.
|
||||
class ParameterizedTestSuiteRegistry {
|
||||
public:
|
||||
ParameterizedTestCaseRegistry() {}
|
||||
~ParameterizedTestCaseRegistry() {
|
||||
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
|
||||
it != test_case_infos_.end(); ++it) {
|
||||
delete *it;
|
||||
ParameterizedTestSuiteRegistry() {}
|
||||
~ParameterizedTestSuiteRegistry() {
|
||||
for (auto& test_suite_info : test_suite_infos_) {
|
||||
delete test_suite_info;
|
||||
}
|
||||
}
|
||||
|
||||
// Looks up or creates and returns a structure containing information about
|
||||
// tests and instantiations of a particular test case.
|
||||
template <class TestCase>
|
||||
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
|
||||
const char* test_case_name,
|
||||
CodeLocation code_location) {
|
||||
ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
|
||||
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
|
||||
it != test_case_infos_.end(); ++it) {
|
||||
if ((*it)->GetTestCaseName() == test_case_name) {
|
||||
if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
|
||||
// tests and instantiations of a particular test suite.
|
||||
template <class TestSuite>
|
||||
ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
|
||||
const char* test_suite_name, CodeLocation code_location) {
|
||||
ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
|
||||
for (auto& test_suite_info : test_suite_infos_) {
|
||||
if (test_suite_info->GetTestSuiteName() == test_suite_name) {
|
||||
if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
|
||||
// Complain about incorrect usage of Google Test facilities
|
||||
// and terminate the program since we cannot guaranty correct
|
||||
// test case setup and tear-down in this case.
|
||||
ReportInvalidTestCaseType(test_case_name, code_location);
|
||||
// test suite setup and tear-down in this case.
|
||||
ReportInvalidTestSuiteType(test_suite_name, code_location);
|
||||
posix::Abort();
|
||||
} else {
|
||||
// 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
|
||||
// without further checks.
|
||||
typed_test_info = CheckedDowncastToActualType<
|
||||
ParameterizedTestCaseInfo<TestCase> >(*it);
|
||||
ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (typed_test_info == NULL) {
|
||||
typed_test_info = new ParameterizedTestCaseInfo<TestCase>(
|
||||
test_case_name, code_location);
|
||||
test_case_infos_.push_back(typed_test_info);
|
||||
if (typed_test_info == nullptr) {
|
||||
typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
|
||||
test_suite_name, code_location);
|
||||
test_suite_infos_.push_back(typed_test_info);
|
||||
}
|
||||
return typed_test_info;
|
||||
}
|
||||
void RegisterTests() {
|
||||
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
|
||||
it != test_case_infos_.end(); ++it) {
|
||||
(*it)->RegisterTests();
|
||||
for (auto& test_suite_info : test_suite_infos_) {
|
||||
test_suite_info->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);
|
||||
};
|
||||
|
||||
// Keep track of what type-parameterized test suite are defined and
|
||||
// where as well as which are intatiated. This allows susequently
|
||||
// identifying suits that are defined but never used.
|
||||
class TypeParameterizedTestSuiteRegistry {
|
||||
public:
|
||||
// Add a suite definition
|
||||
void RegisterTestSuite(const char* test_suite_name,
|
||||
CodeLocation code_location);
|
||||
|
||||
// Add an instantiation of a suit.
|
||||
void RegisterInstantiation(const char* test_suite_name);
|
||||
|
||||
// For each suit repored as defined but not reported as instantiation,
|
||||
// emit a test that reports that fact (configurably, as an error).
|
||||
void CheckForInstantiations();
|
||||
|
||||
private:
|
||||
struct TypeParameterizedTestSuiteInfo {
|
||||
explicit TypeParameterizedTestSuiteInfo(CodeLocation c)
|
||||
: code_location(c), instantiated(false) {}
|
||||
|
||||
CodeLocation code_location;
|
||||
bool instantiated;
|
||||
};
|
||||
|
||||
std::map<std::string, TypeParameterizedTestSuiteInfo> suites_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Forward declarations of ValuesIn(), which is implemented in
|
||||
// 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.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100)
|
||||
#endif
|
||||
|
||||
template <typename... Ts>
|
||||
class ValueArray {
|
||||
public:
|
||||
explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {}
|
||||
|
||||
template <typename T>
|
||||
operator ParamGenerator<T>() const { // NOLINT
|
||||
return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
|
||||
}
|
||||
|
||||
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);
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
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 testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||
+21
-7
@@ -32,20 +32,19 @@
|
||||
// This header file defines the GTEST_OS_* macro.
|
||||
// It is separate from gtest-port.h so that custom/gtest-port.h can include it.
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
|
||||
// Determines the platform on which Google Test is compiled.
|
||||
#ifdef __CYGWIN__
|
||||
# define GTEST_OS_CYGWIN 1
|
||||
#elif defined __SYMBIAN32__
|
||||
# define GTEST_OS_SYMBIAN 1
|
||||
# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||
# define GTEST_OS_WINDOWS_MINGW 1
|
||||
# define GTEST_OS_WINDOWS 1
|
||||
#elif defined _WIN32
|
||||
# define GTEST_OS_WINDOWS 1
|
||||
# ifdef _WIN32_WCE
|
||||
# define GTEST_OS_WINDOWS_MOBILE 1
|
||||
# elif defined(__MINGW__) || defined(__MINGW32__)
|
||||
# define GTEST_OS_WINDOWS_MINGW 1
|
||||
# elif defined(WINAPI_FAMILY)
|
||||
# include <winapifamily.h>
|
||||
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
@@ -65,15 +64,22 @@
|
||||
# else
|
||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
||||
# endif // _WIN32_WCE
|
||||
#elif defined __OS2__
|
||||
# define GTEST_OS_OS2 1
|
||||
#elif defined __APPLE__
|
||||
# define GTEST_OS_MAC 1
|
||||
# include <TargetConditionals.h>
|
||||
# if TARGET_OS_IPHONE
|
||||
# define GTEST_OS_IOS 1
|
||||
# endif
|
||||
#elif defined __DragonFly__
|
||||
# define GTEST_OS_DRAGONFLY 1
|
||||
#elif defined __FreeBSD__
|
||||
# define GTEST_OS_FREEBSD 1
|
||||
#elif defined __Fuchsia__
|
||||
# define GTEST_OS_FUCHSIA 1
|
||||
#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__)
|
||||
# define GTEST_OS_GNU_KFREEBSD 1
|
||||
#elif defined __linux__
|
||||
# define GTEST_OS_LINUX 1
|
||||
# if defined __ANDROID__
|
||||
@@ -95,6 +101,14 @@
|
||||
# define GTEST_OS_OPENBSD 1
|
||||
#elif defined __QNX__
|
||||
# define GTEST_OS_QNX 1
|
||||
#elif defined(__HAIKU__)
|
||||
#define GTEST_OS_HAIKU 1
|
||||
#elif defined ESP8266
|
||||
#define GTEST_OS_ESP8266 1
|
||||
#elif defined ESP32
|
||||
#define GTEST_OS_ESP32 1
|
||||
#elif defined(__XTENSA__)
|
||||
#define GTEST_OS_XTENSA 1
|
||||
#endif // __CYGWIN__
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
+380
-693
File diff suppressed because it is too large.
Load diff
+20
-12
@@ -38,8 +38,8 @@
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
// string.h is not guaranteed to provide strcpy on C++ Builder.
|
||||
@@ -47,6 +47,7 @@
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
@@ -94,7 +95,8 @@ class GTEST_API_ String {
|
||||
static const char* Utf16ToAnsi(LPCWSTR utf16_str);
|
||||
#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
|
||||
// NULL C string is considered different to any non-NULL C string,
|
||||
@@ -107,16 +109,16 @@ class GTEST_API_ String {
|
||||
// returned.
|
||||
static std::string ShowWideCString(const wchar_t* wide_c_str);
|
||||
|
||||
// Compares two wide C strings. Returns true iff they have the same
|
||||
// content.
|
||||
// Compares two wide C strings. Returns true if and only if they have the
|
||||
// same content.
|
||||
//
|
||||
// Unlike wcscmp(), this function can handle NULL argument(s). A
|
||||
// NULL C string is considered different to any non-NULL C string,
|
||||
// including the empty string.
|
||||
static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
|
||||
|
||||
// Compares two C strings, ignoring case. Returns true iff they
|
||||
// have the same content.
|
||||
// Compares two C strings, ignoring case. Returns true if and only if
|
||||
// they have the same content.
|
||||
//
|
||||
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
||||
// A NULL C string is considered different to any non-NULL C string,
|
||||
@@ -124,8 +126,8 @@ class GTEST_API_ String {
|
||||
static bool CaseInsensitiveCStringEquals(const char* lhs,
|
||||
const char* rhs);
|
||||
|
||||
// Compares two wide C strings, ignoring case. Returns true iff they
|
||||
// have the same content.
|
||||
// Compares two wide C strings, ignoring case. Returns true if and only if
|
||||
// they have the same content.
|
||||
//
|
||||
// Unlike wcscasecmp(), this function can handle NULL argument(s).
|
||||
// A NULL C string is considered different to any non-NULL wide C string,
|
||||
@@ -139,17 +141,23 @@ class GTEST_API_ String {
|
||||
static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
|
||||
const wchar_t* rhs);
|
||||
|
||||
// Returns true iff the given string ends with the given suffix, ignoring
|
||||
// case. Any string is considered to end with an empty suffix.
|
||||
// Returns true if and only if the given string ends with the given suffix,
|
||||
// ignoring case. Any string is considered to end with an empty suffix.
|
||||
static bool EndsWithCaseInsensitive(
|
||||
const std::string& str, const std::string& suffix);
|
||||
|
||||
// Formats an int value as "%02d".
|
||||
static std::string FormatIntWidth2(int value); // "%02d" for width == 2
|
||||
|
||||
// Formats an int value to given width with leading zeros.
|
||||
static std::string FormatIntWidthN(int value, int width);
|
||||
|
||||
// Formats an int value as "%X".
|
||||
static std::string FormatHexInt(int value);
|
||||
|
||||
// Formats an int value as "%X".
|
||||
static std::string FormatHexUInt32(uint32_t value);
|
||||
|
||||
// Formats a byte as "%02X".
|
||||
static std::string FormatByte(unsigned char value);
|
||||
|
||||
@@ -164,4 +172,4 @@ GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
-1021
File diff suppressed because it is too large.
Load diff
-348
@@ -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_
|
||||
+77
-3242
File diff suppressed because it is too large.
Load diff
-314
@@ -1,314 +0,0 @@
|
||||
$$ -*- mode: c++; -*-
|
||||
$var n = 50 $$ Maximum length of type lists we want to support.
|
||||
// Copyright 2008 Google Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Type utilities needed for implementing typed and type-parameterized
|
||||
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||
//
|
||||
// Currently we support at most $n types in a list, and at most $n
|
||||
// type-parameterized tests in one type-parameterized test case.
|
||||
// Please contact googletestframework@googlegroups.com if you need
|
||||
// more.
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
||||
// libstdc++ (which is where cxxabi.h comes from).
|
||||
# if GTEST_HAS_CXXABI_H_
|
||||
# include <cxxabi.h>
|
||||
# elif defined(__HP_aCC)
|
||||
# include <acxx_demangle.h>
|
||||
# endif // GTEST_HASH_CXXABI_H_
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Canonicalizes a given name with respect to the Standard C++ Library.
|
||||
// This handles removing the inline namespace within `std` that is
|
||||
// used by various standard libraries (e.g., `std::__1`). Names outside
|
||||
// of namespace std are returned unmodified.
|
||||
inline std::string CanonicalizeForStdLibVersioning(std::string s) {
|
||||
static const char prefix[] = "std::__";
|
||||
if (s.compare(0, strlen(prefix), prefix) == 0) {
|
||||
std::string::size_type end = s.find("::", strlen(prefix));
|
||||
if (end != s.npos) {
|
||||
// Erase everything between the initial `std` and the second `::`.
|
||||
s.erase(strlen("std"), end - strlen("std"));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// GetTypeName<T>() returns a human-readable name of type T.
|
||||
// NB: This function is also used in Google Mock, so don't move it inside of
|
||||
// the typed-test-only section below.
|
||||
template <typename T>
|
||||
std::string GetTypeName() {
|
||||
# if GTEST_HAS_RTTI
|
||||
|
||||
const char* const name = typeid(T).name();
|
||||
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
|
||||
int status = 0;
|
||||
// gcc's implementation of typeid(T).name() mangles the type name,
|
||||
// so we have to demangle it.
|
||||
# if GTEST_HAS_CXXABI_H_
|
||||
using abi::__cxa_demangle;
|
||||
# endif // GTEST_HAS_CXXABI_H_
|
||||
char* const readable_name = __cxa_demangle(name, 0, 0, &status);
|
||||
const std::string name_str(status == 0 ? readable_name : name);
|
||||
free(readable_name);
|
||||
return CanonicalizeForStdLibVersioning(name_str);
|
||||
# else
|
||||
return name;
|
||||
# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
|
||||
|
||||
# else
|
||||
|
||||
return "<type>";
|
||||
|
||||
# endif // GTEST_HAS_RTTI
|
||||
}
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// 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
|
||||
// template Types. This allows us to simulate variadic templates
|
||||
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
||||
// support directly.
|
||||
struct None {};
|
||||
|
||||
// The following family of struct and struct templates are used to
|
||||
// represent type lists. In particular, TypesN<T1, T2, ..., TN>
|
||||
// represents a type list with N types (T1, T2, ..., and TN) in it.
|
||||
// Except for Types0, every struct in the family has two member types:
|
||||
// Head for the first type in the list, and Tail for the rest of the
|
||||
// list.
|
||||
|
||||
// The empty type list.
|
||||
struct Types0 {};
|
||||
|
||||
// Type lists of length 1, 2, 3, and so on.
|
||||
|
||||
template <typename T1>
|
||||
struct Types1 {
|
||||
typedef T1 Head;
|
||||
typedef Types0 Tail;
|
||||
};
|
||||
|
||||
$range i 2..n
|
||||
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k 2..i
|
||||
template <$for j, [[typename T$j]]>
|
||||
struct Types$i {
|
||||
typedef T1 Head;
|
||||
typedef Types$(i-1)<$for k, [[T$k]]> Tail;
|
||||
};
|
||||
|
||||
|
||||
]]
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// We don't want to require the users to write TypesN<...> directly,
|
||||
// as that would require them to count the length. Types<...> is much
|
||||
// easier to write, but generates horrible messages when there is a
|
||||
// compiler error, as gcc insists on printing out each template
|
||||
// argument, even if it has the default value (this means Types<int>
|
||||
// will appear as Types<int, None, None, ..., None> in the compiler
|
||||
// errors).
|
||||
//
|
||||
// Our solution is to combine the best part of the two approaches: a
|
||||
// user would write Types<T1, ..., TN>, and Google Test will translate
|
||||
// that to TypesN<T1, ..., TN> internally to make error messages
|
||||
// readable. The translation is done by the 'type' member of the
|
||||
// Types template.
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[typename T$i = internal::None]]>
|
||||
struct Types {
|
||||
typedef internal::Types$n<$for i, [[T$i]]> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Types<$for i, [[internal::None]]> {
|
||||
typedef internal::Types0 type;
|
||||
};
|
||||
|
||||
$range i 1..n-1
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k i+1..n
|
||||
template <$for j, [[typename T$j]]>
|
||||
struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
|
||||
typedef internal::Types$i<$for j, [[T$j]]> type;
|
||||
};
|
||||
|
||||
]]
|
||||
|
||||
namespace internal {
|
||||
|
||||
# define GTEST_TEMPLATE_ template <typename T> class
|
||||
|
||||
// The template "selector" struct TemplateSel<Tmpl> is used to
|
||||
// represent Tmpl, which must be a class template with one type
|
||||
// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
|
||||
// as the type Tmpl<T>. This allows us to actually instantiate the
|
||||
// template "selected" by TemplateSel<Tmpl>.
|
||||
//
|
||||
// This trick is necessary for simulating typedef for class templates,
|
||||
// which C++ doesn't support directly.
|
||||
template <GTEST_TEMPLATE_ Tmpl>
|
||||
struct TemplateSel {
|
||||
template <typename T>
|
||||
struct Bind {
|
||||
typedef Tmpl<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
# define GTEST_BIND_(TmplSel, T) \
|
||||
TmplSel::template Bind<T>::type
|
||||
|
||||
// A unique struct template used as the default value for the
|
||||
// arguments of class template Templates. This allows us to simulate
|
||||
// variadic templates (e.g. Templates<int>, Templates<int, double>,
|
||||
// and etc), which C++ doesn't support directly.
|
||||
template <typename T>
|
||||
struct NoneT {};
|
||||
|
||||
// The following family of struct and struct templates are used to
|
||||
// represent template lists. In particular, TemplatesN<T1, T2, ...,
|
||||
// TN> represents a list of N templates (T1, T2, ..., and TN). Except
|
||||
// for Templates0, every struct in the family has two member types:
|
||||
// Head for the selector of the first template in the list, and Tail
|
||||
// for the rest of the list.
|
||||
|
||||
// The empty template list.
|
||||
struct Templates0 {};
|
||||
|
||||
// Template lists of length 1, 2, 3, and so on.
|
||||
|
||||
template <GTEST_TEMPLATE_ T1>
|
||||
struct Templates1 {
|
||||
typedef TemplateSel<T1> Head;
|
||||
typedef Templates0 Tail;
|
||||
};
|
||||
|
||||
$range i 2..n
|
||||
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k 2..i
|
||||
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
||||
struct Templates$i {
|
||||
typedef TemplateSel<T1> Head;
|
||||
typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
|
||||
};
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// We don't want to require the users to write TemplatesN<...> directly,
|
||||
// as that would require them to count the length. Templates<...> is much
|
||||
// easier to write, but generates horrible messages when there is a
|
||||
// compiler error, as gcc insists on printing out each template
|
||||
// argument, even if it has the default value (this means Templates<list>
|
||||
// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
|
||||
// errors).
|
||||
//
|
||||
// Our solution is to combine the best part of the two approaches: a
|
||||
// user would write Templates<T1, ..., TN>, and Google Test will translate
|
||||
// that to TemplatesN<T1, ..., TN> internally to make error messages
|
||||
// readable. The translation is done by the 'type' member of the
|
||||
// Templates template.
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
|
||||
struct Templates {
|
||||
typedef Templates$n<$for i, [[T$i]]> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Templates<$for i, [[NoneT]]> {
|
||||
typedef Templates0 type;
|
||||
};
|
||||
|
||||
$range i 1..n-1
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k i+1..n
|
||||
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
||||
struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
|
||||
typedef Templates$i<$for j, [[T$j]]> type;
|
||||
};
|
||||
|
||||
]]
|
||||
|
||||
// The TypeList template makes it possible to use either a single type
|
||||
// or a Types<...> list in TYPED_TEST_CASE() and
|
||||
// INSTANTIATE_TYPED_TEST_CASE_P().
|
||||
|
||||
template <typename T>
|
||||
struct TypeList {
|
||||
typedef Types1<T> type;
|
||||
};
|
||||
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[typename T$i]]>
|
||||
struct TypeList<Types<$for i, [[T$i]]> > {
|
||||
typedef typename Types<$for i, [[T$i]]>::type type;
|
||||
};
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "src/gtest.cc"
|
||||
#include "src/gtest-death-test.cc"
|
||||
#include "src/gtest-filepath.cc"
|
||||
#include "src/gtest-matchers.cc"
|
||||
#include "src/gtest-port.cc"
|
||||
#include "src/gtest-printers.cc"
|
||||
#include "src/gtest-test-part.cc"
|
||||
|
||||
+266
-197
@@ -31,6 +31,10 @@
|
||||
// This file implements death tests.
|
||||
|
||||
#include "gtest/gtest-death-test.h"
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/internal/custom/gtest.h"
|
||||
|
||||
@@ -62,10 +66,16 @@
|
||||
# endif // GTEST_OS_QNX
|
||||
|
||||
# if GTEST_OS_FUCHSIA
|
||||
# include <lib/fdio/fd.h>
|
||||
# include <lib/fdio/io.h>
|
||||
# include <lib/fdio/spawn.h>
|
||||
# include <lib/zx/channel.h>
|
||||
# include <lib/zx/port.h>
|
||||
# include <lib/zx/process.h>
|
||||
# include <lib/zx/socket.h>
|
||||
# include <zircon/processargs.h>
|
||||
# include <zircon/syscalls.h>
|
||||
# include <zircon/syscalls/policy.h>
|
||||
# include <zircon/syscalls/port.h>
|
||||
# endif // GTEST_OS_FUCHSIA
|
||||
|
||||
@@ -113,8 +123,8 @@ GTEST_DEFINE_string_(
|
||||
"Indicates the file, line number, temporal index of "
|
||||
"the single death test to run, and a file descriptor to "
|
||||
"which a success code may be sent, all separated by "
|
||||
"the '|' characters. This flag is specified if and only if the current "
|
||||
"process is a sub-process launched for running a thread-safe "
|
||||
"the '|' characters. This flag is specified if and only if the "
|
||||
"current process is a sub-process launched for running a thread-safe "
|
||||
"death test. FOR INTERNAL USE ONLY.");
|
||||
} // namespace internal
|
||||
|
||||
@@ -238,7 +248,7 @@ static std::string DeathTestThreadWarning(size_t thread_count) {
|
||||
msg << "detected " << thread_count << " threads.";
|
||||
}
|
||||
msg << " See "
|
||||
"https://github.com/google/googletest/blob/master/googletest/docs/"
|
||||
"https://github.com/google/googletest/blob/master/docs/"
|
||||
"advanced.md#death-tests-and-threads"
|
||||
<< " for more explanation and suggested solutions, especially if"
|
||||
<< " this is the last message you see before your test times out.";
|
||||
@@ -266,8 +276,6 @@ static const int kFuchsiaReadPipeFd = 3;
|
||||
// statement, which is not allowed; THREW means that the test statement
|
||||
// returned control by throwing an exception. IN_PROGRESS means the test
|
||||
// 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 };
|
||||
|
||||
// Routine for aborting the program which is safe to call from an
|
||||
@@ -281,7 +289,7 @@ static void DeathTestAbort(const std::string& message) {
|
||||
// the heap for any additional non-minuscule memory requirements.
|
||||
const InternalRunDeathTestFlag* const flag =
|
||||
GetUnitTestImpl()->internal_run_death_test_flag();
|
||||
if (flag != NULL) {
|
||||
if (flag != nullptr) {
|
||||
FILE* parent = posix::FDOpen(flag->write_fd(), "w");
|
||||
fputc(kDeathTestInternalError, parent);
|
||||
fprintf(parent, "%s", message.c_str());
|
||||
@@ -361,7 +369,7 @@ static void FailFromInternalError(int fd) {
|
||||
// for the current test.
|
||||
DeathTest::DeathTest() {
|
||||
TestInfo* const info = GetUnitTestImpl()->current_test_info();
|
||||
if (info == NULL) {
|
||||
if (info == nullptr) {
|
||||
DeathTestAbort("Cannot run a death test outside of a TEST or "
|
||||
"TEST_F construct");
|
||||
}
|
||||
@@ -369,10 +377,11 @@ DeathTest::DeathTest() {
|
||||
|
||||
// Creates and returns a death test by dispatching to the current
|
||||
// death test factory.
|
||||
bool DeathTest::Create(const char* statement, const RE* regex,
|
||||
const char* file, int line, DeathTest** test) {
|
||||
bool DeathTest::Create(const char* statement,
|
||||
Matcher<const std::string&> matcher, const char* file,
|
||||
int line, DeathTest** test) {
|
||||
return GetUnitTestImpl()->death_test_factory()->Create(
|
||||
statement, regex, file, line, test);
|
||||
statement, std::move(matcher), file, line, test);
|
||||
}
|
||||
|
||||
const char* DeathTest::LastMessage() {
|
||||
@@ -388,9 +397,9 @@ std::string DeathTest::last_death_test_message_;
|
||||
// Provides cross platform implementation for some death functionality.
|
||||
class DeathTestImpl : public DeathTest {
|
||||
protected:
|
||||
DeathTestImpl(const char* a_statement, const RE* a_regex)
|
||||
DeathTestImpl(const char* a_statement, Matcher<const std::string&> matcher)
|
||||
: statement_(a_statement),
|
||||
regex_(a_regex),
|
||||
matcher_(std::move(matcher)),
|
||||
spawned_(false),
|
||||
status_(-1),
|
||||
outcome_(IN_PROGRESS),
|
||||
@@ -398,13 +407,12 @@ class DeathTestImpl : public DeathTest {
|
||||
write_fd_(-1) {}
|
||||
|
||||
// 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);
|
||||
virtual bool Passed(bool status_ok);
|
||||
void Abort(AbortReason reason) override;
|
||||
bool Passed(bool status_ok) override;
|
||||
|
||||
const char* statement() const { return statement_; }
|
||||
const RE* regex() const { return regex_; }
|
||||
bool spawned() const { return spawned_; }
|
||||
void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
|
||||
int status() const { return status_; }
|
||||
@@ -422,13 +430,15 @@ class DeathTestImpl : public DeathTest {
|
||||
// case of unexpected codes.
|
||||
void ReadAndInterpretStatusByte();
|
||||
|
||||
// Returns stderr output from the child process.
|
||||
virtual std::string GetErrorLogs();
|
||||
|
||||
private:
|
||||
// The textual content of the code this object is testing. This class
|
||||
// doesn't own this string and should not attempt to delete it.
|
||||
const char* const statement_;
|
||||
// The regular expression which test output must match. DeathTestImpl
|
||||
// doesn't own this object and should not attempt to delete it.
|
||||
const RE* const regex_;
|
||||
// A matcher that's expected to match the stderr output by the child process.
|
||||
Matcher<const std::string&> matcher_;
|
||||
// True if the death test child process has been successfully spawned.
|
||||
bool spawned_;
|
||||
// The exit status of the child process.
|
||||
@@ -490,6 +500,10 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
|
||||
set_read_fd(-1);
|
||||
}
|
||||
|
||||
std::string DeathTestImpl::GetErrorLogs() {
|
||||
return GetCapturedStderr();
|
||||
}
|
||||
|
||||
// Signals that the death test code which should have exited, didn't.
|
||||
// Should be called only in a death test child process.
|
||||
// Writes a status byte to the child's status file descriptor, then
|
||||
@@ -543,22 +557,21 @@ static ::std::string FormatDeathTestOutput(const ::std::string& output) {
|
||||
// in the format specified by wait(2). On Windows, this is the
|
||||
// value supplied to the ExitProcess() API or a numeric code
|
||||
// of the exception that terminated the program.
|
||||
// regex: A regular expression object to be applied to
|
||||
// the test's captured standard error output; the death test
|
||||
// fails if it does not match.
|
||||
// matcher_: A matcher that's expected to match the stderr output by the child
|
||||
// process.
|
||||
//
|
||||
// Argument:
|
||||
// status_ok: true if exit_status is acceptable in the context of
|
||||
// this particular death test, which fails if it is false
|
||||
//
|
||||
// Returns true iff all of the above conditions are met. Otherwise, the
|
||||
// first failing condition, in the order given above, is the one that is
|
||||
// Returns true if and only if all of the above conditions are met. Otherwise,
|
||||
// the first failing condition, in the order given above, is the one that is
|
||||
// reported. Also sets the last death test message string.
|
||||
bool DeathTestImpl::Passed(bool status_ok) {
|
||||
if (!spawned())
|
||||
return false;
|
||||
|
||||
const std::string error_message = GetCapturedStderr();
|
||||
const std::string error_message = GetErrorLogs();
|
||||
|
||||
bool success = false;
|
||||
Message buffer;
|
||||
@@ -579,18 +592,15 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
||||
break;
|
||||
case DIED:
|
||||
if (status_ok) {
|
||||
# if GTEST_USES_PCRE
|
||||
// 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) {
|
||||
if (matcher_.Matches(error_message)) {
|
||||
success = true;
|
||||
} else {
|
||||
std::ostringstream stream;
|
||||
matcher_.DescribeTo(&stream);
|
||||
buffer << " Result: died but not with expected error.\n"
|
||||
<< " Expected: " << regex()->pattern() << "\n"
|
||||
<< "Actual msg:\n" << FormatDeathTestOutput(error_message);
|
||||
<< " Expected: " << stream.str() << "\n"
|
||||
<< "Actual msg:\n"
|
||||
<< FormatDeathTestOutput(error_message);
|
||||
}
|
||||
} else {
|
||||
buffer << " Result: died but not with expected exit code:\n"
|
||||
@@ -639,11 +649,11 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
||||
//
|
||||
class WindowsDeathTest : public DeathTestImpl {
|
||||
public:
|
||||
WindowsDeathTest(const char* a_statement,
|
||||
const RE* a_regex,
|
||||
const char* file,
|
||||
int line)
|
||||
: DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
|
||||
WindowsDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
|
||||
const char* file, int line)
|
||||
: DeathTestImpl(a_statement, std::move(matcher)),
|
||||
file_(file),
|
||||
line_(line) {}
|
||||
|
||||
// All of these virtual functions are inherited from DeathTest.
|
||||
virtual int Wait();
|
||||
@@ -720,7 +730,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||
const TestInfo* const info = impl->current_test_info();
|
||||
const int death_test_index = info->result()->death_test_count();
|
||||
|
||||
if (flag != NULL) {
|
||||
if (flag != nullptr) {
|
||||
// ParseInternalRunDeathTestFlag() has performed all the necessary
|
||||
// processing.
|
||||
set_write_fd(flag->write_fd());
|
||||
@@ -729,8 +739,8 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||
|
||||
// WindowsDeathTest uses an anonymous pipe to communicate results of
|
||||
// a death test.
|
||||
SECURITY_ATTRIBUTES handles_are_inheritable = {
|
||||
sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
|
||||
SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
|
||||
nullptr, TRUE};
|
||||
HANDLE read_handle, write_handle;
|
||||
GTEST_DEATH_TEST_CHECK_(
|
||||
::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
|
||||
@@ -741,13 +751,13 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||
write_handle_.Reset(write_handle);
|
||||
event_handle_.Reset(::CreateEvent(
|
||||
&handles_are_inheritable,
|
||||
TRUE, // The event will automatically reset to non-signaled state.
|
||||
FALSE, // The initial state is non-signalled.
|
||||
NULL)); // The even is unnamed.
|
||||
GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
|
||||
const std::string filter_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" +
|
||||
info->test_case_name() + "." + info->name();
|
||||
TRUE, // The event will automatically reset to non-signaled state.
|
||||
FALSE, // The initial state is non-signalled.
|
||||
nullptr)); // The even is unnamed.
|
||||
GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
|
||||
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||
kFilterFlag + "=" + info->test_suite_name() +
|
||||
"." + info->name();
|
||||
const std::string internal_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
|
||||
"=" + file_ + "|" + StreamableToString(line_) + "|" +
|
||||
@@ -760,10 +770,9 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||
"|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
|
||||
|
||||
char executable_path[_MAX_PATH + 1]; // NOLINT
|
||||
GTEST_DEATH_TEST_CHECK_(
|
||||
_MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
|
||||
executable_path,
|
||||
_MAX_PATH));
|
||||
GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
|
||||
executable_path,
|
||||
_MAX_PATH));
|
||||
|
||||
std::string command_line =
|
||||
std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
|
||||
@@ -784,17 +793,16 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||
startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
PROCESS_INFORMATION process_info;
|
||||
GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
|
||||
executable_path,
|
||||
const_cast<char*>(command_line.c_str()),
|
||||
NULL, // Retuned process handle is not inheritable.
|
||||
NULL, // Retuned thread handle is not inheritable.
|
||||
TRUE, // Child inherits all inheritable handles (for write_handle_).
|
||||
0x0, // Default creation flags.
|
||||
NULL, // Inherit the parent's environment.
|
||||
UnitTest::GetInstance()->original_working_dir(),
|
||||
&startup_info,
|
||||
&process_info) != FALSE);
|
||||
GTEST_DEATH_TEST_CHECK_(
|
||||
::CreateProcessA(
|
||||
executable_path, const_cast<char*>(command_line.c_str()),
|
||||
nullptr, // Retuned process handle is not inheritable.
|
||||
nullptr, // Retuned thread handle is not inheritable.
|
||||
TRUE, // Child inherits all inheritable handles (for write_handle_).
|
||||
0x0, // Default creation flags.
|
||||
nullptr, // Inherit the parent's environment.
|
||||
UnitTest::GetInstance()->original_working_dir(), &startup_info,
|
||||
&process_info) != FALSE);
|
||||
child_handle_.Reset(process_info.hProcess);
|
||||
::CloseHandle(process_info.hThread);
|
||||
set_spawned(true);
|
||||
@@ -805,38 +813,34 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||
|
||||
class FuchsiaDeathTest : public DeathTestImpl {
|
||||
public:
|
||||
FuchsiaDeathTest(const char* a_statement,
|
||||
const RE* a_regex,
|
||||
const char* file,
|
||||
int line)
|
||||
: DeathTestImpl(a_statement, a_regex), file_(file), 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);
|
||||
}
|
||||
FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
|
||||
const char* file, int line)
|
||||
: DeathTestImpl(a_statement, std::move(matcher)),
|
||||
file_(file),
|
||||
line_(line) {}
|
||||
|
||||
// All of these virtual functions are inherited from DeathTest.
|
||||
virtual int Wait();
|
||||
virtual TestRole AssumeRole();
|
||||
int Wait() override;
|
||||
TestRole AssumeRole() override;
|
||||
std::string GetErrorLogs() override;
|
||||
|
||||
private:
|
||||
// The name of the file in which the death test is located.
|
||||
const char* const file_;
|
||||
// The line number on which the death test is located.
|
||||
const int line_;
|
||||
// The stderr data captured by the child process.
|
||||
std::string captured_stderr_;
|
||||
|
||||
zx_handle_t child_process_ = ZX_HANDLE_INVALID;
|
||||
zx_handle_t port_ = ZX_HANDLE_INVALID;
|
||||
zx::process child_process_;
|
||||
zx::channel exception_channel_;
|
||||
zx::socket stderr_socket_;
|
||||
};
|
||||
|
||||
// Utility class for accumulating command-line arguments.
|
||||
class Arguments {
|
||||
public:
|
||||
Arguments() {
|
||||
args_.push_back(NULL);
|
||||
}
|
||||
Arguments() { args_.push_back(nullptr); }
|
||||
|
||||
~Arguments() {
|
||||
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
|
||||
@@ -861,7 +865,7 @@ class Arguments {
|
||||
}
|
||||
|
||||
int size() {
|
||||
return args_.size() - 1;
|
||||
return static_cast<int>(args_.size()) - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -872,55 +876,90 @@ class Arguments {
|
||||
// status, or 0 if no child process exists. As a side effect, sets the
|
||||
// outcome data member.
|
||||
int FuchsiaDeathTest::Wait() {
|
||||
const int kProcessKey = 0;
|
||||
const int kSocketKey = 1;
|
||||
const int kExceptionKey = 2;
|
||||
|
||||
if (!spawned())
|
||||
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;
|
||||
status_zx = zx_object_wait_async(child_process_,
|
||||
port_,
|
||||
0 /* key */,
|
||||
ZX_PROCESS_TERMINATED,
|
||||
ZX_WAIT_ASYNC_ONCE);
|
||||
zx::port port;
|
||||
status_zx = zx::port::create(0, &port);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
// Wait for it to terminate, or an exception to be received.
|
||||
zx_port_packet_t packet;
|
||||
status_zx = zx_port_wait(port_, ZX_TIME_INFINITE, &packet);
|
||||
// Register to wait for the child process to terminate.
|
||||
status_zx = child_process_.wait_async(
|
||||
port, kProcessKey, ZX_PROCESS_TERMINATED, 0);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
if (ZX_PKT_IS_EXCEPTION(packet.type)) {
|
||||
// Process encountered an exception. Kill it directly rather than letting
|
||||
// other handlers process the event.
|
||||
status_zx = zx_task_kill(child_process_);
|
||||
// Register to wait for the socket to be readable or closed.
|
||||
status_zx = stderr_socket_.wait_async(
|
||||
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
// Register to wait for an exception.
|
||||
status_zx = exception_channel_.wait_async(
|
||||
port, kExceptionKey, ZX_CHANNEL_READABLE, 0);
|
||||
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);
|
||||
|
||||
// Now wait for |child_process_| to terminate.
|
||||
zx_signals_t signals = 0;
|
||||
status_zx = zx_object_wait_one(
|
||||
child_process_, ZX_PROCESS_TERMINATED, ZX_TIME_INFINITE, &signals);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
GTEST_DEATH_TEST_CHECK_(signals & ZX_PROCESS_TERMINATED);
|
||||
} else {
|
||||
// Process terminated.
|
||||
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
|
||||
GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
|
||||
}
|
||||
if (packet.key == kExceptionKey) {
|
||||
// Process encountered an exception. Kill it directly rather than
|
||||
// letting other handlers process the event. We will get a kProcessKey
|
||||
// event when the process actually terminates.
|
||||
status_zx = child_process_.kill();
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
} else if (packet.key == kProcessKey) {
|
||||
// Process terminated.
|
||||
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
|
||||
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, 0);
|
||||
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();
|
||||
|
||||
zx_info_process_t buffer;
|
||||
status_zx = zx_object_get_info(
|
||||
child_process_,
|
||||
ZX_INFO_PROCESS,
|
||||
&buffer,
|
||||
sizeof(buffer),
|
||||
nullptr,
|
||||
nullptr);
|
||||
status_zx = child_process_.get_info(ZX_INFO_PROCESS, &buffer, sizeof(buffer),
|
||||
nullptr, nullptr);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(buffer.exited);
|
||||
set_status(buffer.return_code);
|
||||
GTEST_DEATH_TEST_CHECK_(buffer.flags & ZX_INFO_PROCESS_FLAG_EXITED);
|
||||
set_status(static_cast<int>(buffer.return_code));
|
||||
return status();
|
||||
}
|
||||
|
||||
@@ -936,21 +975,20 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||
const TestInfo* const info = impl->current_test_info();
|
||||
const int death_test_index = info->result()->death_test_count();
|
||||
|
||||
if (flag != NULL) {
|
||||
if (flag != nullptr) {
|
||||
// ParseInternalRunDeathTestFlag() has performed all the necessary
|
||||
// processing.
|
||||
set_write_fd(kFuchsiaReadPipeFd);
|
||||
return EXECUTE_TEST;
|
||||
}
|
||||
|
||||
CaptureStderr();
|
||||
// Flush the log buffers since the log streams are shared with the child.
|
||||
FlushInfoLog();
|
||||
|
||||
// Build the child process command line.
|
||||
const std::string filter_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
|
||||
+ info->test_case_name() + "." + info->name();
|
||||
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||
kFilterFlag + "=" + info->test_suite_name() +
|
||||
"." + info->name();
|
||||
const std::string internal_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
||||
+ file_ + "|"
|
||||
@@ -964,35 +1002,68 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||
// Build the pipe for communication with the child.
|
||||
zx_status_t status;
|
||||
zx_handle_t child_pipe_handle;
|
||||
uint32_t type;
|
||||
status = fdio_pipe_half(&child_pipe_handle, &type);
|
||||
GTEST_DEATH_TEST_CHECK_(status >= 0);
|
||||
set_read_fd(status);
|
||||
int child_pipe_fd;
|
||||
status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
set_read_fd(child_pipe_fd);
|
||||
|
||||
// Set the pipe handle for the child.
|
||||
fdio_spawn_action_t add_handle_action = {};
|
||||
add_handle_action.action = FDIO_SPAWN_ACTION_ADD_HANDLE;
|
||||
add_handle_action.h.id = PA_HND(type, kFuchsiaReadPipeFd);
|
||||
add_handle_action.h.handle = child_pipe_handle;
|
||||
fdio_spawn_action_t spawn_actions[2] = {};
|
||||
fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
|
||||
add_handle_action->action = FDIO_SPAWN_ACTION_ADD_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.
|
||||
status = fdio_spawn_etc(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL,
|
||||
args.Argv()[0], args.Argv(), nullptr, 1,
|
||||
&add_handle_action, &child_process_, 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 */);
|
||||
status = fdio_spawn_etc(
|
||||
child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
|
||||
2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
|
||||
set_spawned(true);
|
||||
return OVERSEE_TEST;
|
||||
}
|
||||
|
||||
std::string FuchsiaDeathTest::GetErrorLogs() {
|
||||
return captured_stderr_;
|
||||
}
|
||||
|
||||
#else // We are neither on Windows, nor on Fuchsia.
|
||||
|
||||
// ForkingDeathTest provides implementations for most of the abstract
|
||||
@@ -1000,10 +1071,10 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||
// left undefined.
|
||||
class ForkingDeathTest : public DeathTestImpl {
|
||||
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.
|
||||
virtual int Wait();
|
||||
int Wait() override;
|
||||
|
||||
protected:
|
||||
void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
|
||||
@@ -1014,9 +1085,9 @@ class ForkingDeathTest : public DeathTestImpl {
|
||||
};
|
||||
|
||||
// Constructs a ForkingDeathTest.
|
||||
ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
|
||||
: DeathTestImpl(a_statement, a_regex),
|
||||
child_pid_(-1) {}
|
||||
ForkingDeathTest::ForkingDeathTest(const char* a_statement,
|
||||
Matcher<const std::string&> matcher)
|
||||
: DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {}
|
||||
|
||||
// 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
|
||||
@@ -1037,9 +1108,9 @@ int ForkingDeathTest::Wait() {
|
||||
// in the child process.
|
||||
class NoExecDeathTest : public ForkingDeathTest {
|
||||
public:
|
||||
NoExecDeathTest(const char* a_statement, const RE* a_regex) :
|
||||
ForkingDeathTest(a_statement, a_regex) { }
|
||||
virtual TestRole AssumeRole();
|
||||
NoExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher)
|
||||
: ForkingDeathTest(a_statement, std::move(matcher)) {}
|
||||
TestRole AssumeRole() override;
|
||||
};
|
||||
|
||||
// The AssumeRole process for a fork-and-run death test. It implements a
|
||||
@@ -1092,10 +1163,13 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
|
||||
// only this specific death test to be run.
|
||||
class ExecDeathTest : public ForkingDeathTest {
|
||||
public:
|
||||
ExecDeathTest(const char* a_statement, const RE* a_regex,
|
||||
const char* file, int line) :
|
||||
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
|
||||
virtual TestRole AssumeRole();
|
||||
ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
|
||||
const char* file, int line)
|
||||
: ForkingDeathTest(a_statement, std::move(matcher)),
|
||||
file_(file),
|
||||
line_(line) {}
|
||||
TestRole AssumeRole() override;
|
||||
|
||||
private:
|
||||
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
|
||||
::std::vector<std::string> args = GetInjectableArgvs();
|
||||
@@ -1115,9 +1189,7 @@ class ExecDeathTest : public ForkingDeathTest {
|
||||
// Utility class for accumulating command-line arguments.
|
||||
class Arguments {
|
||||
public:
|
||||
Arguments() {
|
||||
args_.push_back(NULL);
|
||||
}
|
||||
Arguments() { args_.push_back(nullptr); }
|
||||
|
||||
~Arguments() {
|
||||
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
|
||||
@@ -1152,21 +1224,9 @@ struct ExecDeathTestArgs {
|
||||
int close_fd; // File descriptor to close; the read end of a pipe
|
||||
};
|
||||
|
||||
# if GTEST_OS_MAC
|
||||
inline char** GetEnviron() {
|
||||
// When Google Test is built as a framework on MacOS X, the environ variable
|
||||
// is unavailable. Apple's documentation (man environ) recommends using
|
||||
// _NSGetEnviron() instead.
|
||||
return *_NSGetEnviron();
|
||||
}
|
||||
# else
|
||||
// Some POSIX platforms expect you to declare environ. extern "C" makes
|
||||
// it reside in the global namespace.
|
||||
# if GTEST_OS_QNX
|
||||
extern "C" char** environ;
|
||||
inline char** GetEnviron() { return environ; }
|
||||
# endif // GTEST_OS_MAC
|
||||
|
||||
# if !GTEST_OS_QNX
|
||||
# else // GTEST_OS_QNX
|
||||
// The main function for a threadsafe-style death test child process.
|
||||
// This function is called in a clone()-ed process and thus must avoid
|
||||
// any potentially unsafe operations like malloc or libc functions.
|
||||
@@ -1186,18 +1246,18 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// We can safely call execve() as it's a direct system call. We
|
||||
// We can safely call execv() as it's almost a direct system call. We
|
||||
// cannot use execvp() as it's a libc function and thus potentially
|
||||
// unsafe. Since execve() doesn't search the PATH, the user must
|
||||
// unsafe. Since execv() doesn't search the PATH, the user must
|
||||
// invoke the test program via a valid path that contains at least
|
||||
// one path separator.
|
||||
execve(args->argv[0], args->argv, GetEnviron());
|
||||
DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
|
||||
execv(args->argv[0], args->argv);
|
||||
DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " +
|
||||
original_dir + " failed: " +
|
||||
GetLastErrnoDescription());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
# endif // !GTEST_OS_QNX
|
||||
# endif // GTEST_OS_QNX
|
||||
|
||||
# if GTEST_HAS_CLONE
|
||||
// Two utility routines that together determine the direction the stack
|
||||
@@ -1211,15 +1271,24 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||
// correct answer.
|
||||
static void StackLowerThanAddress(const void* ptr,
|
||||
bool* result) GTEST_NO_INLINE_;
|
||||
// Make sure sanitizers do not tamper with the stack here.
|
||||
// Ideally, we want to use `__builtin_frame_address` instead of a local variable
|
||||
// address with sanitizer disabled, but it does not work when the
|
||||
// compiler optimizes the stack frame out, which happens on PowerPC targets.
|
||||
// HWAddressSanitizer add a random tag to the MSB of the local variable address,
|
||||
// making comparison result unpredictable.
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
static void StackLowerThanAddress(const void* ptr, bool* result) {
|
||||
int dummy;
|
||||
*result = (&dummy < ptr);
|
||||
int dummy = 0;
|
||||
*result = std::less<const void*>()(&dummy, ptr);
|
||||
}
|
||||
|
||||
// Make sure AddressSanitizer does not tamper with the stack here.
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
static bool StackGrowsDown() {
|
||||
int dummy;
|
||||
int dummy = 0;
|
||||
bool result;
|
||||
StackLowerThanAddress(&dummy, &result);
|
||||
return result;
|
||||
@@ -1262,7 +1331,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||
fd_flags | FD_CLOEXEC));
|
||||
struct inheritance inherit = {0};
|
||||
// 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, environ);
|
||||
// Restores the current working directory.
|
||||
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
||||
@@ -1286,9 +1355,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||
|
||||
if (!use_fork) {
|
||||
static const bool stack_grows_down = StackGrowsDown();
|
||||
const size_t stack_size = getpagesize();
|
||||
const auto stack_size = static_cast<size_t>(getpagesize() * 2);
|
||||
// MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
|
||||
void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
|
||||
void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
|
||||
|
||||
@@ -1302,8 +1371,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||
void* const stack_top =
|
||||
static_cast<char*>(stack) +
|
||||
(stack_grows_down ? stack_size - kMaxStackAlignment : 0);
|
||||
GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment &&
|
||||
reinterpret_cast<intptr_t>(stack_top) % kMaxStackAlignment == 0);
|
||||
GTEST_DEATH_TEST_CHECK_(
|
||||
static_cast<size_t>(stack_size) > kMaxStackAlignment &&
|
||||
reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0);
|
||||
|
||||
child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
|
||||
|
||||
@@ -1320,7 +1390,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||
# endif // GTEST_OS_QNX
|
||||
# if GTEST_OS_LINUX
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||
sigaction(SIGPROF, &saved_sigprof_action, NULL));
|
||||
sigaction(SIGPROF, &saved_sigprof_action, nullptr));
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
||||
@@ -1338,7 +1408,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||
const TestInfo* const info = impl->current_test_info();
|
||||
const int death_test_index = info->result()->death_test_count();
|
||||
|
||||
if (flag != NULL) {
|
||||
if (flag != nullptr) {
|
||||
set_write_fd(flag->write_fd());
|
||||
return EXECUTE_TEST;
|
||||
}
|
||||
@@ -1349,9 +1419,9 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||
// it be closed when the child process does an exec:
|
||||
GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
|
||||
|
||||
const std::string filter_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
|
||||
+ info->test_case_name() + "." + info->name();
|
||||
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||
kFilterFlag + "=" + info->test_suite_name() +
|
||||
"." + info->name();
|
||||
const std::string internal_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
||||
+ file_ + "|" + StreamableToString(line_) + "|"
|
||||
@@ -1384,7 +1454,8 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||
// by the "test" argument to its address. If the test should be
|
||||
// skipped, sets that pointer to NULL. Returns true, unless the
|
||||
// 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,
|
||||
DeathTest** test) {
|
||||
UnitTestImpl* const impl = GetUnitTestImpl();
|
||||
@@ -1393,7 +1464,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
||||
const int death_test_index = impl->current_test_info()
|
||||
->increment_death_test_count();
|
||||
|
||||
if (flag != NULL) {
|
||||
if (flag != nullptr) {
|
||||
if (death_test_index > flag->index()) {
|
||||
DeathTest::set_last_death_test_message(
|
||||
"Death test count (" + StreamableToString(death_test_index)
|
||||
@@ -1404,7 +1475,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
||||
|
||||
if (!(flag->file() == file && flag->line() == line &&
|
||||
flag->index() == death_test_index)) {
|
||||
*test = NULL;
|
||||
*test = nullptr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1413,22 +1484,22 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
||||
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
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
||||
GTEST_FLAG(death_test_style) == "fast") {
|
||||
*test = new FuchsiaDeathTest(statement, regex, file, line);
|
||||
*test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
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") {
|
||||
*test = new NoExecDeathTest(statement, regex);
|
||||
*test = new NoExecDeathTest(statement, std::move(matcher));
|
||||
}
|
||||
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
@@ -1458,8 +1529,6 @@ static int GetStatusFileDescriptor(unsigned int 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));
|
||||
|
||||
const HANDLE write_handle =
|
||||
@@ -1515,7 +1584,7 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
||||
// the flag is specified; otherwise returns NULL.
|
||||
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
|
||||
// can use it here.
|
||||
|
||||
+25
-41
@@ -38,9 +38,6 @@
|
||||
#elif GTEST_OS_WINDOWS
|
||||
# include <direct.h>
|
||||
# include <io.h>
|
||||
#elif GTEST_OS_SYMBIAN
|
||||
// Symbian OpenC has PATH_MAX in sys/syslimits.h
|
||||
# include <sys/syslimits.h>
|
||||
#else
|
||||
# include <limits.h>
|
||||
# include <climits> // Some Linux distributions define PATH_MAX here.
|
||||
@@ -95,13 +92,15 @@ static bool IsPathSeparator(char c) {
|
||||
|
||||
// Returns the current working directory, or "" if unsuccessful.
|
||||
FilePath FilePath::GetCurrentDir() {
|
||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
|
||||
// Windows CE doesn't have a current directory, so we just return
|
||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
|
||||
GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 || \
|
||||
GTEST_OS_XTENSA
|
||||
// These platforms do not have a current directory, so we just return
|
||||
// something reasonable.
|
||||
return FilePath(kCurrentDirectoryString);
|
||||
#elif GTEST_OS_WINDOWS
|
||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||
return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
|
||||
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
|
||||
#else
|
||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||
char* result = getcwd(cwd, sizeof(cwd));
|
||||
@@ -109,9 +108,9 @@ FilePath FilePath::GetCurrentDir() {
|
||||
// getcwd will likely fail in NaCl due to the sandbox, so return something
|
||||
// reasonable. The user may have provided a shim implementation for getcwd,
|
||||
// however, so fallback only when failure is detected.
|
||||
return FilePath(result == NULL ? kCurrentDirectoryString : cwd);
|
||||
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
|
||||
# endif // GTEST_OS_NACL
|
||||
return FilePath(result == NULL ? "" : cwd);
|
||||
return FilePath(result == nullptr ? "" : cwd);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
||||
@@ -136,8 +135,8 @@ const char* FilePath::FindLastPathSeparator() const {
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
||||
// Comparing two pointers of which only one is NULL is undefined.
|
||||
if (last_alt_sep != NULL &&
|
||||
(last_sep == NULL || last_alt_sep > last_sep)) {
|
||||
if (last_alt_sep != nullptr &&
|
||||
(last_sep == nullptr || last_alt_sep > last_sep)) {
|
||||
return last_alt_sep;
|
||||
}
|
||||
#endif
|
||||
@@ -165,7 +164,7 @@ FilePath FilePath::RemoveFileName() const {
|
||||
const char* const last_sep = FindLastPathSeparator();
|
||||
std::string dir;
|
||||
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 {
|
||||
dir = kCurrentDirectoryString;
|
||||
}
|
||||
@@ -211,7 +210,7 @@ bool FilePath::FileOrDirectoryExists() const {
|
||||
delete [] unicode;
|
||||
return attributes != kInvalidFileAttributes;
|
||||
#else
|
||||
posix::StatStruct file_stat;
|
||||
posix::StatStruct file_stat{};
|
||||
return posix::Stat(pathname_.c_str(), &file_stat) == 0;
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
@@ -238,7 +237,7 @@ bool FilePath::DirectoryExists() const {
|
||||
result = true;
|
||||
}
|
||||
#else
|
||||
posix::StatStruct file_stat;
|
||||
posix::StatStruct file_stat{};
|
||||
result = posix::Stat(path.c_str(), &file_stat) == 0 &&
|
||||
posix::IsDir(file_stat);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
@@ -250,9 +249,6 @@ bool FilePath::DirectoryExists() const {
|
||||
// root directory per disk drive.)
|
||||
bool FilePath::IsRootDirectory() const {
|
||||
#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();
|
||||
#else
|
||||
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
|
||||
@@ -324,10 +320,13 @@ bool FilePath::CreateFolder() const {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
||||
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
||||
int result = CreateDirectory(unicode, NULL) ? 0 : -1;
|
||||
int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
|
||||
delete [] unicode;
|
||||
#elif GTEST_OS_WINDOWS
|
||||
int result = _mkdir(pathname_.c_str());
|
||||
#elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA
|
||||
// do nothing
|
||||
int result = 0;
|
||||
#else
|
||||
int result = mkdir(pathname_.c_str(), 0777);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
@@ -350,35 +349,20 @@ FilePath FilePath::RemoveTrailingPathSeparator() const {
|
||||
// Removes any redundant separators that might be in the pathname.
|
||||
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||
// redundancies that might be in a pathname involving "." or "..".
|
||||
// FIXME: handle Windows network shares (e.g. \\server\share).
|
||||
void FilePath::Normalize() {
|
||||
if (pathname_.c_str() == NULL) {
|
||||
pathname_ = "";
|
||||
return;
|
||||
}
|
||||
const char* src = pathname_.c_str();
|
||||
char* const dest = new char[pathname_.length() + 1];
|
||||
char* dest_ptr = dest;
|
||||
memset(dest_ptr, 0, pathname_.length() + 1);
|
||||
auto out = pathname_.begin();
|
||||
|
||||
while (*src != '\0') {
|
||||
*dest_ptr = *src;
|
||||
if (!IsPathSeparator(*src)) {
|
||||
src++;
|
||||
for (const char character : pathname_) {
|
||||
if (!IsPathSeparator(character)) {
|
||||
*(out++) = character;
|
||||
} else if (out == pathname_.begin() || *std::prev(out) != kPathSeparator) {
|
||||
*(out++) = kPathSeparator;
|
||||
} else {
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
if (*dest_ptr == kAlternatePathSeparator) {
|
||||
*dest_ptr = kPathSeparator;
|
||||
}
|
||||
#endif
|
||||
while (IsPathSeparator(*src))
|
||||
src++;
|
||||
continue;
|
||||
}
|
||||
dest_ptr++;
|
||||
}
|
||||
*dest_ptr = '\0';
|
||||
pathname_ = dest;
|
||||
delete[] dest;
|
||||
|
||||
pathname_.erase(out, pathname_.end());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
+173
-139
@@ -31,8 +31,8 @@
|
||||
// This file contains purely Google Test's internal implementation. Please
|
||||
// DO NOT #INCLUDE IT IN A USER PROGRAM.
|
||||
|
||||
#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#define GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#ifndef GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#define GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
# include <errno.h>
|
||||
@@ -42,6 +42,8 @@
|
||||
#include <string.h> // For memmove.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -82,9 +84,11 @@ const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
|
||||
const char kBreakOnFailureFlag[] = "break_on_failure";
|
||||
const char kCatchExceptionsFlag[] = "catch_exceptions";
|
||||
const char kColorFlag[] = "color";
|
||||
const char kFailFast[] = "fail_fast";
|
||||
const char kFilterFlag[] = "filter";
|
||||
const char kListTestsFlag[] = "list_tests";
|
||||
const char kOutputFlag[] = "output";
|
||||
const char kBriefFlag[] = "brief";
|
||||
const char kPrintTimeFlag[] = "print_time";
|
||||
const char kPrintUTF8Flag[] = "print_utf8";
|
||||
const char kRandomSeedFlag[] = "random_seed";
|
||||
@@ -98,14 +102,14 @@ const char kFlagfileFlag[] = "flagfile";
|
||||
// A valid random seed must be in [1, kMaxRandomSeed].
|
||||
const int kMaxRandomSeed = 99999;
|
||||
|
||||
// g_help_flag is true iff the --help flag or an equivalent form is
|
||||
// specified on the command line.
|
||||
// g_help_flag is true if and only if the --help flag or an equivalent form
|
||||
// is specified on the command line.
|
||||
GTEST_API_ extern bool g_help_flag;
|
||||
|
||||
// Returns the current time in milliseconds.
|
||||
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);
|
||||
|
||||
// Formats the given time in milliseconds as seconds.
|
||||
@@ -122,11 +126,11 @@ GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
|
||||
// On success, stores the value of the flag in *value, and returns
|
||||
// true. On failure, returns false without changing *value.
|
||||
GTEST_API_ bool ParseInt32Flag(
|
||||
const char* str, const char* flag, Int32* value);
|
||||
const char* str, const char* flag, int32_t* value);
|
||||
|
||||
// Returns a random seed in range [1, kMaxRandomSeed] based on the
|
||||
// given --gtest_random_seed flag value.
|
||||
inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
|
||||
inline int GetRandomSeedFromFlag(int32_t random_seed_flag) {
|
||||
const unsigned int raw_seed = (random_seed_flag == 0) ?
|
||||
static_cast<unsigned int>(GetTimeInMillis()) :
|
||||
static_cast<unsigned int>(random_seed_flag);
|
||||
@@ -162,10 +166,12 @@ class GTestFlagSaver {
|
||||
color_ = GTEST_FLAG(color);
|
||||
death_test_style_ = GTEST_FLAG(death_test_style);
|
||||
death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
|
||||
fail_fast_ = GTEST_FLAG(fail_fast);
|
||||
filter_ = GTEST_FLAG(filter);
|
||||
internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
|
||||
list_tests_ = GTEST_FLAG(list_tests);
|
||||
output_ = GTEST_FLAG(output);
|
||||
brief_ = GTEST_FLAG(brief);
|
||||
print_time_ = GTEST_FLAG(print_time);
|
||||
print_utf8_ = GTEST_FLAG(print_utf8);
|
||||
random_seed_ = GTEST_FLAG(random_seed);
|
||||
@@ -185,9 +191,11 @@ class GTestFlagSaver {
|
||||
GTEST_FLAG(death_test_style) = death_test_style_;
|
||||
GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
|
||||
GTEST_FLAG(filter) = filter_;
|
||||
GTEST_FLAG(fail_fast) = fail_fast_;
|
||||
GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
|
||||
GTEST_FLAG(list_tests) = list_tests_;
|
||||
GTEST_FLAG(output) = output_;
|
||||
GTEST_FLAG(brief) = brief_;
|
||||
GTEST_FLAG(print_time) = print_time_;
|
||||
GTEST_FLAG(print_utf8) = print_utf8_;
|
||||
GTEST_FLAG(random_seed) = random_seed_;
|
||||
@@ -206,16 +214,18 @@ class GTestFlagSaver {
|
||||
std::string color_;
|
||||
std::string death_test_style_;
|
||||
bool death_test_use_fork_;
|
||||
bool fail_fast_;
|
||||
std::string filter_;
|
||||
std::string internal_run_death_test_;
|
||||
bool list_tests_;
|
||||
std::string output_;
|
||||
bool brief_;
|
||||
bool print_time_;
|
||||
bool print_utf8_;
|
||||
internal::Int32 random_seed_;
|
||||
internal::Int32 repeat_;
|
||||
int32_t random_seed_;
|
||||
int32_t repeat_;
|
||||
bool shuffle_;
|
||||
internal::Int32 stack_trace_depth_;
|
||||
int32_t stack_trace_depth_;
|
||||
std::string stream_result_to_;
|
||||
bool throw_on_failure_;
|
||||
} GTEST_ATTRIBUTE_UNUSED_;
|
||||
@@ -226,11 +236,11 @@ class GTestFlagSaver {
|
||||
// If the code_point is not a valid Unicode code point
|
||||
// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
|
||||
// to "(Invalid Unicode 0xXXXXXXXX)".
|
||||
GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
|
||||
GTEST_API_ std::string CodePointToUtf8(uint32_t code_point);
|
||||
|
||||
// Converts a wide string to a narrow string in UTF-8 encoding.
|
||||
// The wide string is assumed to have the following encoding:
|
||||
// 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)
|
||||
// Parameter str points to a null-terminated wide string.
|
||||
// Parameter num_chars may additionally limit the number
|
||||
@@ -259,14 +269,14 @@ GTEST_API_ bool ShouldShard(const char* total_shards_str,
|
||||
const char* shard_index_str,
|
||||
bool in_subprocess_for_death_test);
|
||||
|
||||
// Parses the environment variable var as an Int32. If it is unset,
|
||||
// returns default_val. If it is not an Int32, prints an error and
|
||||
// Parses the environment variable var as a 32-bit integer. If it is unset,
|
||||
// returns default_val. If it is not a 32-bit integer, prints an error and
|
||||
// and aborts.
|
||||
GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
|
||||
GTEST_API_ int32_t Int32FromEnvOrDie(const char* env_var, int32_t default_val);
|
||||
|
||||
// Given the total number of shards, the shard index, and the test id,
|
||||
// returns true iff the test should be run on this shard. The test id is
|
||||
// some arbitrary but unique non-negative integer assigned to each test
|
||||
// returns true if and only if the test should be run on this shard. The test id
|
||||
// is some arbitrary but unique non-negative integer assigned to each test
|
||||
// method. Assumes that 0 <= shard_index < total_shards.
|
||||
GTEST_API_ bool ShouldRunTestOnShard(
|
||||
int total_shards, int shard_index, int test_id);
|
||||
@@ -297,7 +307,8 @@ void ForEach(const Container& c, Functor functor) {
|
||||
// in range [0, v.size()).
|
||||
template <typename E>
|
||||
inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
|
||||
return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
|
||||
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.
|
||||
@@ -319,8 +330,11 @@ void ShuffleRange(internal::Random* random, int begin, int end,
|
||||
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
|
||||
for (int range_width = end - begin; range_width >= 2; range_width--) {
|
||||
const int last_in_range = begin + range_width - 1;
|
||||
const int selected = begin + random->Generate(range_width);
|
||||
std::swap((*v)[selected], (*v)[last_in_range]);
|
||||
const int selected =
|
||||
begin +
|
||||
static_cast<int>(random->Generate(static_cast<uint32_t>(range_width)));
|
||||
std::swap((*v)[static_cast<size_t>(selected)],
|
||||
(*v)[static_cast<size_t>(last_in_range)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +361,7 @@ class TestPropertyKeyIs {
|
||||
// TestPropertyKeyIs has NO default constructor.
|
||||
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 {
|
||||
return test_property.key() == key_;
|
||||
}
|
||||
@@ -380,17 +394,10 @@ class GTEST_API_ UnitTestOptions {
|
||||
|
||||
// Functions for processing the gtest_filter flag.
|
||||
|
||||
// Returns true iff the wildcard pattern matches the string. The
|
||||
// first ':' or '\0' character in pattern marks the end of it.
|
||||
//
|
||||
// This recursive algorithm isn't very efficient, but is clear and
|
||||
// works well enough for matching test names, which are short.
|
||||
static bool PatternMatchesString(const char *pattern, const char *str);
|
||||
|
||||
// Returns true iff the user-specified filter matches the test case
|
||||
// name and the test name.
|
||||
static bool FilterMatchesTest(const std::string &test_case_name,
|
||||
const std::string &test_name);
|
||||
// Returns true if and only if the user-specified filter matches the test
|
||||
// suite name and the test name.
|
||||
static bool FilterMatchesTest(const std::string& test_suite_name,
|
||||
const std::string& test_name);
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Function for supporting the gtest_catch_exception flag.
|
||||
@@ -442,8 +449,8 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface {
|
||||
public:
|
||||
OsStackTraceGetter() {}
|
||||
|
||||
virtual std::string CurrentStackTrace(int max_depth, int skip_count);
|
||||
virtual void UponLeavingGTest();
|
||||
std::string CurrentStackTrace(int max_depth, int skip_count) override;
|
||||
void UponLeavingGTest() override;
|
||||
|
||||
private:
|
||||
#if GTEST_HAS_ABSL
|
||||
@@ -474,7 +481,7 @@ class DefaultGlobalTestPartResultReporter
|
||||
explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
|
||||
// Implements the TestPartResultReporterInterface. Reports the test part
|
||||
// result in the current test.
|
||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
||||
void ReportTestPartResult(const TestPartResult& result) override;
|
||||
|
||||
private:
|
||||
UnitTestImpl* const unit_test_;
|
||||
@@ -490,7 +497,7 @@ class DefaultPerThreadTestPartResultReporter
|
||||
explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
|
||||
// Implements the TestPartResultReporterInterface. The implementation just
|
||||
// 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:
|
||||
UnitTestImpl* const unit_test_;
|
||||
@@ -528,22 +535,25 @@ class GTEST_API_ UnitTestImpl {
|
||||
void SetTestPartResultReporterForCurrentThread(
|
||||
TestPartResultReporterInterface* reporter);
|
||||
|
||||
// Gets the number of successful test cases.
|
||||
int successful_test_case_count() const;
|
||||
// Gets the number of successful test suites.
|
||||
int successful_test_suite_count() const;
|
||||
|
||||
// Gets the number of failed test cases.
|
||||
int failed_test_case_count() const;
|
||||
// Gets the number of failed test suites.
|
||||
int failed_test_suite_count() const;
|
||||
|
||||
// Gets the number of all test cases.
|
||||
int total_test_case_count() const;
|
||||
// Gets the number of all test suites.
|
||||
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.
|
||||
int test_case_to_run_count() const;
|
||||
int test_suite_to_run_count() const;
|
||||
|
||||
// Gets the number of successful tests.
|
||||
int successful_test_count() const;
|
||||
|
||||
// Gets the number of skipped tests.
|
||||
int skipped_test_count() const;
|
||||
|
||||
// Gets the number of failed tests.
|
||||
int failed_test_count() const;
|
||||
|
||||
@@ -569,27 +579,33 @@ class GTEST_API_ UnitTestImpl {
|
||||
// Gets the elapsed time, in milliseconds.
|
||||
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(); }
|
||||
|
||||
// Returns true iff the unit test failed (i.e. some test case failed
|
||||
// or something outside of all tests failed).
|
||||
// Returns true if and only if the unit test failed (i.e. some test suite
|
||||
// failed or something outside of all tests failed).
|
||||
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
|
||||
// total_test_case_count() - 1. If i is not in that range, returns NULL.
|
||||
const TestCase* GetTestCase(int i) const {
|
||||
const int index = GetElementOr(test_case_indices_, i, -1);
|
||||
return index < 0 ? NULL : test_cases_[i];
|
||||
// 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.
|
||||
const TestSuite* GetTestSuite(int i) const {
|
||||
const int index = GetElementOr(test_suite_indices_, i, -1);
|
||||
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
|
||||
// total_test_case_count() - 1. If i is not in that range, returns NULL.
|
||||
TestCase* GetMutableTestCase(int i) {
|
||||
const int index = GetElementOr(test_case_indices_, i, -1);
|
||||
return index < 0 ? NULL : test_cases_[index];
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
const TestCase* GetTestCase(int i) const { return GetTestSuite(i); }
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
// 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.
|
||||
@@ -626,31 +642,40 @@ class GTEST_API_ UnitTestImpl {
|
||||
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
|
||||
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.
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// test_case_name: name of the test case
|
||||
// type_param: the name of the test's type parameter, or NULL if
|
||||
// this is not a typed or a type-parameterized test.
|
||||
// set_up_tc: pointer to the function that sets up the test case
|
||||
// tear_down_tc: pointer to the function that tears down the test case
|
||||
TestCase* GetTestCase(const char* test_case_name,
|
||||
const char* type_param,
|
||||
Test::SetUpTestCaseFunc set_up_tc,
|
||||
Test::TearDownTestCaseFunc tear_down_tc);
|
||||
// test_suite_name: name of the test suite
|
||||
// type_param: the name of the test's type parameter, or NULL if
|
||||
// this is not a typed or a type-parameterized test.
|
||||
// set_up_tc: pointer to the function that sets up the test suite
|
||||
// tear_down_tc: pointer to the function that tears down the test suite
|
||||
TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param,
|
||||
internal::SetUpTestSuiteFunc set_up_tc,
|
||||
internal::TearDownTestSuiteFunc 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.
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// set_up_tc: pointer to the function that sets up the test case
|
||||
// tear_down_tc: pointer to the function that tears down the test case
|
||||
// set_up_tc: pointer to the function that sets up the test suite
|
||||
// tear_down_tc: pointer to the function that tears down the test suite
|
||||
// test_info: the TestInfo object
|
||||
void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
|
||||
Test::TearDownTestCaseFunc tear_down_tc,
|
||||
void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
|
||||
internal::TearDownTestSuiteFunc tear_down_tc,
|
||||
TestInfo* test_info) {
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
// In order to support thread-safe death tests, we need to
|
||||
// remember the original working directory when the test program
|
||||
// was first invoked. We cannot do this in RUN_ALL_TESTS(), as
|
||||
@@ -663,22 +688,33 @@ class GTEST_API_ UnitTestImpl {
|
||||
GTEST_CHECK_(!original_working_dir_.IsEmpty())
|
||||
<< "Failed to get the current working directory.";
|
||||
}
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
GetTestCase(test_info->test_case_name(),
|
||||
test_info->type_param(),
|
||||
set_up_tc,
|
||||
tear_down_tc)->AddTestInfo(test_info);
|
||||
GetTestSuite(test_info->test_suite_name(), test_info->type_param(),
|
||||
set_up_tc, 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.
|
||||
internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
|
||||
internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() {
|
||||
return parameterized_test_registry_;
|
||||
}
|
||||
|
||||
// Sets the TestCase object for the test that's currently running.
|
||||
void set_current_test_case(TestCase* a_current_test_case) {
|
||||
current_test_case_ = a_current_test_case;
|
||||
std::set<std::string>* ignored_parameterized_test_suites() {
|
||||
return &ignored_parameterized_test_suites_;
|
||||
}
|
||||
|
||||
// Returns TypeParameterizedTestSuiteRegistry object used to keep track of
|
||||
// type-parameterized tests and instantiations of them.
|
||||
internal::TypeParameterizedTestSuiteRegistry&
|
||||
type_parameterized_test_registry() {
|
||||
return type_parameterized_test_registry_;
|
||||
}
|
||||
|
||||
// Sets the TestSuite object for the test that's currently running.
|
||||
void set_current_test_suite(TestSuite* a_current_test_suite) {
|
||||
current_test_suite_ = a_current_test_suite;
|
||||
}
|
||||
|
||||
// Sets the TestInfo object for the test that's currently running. If
|
||||
@@ -689,7 +725,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
}
|
||||
|
||||
// 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
|
||||
// protecting from registering the tests more then once. If
|
||||
// value-parameterized tests are disabled, RegisterParameterizedTests is
|
||||
@@ -704,7 +740,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
|
||||
// Clears the results of all tests, except the ad hoc tests.
|
||||
void ClearNonAdHocTestResult() {
|
||||
ForEach(test_cases_, TestCase::ClearTestCaseResult);
|
||||
ForEach(test_suites_, TestSuite::ClearTestSuiteResult);
|
||||
}
|
||||
|
||||
// Clears the results of ad-hoc test assertions.
|
||||
@@ -713,7 +749,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
}
|
||||
|
||||
// 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
|
||||
// updated.
|
||||
void RecordProperty(const TestProperty& test_property);
|
||||
@@ -725,7 +761,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
|
||||
// Matches the full name of each test against the user-specified
|
||||
// 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
|
||||
// based on sharding variables in the environment.
|
||||
// Returns the number of tests that should run.
|
||||
@@ -734,7 +770,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
// Prints the names of the tests matching the user-specified filter flag.
|
||||
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_; }
|
||||
const TestInfo* current_test_info() const { return current_test_info_; }
|
||||
|
||||
@@ -795,11 +831,11 @@ class GTEST_API_ UnitTestImpl {
|
||||
// Gets the random number generator.
|
||||
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.
|
||||
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();
|
||||
|
||||
// Returns the value of GTEST_FLAG(catch_exceptions) at the moment
|
||||
@@ -839,31 +875,37 @@ class GTEST_API_ UnitTestImpl {
|
||||
// before/after the tests are run.
|
||||
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.
|
||||
std::vector<TestCase*> test_cases_;
|
||||
std::vector<TestSuite*> test_suites_;
|
||||
|
||||
// Provides a level of indirection for the test case list to allow
|
||||
// easy shuffling and restoring the test case order. The i-th
|
||||
// element of this vector is the index of the i-th test case in the
|
||||
// Provides a level of indirection for the test suite list to allow
|
||||
// easy shuffling and restoring the test suite order. The i-th
|
||||
// element of this vector is the index of the i-th test suite in the
|
||||
// shuffled order.
|
||||
std::vector<int> test_case_indices_;
|
||||
std::vector<int> test_suite_indices_;
|
||||
|
||||
// ParameterizedTestRegistry object used to register value-parameterized
|
||||
// tests.
|
||||
internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
|
||||
internal::ParameterizedTestSuiteRegistry parameterized_test_registry_;
|
||||
internal::TypeParameterizedTestSuiteRegistry
|
||||
type_parameterized_test_registry_;
|
||||
|
||||
// The set holding the name of parameterized
|
||||
// test suites that may go uninstantiated.
|
||||
std::set<std::string> ignored_parameterized_test_suites_;
|
||||
|
||||
// Indicates whether RegisterParameterizedTests() has been called already.
|
||||
bool parameterized_tests_registered_;
|
||||
|
||||
// Index of the last death test case registered. Initially -1.
|
||||
int last_death_test_case_;
|
||||
// Index of the last death test suite registered. Initially -1.
|
||||
int last_death_test_suite_;
|
||||
|
||||
// This points to the TestCase for the currently running test. It
|
||||
// changes as Google Test goes through one test case after another.
|
||||
// This points to the TestSuite for the currently running test. It
|
||||
// changes as Google Test goes through one test suite after another.
|
||||
// When no test is running, this is set to NULL and Google Test
|
||||
// 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
|
||||
// changes as Google Test goes through one test after another. When
|
||||
@@ -891,7 +933,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
// desired.
|
||||
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_;
|
||||
|
||||
// The random number seed used at the beginning of the test run.
|
||||
@@ -910,8 +952,8 @@ class GTEST_API_ UnitTestImpl {
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
// The decomposed components of the gtest_internal_run_death_test flag,
|
||||
// parsed when RUN_ALL_TESTS is called.
|
||||
internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
|
||||
internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
|
||||
std::unique_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
|
||||
std::unique_ptr<internal::DeathTestFactory> death_test_factory_;
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
// A per-thread stack of traces created by the SCOPED_TRACE() macro.
|
||||
@@ -978,24 +1020,11 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
|
||||
char* end;
|
||||
// BiggestConvertible is the largest integer type that system-provided
|
||||
// string-to-number conversion routines can return.
|
||||
using BiggestConvertible = unsigned long long; // NOLINT
|
||||
|
||||
# if GTEST_OS_WINDOWS && !defined(__GNUC__)
|
||||
|
||||
// MSVC and C++ Builder define __int64 instead of the standard long long.
|
||||
typedef unsigned __int64 BiggestConvertible;
|
||||
const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
|
||||
|
||||
# else
|
||||
|
||||
typedef unsigned long long BiggestConvertible; // NOLINT
|
||||
const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
|
||||
|
||||
# endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
|
||||
|
||||
const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); // NOLINT
|
||||
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));
|
||||
|
||||
const Integer result = static_cast<Integer>(parsed);
|
||||
@@ -1059,18 +1088,18 @@ class StreamingListener : public EmptyTestEventListener {
|
||||
MakeConnection();
|
||||
}
|
||||
|
||||
virtual ~SocketWriter() {
|
||||
~SocketWriter() override {
|
||||
if (sockfd_ != -1)
|
||||
CloseConnection();
|
||||
}
|
||||
|
||||
// Sends a string to the socket.
|
||||
virtual void Send(const std::string& message) {
|
||||
void Send(const std::string& message) override {
|
||||
GTEST_CHECK_(sockfd_ != -1)
|
||||
<< "Send() can be called only when there is a connection.";
|
||||
|
||||
const int len = static_cast<int>(message.length());
|
||||
if (write(sockfd_, message.c_str(), len) != len) {
|
||||
const auto len = static_cast<size_t>(message.length());
|
||||
if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
|
||||
GTEST_LOG_(WARNING)
|
||||
<< "stream_result_to: failed to stream to "
|
||||
<< host_name_ << ":" << port_num_;
|
||||
@@ -1082,7 +1111,7 @@ class StreamingListener : public EmptyTestEventListener {
|
||||
void MakeConnection();
|
||||
|
||||
// Closes the socket.
|
||||
void CloseConnection() {
|
||||
void CloseConnection() override {
|
||||
GTEST_CHECK_(sockfd_ != -1)
|
||||
<< "CloseConnection() can be called only when there is a connection.";
|
||||
|
||||
@@ -1108,11 +1137,11 @@ class StreamingListener : public EmptyTestEventListener {
|
||||
explicit StreamingListener(AbstractSocketWriter* socket_writer)
|
||||
: socket_writer_(socket_writer) { Start(); }
|
||||
|
||||
void OnTestProgramStart(const UnitTest& /* unit_test */) {
|
||||
void OnTestProgramStart(const UnitTest& /* unit_test */) override {
|
||||
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
|
||||
// test iteration, not for the entire test program.
|
||||
SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
|
||||
@@ -1121,42 +1150,47 @@ class StreamingListener : public EmptyTestEventListener {
|
||||
socket_writer_->CloseConnection();
|
||||
}
|
||||
|
||||
void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
|
||||
void OnTestIterationStart(const UnitTest& /* unit_test */,
|
||||
int iteration) override {
|
||||
SendLn("event=TestIterationStart&iteration=" +
|
||||
StreamableToString(iteration));
|
||||
}
|
||||
|
||||
void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
|
||||
void OnTestIterationEnd(const UnitTest& unit_test,
|
||||
int /* iteration */) override {
|
||||
SendLn("event=TestIterationEnd&passed=" +
|
||||
FormatBool(unit_test.Passed()) + "&elapsed_time=" +
|
||||
StreamableToString(unit_test.elapsed_time()) + "ms");
|
||||
}
|
||||
|
||||
void OnTestCaseStart(const TestCase& test_case) {
|
||||
// Note that "event=TestCaseStart" is a wire format and has to remain
|
||||
// "case" for compatibility
|
||||
void OnTestCaseStart(const TestCase& test_case) override {
|
||||
SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
|
||||
}
|
||||
|
||||
void OnTestCaseEnd(const TestCase& test_case) {
|
||||
SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed())
|
||||
+ "&elapsed_time=" + StreamableToString(test_case.elapsed_time())
|
||||
+ "ms");
|
||||
// Note that "event=TestCaseEnd" is a wire format and has to remain
|
||||
// "case" for compatibility
|
||||
void OnTestCaseEnd(const TestCase& test_case) override {
|
||||
SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) +
|
||||
"&elapsed_time=" + StreamableToString(test_case.elapsed_time()) +
|
||||
"ms");
|
||||
}
|
||||
|
||||
void OnTestStart(const TestInfo& test_info) {
|
||||
void OnTestStart(const TestInfo& test_info) override {
|
||||
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=" +
|
||||
FormatBool((test_info.result())->Passed()) +
|
||||
"&elapsed_time=" +
|
||||
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();
|
||||
if (file_name == NULL)
|
||||
file_name = "";
|
||||
if (file_name == nullptr) file_name = "";
|
||||
SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
|
||||
"&line=" + StreamableToString(test_part_result.line_number()) +
|
||||
"&message=" + UrlEncode(test_part_result.message()));
|
||||
@@ -1172,7 +1206,7 @@ class StreamingListener : public EmptyTestEventListener {
|
||||
|
||||
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);
|
||||
}; // class StreamingListener
|
||||
@@ -1184,4 +1218,4 @@ class StreamingListener : public EmptyTestEventListener {
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#endif // GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
@@ -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_INTERNAL_HAS_STRING_VIEW
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const internal::StringView&>::Matcher(const std::string& s) {
|
||||
*this = Eq(s);
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const internal::StringView&>::Matcher(const char* s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const internal::StringView&>::Matcher(internal::StringView s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<internal::StringView>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<internal::StringView>::Matcher(const char* s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<internal::StringView>::Matcher(internal::StringView s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
} // namespace testing
|
||||
+228
-113
@@ -31,16 +31,21 @@
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# include <sys/stat.h>
|
||||
# include <map> // Used in ThreadLocal.
|
||||
# ifdef _MSC_VER
|
||||
# include <crtdbg.h>
|
||||
# endif // _MSC_VER
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
@@ -51,6 +56,14 @@
|
||||
# include <mach/vm_map.h>
|
||||
#endif // GTEST_OS_MAC
|
||||
|
||||
#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
|
||||
GTEST_OS_NETBSD || GTEST_OS_OPENBSD
|
||||
# include <sys/sysctl.h>
|
||||
# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
|
||||
# include <sys/user.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if GTEST_OS_QNX
|
||||
# include <devctl.h>
|
||||
# include <fcntl.h>
|
||||
@@ -105,7 +118,7 @@ T ReadProcFileField(const std::string& filename, int field) {
|
||||
size_t GetThreadCount() {
|
||||
const std::string filename =
|
||||
(Message() << "/proc/" << getpid() << "/stat").GetString();
|
||||
return ReadProcFileField<int>(filename, 19);
|
||||
return ReadProcFileField<size_t>(filename, 19);
|
||||
}
|
||||
|
||||
#elif GTEST_OS_MAC
|
||||
@@ -127,6 +140,82 @@ 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] = static_cast<int>(size / static_cast<size_t>(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
|
||||
size_t nthreads = 0;
|
||||
for (size_t i = 0; i < size / static_cast<size_t>(mib[4]); i++) {
|
||||
if (info[i].p_tid != -1)
|
||||
nthreads++;
|
||||
}
|
||||
return nthreads;
|
||||
}
|
||||
|
||||
#elif GTEST_OS_QNX
|
||||
|
||||
// Returns the number of threads running in the process, or 0 to indicate that
|
||||
@@ -138,7 +227,7 @@ size_t GetThreadCount() {
|
||||
}
|
||||
procfs_info process_info;
|
||||
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);
|
||||
if (status == EOK) {
|
||||
return static_cast<size_t>(process_info.num_threads);
|
||||
@@ -152,7 +241,7 @@ size_t GetThreadCount() {
|
||||
size_t GetThreadCount() {
|
||||
struct procentry64 entry;
|
||||
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) {
|
||||
return entry.pi_thcount;
|
||||
} else {
|
||||
@@ -192,7 +281,7 @@ size_t GetThreadCount() {
|
||||
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
||||
|
||||
void SleepMilliseconds(int n) {
|
||||
::Sleep(n);
|
||||
::Sleep(static_cast<DWORD>(n));
|
||||
}
|
||||
|
||||
AutoHandle::AutoHandle()
|
||||
@@ -230,15 +319,15 @@ void AutoHandle::Reset(HANDLE handle) {
|
||||
bool AutoHandle::IsCloseable() const {
|
||||
// Different Windows APIs may use either of these values to represent an
|
||||
// invalid handle.
|
||||
return handle_ != NULL && handle_ != INVALID_HANDLE_VALUE;
|
||||
return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
Notification::Notification()
|
||||
: event_(::CreateEvent(NULL, // Default security attributes.
|
||||
TRUE, // Do not reset automatically.
|
||||
FALSE, // Initially unset.
|
||||
NULL)) { // Anonymous event.
|
||||
GTEST_CHECK_(event_.Get() != NULL);
|
||||
: event_(::CreateEvent(nullptr, // Default security attributes.
|
||||
TRUE, // Do not reset automatically.
|
||||
FALSE, // Initially unset.
|
||||
nullptr)) { // Anonymous event.
|
||||
GTEST_CHECK_(event_.Get() != nullptr);
|
||||
}
|
||||
|
||||
void Notification::Notify() {
|
||||
@@ -261,13 +350,10 @@ Mutex::Mutex()
|
||||
Mutex::~Mutex() {
|
||||
// Static mutexes are leaked intentionally. It is not thread-safe to try
|
||||
// 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) {
|
||||
::DeleteCriticalSection(critical_section_);
|
||||
delete critical_section_;
|
||||
critical_section_ = NULL;
|
||||
critical_section_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +382,7 @@ void Mutex::AssertHeld() {
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Use the RAII idiom to flag mem allocs that are intentionally never
|
||||
// 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
|
||||
@@ -308,19 +395,15 @@ class MemoryIsNotDeallocated
|
||||
{
|
||||
public:
|
||||
MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
|
||||
#ifdef _MSC_VER
|
||||
old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||
// Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
|
||||
// doesn't report mem leak if there's no matching deallocation.
|
||||
_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
|
||||
~MemoryIsNotDeallocated() {
|
||||
#ifdef _MSC_VER
|
||||
// Restore the original _CRTDBG_ALLOC_MEM_DF flag
|
||||
_CrtSetDbgFlag(old_crtdbg_flag_);
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -328,6 +411,7 @@ class MemoryIsNotDeallocated
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
|
||||
};
|
||||
#endif // _MSC_VER
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -343,7 +427,9 @@ void Mutex::ThreadSafeLazyInit() {
|
||||
owner_thread_id_ = 0;
|
||||
{
|
||||
// Use RAII to flag that following mem alloc is never deallocated.
|
||||
#ifdef _MSC_VER
|
||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
#endif // _MSC_VER
|
||||
critical_section_ = new CRITICAL_SECTION;
|
||||
}
|
||||
::InitializeCriticalSection(critical_section_);
|
||||
@@ -384,17 +470,16 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
||||
Notification* thread_can_start) {
|
||||
ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
|
||||
DWORD thread_id;
|
||||
// FIXME: Consider to use _beginthreadex instead.
|
||||
HANDLE thread_handle = ::CreateThread(
|
||||
NULL, // Default security.
|
||||
0, // Default stack size.
|
||||
nullptr, // Default security.
|
||||
0, // Default stack size.
|
||||
&ThreadWithParamSupport::ThreadMain,
|
||||
param, // Parameter to ThreadMainStatic
|
||||
0x0, // Default creation flags.
|
||||
param, // Parameter to ThreadMainStatic
|
||||
0x0, // Default creation flags.
|
||||
&thread_id); // Need a valid pointer for the call to work under Win98.
|
||||
GTEST_CHECK_(thread_handle != NULL) << "CreateThread failed with error "
|
||||
<< ::GetLastError() << ".";
|
||||
if (thread_handle == NULL) {
|
||||
GTEST_CHECK_(thread_handle != nullptr)
|
||||
<< "CreateThread failed with error " << ::GetLastError() << ".";
|
||||
if (thread_handle == nullptr) {
|
||||
delete param;
|
||||
}
|
||||
return thread_handle;
|
||||
@@ -406,15 +491,15 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
||||
: runnable_(runnable),
|
||||
thread_can_start_(thread_can_start) {
|
||||
}
|
||||
scoped_ptr<Runnable> runnable_;
|
||||
std::unique_ptr<Runnable> runnable_;
|
||||
// Does not own.
|
||||
Notification* thread_can_start_;
|
||||
};
|
||||
|
||||
static DWORD WINAPI ThreadMain(void* ptr) {
|
||||
// Transfers ownership.
|
||||
scoped_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
|
||||
if (param->thread_can_start_ != NULL)
|
||||
std::unique_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
|
||||
if (param->thread_can_start_ != nullptr)
|
||||
param->thread_can_start_->WaitForNotification();
|
||||
param->runnable_->Run();
|
||||
return 0;
|
||||
@@ -453,6 +538,9 @@ class ThreadLocalRegistryImpl {
|
||||
// Returns a value that can be used to identify the thread from other threads.
|
||||
static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
|
||||
const ThreadLocalBase* thread_local_instance) {
|
||||
#ifdef _MSC_VER
|
||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
#endif // _MSC_VER
|
||||
DWORD current_thread = ::GetCurrentThreadId();
|
||||
MutexLock lock(&mutex_);
|
||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||
@@ -472,7 +560,7 @@ class ThreadLocalRegistryImpl {
|
||||
thread_local_values
|
||||
.insert(std::make_pair(
|
||||
thread_local_instance,
|
||||
linked_ptr<ThreadLocalValueHolderBase>(
|
||||
std::shared_ptr<ThreadLocalValueHolderBase>(
|
||||
thread_local_instance->NewValueForCurrentThread())))
|
||||
.first;
|
||||
}
|
||||
@@ -481,7 +569,7 @@ class ThreadLocalRegistryImpl {
|
||||
|
||||
static void OnThreadLocalDestroyed(
|
||||
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
|
||||
// defer the destruction of the ThreadLocalValueHolderBases.
|
||||
{
|
||||
@@ -509,7 +597,7 @@ class ThreadLocalRegistryImpl {
|
||||
|
||||
static void OnThreadExit(DWORD thread_id) {
|
||||
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
|
||||
// lock, but defer the destruction of the ThreadLocalValueHolderBases.
|
||||
{
|
||||
@@ -536,7 +624,8 @@ class ThreadLocalRegistryImpl {
|
||||
private:
|
||||
// In a particular thread, maps a ThreadLocal object to its value.
|
||||
typedef std::map<const ThreadLocalBase*,
|
||||
linked_ptr<ThreadLocalValueHolderBase> > ThreadLocalValues;
|
||||
std::shared_ptr<ThreadLocalValueHolderBase> >
|
||||
ThreadLocalValues;
|
||||
// Stores all ThreadIdToThreadLocals having values in a thread, indexed by
|
||||
// thread's ID.
|
||||
typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
|
||||
@@ -551,18 +640,17 @@ class ThreadLocalRegistryImpl {
|
||||
HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
|
||||
FALSE,
|
||||
thread_id);
|
||||
GTEST_CHECK_(thread != NULL);
|
||||
GTEST_CHECK_(thread != nullptr);
|
||||
// We need to pass a valid thread ID pointer into CreateThread for it
|
||||
// to work correctly under Win98.
|
||||
DWORD watcher_thread_id;
|
||||
HANDLE watcher_thread = ::CreateThread(
|
||||
NULL, // Default security.
|
||||
0, // Default stack size
|
||||
nullptr, // Default security.
|
||||
0, // Default stack size
|
||||
&ThreadLocalRegistryImpl::WatcherThreadFunc,
|
||||
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
|
||||
CREATE_SUSPENDED,
|
||||
&watcher_thread_id);
|
||||
GTEST_CHECK_(watcher_thread != NULL);
|
||||
CREATE_SUSPENDED, &watcher_thread_id);
|
||||
GTEST_CHECK_(watcher_thread != nullptr);
|
||||
// Give the watcher thread the same priority as ours to avoid being
|
||||
// blocked by it.
|
||||
::SetThreadPriority(watcher_thread,
|
||||
@@ -587,7 +675,9 @@ class ThreadLocalRegistryImpl {
|
||||
// Returns map of thread local instances.
|
||||
static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
|
||||
mutex_.AssertHeld();
|
||||
#ifdef _MSC_VER
|
||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
#endif // _MSC_VER
|
||||
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
|
||||
return map;
|
||||
}
|
||||
@@ -598,8 +688,8 @@ class ThreadLocalRegistryImpl {
|
||||
static Mutex thread_map_mutex_;
|
||||
};
|
||||
|
||||
Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);
|
||||
Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex);
|
||||
Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex); // NOLINT
|
||||
Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex); // NOLINT
|
||||
|
||||
ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
|
||||
const ThreadLocalBase* thread_local_instance) {
|
||||
@@ -630,7 +720,7 @@ RE::~RE() {
|
||||
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) {
|
||||
if (!re.is_valid_) return false;
|
||||
|
||||
@@ -638,8 +728,8 @@ bool RE::FullMatch(const char* str, const RE& re) {
|
||||
return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
|
||||
}
|
||||
|
||||
// Returns true iff regular expression re matches a substring of str
|
||||
// (including str itself).
|
||||
// Returns true if and only if regular expression re matches a substring of
|
||||
// str (including str itself).
|
||||
bool RE::PartialMatch(const char* str, const RE& re) {
|
||||
if (!re.is_valid_) return false;
|
||||
|
||||
@@ -679,14 +769,14 @@ void RE::Init(const char* regex) {
|
||||
|
||||
#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).
|
||||
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
|
||||
// similar functions in <ctype.h>, these aren't affected by the
|
||||
// Returns true if and only if ch belongs to the given classification.
|
||||
// Unlike similar functions in <ctype.h>, these aren't affected by the
|
||||
// current locale.
|
||||
bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
|
||||
bool IsAsciiPunct(char ch) {
|
||||
@@ -699,13 +789,13 @@ bool IsAsciiWordChar(char 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) {
|
||||
return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
|
||||
}
|
||||
|
||||
// Returns true iff the given atom (specified by escaped and pattern)
|
||||
// matches ch. The result is undefined if the atom is invalid.
|
||||
// Returns true if and only if the given atom (specified by escaped and
|
||||
// pattern) matches ch. The result is undefined if the atom is invalid.
|
||||
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
||||
if (escaped) { // "\\p" where p is pattern_char.
|
||||
switch (pattern_char) {
|
||||
@@ -736,17 +826,14 @@ static std::string FormatRegexSyntaxError(const char* regex, int index) {
|
||||
// Generates non-fatal failures and returns false if regex is invalid;
|
||||
// otherwise returns true.
|
||||
bool ValidateRegex(const char* regex) {
|
||||
if (regex == NULL) {
|
||||
// FIXME: fix the source file location in the
|
||||
// assertion failures to match where the regex is used in user
|
||||
// code.
|
||||
if (regex == nullptr) {
|
||||
ADD_FAILURE() << "NULL is not a valid simple regular expression.";
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
for (int i = 0; regex[i]; i++) {
|
||||
if (regex[i] == '\\') { // An escape sequence
|
||||
@@ -822,8 +909,8 @@ bool MatchRepetitionAndRegexAtHead(
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true iff regex matches a prefix of str. regex must be a
|
||||
// valid simple regular expression and not start with "^", or the
|
||||
// Returns true if and only if regex matches a prefix of str. regex must
|
||||
// be a valid simple regular expression and not start with "^", or the
|
||||
// result is undefined.
|
||||
bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||
if (*regex == '\0') // An empty regex matches a prefix of anything.
|
||||
@@ -853,8 +940,8 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true iff regex matches any substring of str. regex must be
|
||||
// a valid simple regular expression, or the result is undefined.
|
||||
// Returns true if and only if regex matches any substring of str. regex must
|
||||
// be a valid simple regular expression, or the result is undefined.
|
||||
//
|
||||
// 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
|
||||
@@ -862,8 +949,7 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||
// exponential with respect to the regex length + the string length,
|
||||
// but usually it's must faster (often close to linear).
|
||||
bool MatchRegexAnywhere(const char* regex, const char* str) {
|
||||
if (regex == NULL || str == NULL)
|
||||
return false;
|
||||
if (regex == nullptr || str == nullptr) return false;
|
||||
|
||||
if (*regex == '^')
|
||||
return MatchRegexAtHead(regex + 1, str);
|
||||
@@ -883,21 +969,21 @@ RE::~RE() {
|
||||
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) {
|
||||
return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
|
||||
}
|
||||
|
||||
// Returns true iff regular expression re matches a substring of str
|
||||
// (including str itself).
|
||||
// Returns true if and only if regular expression re matches a substring of
|
||||
// str (including str itself).
|
||||
bool RE::PartialMatch(const char* str, const RE& re) {
|
||||
return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
|
||||
}
|
||||
|
||||
// Initializes an RE from its string representation.
|
||||
void RE::Init(const char* regex) {
|
||||
pattern_ = full_pattern_ = NULL;
|
||||
if (regex != NULL) {
|
||||
pattern_ = full_pattern_ = nullptr;
|
||||
if (regex != nullptr) {
|
||||
pattern_ = posix::StrDup(regex);
|
||||
}
|
||||
|
||||
@@ -935,7 +1021,7 @@ const char kUnknownFile[] = "unknown file";
|
||||
// Formats a source file path and a line number as they would appear
|
||||
// in an error message from the compiler used to compile this code.
|
||||
GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
|
||||
const std::string file_name(file == NULL ? kUnknownFile : file);
|
||||
const std::string file_name(file == nullptr ? kUnknownFile : file);
|
||||
|
||||
if (line < 0) {
|
||||
return file_name + ":";
|
||||
@@ -954,7 +1040,7 @@ GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
|
||||
// to the file location it produces, unlike FormatFileLocation().
|
||||
GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
|
||||
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)
|
||||
return file_name;
|
||||
@@ -1009,9 +1095,9 @@ class CapturedStream {
|
||||
filename_ = temp_file_path;
|
||||
# else
|
||||
// There's no guarantee that a test has write access to the current
|
||||
// directory, so we create the temporary file in the /tmp directory
|
||||
// instead. We use /tmp on most systems, and /sdcard on Android.
|
||||
// That's because Android doesn't have /tmp.
|
||||
// directory, so we create the temporary file in a temporary directory.
|
||||
std::string name_template;
|
||||
|
||||
# if GTEST_OS_LINUX_ANDROID
|
||||
// Note: Android applications are expected to call the framework's
|
||||
// Context.getExternalStorageDirectory() method through JNI to get
|
||||
@@ -1021,20 +1107,51 @@ class CapturedStream {
|
||||
// code as part of a regular standalone executable, which doesn't
|
||||
// run in a Dalvik process (e.g. when running it through 'adb shell').
|
||||
//
|
||||
// The location /sdcard is directly accessible from native code
|
||||
// and is the only location (unofficially) supported by the Android
|
||||
// team. It's generally a symlink to the real SD Card mount point
|
||||
// which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or
|
||||
// other OEM-customized locations. Never rely on these, and always
|
||||
// use /sdcard.
|
||||
char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
|
||||
// The location /data/local/tmp is directly accessible from native code.
|
||||
// '/sdcard' and other variants cannot be relied on, as they are not
|
||||
// guaranteed to be mounted, or may have a delay in mounting.
|
||||
name_template = "/data/local/tmp/";
|
||||
# elif GTEST_OS_IOS
|
||||
char user_temp_dir[PATH_MAX + 1];
|
||||
|
||||
// Documented alternative to NSTemporaryDirectory() (for obtaining creating
|
||||
// a temporary directory) at
|
||||
// https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
|
||||
//
|
||||
// _CS_DARWIN_USER_TEMP_DIR (as well as _CS_DARWIN_USER_CACHE_DIR) is not
|
||||
// documented in the confstr() man page at
|
||||
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/confstr.3.html#//apple_ref/doc/man/3/confstr
|
||||
// but are still available, according to the WebKit patches at
|
||||
// https://trac.webkit.org/changeset/262004/webkit
|
||||
// https://trac.webkit.org/changeset/263705/webkit
|
||||
//
|
||||
// The confstr() implementation falls back to getenv("TMPDIR"). See
|
||||
// https://opensource.apple.com/source/Libc/Libc-1439.100.3/gen/confstr.c.auto.html
|
||||
::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir, sizeof(user_temp_dir));
|
||||
|
||||
name_template = user_temp_dir;
|
||||
if (name_template.back() != GTEST_PATH_SEP_[0])
|
||||
name_template.push_back(GTEST_PATH_SEP_[0]);
|
||||
# else
|
||||
char name_template[] = "/tmp/captured_stream.XXXXXX";
|
||||
# endif // GTEST_OS_LINUX_ANDROID
|
||||
const int captured_fd = mkstemp(name_template);
|
||||
filename_ = name_template;
|
||||
name_template = "/tmp/";
|
||||
# endif
|
||||
name_template.append("gtest_captured_stream.XXXXXX");
|
||||
|
||||
// mkstemp() modifies the string bytes in place, and does not go beyond the
|
||||
// string's length. This results in well-defined behavior in C++17.
|
||||
//
|
||||
// The const_cast is needed below C++17. The constraints on std::string
|
||||
// implementations in C++11 and above make assumption behind the const_cast
|
||||
// fairly safe.
|
||||
const int captured_fd = ::mkstemp(const_cast<char*>(name_template.data()));
|
||||
if (captured_fd == -1) {
|
||||
GTEST_LOG_(WARNING)
|
||||
<< "Failed to create tmp file " << name_template
|
||||
<< " for test; does the test have access to the /tmp directory?";
|
||||
}
|
||||
filename_ = std::move(name_template);
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
fflush(NULL);
|
||||
fflush(nullptr);
|
||||
dup2(captured_fd, fd_);
|
||||
close(captured_fd);
|
||||
}
|
||||
@@ -1046,13 +1163,17 @@ class CapturedStream {
|
||||
std::string GetCapturedString() {
|
||||
if (uncaptured_fd_ != -1) {
|
||||
// Restores the original stream.
|
||||
fflush(NULL);
|
||||
fflush(nullptr);
|
||||
dup2(uncaptured_fd_, fd_);
|
||||
close(uncaptured_fd_);
|
||||
uncaptured_fd_ = -1;
|
||||
}
|
||||
|
||||
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);
|
||||
posix::FClose(file);
|
||||
return content;
|
||||
@@ -1069,13 +1190,13 @@ class CapturedStream {
|
||||
|
||||
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
||||
|
||||
static CapturedStream* g_captured_stderr = NULL;
|
||||
static CapturedStream* g_captured_stdout = NULL;
|
||||
static CapturedStream* g_captured_stderr = nullptr;
|
||||
static CapturedStream* g_captured_stdout = nullptr;
|
||||
|
||||
// Starts capturing an output stream (stdout/stderr).
|
||||
static void CaptureStream(int fd, const char* stream_name,
|
||||
CapturedStream** stream) {
|
||||
if (*stream != NULL) {
|
||||
if (*stream != nullptr) {
|
||||
GTEST_LOG_(FATAL) << "Only one " << stream_name
|
||||
<< " capturer can exist at a time.";
|
||||
}
|
||||
@@ -1087,7 +1208,7 @@ static std::string GetCapturedStream(CapturedStream** captured_stream) {
|
||||
const std::string content = (*captured_stream)->GetCapturedString();
|
||||
|
||||
delete *captured_stream;
|
||||
*captured_stream = NULL;
|
||||
*captured_stream = nullptr;
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -1146,10 +1267,11 @@ std::string ReadEntireFile(FILE* file) {
|
||||
}
|
||||
|
||||
#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() {
|
||||
if (g_injected_test_argvs != NULL) {
|
||||
if (g_injected_test_argvs != nullptr) {
|
||||
return *g_injected_test_argvs;
|
||||
}
|
||||
return GetArgvs();
|
||||
@@ -1165,16 +1287,9 @@ void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
|
||||
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() {
|
||||
delete g_injected_test_argvs;
|
||||
g_injected_test_argvs = NULL;
|
||||
g_injected_test_argvs = nullptr;
|
||||
}
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
@@ -1205,9 +1320,9 @@ static std::string FlagToEnvVar(const char* flag) {
|
||||
// Parses 'str' for a 32-bit signed integer. If successful, writes
|
||||
// the result to *value and returns true; otherwise leaves *value
|
||||
// unchanged and returns false.
|
||||
bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
|
||||
bool ParseInt32(const Message& src_text, const char* str, int32_t* value) {
|
||||
// Parses the environment variable as a decimal integer.
|
||||
char* end = NULL;
|
||||
char* end = nullptr;
|
||||
const long long_value = strtol(str, &end, 10); // NOLINT
|
||||
|
||||
// Has strtol() consumed all characters in the string?
|
||||
@@ -1222,13 +1337,13 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the parsed value in the range of an Int32?
|
||||
const Int32 result = static_cast<Int32>(long_value);
|
||||
// Is the parsed value in the range of an int32_t?
|
||||
const auto result = static_cast<int32_t>(long_value);
|
||||
if (long_value == LONG_MAX || long_value == LONG_MIN ||
|
||||
// The parsed value overflows as a long. (strtol() returns
|
||||
// LONG_MAX or LONG_MIN when the input overflows.)
|
||||
result != long_value
|
||||
// The parsed value overflows as an Int32.
|
||||
// The parsed value overflows as an int32_t.
|
||||
) {
|
||||
Message msg;
|
||||
msg << "WARNING: " << src_text
|
||||
@@ -1246,33 +1361,33 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
|
||||
// Reads and returns the Boolean environment variable corresponding to
|
||||
// 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) {
|
||||
#if defined(GTEST_GET_BOOL_FROM_ENV_)
|
||||
return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
|
||||
#else
|
||||
const std::string env_var = FlagToEnvVar(flag);
|
||||
const char* const string_value = posix::GetEnv(env_var.c_str());
|
||||
return string_value == NULL ?
|
||||
default_value : strcmp(string_value, "0") != 0;
|
||||
return string_value == nullptr ? default_value
|
||||
: strcmp(string_value, "0") != 0;
|
||||
#endif // defined(GTEST_GET_BOOL_FROM_ENV_)
|
||||
}
|
||||
|
||||
// Reads and returns a 32-bit integer stored in the environment
|
||||
// variable corresponding to the given flag; if it isn't set or
|
||||
// doesn't represent a valid 32-bit integer, returns default_value.
|
||||
Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
||||
int32_t Int32FromGTestEnv(const char* flag, int32_t default_value) {
|
||||
#if defined(GTEST_GET_INT32_FROM_ENV_)
|
||||
return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
|
||||
#else
|
||||
const std::string env_var = FlagToEnvVar(flag);
|
||||
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.
|
||||
return default_value;
|
||||
}
|
||||
|
||||
Int32 result = default_value;
|
||||
int32_t result = default_value;
|
||||
if (!ParseInt32(Message() << "Environment variable " << env_var,
|
||||
string_value, &result)) {
|
||||
printf("The default value %s is used.\n",
|
||||
@@ -1296,7 +1411,7 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
||||
std::string OutputFlagAlsoCheckEnvVar(){
|
||||
std::string default_value_for_output_flag = "";
|
||||
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;
|
||||
}
|
||||
return default_value_for_output_flag;
|
||||
@@ -1310,7 +1425,7 @@ const char* StringFromGTestEnv(const char* flag, const char* default_value) {
|
||||
#else
|
||||
const std::string env_var = FlagToEnvVar(flag);
|
||||
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_)
|
||||
}
|
||||
|
||||
|
||||
+146
-70
@@ -42,11 +42,16 @@
|
||||
// defines Foo.
|
||||
|
||||
#include "gtest/gtest-printers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <cwchar>
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "src/gtest-internal-inl.h"
|
||||
|
||||
@@ -59,6 +64,7 @@ using ::std::ostream;
|
||||
// Prints a segment of bytes in the given object.
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||
size_t count, ostream* os) {
|
||||
@@ -89,7 +95,6 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
||||
// If the object size is bigger than kThreshold, we'll have to omit
|
||||
// some details by printing only the first and the last kChunkSize
|
||||
// bytes.
|
||||
// FIXME: let the user control the threshold using a flag.
|
||||
if (count < kThreshold) {
|
||||
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
|
||||
} else {
|
||||
@@ -102,9 +107,19 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
||||
*os << ">";
|
||||
}
|
||||
|
||||
// Helpers for widening a character to char32_t. Since the standard does not
|
||||
// specify if char / wchar_t is signed or unsigned, it is important to first
|
||||
// convert it to the unsigned type of the same width before widening it to
|
||||
// char32_t.
|
||||
template <typename CharType>
|
||||
char32_t ToChar32(CharType in) {
|
||||
return static_cast<char32_t>(
|
||||
static_cast<typename std::make_unsigned<CharType>::type>(in));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace internal2 {
|
||||
namespace internal {
|
||||
|
||||
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
|
||||
// given object. The delegation simplifies the implementation, which
|
||||
@@ -116,10 +131,6 @@ void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
|
||||
PrintBytesInObjectToImpl(obj_bytes, count, os);
|
||||
}
|
||||
|
||||
} // namespace internal2
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Depending on the value of a char (or wchar_t), we print it in one
|
||||
// of three formats:
|
||||
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
|
||||
@@ -134,17 +145,15 @@ enum CharFormat {
|
||||
// Returns true if c is a printable ASCII character. We test the
|
||||
// value of c directly instead of calling isprint(), which is buggy on
|
||||
// Windows Mobile.
|
||||
inline bool IsPrintableAscii(wchar_t c) {
|
||||
return 0x20 <= c && c <= 0x7E;
|
||||
}
|
||||
inline bool IsPrintableAscii(char32_t c) { return 0x20 <= c && c <= 0x7E; }
|
||||
|
||||
// Prints a wide or narrow char c as a character literal without the
|
||||
// quotes, escaping it when necessary; returns how c was formatted.
|
||||
// The template argument UnsignedChar is the unsigned version of Char,
|
||||
// which is the type of c.
|
||||
template <typename UnsignedChar, typename Char>
|
||||
// Prints c (of type char, char8_t, char16_t, char32_t, or wchar_t) as a
|
||||
// character literal without the quotes, escaping it when necessary; returns how
|
||||
// c was formatted.
|
||||
template <typename Char>
|
||||
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||
switch (static_cast<wchar_t>(c)) {
|
||||
const char32_t u_c = ToChar32(c);
|
||||
switch (u_c) {
|
||||
case L'\0':
|
||||
*os << "\\0";
|
||||
break;
|
||||
@@ -176,13 +185,12 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||
*os << "\\v";
|
||||
break;
|
||||
default:
|
||||
if (IsPrintableAscii(c)) {
|
||||
if (IsPrintableAscii(u_c)) {
|
||||
*os << static_cast<char>(c);
|
||||
return kAsIs;
|
||||
} else {
|
||||
ostream::fmtflags flags = os->flags();
|
||||
*os << "\\x" << std::hex << std::uppercase
|
||||
<< static_cast<int>(static_cast<UnsignedChar>(c));
|
||||
*os << "\\x" << std::hex << std::uppercase << static_cast<int>(u_c);
|
||||
os->flags(flags);
|
||||
return kHexEscape;
|
||||
}
|
||||
@@ -190,9 +198,9 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||
return kSpecialEscape;
|
||||
}
|
||||
|
||||
// Prints a wchar_t c as if it's part of a string literal, escaping it when
|
||||
// Prints a char32_t c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||
static CharFormat PrintAsStringLiteralTo(char32_t c, ostream* os) {
|
||||
switch (c) {
|
||||
case L'\'':
|
||||
*os << "'";
|
||||
@@ -201,26 +209,68 @@ static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||
*os << "\\\"";
|
||||
return kSpecialEscape;
|
||||
default:
|
||||
return PrintAsCharLiteralTo<wchar_t>(c, os);
|
||||
return PrintAsCharLiteralTo(c, os);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(signed char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(unsigned char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
static const char* GetCharWidthPrefix(char8_t) {
|
||||
return "u8";
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* GetCharWidthPrefix(char16_t) {
|
||||
return "u";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(char32_t) {
|
||||
return "U";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(wchar_t) {
|
||||
return "L";
|
||||
}
|
||||
|
||||
// Prints a char c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(
|
||||
static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
// Prints a wide or narrow character c and its code. '\0' is printed
|
||||
// as "'\\0'", other unprintable characters are also properly escaped
|
||||
// using the standard C++ escape sequence. The template argument
|
||||
// UnsignedChar is the unsigned version of Char, which is the type of c.
|
||||
template <typename UnsignedChar, typename Char>
|
||||
#ifdef __cpp_char8_t
|
||||
static CharFormat PrintAsStringLiteralTo(char8_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
#endif
|
||||
|
||||
static CharFormat PrintAsStringLiteralTo(char16_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
// Prints a character c (of type char, char8_t, char16_t, char32_t, or wchar_t)
|
||||
// and its code. '\0' is printed as "'\\0'", other unprintable characters are
|
||||
// also properly escaped using the standard C++ escape sequence.
|
||||
template <typename Char>
|
||||
void PrintCharAndCodeTo(Char c, ostream* os) {
|
||||
// First, print c as a literal in the most readable form we can find.
|
||||
*os << ((sizeof(c) > 1) ? "L'" : "'");
|
||||
const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
|
||||
*os << GetCharWidthPrefix(c) << "'";
|
||||
const CharFormat format = PrintAsCharLiteralTo(c, os);
|
||||
*os << "'";
|
||||
|
||||
// To aid user debugging, we also print c's code in decimal, unless
|
||||
@@ -236,36 +286,37 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
|
||||
if (format == kHexEscape || (1 <= c && c <= 9)) {
|
||||
// Do nothing.
|
||||
} else {
|
||||
*os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
|
||||
*os << ", 0x" << String::FormatHexInt(static_cast<int>(c));
|
||||
}
|
||||
*os << ")";
|
||||
}
|
||||
|
||||
void PrintTo(unsigned char c, ::std::ostream* os) {
|
||||
PrintCharAndCodeTo<unsigned char>(c, os);
|
||||
}
|
||||
void PrintTo(signed char c, ::std::ostream* os) {
|
||||
PrintCharAndCodeTo<unsigned char>(c, os);
|
||||
}
|
||||
void PrintTo(unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
|
||||
void PrintTo(signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
|
||||
|
||||
// Prints a wchar_t as a symbol if it is printable or as its internal
|
||||
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
|
||||
void PrintTo(wchar_t wc, ostream* os) {
|
||||
PrintCharAndCodeTo<wchar_t>(wc, os);
|
||||
void PrintTo(wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); }
|
||||
|
||||
// TODO(dcheng): Consider making this delegate to PrintCharAndCodeTo() as well.
|
||||
void PrintTo(char32_t c, ::std::ostream* os) {
|
||||
*os << std::hex << "U+" << std::uppercase << std::setfill('0') << std::setw(4)
|
||||
<< static_cast<uint32_t>(c);
|
||||
}
|
||||
|
||||
// Prints the given array of characters to the ostream. CharType must be either
|
||||
// char or wchar_t.
|
||||
// char, char8_t, char16_t, char32_t, or wchar_t.
|
||||
// The array starts at begin, the length is len, it may include '\0' characters
|
||||
// and may not be NUL-terminated.
|
||||
template <typename CharType>
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
static CharFormat PrintCharsAsStringTo(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
||||
*os << kQuoteBegin;
|
||||
const char* const quote_prefix = GetCharWidthPrefix(*begin);
|
||||
*os << quote_prefix << "\"";
|
||||
bool is_previous_hex = false;
|
||||
CharFormat print_format = kAsIs;
|
||||
for (size_t index = 0; index < len; ++index) {
|
||||
@@ -274,7 +325,7 @@ static CharFormat PrintCharsAsStringTo(
|
||||
// Previous character is of '\x..' form and this character can be
|
||||
// interpreted as another hexadecimal digit in its number. Break string to
|
||||
// disambiguate.
|
||||
*os << "\" " << kQuoteBegin;
|
||||
*os << "\" " << quote_prefix << "\"";
|
||||
}
|
||||
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
|
||||
// Remember if any characters required hex escaping.
|
||||
@@ -291,6 +342,7 @@ static CharFormat PrintCharsAsStringTo(
|
||||
template <typename CharType>
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
static void UniversalPrintCharArray(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
@@ -319,22 +371,57 @@ void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
// Prints a (const) char8_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char8_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Prints a (const) char16_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char16_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints a (const) char32_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char32_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints a (const) wchar_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints the given C string to the ostream.
|
||||
void PrintTo(const char* s, ostream* os) {
|
||||
if (s == NULL) {
|
||||
namespace {
|
||||
|
||||
// Prints a null-terminated C-style string to the ostream.
|
||||
template <typename Char>
|
||||
void PrintCStringTo(const Char* s, ostream* os) {
|
||||
if (s == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||
PrintCharsAsStringTo(s, strlen(s), os);
|
||||
PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void PrintTo(const char* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
void PrintTo(const char8_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
#endif
|
||||
|
||||
void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
// MSVC compiler can be configured to define whar_t as a typedef
|
||||
// of unsigned short. Defining an overload for const wchar_t* in that case
|
||||
// would cause pointers to unsigned shorts be printed as wide strings,
|
||||
@@ -343,14 +430,7 @@ void PrintTo(const char* s, ostream* os) {
|
||||
// wchar_t is implemented as a native type.
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
// Prints the given wide C string to the ostream.
|
||||
void PrintTo(const wchar_t* s, ostream* os) {
|
||||
if (s == NULL) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||
PrintCharsAsStringTo(s, wcslen(s), os);
|
||||
}
|
||||
}
|
||||
void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
#endif // wchar_t is native
|
||||
|
||||
namespace {
|
||||
@@ -420,17 +500,6 @@ void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
|
||||
|
||||
} // 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) {
|
||||
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
||||
if (GTEST_FLAG(print_utf8)) {
|
||||
@@ -439,12 +508,19 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||
}
|
||||
}
|
||||
|
||||
// Prints a ::wstring object.
|
||||
#if GTEST_HAS_GLOBAL_WSTRING
|
||||
void PrintWideStringTo(const ::wstring& s, ostream* os) {
|
||||
#ifdef __cpp_char8_t
|
||||
void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
|
||||
void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||
|
||||
#include "gtest/gtest-test-part.h"
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "src/gtest-internal-inl.h"
|
||||
|
||||
namespace testing {
|
||||
@@ -41,18 +43,23 @@ using internal::GetUnitTestImpl;
|
||||
// in it.
|
||||
std::string TestPartResult::ExtractSummary(const char* message) {
|
||||
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
|
||||
return stack_trace == NULL ? message :
|
||||
std::string(message, stack_trace);
|
||||
return stack_trace == nullptr ? message : std::string(message, stack_trace);
|
||||
}
|
||||
|
||||
// Prints a TestPartResult object.
|
||||
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
||||
return os
|
||||
<< result.file_name() << ":" << result.line_number() << ": "
|
||||
<< (result.type() == TestPartResult::kSuccess ? "Success" :
|
||||
result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
|
||||
"Non-fatal failure") << ":\n"
|
||||
<< result.message() << std::endl;
|
||||
return os << internal::FormatFileLocation(result.file_name(),
|
||||
result.line_number())
|
||||
<< " "
|
||||
<< (result.type() == TestPartResult::kSuccess
|
||||
? "Success"
|
||||
: result.type() == TestPartResult::kSkip
|
||||
? "Skipped"
|
||||
: result.type() == TestPartResult::kFatalFailure
|
||||
? "Fatal failure"
|
||||
: "Non-fatal failure")
|
||||
<< ":\n"
|
||||
<< result.message() << std::endl;
|
||||
}
|
||||
|
||||
// Appends a TestPartResult to the array.
|
||||
@@ -67,7 +74,7 @@ const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
|
||||
internal::posix::Abort();
|
||||
}
|
||||
|
||||
return array_[index];
|
||||
return array_[static_cast<size_t>(index)];
|
||||
}
|
||||
|
||||
// Returns the number of TestPartResult objects in the array.
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// Skips to the first non-space char in str. Returns an empty string if str
|
||||
// contains only whitespace characters.
|
||||
static const char* SkipSpaces(const char* str) {
|
||||
@@ -48,7 +46,7 @@ static const char* SkipSpaces(const char* str) {
|
||||
static std::vector<std::string> SplitIntoTestNames(const char* src) {
|
||||
std::vector<std::string> name_vec;
|
||||
src = SkipSpaces(src);
|
||||
for (; src != NULL; src = SkipComma(src)) {
|
||||
for (; src != nullptr; src = SkipComma(src)) {
|
||||
name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
|
||||
}
|
||||
return name_vec;
|
||||
@@ -57,8 +55,11 @@ static std::vector<std::string> SplitIntoTestNames(const char* src) {
|
||||
// Verifies that registered_tests match the test names in
|
||||
// registered_tests_; returns registered_tests if successful, or
|
||||
// aborts the program otherwise.
|
||||
const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||
const char* file, int line, const char* registered_tests) {
|
||||
const char* TypedTestSuitePState::VerifyRegisteredTestNames(
|
||||
const char* test_suite_name, const char* file, int line,
|
||||
const char* registered_tests) {
|
||||
RegisterTypeParameterizedTestSuite(test_suite_name, CodeLocation(file, line));
|
||||
|
||||
typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
|
||||
registered_ = true;
|
||||
|
||||
@@ -75,21 +76,11 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||
continue;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (RegisteredTestIter it = registered_tests_.begin();
|
||||
it != registered_tests_.end();
|
||||
++it) {
|
||||
if (name == it->first) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (registered_tests_.count(name) != 0) {
|
||||
tests.insert(name);
|
||||
} else {
|
||||
errors << "No test named " << name
|
||||
<< " can be found in this test case.\n";
|
||||
<< " can be found in this test suite.\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +103,5 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||
return registered_tests;
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
+1746
-1007
File diff suppressed because it is too large.
Load diff
+18
-1
@@ -27,11 +27,28 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
|
||||
#if GTEST_OS_ESP8266
|
||||
extern "C" {
|
||||
#endif
|
||||
void setup() {
|
||||
testing::InitGoogleTest();
|
||||
}
|
||||
|
||||
void loop() { RUN_ALL_TESTS(); }
|
||||
|
||||
#if GTEST_OS_ESP8266
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
GTEST_API_ int main(int argc, char **argv) {
|
||||
printf("Running main() from %s\n", __FILE__);
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user