Initial commit.
This commit is contained in:
parent
85d9664df7
commit
b2b1ba7abe
|
@ -0,0 +1,73 @@
|
||||||
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
Changes for 1.5.0:
|
||||||
|
|
||||||
|
* New feature: Google Mock can be safely used in multi-threaded tests
|
||||||
|
on platforms having pthreads.
|
||||||
|
* New feature: function for printing a value of arbitrary type.
|
||||||
|
* New feature: function ExplainMatchResult() for easy definition of
|
||||||
|
composite matchers.
|
||||||
|
* The new matcher API lets user-defined matchers generate custom
|
||||||
|
explanations more directly and efficiently.
|
||||||
|
* Better failure messages all around.
|
||||||
|
* NotNull() and IsNull() now work with smart pointers.
|
||||||
|
* Field() and Property() now work when the matcher argument is a pointer
|
||||||
|
passed by reference.
|
||||||
|
* Regular expression matchers on all platforms.
|
||||||
|
* Added GCC 4.0 support for Google Mock Doctor.
|
||||||
|
* Added gmock_all_test.cc for compiling most Google Mock tests
|
||||||
|
in a single file.
|
||||||
|
* Significantly cleaned up compiler warnings.
|
||||||
|
* Bug fixes, better test coverage, and implementation clean-ups.
|
||||||
|
|
||||||
|
Potentially breaking changes:
|
||||||
|
|
||||||
|
* Custom matchers defined using MatcherInterface or MakePolymorphicMatcher()
|
||||||
|
need to be updated after upgrading to Google Mock 1.5.0; matchers defined
|
||||||
|
using MATCHER or MATCHER_P* aren't affected.
|
||||||
|
* Dropped support for 'make install'.
|
||||||
|
|
||||||
|
Changes for 1.4.0 (we skipped 1.2.* and 1.3.* to match the version of
|
||||||
|
Google Test):
|
||||||
|
|
||||||
|
* Works in more environments: Symbian and minGW, Visual C++ 7.1.
|
||||||
|
* Lighter weight: comes with our own implementation of TR1 tuple (no
|
||||||
|
more dependency on Boost!).
|
||||||
|
* New feature: --gmock_catch_leaked_mocks for detecting leaked mocks.
|
||||||
|
* New feature: ACTION_TEMPLATE for defining templatized actions.
|
||||||
|
* New feature: the .After() clause for specifying expectation order.
|
||||||
|
* New feature: the .With() clause for for specifying inter-argument
|
||||||
|
constraints.
|
||||||
|
* New feature: actions ReturnArg<k>(), ReturnNew<T>(...), and
|
||||||
|
DeleteArg<k>().
|
||||||
|
* New feature: matchers Key(), Pair(), Args<...>(), AllArgs(), IsNull(),
|
||||||
|
and Contains().
|
||||||
|
* New feature: utility class MockFunction<F>, useful for checkpoints, etc.
|
||||||
|
* New feature: functions Value(x, m) and SafeMatcherCast<T>(m).
|
||||||
|
* New feature: copying a mock object is rejected at compile time.
|
||||||
|
* New feature: a script for fusing all Google Mock and Google Test
|
||||||
|
source files for easy deployment.
|
||||||
|
* Improved the Google Mock doctor to diagnose more diseases.
|
||||||
|
* Improved the Google Mock generator script.
|
||||||
|
* Compatibility fixes for Mac OS X and gcc.
|
||||||
|
* Bug fixes and implementation clean-ups.
|
||||||
|
|
||||||
|
Changes for 1.1.0:
|
||||||
|
|
||||||
|
* New feature: ability to use Google Mock with any testing framework.
|
||||||
|
* New feature: macros for easily defining new matchers
|
||||||
|
* New feature: macros for easily defining new actions.
|
||||||
|
* New feature: more container matchers.
|
||||||
|
* New feature: actions for accessing function arguments and throwing
|
||||||
|
exceptions.
|
||||||
|
* Improved the Google Mock doctor script for diagnosing compiler errors.
|
||||||
|
* Bug fixes and implementation clean-ups.
|
||||||
|
|
||||||
|
Changes for 1.0.0:
|
||||||
|
|
||||||
|
* Initial Open Source release of Google Mock
|
|
@ -0,0 +1,40 @@
|
||||||
|
# This file contains a list of people who've made non-trivial
|
||||||
|
# contribution to the Google C++ Mocking Framework project. People
|
||||||
|
# who commit code to the project are encouraged to add their names
|
||||||
|
# here. Please keep the list sorted by first names.
|
||||||
|
|
||||||
|
Benoit Sigoure <tsuna@google.com>
|
||||||
|
Bogdan Piloca <boo@google.com>
|
||||||
|
Chandler Carruth <chandlerc@google.com>
|
||||||
|
Dave MacLachlan <dmaclach@gmail.com>
|
||||||
|
David Anderson <danderson@google.com>
|
||||||
|
Dean Sturtevant
|
||||||
|
Gene Volovich <gv@cite.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>
|
||||||
|
Keir Mierle <mierle@gmail.com>
|
||||||
|
Keith Ray <keith.ray@gmail.com>
|
||||||
|
Kostya Serebryany <kcc@google.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>
|
||||||
|
Mike Bland <mbland@google.com>
|
||||||
|
Neal Norwitz <nnorwitz@gmail.com>
|
||||||
|
Nermin Ozkiranartli <nermin@google.com>
|
||||||
|
Owen Carlsen <ocarlsen@google.com>
|
||||||
|
Paneendra Ba <paneendra@google.com>
|
||||||
|
Paul Menage <menage@google.com>
|
||||||
|
Piotr Kaminski <piotrk@google.com>
|
||||||
|
Russ Rufer <russ@pentad.com>
|
||||||
|
Sverre Sundsdal <sundsdal@gmail.com>
|
||||||
|
Takeshi Yoshino <tyoshino@google.com>
|
||||||
|
Vadim Berman <vadimb@google.com>
|
||||||
|
Vlad Losev <vladl@google.com>
|
||||||
|
Wolfgang Klier <wklier@google.com>
|
||||||
|
Zhanyong Wan <wan@google.com>
|
|
@ -0,0 +1,28 @@
|
||||||
|
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.
|
|
@ -0,0 +1,352 @@
|
||||||
|
Google C++ Mocking Framework
|
||||||
|
============================
|
||||||
|
|
||||||
|
http://code.google.com/p/googlemock/
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
Google's framework for writing and using C++ mock classes on a variety
|
||||||
|
of platforms (Linux, Mac OS X, Windows, Windows CE, Symbian, etc).
|
||||||
|
Inspired by jMock, EasyMock, and Hamcrest, and designed with C++'s
|
||||||
|
specifics in mind, it can help you derive better designs of your
|
||||||
|
system and write better tests.
|
||||||
|
|
||||||
|
Google Mock:
|
||||||
|
|
||||||
|
- provides a declarative syntax for defining mocks,
|
||||||
|
- can easily define partial (hybrid) mocks, which are a cross of real
|
||||||
|
and mock objects,
|
||||||
|
- handles functions of arbitrary types and overloaded functions,
|
||||||
|
- comes with a rich set of matchers for validating function arguments,
|
||||||
|
- uses an intuitive syntax for controlling the behavior of a mock,
|
||||||
|
- does automatic verification of expectations (no record-and-replay
|
||||||
|
needed),
|
||||||
|
- allows arbitrary (partial) ordering constraints on
|
||||||
|
function calls to be expressed,
|
||||||
|
- lets a user extend it by defining new matchers and actions.
|
||||||
|
- does not use exceptions, and
|
||||||
|
- is easy to learn and use.
|
||||||
|
|
||||||
|
Please see the project page above for more information as well as the
|
||||||
|
mailing list for questions, discussions, and development. There is
|
||||||
|
also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please
|
||||||
|
join us!
|
||||||
|
|
||||||
|
Please note that code under scripts/generator/ is from the cppclean
|
||||||
|
project (http://code.google.com/p/cppclean/) and under the Apache
|
||||||
|
License, which is different from Google Mock's license.
|
||||||
|
|
||||||
|
Requirements for End Users
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Google Mock is implemented on top of the Google Test C++ testing
|
||||||
|
framework (http://code.google.com/p/googletest/), and includes the
|
||||||
|
latter as part of the SVN repositary and distribution package. You
|
||||||
|
must use the bundled version of Google Test when using Google Mock, or
|
||||||
|
you may get compiler/linker errors.
|
||||||
|
|
||||||
|
You can also easily configure Google Mock to work with another testing
|
||||||
|
framework of your choice; although it will still need Google Test as
|
||||||
|
an internal dependency. Please read
|
||||||
|
http://code.google.com/p/googlemock/wiki/ForDummies#Using_Google_Mock_with_Any_Testing_Framework
|
||||||
|
for how to do it.
|
||||||
|
|
||||||
|
Google Mock depends on advanced C++ features and thus requires a more
|
||||||
|
modern compiler. The following are needed to use Google Mock:
|
||||||
|
|
||||||
|
### Linux Requirements ###
|
||||||
|
|
||||||
|
These are the base requirements to build and use Google Mock from a source
|
||||||
|
package (as described below):
|
||||||
|
|
||||||
|
* GNU-compatible Make or "gmake"
|
||||||
|
* POSIX-standard shell
|
||||||
|
* POSIX(-2) Regular Expressions (regex.h)
|
||||||
|
* C++98-standard-compliant compiler (e.g. GCC 3.4 or newer)
|
||||||
|
|
||||||
|
### Windows Requirements ###
|
||||||
|
|
||||||
|
* Microsoft Visual C++ 8.0 SP1 or newer
|
||||||
|
|
||||||
|
### Mac OS X Requirements ###
|
||||||
|
|
||||||
|
* Mac OS X 10.4 Tiger or newer
|
||||||
|
* Developer Tools Installed
|
||||||
|
|
||||||
|
Requirements for Contributors
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
We welcome patches. If you plan to contribute a patch, you need to
|
||||||
|
build Google Mock and its own tests from an SVN checkout (described
|
||||||
|
below), which has further requirements:
|
||||||
|
|
||||||
|
* Automake version 1.9 or newer
|
||||||
|
* Autoconf version 2.59 or newer
|
||||||
|
* Libtool / Libtoolize
|
||||||
|
* Python version 2.3 or newer (for running some of the tests and
|
||||||
|
re-generating certain source files from templates)
|
||||||
|
|
||||||
|
Getting the Source
|
||||||
|
------------------
|
||||||
|
|
||||||
|
There are two primary ways of getting Google Mock's source code: you
|
||||||
|
can download a stable source release in your preferred archive format,
|
||||||
|
or directly check out the source from our Subversion (SVN) repositary.
|
||||||
|
The SVN checkout requires a few extra steps and some extra software
|
||||||
|
packages on your system, but lets you track development and make
|
||||||
|
patches much more easily, so we highly encourage it.
|
||||||
|
|
||||||
|
### Source Package ###
|
||||||
|
|
||||||
|
Google Mock is released in versioned source packages which can be
|
||||||
|
downloaded from the download page [1]. Several different archive
|
||||||
|
formats are provided, but the only difference is the tools needed to
|
||||||
|
extract their contents, and the size of the resulting file. Download
|
||||||
|
whichever you are most comfortable with.
|
||||||
|
|
||||||
|
[1] http://code.google.com/p/googlemock/downloads/list
|
||||||
|
|
||||||
|
Once downloaded expand the archive using whichever tools you prefer
|
||||||
|
for that type. This will always result in a new directory with the
|
||||||
|
name "gmock-X.Y.Z" which contains all of the source code. Here are
|
||||||
|
some examples on Linux:
|
||||||
|
|
||||||
|
tar -xvzf gmock-X.Y.Z.tar.gz
|
||||||
|
tar -xvjf gmock-X.Y.Z.tar.bz2
|
||||||
|
unzip gmock-X.Y.Z.zip
|
||||||
|
|
||||||
|
### SVN Checkout ###
|
||||||
|
|
||||||
|
To check out the main branch (also known as the "trunk") of Google
|
||||||
|
Mock, run the following Subversion command:
|
||||||
|
|
||||||
|
svn checkout http://googlemock.googlecode.com/svn/trunk/ gmock-svn
|
||||||
|
|
||||||
|
If you are using a *nix system and plan to use the GNU Autotools build
|
||||||
|
system to build Google Mock (described below), you'll need to
|
||||||
|
configure it now. Otherwise you are done with getting the source
|
||||||
|
files.
|
||||||
|
|
||||||
|
To prepare the Autotools build system, enter the target directory of
|
||||||
|
the checkout command you used ('gmock-svn') and proceed with the
|
||||||
|
following command:
|
||||||
|
|
||||||
|
autoreconf -fvi
|
||||||
|
|
||||||
|
Once you have completed this step, you are ready to build the library.
|
||||||
|
Note that you should only need to complete this step once. The
|
||||||
|
subsequent 'make' invocations will automatically re-generate the bits
|
||||||
|
of the build system that need to be changed.
|
||||||
|
|
||||||
|
If your system uses older versions of the autotools, the above command
|
||||||
|
will fail. You may need to explicitly specify a version to use. For
|
||||||
|
instance, if you have both GNU Automake 1.4 and 1.9 installed and
|
||||||
|
'automake' would invoke the 1.4, use instead:
|
||||||
|
|
||||||
|
AUTOMAKE=automake-1.9 ACLOCAL=aclocal-1.9 autoreconf -fvi
|
||||||
|
|
||||||
|
Make sure you're using the same version of automake and aclocal.
|
||||||
|
|
||||||
|
Setting up the Build
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
To build Google Mock 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.
|
||||||
|
|
||||||
|
### Generic Build Instructions ###
|
||||||
|
|
||||||
|
This section shows how you can integrate Google Mock into your
|
||||||
|
existing build system.
|
||||||
|
|
||||||
|
Suppose you put Google Mock in directory ${GMOCK_DIR} and Google Test
|
||||||
|
in ${GTEST_DIR} (the latter is ${GMOCK_DIR}/gtest by default). To
|
||||||
|
build Google Mock, create a library build target (or a project as
|
||||||
|
called by Visual Studio and Xcode) to compile
|
||||||
|
|
||||||
|
${GTEST_DIR}/src/gtest-all.cc and ${GMOCK_DIR}/src/gmock-all.cc
|
||||||
|
|
||||||
|
with
|
||||||
|
|
||||||
|
${GTEST_DIR}/include, ${GTEST_DIR}, ${GMOCK_DIR}/include, and ${GMOCK_DIR}
|
||||||
|
|
||||||
|
in the header search path. Assuming a Linux-like system and gcc,
|
||||||
|
something like the following will do:
|
||||||
|
|
||||||
|
g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -I${GMOCK_DIR}/include \
|
||||||
|
-I${GMOCK_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
|
||||||
|
g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -I${GMOCK_DIR}/include \
|
||||||
|
-I${GMOCK_DIR} -c ${GMOCK_DIR}/src/gmock-all.cc
|
||||||
|
ar -rv libgmock.a gtest-all.o gmock-all.o
|
||||||
|
|
||||||
|
Next, you should compile your test source file with
|
||||||
|
${GTEST_DIR}/include and ${GMOCK_DIR}/include in the header search
|
||||||
|
path, and link it with gmock and any other necessary libraries:
|
||||||
|
|
||||||
|
g++ -I${GTEST_DIR}/include -I${GMOCK_DIR}/include \
|
||||||
|
path/to/your_test.cc libgmock.a -o your_test
|
||||||
|
|
||||||
|
As an example, the make/ directory contains a Makefile that you can
|
||||||
|
use to build Google Mock on systems where GNU make is available
|
||||||
|
(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google
|
||||||
|
Mock's own tests. Instead, it just builds the Google Mock 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 ${GMOCK_DIR}/make
|
||||||
|
make
|
||||||
|
./gmock_test
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
|
||||||
|
The msvc/ directory contains VC++ 2005 projects for building Google
|
||||||
|
Mock and selected tests.
|
||||||
|
|
||||||
|
Open msvc/gmock.sln and build the library and tests. If you want to
|
||||||
|
create your own project to use with Google Mock, you'll have to
|
||||||
|
configure it to use the gmock_config propety sheet. For that:
|
||||||
|
|
||||||
|
* Open the Property Manager window (View | Other Windows | Property Manager)
|
||||||
|
* Right-click on your project and select "Add Existing Property Sheet..."
|
||||||
|
* Navigate to gmock_config.vsprops and select it.
|
||||||
|
* In Project Properties | Configuration Properties | General | Additional
|
||||||
|
Include Directories, type <path to Google Mock>/include.
|
||||||
|
|
||||||
|
Tweaking Google Mock
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Google Mock 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 Mock 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 ${GTEST_DIR}/include/gtest/internal/gtest-port.h.
|
||||||
|
|
||||||
|
### Choosing a TR1 Tuple Library ###
|
||||||
|
|
||||||
|
Google Mock uses the C++ Technical Report 1 (TR1) tuple library
|
||||||
|
heavily. Unfortunately TR1 tuple is not yet widely available with all
|
||||||
|
compilers. The good news is that Google Test 1.4.0+ implements a
|
||||||
|
subset of TR1 tuple that's enough for Google Mock's need. Google Mock
|
||||||
|
will automatically use that implementation when the compiler doesn't
|
||||||
|
provide TR1 tuple.
|
||||||
|
|
||||||
|
Usually you don't need to care about which tuple library Google Test
|
||||||
|
and Google Mock use. However, if your project already uses TR1 tuple,
|
||||||
|
you need to tell Google Test and Google Mock 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, Google Mock, and
|
||||||
|
your tests. If you want to force Google Test and Google Mock to use
|
||||||
|
their own tuple library, just add
|
||||||
|
|
||||||
|
-DGTEST_USE_OWN_TR1_TUPLE=1
|
||||||
|
|
||||||
|
to the compiler flags instead.
|
||||||
|
|
||||||
|
If you want to use Boost's TR1 tuple library with Google Mock, please
|
||||||
|
refer to the Boost website (http://www.boost.org/) for how to obtain
|
||||||
|
it and set it up.
|
||||||
|
|
||||||
|
### Tweaking Google Test ###
|
||||||
|
|
||||||
|
Most of Google Test's control macros apply to Google Mock as well.
|
||||||
|
Please see file ${GTEST_DIR}/README for how to tweak them.
|
||||||
|
|
||||||
|
Upgrading from an Earlier Version
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
We strive to keep Google Mock releases backward compatible.
|
||||||
|
Sometimes, though, we have to make some breaking changes for the
|
||||||
|
users' long-term benefits. This section describes what you'll need to
|
||||||
|
do if you are upgrading from an earlier version of Google Mock.
|
||||||
|
|
||||||
|
### Upgrading from 1.1.0 or Earlier ###
|
||||||
|
|
||||||
|
You may need to explicitly enable or disable Google Test's own TR1
|
||||||
|
tuple library. See the instructions in section "Choosing a TR1 Tuple
|
||||||
|
Library".
|
||||||
|
|
||||||
|
### Upgrading from 1.4.0 or Earlier ###
|
||||||
|
|
||||||
|
On platforms where the pthread library is available, Google Test and
|
||||||
|
Google Mock use it in order to be thread-safe. For this to work, you
|
||||||
|
may need to tweak your compiler and/or linker flags. Please see the
|
||||||
|
"Multi-threaded Tests" section in file ${GTEST_DIR}/README for what
|
||||||
|
you may need to do.
|
||||||
|
|
||||||
|
If you have custom matchers defined using MatcherInterface or
|
||||||
|
MakePolymorphicMatcher(), you'll need to update their definitions to
|
||||||
|
use the new matcher API [2]. Matchers defined using MATCHER() or
|
||||||
|
MATCHER_P*() aren't affected.
|
||||||
|
|
||||||
|
[2] http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Monomorphic_Matchers,
|
||||||
|
http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Polymorphic_Matchers
|
||||||
|
|
||||||
|
Developing Google Mock
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
This section discusses how to make your own changes to Google Mock.
|
||||||
|
|
||||||
|
### Testing Google Mock Itself ###
|
||||||
|
|
||||||
|
To make sure your changes work as intended and don't break existing
|
||||||
|
functionality, you'll want to compile and run Google Test's own tests.
|
||||||
|
For that you'll need Autotools. First, make sure you have followed
|
||||||
|
the instructions in section "SVN Checkout" to configure Google Mock.
|
||||||
|
Then, create a build output directory and enter it. Next,
|
||||||
|
|
||||||
|
${GMOCK_DIR}/configure # Standard GNU configure script, --help for more info
|
||||||
|
|
||||||
|
Once you have successfully configured Google Mock, the build steps are
|
||||||
|
standard for GNU-style OSS packages.
|
||||||
|
|
||||||
|
make # Standard makefile following GNU conventions
|
||||||
|
make check # Builds and runs all tests - all should pass.
|
||||||
|
|
||||||
|
Note that when building your project against Google Mock, you are building
|
||||||
|
against Google Test as well. There is no need to configure Google Test
|
||||||
|
separately.
|
||||||
|
|
||||||
|
### Regenerating Source Files ###
|
||||||
|
|
||||||
|
Some of Google Mock's source files are generated from templates (not
|
||||||
|
in the C++ sense) using a script. A template file is named FOO.pump,
|
||||||
|
where FOO is the name of the file it will generate. For example, the
|
||||||
|
file include/gmock/gmock-generated-actions.h.pump is used to generate
|
||||||
|
gmock-generated-actions.h in the same directory.
|
||||||
|
|
||||||
|
Normally you don't need to worry about regenerating the source files,
|
||||||
|
unless you need to modify them. In that case, you should modify the
|
||||||
|
corresponding .pump files instead and run the 'pump' script (for Pump
|
||||||
|
is Useful for Meta Programming) to regenerate them. You can find
|
||||||
|
pump.py in the ${GTEST_DIR}/scripts/ directory. Read the Pump manual
|
||||||
|
[3] for how to use it.
|
||||||
|
|
||||||
|
[3] http://code.google.com/p/googletest/wiki/PumpManual.
|
||||||
|
|
||||||
|
### Contributing a Patch ###
|
||||||
|
|
||||||
|
We welcome patches. Please read the Google Mock developer's guide [4]
|
||||||
|
for how you can contribute. In particular, make sure you have signed
|
||||||
|
the Contributor License Agreement, or we won't be able to accept the
|
||||||
|
patch.
|
||||||
|
|
||||||
|
[4] http://code.google.com/p/googlemock/wiki/DevGuide
|
||||||
|
|
||||||
|
Happy testing!
|
|
@ -0,0 +1,98 @@
|
||||||
|
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
|
|
@ -0,0 +1,36 @@
|
||||||
|
# This file contains a list of people who've made non-trivial
|
||||||
|
# contribution to the Google C++ Testing Framework project. People
|
||||||
|
# who commit code to the project are encouraged to add their names
|
||||||
|
# here. Please keep the list sorted by first names.
|
||||||
|
|
||||||
|
Ajay Joshi <jaj@google.com>
|
||||||
|
Balázs Dán <balazs.dan@gmail.com>
|
||||||
|
Bharat Mediratta <bharat@menalto.com>
|
||||||
|
Chandler Carruth <chandlerc@google.com>
|
||||||
|
Chris Prince <cprince@google.com>
|
||||||
|
Chris Taylor <taylorc@google.com>
|
||||||
|
Dan Egnor <egnor@google.com>
|
||||||
|
Eric Roman <eroman@chromium.org>
|
||||||
|
Hady Zalek <hady.zalek@gmail.com>
|
||||||
|
Jeffrey Yasskin <jyasskin@google.com>
|
||||||
|
Jói Sigurðsson <joi@google.com>
|
||||||
|
Keir Mierle <mierle@gmail.com>
|
||||||
|
Keith Ray <keith.ray@gmail.com>
|
||||||
|
Kenton Varda <kenton@google.com>
|
||||||
|
Manuel Klimek <klimek@google.com>
|
||||||
|
Markus Heule <markus.heule@gmail.com>
|
||||||
|
Mika Raento <mikie@iki.fi>
|
||||||
|
Miklós Fazekas <mfazekas@szemafor.com>
|
||||||
|
Patrick Hanna <phanna@google.com>
|
||||||
|
Patrick Riley <pfr@google.com>
|
||||||
|
Peter Kaminski <piotrk@google.com>
|
||||||
|
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>
|
||||||
|
Tracy Bialik <tracy@pentad.com>
|
||||||
|
Vadim Berman <vadimb@google.com>
|
||||||
|
Vlad Losev <vladl@google.com>
|
||||||
|
Zhanyong Wan <wan@google.com>
|
|
@ -0,0 +1,28 @@
|
||||||
|
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.
|
|
@ -0,0 +1,417 @@
|
||||||
|
Google C++ Testing Framework
|
||||||
|
============================
|
||||||
|
|
||||||
|
http://code.google.com/p/googletest/
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
Google's framework for writing C++ tests on a variety of platforms
|
||||||
|
(Linux, Mac OS X, Windows, Windows CE, Symbian, etc). Based on the
|
||||||
|
xUnit architecture. Supports automatic test discovery, a rich set of
|
||||||
|
assertions, user-defined assertions, death tests, fatal and non-fatal
|
||||||
|
failures, various options for running the tests, and XML test report
|
||||||
|
generation.
|
||||||
|
|
||||||
|
Please see the project page above for more information as well as the
|
||||||
|
mailing list for questions, discussions, and development. There is
|
||||||
|
also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please
|
||||||
|
join us!
|
||||||
|
|
||||||
|
Requirements for End Users
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Google Test is designed to have fairly minimal requirements to build
|
||||||
|
and use with your projects, but there are some. Currently, we support
|
||||||
|
Linux, Windows, Mac OS X, and Cygwin. We will also make our best
|
||||||
|
effort to support other platforms (e.g. Solaris, AIX, and z/OS).
|
||||||
|
However, since core members of the Google Test project have no access
|
||||||
|
to these platforms, Google Test may have outstanding issues there. If
|
||||||
|
you notice any problems on your platform, please notify
|
||||||
|
googletestframework@googlegroups.com. Patches for fixing them are
|
||||||
|
even more welcome!
|
||||||
|
|
||||||
|
### Linux Requirements ###
|
||||||
|
|
||||||
|
These are the base requirements to build and use Google Test from a source
|
||||||
|
package (as described below):
|
||||||
|
* GNU-compatible Make or gmake
|
||||||
|
* POSIX-standard shell
|
||||||
|
* POSIX(-2) Regular Expressions (regex.h)
|
||||||
|
* A C++98-standard-compliant compiler
|
||||||
|
|
||||||
|
### Windows Requirements ###
|
||||||
|
|
||||||
|
* Microsoft Visual C++ 7.1 or newer
|
||||||
|
|
||||||
|
### Cygwin Requirements ###
|
||||||
|
|
||||||
|
* Cygwin 1.5.25-14 or newer
|
||||||
|
|
||||||
|
### Mac OS X Requirements ###
|
||||||
|
|
||||||
|
* Mac OS X 10.4 Tiger or newer
|
||||||
|
* Developer Tools Installed
|
||||||
|
|
||||||
|
Also, you'll need CMake 2.6.4 or higher if you want to build the
|
||||||
|
samples using the provided CMake script, regardless of the platform.
|
||||||
|
|
||||||
|
Requirements for Contributors
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
We welcome patches. If you plan to contribute a patch, you need to
|
||||||
|
build Google Test and its own tests from an SVN checkout (described
|
||||||
|
below), which has further requirements:
|
||||||
|
|
||||||
|
* Python version 2.3 or newer (for running some of the tests and
|
||||||
|
re-generating certain source files from templates)
|
||||||
|
* CMake 2.6.4 or newer
|
||||||
|
|
||||||
|
Getting the Source
|
||||||
|
------------------
|
||||||
|
|
||||||
|
There are two primary ways of getting Google Test's source code: you
|
||||||
|
can download a stable source release in your preferred archive format,
|
||||||
|
or directly check out the source from our Subversion (SVN) repositary.
|
||||||
|
The SVN checkout requires a few extra steps and some extra software
|
||||||
|
packages on your system, but lets you track the latest development and
|
||||||
|
make patches much more easily, so we highly encourage it.
|
||||||
|
|
||||||
|
### Source Package ###
|
||||||
|
|
||||||
|
Google Test is released in versioned source packages which can be
|
||||||
|
downloaded from the download page [1]. Several different archive
|
||||||
|
formats are provided, but the only difference is the tools used to
|
||||||
|
manipulate them, and the size of the resulting file. Download
|
||||||
|
whichever you are most comfortable with.
|
||||||
|
|
||||||
|
[1] http://code.google.com/p/googletest/downloads/list
|
||||||
|
|
||||||
|
Once the package is downloaded, expand it using whichever tools you
|
||||||
|
prefer for that type. This will result in a new directory with the
|
||||||
|
name "gtest-X.Y.Z" which contains all of the source code. Here are
|
||||||
|
some examples on Linux:
|
||||||
|
|
||||||
|
tar -xvzf gtest-X.Y.Z.tar.gz
|
||||||
|
tar -xvjf gtest-X.Y.Z.tar.bz2
|
||||||
|
unzip gtest-X.Y.Z.zip
|
||||||
|
|
||||||
|
### SVN Checkout ###
|
||||||
|
|
||||||
|
To check out the main branch (also known as the "trunk") of Google
|
||||||
|
Test, run the following Subversion command:
|
||||||
|
|
||||||
|
svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
|
||||||
|
|
||||||
|
Setting up the Build
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
To build Google Test and your tests that use it, you need to tell your
|
||||||
|
build system where to find its headers and source files. The exact
|
||||||
|
way to do it depends on which build system you use, and is usually
|
||||||
|
straightforward.
|
||||||
|
|
||||||
|
### Generic Build Instructions ###
|
||||||
|
|
||||||
|
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 and ${GTEST_DIR}
|
||||||
|
|
||||||
|
in the header search path. Assuming a Linux-like system and gcc,
|
||||||
|
something like the following will do:
|
||||||
|
|
||||||
|
g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
|
||||||
|
ar -rv libgtest.a gtest-all.o
|
||||||
|
|
||||||
|
Next, you should compile your test source file with
|
||||||
|
${GTEST_DIR}/include in the header search path, and link it with gtest
|
||||||
|
and any other necessary libraries:
|
||||||
|
|
||||||
|
g++ -I${GTEST_DIR}/include 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) that can
|
||||||
|
be used on a wide range of platforms ("C" stands for cross-platofrm.).
|
||||||
|
If you don't have CMake installed already, you can download it for
|
||||||
|
free from http://www.cmake.org/.
|
||||||
|
|
||||||
|
CMake works by generating native makefiles or build projects that can
|
||||||
|
be used in the compiler environment of your choice. The typical
|
||||||
|
workflow starts with:
|
||||||
|
|
||||||
|
mkdir mybuild # Create a directory to hold the build output.
|
||||||
|
cd mybuild
|
||||||
|
cmake ${GTEST_DIR} # Generate native build scripts.
|
||||||
|
|
||||||
|
If you want to build Google Test's samples, you should replace the
|
||||||
|
last command with
|
||||||
|
|
||||||
|
cmake -Dbuild_gtest_samples=ON ${GTEST_DIR}
|
||||||
|
|
||||||
|
If you are on a *nix system, you should now see a Makefile in the
|
||||||
|
current directory. Just type 'make' to build gtest.
|
||||||
|
|
||||||
|
If you use Windows and have Vistual Studio installed, a gtest.sln file
|
||||||
|
and several .vcproj files will be created. You can then build them
|
||||||
|
using Visual Studio.
|
||||||
|
|
||||||
|
On Mac OS X with Xcode installed, a .xcodeproj file will be generated.
|
||||||
|
|
||||||
|
### Legacy Build Scripts ###
|
||||||
|
|
||||||
|
Before settling on CMake, we have been providing hand-maintained build
|
||||||
|
projects/scripts for Visual Studio, Xcode, and Autotools. While we
|
||||||
|
continue to provide them for convenience, they are not actively
|
||||||
|
maintained any more. We highly recommend that you follow the
|
||||||
|
instructions in the previous two sections to integrate Google Test
|
||||||
|
with your existing build system.
|
||||||
|
|
||||||
|
If you still need to use the legacy build scripts, here's how:
|
||||||
|
|
||||||
|
The msvc\ folder contains two solutions with Visual C++ projects.
|
||||||
|
Open the gtest.sln or gtest-md.sln file using Visual Studio, and you
|
||||||
|
are ready to build Google Test the same way you build any Visual
|
||||||
|
Studio project. Files that have names ending with -md use DLL
|
||||||
|
versions of Microsoft runtime libraries (the /MD or the /MDd compiler
|
||||||
|
option). Files without that suffix use static versions of the runtime
|
||||||
|
libraries (the /MT or the /MTd option). Please note that one must use
|
||||||
|
the same option to compile both gtest and the test code. If you use
|
||||||
|
Visual Studio 2005 or above, we recommend the -md version as /MD is
|
||||||
|
the default for new projects in these versions of Visual Studio.
|
||||||
|
|
||||||
|
On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using
|
||||||
|
Xcode. Build the "gtest" target. The universal binary framework will
|
||||||
|
end up in your selected build directory (selected in the Xcode
|
||||||
|
"Preferences..." -> "Building" pane and defaults to xcode/build).
|
||||||
|
Alternatively, at the command line, enter:
|
||||||
|
|
||||||
|
xcodebuild
|
||||||
|
|
||||||
|
This will build the "Release" configuration of gtest.framework in your
|
||||||
|
default build location. See the "xcodebuild" man page for more
|
||||||
|
information about building different configurations and building in
|
||||||
|
different locations.
|
||||||
|
|
||||||
|
Tweaking Google Test
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Google Test can be used in diverse environments. The default
|
||||||
|
configuration may not work (or may not work well) out of the box in
|
||||||
|
some environments. However, you can easily tweak Google Test by
|
||||||
|
defining control macros on the compiler command line. Generally,
|
||||||
|
these macros are named like GTEST_XYZ and you define them to either 1
|
||||||
|
or 0 to enable or disable a certain feature.
|
||||||
|
|
||||||
|
We list the most frequently used macros below. For a complete list,
|
||||||
|
see file include/gtest/internal/gtest-port.h.
|
||||||
|
|
||||||
|
### Choosing a TR1 Tuple Library ###
|
||||||
|
|
||||||
|
Some Google Test features require the C++ Technical Report 1 (TR1)
|
||||||
|
tuple library, which is not yet available with all compilers. The
|
||||||
|
good news is that Google Test implements a subset of TR1 tuple that's
|
||||||
|
enough for its own need, and will automatically use this when the
|
||||||
|
compiler doesn't provide TR1 tuple.
|
||||||
|
|
||||||
|
Usually you don't need to care about which tuple library Google Test
|
||||||
|
uses. However, if your project already uses TR1 tuple, you need to
|
||||||
|
tell Google Test to use the same TR1 tuple library the rest of your
|
||||||
|
project uses, or the two tuple implementations will clash. To do
|
||||||
|
that, add
|
||||||
|
|
||||||
|
-DGTEST_USE_OWN_TR1_TUPLE=0
|
||||||
|
|
||||||
|
to the compiler flags while compiling Google Test and your tests. If
|
||||||
|
you want to force Google Test to use its own tuple library, just add
|
||||||
|
|
||||||
|
-DGTEST_USE_OWN_TR1_TUPLE=1
|
||||||
|
|
||||||
|
to the compiler flags instead.
|
||||||
|
|
||||||
|
If you don't want Google Test to use tuple at all, add
|
||||||
|
|
||||||
|
-DGTEST_HAS_TR1_TUPLE=0
|
||||||
|
|
||||||
|
and all features using tuple will be disabled.
|
||||||
|
|
||||||
|
### Multi-threaded Tests ###
|
||||||
|
|
||||||
|
Google Test is thread-safe where the pthread library is available.
|
||||||
|
After #include <gtest/gtest.h>, you can check the GTEST_IS_THREADSAFE
|
||||||
|
macro to see whether this is the case (yes if the macro is #defined to
|
||||||
|
1, no if it's undefined.).
|
||||||
|
|
||||||
|
If Google Test doesn't correctly detect whether pthread is available
|
||||||
|
in your environment, you can force it with
|
||||||
|
|
||||||
|
-DGTEST_HAS_PTHREAD=1
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
-DGTEST_HAS_PTHREAD=0
|
||||||
|
|
||||||
|
When Google Test uses pthread, you may need to add flags to your
|
||||||
|
compiler and/or linker to select the pthread library, or you'll get
|
||||||
|
link errors. If you use the CMake script or the deprecated Autotools
|
||||||
|
script, this is taken care of for you. If you use your own build
|
||||||
|
script, you'll need to read your compiler and linker's manual to
|
||||||
|
figure out what flags to add.
|
||||||
|
|
||||||
|
### As a Shared Library (DLL) ###
|
||||||
|
|
||||||
|
Google Test is compact, so most users can build and link it as a
|
||||||
|
static library for the simplicity. You can choose to use Google Test
|
||||||
|
as a shared library (known as a DLL on Windows) if you prefer.
|
||||||
|
|
||||||
|
To compile gtest as a shared library, add
|
||||||
|
|
||||||
|
-DGTEST_CREATE_SHARED_LIBRARY=1
|
||||||
|
|
||||||
|
to the compiler flags. You'll also need to tell the linker to produce
|
||||||
|
a shared library instead - consult your linker's manual for how to do
|
||||||
|
it.
|
||||||
|
|
||||||
|
To compile your tests that use the gtest shared library, add
|
||||||
|
|
||||||
|
-DGTEST_LINKED_AS_SHARED_LIBRARY=1
|
||||||
|
|
||||||
|
to the compiler flags.
|
||||||
|
|
||||||
|
### Avoiding Macro Name Clashes ###
|
||||||
|
|
||||||
|
In C++, macros don't obey namespaces. Therefore two libraries that
|
||||||
|
both define a macro of the same name will clash if you #include both
|
||||||
|
definitions. In case a Google Test macro clashes with another
|
||||||
|
library, you can force Google Test to rename its macro to avoid the
|
||||||
|
conflict.
|
||||||
|
|
||||||
|
Specifically, if both Google Test and some other code define macro
|
||||||
|
FOO, you can add
|
||||||
|
|
||||||
|
-DGTEST_DONT_DEFINE_FOO=1
|
||||||
|
|
||||||
|
to the compiler flags to tell Google Test to change the macro's name
|
||||||
|
from FOO to GTEST_FOO. Currently FOO can be FAIL, SUCCEED, or TEST.
|
||||||
|
For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write
|
||||||
|
|
||||||
|
GTEST_TEST(SomeTest, DoesThis) { ... }
|
||||||
|
|
||||||
|
instead of
|
||||||
|
|
||||||
|
TEST(SomeTest, DoesThis) { ... }
|
||||||
|
|
||||||
|
in order to define a test.
|
||||||
|
|
||||||
|
Upgrating from an Earlier Version
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
We strive to keep Google Test releases backward compatible.
|
||||||
|
Sometimes, though, we have to make some breaking changes for the
|
||||||
|
users' long-term benefits. This section describes what you'll need to
|
||||||
|
do if you are upgrading from an earlier version of Google Test.
|
||||||
|
|
||||||
|
### Upgrading from 1.3.0 or Earlier ###
|
||||||
|
|
||||||
|
You may need to explicitly enable or disable Google Test's own TR1
|
||||||
|
tuple library. See the instructions in section "Choosing a TR1 Tuple
|
||||||
|
Library".
|
||||||
|
|
||||||
|
### Upgrading from 1.4.0 or Earlier ###
|
||||||
|
|
||||||
|
The Autotools build script (configure + make) is no longer officially
|
||||||
|
supportted. You are encouraged to migrate to your own build system or
|
||||||
|
use CMake. If you still need to use Autotools, you can find
|
||||||
|
instructions in the README file from Google Test 1.4.0.
|
||||||
|
|
||||||
|
On platforms where the pthread library is available, Google Test uses
|
||||||
|
it in order to be thread-safe. See the "Multi-threaded Tests" section
|
||||||
|
for what this means to your build script.
|
||||||
|
|
||||||
|
If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google
|
||||||
|
Test will no longer compile. This should affect very few people, as a
|
||||||
|
large portion of STL (including <string>) doesn't compile in this mode
|
||||||
|
anyway. We decided to stop supporting it in order to greatly simplify
|
||||||
|
Google Test's implementation.
|
||||||
|
|
||||||
|
Developing Google Test
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
This section discusses how to make your own changes to Google Test.
|
||||||
|
|
||||||
|
### Testing Google Test Itself ###
|
||||||
|
|
||||||
|
To make sure your changes work as intended and don't break existing
|
||||||
|
functionality, you'll want to compile and run Google Test's own tests.
|
||||||
|
For that you can use CMake:
|
||||||
|
|
||||||
|
mkdir mybuild
|
||||||
|
cd mybuild
|
||||||
|
cmake -Dbuild_all_gtest_tests=ON ${GTEST_DIR}
|
||||||
|
|
||||||
|
Make sure you have Python installed, as some of Google Test's tests
|
||||||
|
are written in Python. If the cmake command complains about not being
|
||||||
|
able to find Python ("Could NOT find PythonInterp (missing:
|
||||||
|
PYTHON_EXECUTABLE)"), try telling it explicitly where your Python
|
||||||
|
executable can be found:
|
||||||
|
|
||||||
|
cmake -DPYTHON_EXECUTABLE=path/to/python -Dbuild_all_gtest_tests=ON \
|
||||||
|
${GTEST_DIR}
|
||||||
|
|
||||||
|
Next, you can build Google Test and all of its own tests. On *nix,
|
||||||
|
this is usually done by 'make'. To run the tests, do
|
||||||
|
|
||||||
|
make test
|
||||||
|
|
||||||
|
All tests should pass.
|
||||||
|
|
||||||
|
### Regenerating Source Files ###
|
||||||
|
|
||||||
|
Some of Google Test's source files are generated from templates (not
|
||||||
|
in the C++ sense) using a script. A template file is named FOO.pump,
|
||||||
|
where FOO is the name of the file it will generate. For example, the
|
||||||
|
file include/gtest/internal/gtest-type-util.h.pump is used to generate
|
||||||
|
gtest-type-util.h in the same directory.
|
||||||
|
|
||||||
|
Normally you don't need to worry about regenerating the source files,
|
||||||
|
unless you need to modify them. In that case, you should modify the
|
||||||
|
corresponding .pump files instead and run the pump.py Python script to
|
||||||
|
regenerate them. You can find pump.py in the scripts/ directory.
|
||||||
|
Read the Pump manual [2] for how to use it.
|
||||||
|
|
||||||
|
[2] http://code.google.com/p/googletest/wiki/PumpManual
|
||||||
|
|
||||||
|
### Contributing a Patch ###
|
||||||
|
|
||||||
|
We welcome patches. Please read the Google Test developer's guide [3]
|
||||||
|
for how you can contribute. In particular, make sure you have signed
|
||||||
|
the Contributor License Agreement, or we won't be able to accept the
|
||||||
|
patch.
|
||||||
|
|
||||||
|
[3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide
|
||||||
|
|
||||||
|
Happy testing!
|
|
@ -0,0 +1,138 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectGuid>{bca37a72-5b07-46cf-b44e-89f8e06451a2}</ProjectGuid>
|
||||||
|
<Config Condition="'$(Config)'==''">Release</Config>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
<Cfg_1>true</Cfg_1>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
<Cfg_2>true</Cfg_2>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base)'!=''">
|
||||||
|
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>
|
||||||
|
<OutputExt>lib</OutputExt>
|
||||||
|
<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
|
||||||
|
<Defines>NO_STRICT</Defines>
|
||||||
|
<DynamicRTL>true</DynamicRTL>
|
||||||
|
<UsePackages>true</UsePackages>
|
||||||
|
<ProjectType>CppStaticLibrary</ProjectType>
|
||||||
|
<BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>
|
||||||
|
<PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;GR32_BDS2006.bpi;GR32_DSGN_BDS2006.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi;CExceptionExpert11.bpi</PackageImports>
|
||||||
|
<BCC_wpar>false</BCC_wpar>
|
||||||
|
<IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</IncludePath>
|
||||||
|
<AllPackageLibs>rtl.lib;vcl.lib</AllPackageLibs>
|
||||||
|
<TLIB_PageSize>32</TLIB_PageSize>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</ILINK_LibraryPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_1)'!=''">
|
||||||
|
<BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>
|
||||||
|
<DCC_Optimize>false</DCC_Optimize>
|
||||||
|
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
|
||||||
|
<Defines>_DEBUG;$(Defines)</Defines>
|
||||||
|
<ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>
|
||||||
|
<BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>
|
||||||
|
<ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>
|
||||||
|
<BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>
|
||||||
|
<DCC_Define>DEBUG</DCC_Define>
|
||||||
|
<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
|
||||||
|
<IntermediateOutputDir>Debug</IntermediateOutputDir>
|
||||||
|
<TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>
|
||||||
|
<BCC_StackFrames>true</BCC_StackFrames>
|
||||||
|
<BCC_DisableOptimizations>true</BCC_DisableOptimizations>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>
|
||||||
|
<TASM_Debugging>Full</TASM_Debugging>
|
||||||
|
<BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
||||||
|
<Defines>NDEBUG;$(Defines)</Defines>
|
||||||
|
<IntermediateOutputDir>Release</IntermediateOutputDir>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>
|
||||||
|
<TASM_Debugging>None</TASM_Debugging>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>
|
||||||
|
<Borland.ProjectType>CppStaticLibrary</Borland.ProjectType>
|
||||||
|
<BorlandProject>
|
||||||
|
<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>
|
||||||
|
|
||||||
|
|
||||||
|
<Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>
|
||||||
|
</Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\src;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">1</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines><HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Count">1</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item0">32</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item1">16</HistoryLists_hlTLIB_PageSize></HistoryLists_hlTLIB_PageSize></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>
|
||||||
|
</ProjectExtensions>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\include\gtest\gtest-death-test.h">
|
||||||
|
<BuildOrder>3</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\gtest-message.h">
|
||||||
|
<BuildOrder>4</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\gtest-param-test.h">
|
||||||
|
<BuildOrder>5</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\gtest-spi.h">
|
||||||
|
<BuildOrder>6</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\gtest-test-part.h">
|
||||||
|
<BuildOrder>7</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\gtest-typed-test.h">
|
||||||
|
<BuildOrder>8</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\gtest.h">
|
||||||
|
<BuildOrder>0</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\gtest_pred_impl.h">
|
||||||
|
<BuildOrder>1</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\gtest_prod.h">
|
||||||
|
<BuildOrder>2</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-death-test-internal.h">
|
||||||
|
<BuildOrder>9</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-filepath.h">
|
||||||
|
<BuildOrder>10</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-internal.h">
|
||||||
|
<BuildOrder>11</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-linked_ptr.h">
|
||||||
|
<BuildOrder>12</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-param-util-generated.h">
|
||||||
|
<BuildOrder>14</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-param-util.h">
|
||||||
|
<BuildOrder>13</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-port.h">
|
||||||
|
<BuildOrder>15</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-string.h">
|
||||||
|
<BuildOrder>16</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<None Include="..\include\gtest\internal\gtest-type-util.h">
|
||||||
|
<BuildOrder>17</BuildOrder>
|
||||||
|
</None>
|
||||||
|
<CppCompile Include="gtest_all.cc">
|
||||||
|
<BuildOrder>18</BuildOrder>
|
||||||
|
</CppCompile>
|
||||||
|
<BuildConfiguration Include="Debug">
|
||||||
|
<Key>Cfg_1</Key>
|
||||||
|
</BuildConfiguration>
|
||||||
|
<BuildConfiguration Include="Release">
|
||||||
|
<Key>Cfg_2</Key>
|
||||||
|
</BuildConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,54 @@
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectGuid>{c1d923e0-6cba-4332-9b6f-3420acbf5091}</ProjectGuid>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup />
|
||||||
|
<ItemGroup>
|
||||||
|
<Projects Include="gtest.cbproj" />
|
||||||
|
<Projects Include="gtest_main.cbproj" />
|
||||||
|
<Projects Include="gtest_unittest.cbproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<Borland.Personality>Default.Personality</Borland.Personality>
|
||||||
|
<Borland.ProjectType />
|
||||||
|
<BorlandProject>
|
||||||
|
<BorlandProject xmlns=""><Default.Personality></Default.Personality></BorlandProject></BorlandProject>
|
||||||
|
</ProjectExtensions>
|
||||||
|
<Target Name="gtest">
|
||||||
|
<MSBuild Projects="gtest.cbproj" Targets="" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="gtest:Clean">
|
||||||
|
<MSBuild Projects="gtest.cbproj" Targets="Clean" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="gtest:Make">
|
||||||
|
<MSBuild Projects="gtest.cbproj" Targets="Make" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="gtest_main">
|
||||||
|
<MSBuild Projects="gtest_main.cbproj" Targets="" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="gtest_main:Clean">
|
||||||
|
<MSBuild Projects="gtest_main.cbproj" Targets="Clean" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="gtest_main:Make">
|
||||||
|
<MSBuild Projects="gtest_main.cbproj" Targets="Make" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="gtest_unittest">
|
||||||
|
<MSBuild Projects="gtest_unittest.cbproj" Targets="" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="gtest_unittest:Clean">
|
||||||
|
<MSBuild Projects="gtest_unittest.cbproj" Targets="Clean" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="gtest_unittest:Make">
|
||||||
|
<MSBuild Projects="gtest_unittest.cbproj" Targets="Make" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="Build">
|
||||||
|
<CallTarget Targets="gtest;gtest_main;gtest_unittest" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="Clean">
|
||||||
|
<CallTarget Targets="gtest:Clean;gtest_main:Clean;gtest_unittest:Clean" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="Make">
|
||||||
|
<CallTarget Targets="gtest:Make;gtest_main:Make;gtest_unittest:Make" />
|
||||||
|
</Target>
|
||||||
|
<Import Condition="Exists('$(MSBuildBinPath)\Borland.Group.Targets')" Project="$(MSBuildBinPath)\Borland.Group.Targets" />
|
||||||
|
</Project>
|
|
@ -0,0 +1,38 @@
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Author: Josh Kelley (joshkel@gmail.com)
|
||||||
|
//
|
||||||
|
// Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// C++Builder's IDE cannot build a static library from files with hyphens
|
||||||
|
// in their name. See http://qc.codegear.com/wc/qcmain.aspx?d=70977 .
|
||||||
|
// This file serves as a workaround.
|
||||||
|
|
||||||
|
#include "src/gtest-all.cc"
|
|
@ -0,0 +1,40 @@
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Author: Josh Kelley (joshkel@gmail.com)
|
||||||
|
//
|
||||||
|
// Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// Links gtest.lib and gtest_main.lib into the current project in C++Builder.
|
||||||
|
// This means that these libraries can't be renamed, but it's the only way to
|
||||||
|
// ensure that Debug versus Release test builds are linked against the
|
||||||
|
// appropriate Debug or Release build of the libraries.
|
||||||
|
|
||||||
|
#pragma link "gtest.lib"
|
||||||
|
#pragma link "gtest_main.lib"
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectGuid>{bca37a72-5b07-46cf-b44e-89f8e06451a2}</ProjectGuid>
|
||||||
|
<Config Condition="'$(Config)'==''">Release</Config>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
<Cfg_1>true</Cfg_1>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
<Cfg_2>true</Cfg_2>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base)'!=''">
|
||||||
|
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>
|
||||||
|
<OutputExt>lib</OutputExt>
|
||||||
|
<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
|
||||||
|
<Defines>NO_STRICT</Defines>
|
||||||
|
<DynamicRTL>true</DynamicRTL>
|
||||||
|
<UsePackages>true</UsePackages>
|
||||||
|
<ProjectType>CppStaticLibrary</ProjectType>
|
||||||
|
<BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>
|
||||||
|
<PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;GR32_BDS2006.bpi;GR32_DSGN_BDS2006.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi;CExceptionExpert11.bpi</PackageImports>
|
||||||
|
<BCC_wpar>false</BCC_wpar>
|
||||||
|
<IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</IncludePath>
|
||||||
|
<AllPackageLibs>rtl.lib;vcl.lib</AllPackageLibs>
|
||||||
|
<TLIB_PageSize>32</TLIB_PageSize>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</ILINK_LibraryPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_1)'!=''">
|
||||||
|
<BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>
|
||||||
|
<DCC_Optimize>false</DCC_Optimize>
|
||||||
|
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
|
||||||
|
<Defines>_DEBUG;$(Defines)</Defines>
|
||||||
|
<ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>
|
||||||
|
<BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>
|
||||||
|
<ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>
|
||||||
|
<BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>
|
||||||
|
<DCC_Define>DEBUG</DCC_Define>
|
||||||
|
<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
|
||||||
|
<IntermediateOutputDir>Debug</IntermediateOutputDir>
|
||||||
|
<TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>
|
||||||
|
<BCC_StackFrames>true</BCC_StackFrames>
|
||||||
|
<BCC_DisableOptimizations>true</BCC_DisableOptimizations>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>
|
||||||
|
<TASM_Debugging>Full</TASM_Debugging>
|
||||||
|
<BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
||||||
|
<Defines>NDEBUG;$(Defines)</Defines>
|
||||||
|
<IntermediateOutputDir>Release</IntermediateOutputDir>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>
|
||||||
|
<TASM_Debugging>None</TASM_Debugging>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>
|
||||||
|
<Borland.ProjectType>CppStaticLibrary</Borland.ProjectType>
|
||||||
|
<BorlandProject>
|
||||||
|
<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>
|
||||||
|
</Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\src;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">1</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines><HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Count">1</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item0">32</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item1">16</HistoryLists_hlTLIB_PageSize></HistoryLists_hlTLIB_PageSize></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>
|
||||||
|
</ProjectExtensions>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />
|
||||||
|
<ItemGroup>
|
||||||
|
<CppCompile Include="..\src\gtest_main.cc">
|
||||||
|
<BuildOrder>0</BuildOrder>
|
||||||
|
</CppCompile>
|
||||||
|
<BuildConfiguration Include="Debug">
|
||||||
|
<Key>Cfg_1</Key>
|
||||||
|
</BuildConfiguration>
|
||||||
|
<BuildConfiguration Include="Release">
|
||||||
|
<Key>Cfg_2</Key>
|
||||||
|
</BuildConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectGuid>{eea63393-5ac5-4b9c-8909-d75fef2daa41}</ProjectGuid>
|
||||||
|
<Config Condition="'$(Config)'==''">Release</Config>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
<Cfg_1>true</Cfg_1>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
<Cfg_2>true</Cfg_2>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base)'!=''">
|
||||||
|
<OutputExt>exe</OutputExt>
|
||||||
|
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>
|
||||||
|
<Defines>NO_STRICT</Defines>
|
||||||
|
<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
|
||||||
|
<DynamicRTL>true</DynamicRTL>
|
||||||
|
<ILINK_ObjectSearchPath>..\test</ILINK_ObjectSearchPath>
|
||||||
|
<UsePackages>true</UsePackages>
|
||||||
|
<ProjectType>CppConsoleApplication</ProjectType>
|
||||||
|
<NoVCL>true</NoVCL>
|
||||||
|
<BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>
|
||||||
|
<PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi</PackageImports>
|
||||||
|
<BCC_wpar>false</BCC_wpar>
|
||||||
|
<IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</IncludePath>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</ILINK_LibraryPath>
|
||||||
|
<Multithreaded>true</Multithreaded>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_1)'!=''">
|
||||||
|
<BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>
|
||||||
|
<DCC_Optimize>false</DCC_Optimize>
|
||||||
|
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
|
||||||
|
<Defines>_DEBUG;$(Defines)</Defines>
|
||||||
|
<ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>
|
||||||
|
<BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>
|
||||||
|
<ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>
|
||||||
|
<BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>
|
||||||
|
<DCC_Define>DEBUG</DCC_Define>
|
||||||
|
<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
|
||||||
|
<IntermediateOutputDir>Debug</IntermediateOutputDir>
|
||||||
|
<TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>
|
||||||
|
<BCC_StackFrames>true</BCC_StackFrames>
|
||||||
|
<BCC_DisableOptimizations>true</BCC_DisableOptimizations>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>
|
||||||
|
<TASM_Debugging>Full</TASM_Debugging>
|
||||||
|
<BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
||||||
|
<Defines>NDEBUG;$(Defines)</Defines>
|
||||||
|
<IntermediateOutputDir>Release</IntermediateOutputDir>
|
||||||
|
<ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>
|
||||||
|
<TASM_Debugging>None</TASM_Debugging>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>
|
||||||
|
<Borland.ProjectType>CppConsoleApplication</Borland.ProjectType>
|
||||||
|
<BorlandProject>
|
||||||
|
<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>
|
||||||
|
|
||||||
|
|
||||||
|
<Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>
|
||||||
|
</Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item1">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item2">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;$(OUTPUTDIR);..\test</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">2</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item1">STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>
|
||||||
|
</ProjectExtensions>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />
|
||||||
|
<ItemGroup>
|
||||||
|
<CppCompile Include="..\test\gtest_unittest.cc">
|
||||||
|
<BuildOrder>0</BuildOrder>
|
||||||
|
</CppCompile>
|
||||||
|
<CppCompile Include="gtest_link.cc">
|
||||||
|
<BuildOrder>1</BuildOrder>
|
||||||
|
</CppCompile>
|
||||||
|
<BuildConfiguration Include="Debug">
|
||||||
|
<Key>Cfg_1</Key>
|
||||||
|
</BuildConfiguration>
|
||||||
|
<BuildConfiguration Include="Release">
|
||||||
|
<Key>Cfg_2</Key>
|
||||||
|
</BuildConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,283 @@
|
||||||
|
// Copyright 2005, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
//
|
||||||
|
// The Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This header file defines the public API for death tests. It is
|
||||||
|
// #included by gtest.h so a user doesn't need to include this
|
||||||
|
// directly.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-death-test-internal.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// This flag controls the style of death tests. Valid values are "threadsafe",
|
||||||
|
// meaning that the death test child process will re-execute the test binary
|
||||||
|
// from the start, running only a single death test, or "fast",
|
||||||
|
// meaning that the child process will execute the test logic immediately
|
||||||
|
// after forking.
|
||||||
|
GTEST_DECLARE_string_(death_test_style);
|
||||||
|
|
||||||
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
// The following macros are useful for writing death tests.
|
||||||
|
|
||||||
|
// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
|
||||||
|
// executed:
|
||||||
|
//
|
||||||
|
// 1. It generates a warning if there is more than one active
|
||||||
|
// thread. This is because it's safe to fork() or clone() only
|
||||||
|
// when there is a single thread.
|
||||||
|
//
|
||||||
|
// 2. The parent process clone()s a sub-process and runs the death
|
||||||
|
// test in it; the sub-process exits with code 0 at the end of the
|
||||||
|
// death test, if it hasn't exited already.
|
||||||
|
//
|
||||||
|
// 3. The parent process waits for the sub-process to terminate.
|
||||||
|
//
|
||||||
|
// 4. The parent process checks the exit code and error message of
|
||||||
|
// the sub-process.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
//
|
||||||
|
// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
|
||||||
|
// for (int i = 0; i < 5; i++) {
|
||||||
|
// EXPECT_DEATH(server.ProcessRequest(i),
|
||||||
|
// "Invalid request .* in ProcessRequest()")
|
||||||
|
// << "Failed to die on request " << i);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
|
||||||
|
//
|
||||||
|
// bool KilledBySIGHUP(int exit_code) {
|
||||||
|
// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
|
||||||
|
//
|
||||||
|
// On the regular expressions used in death tests:
|
||||||
|
//
|
||||||
|
// On POSIX-compliant systems (*nix), we use the <regex.h> library,
|
||||||
|
// which uses the POSIX extended regex syntax.
|
||||||
|
//
|
||||||
|
// On other platforms (e.g. Windows), we only support a simple regex
|
||||||
|
// syntax implemented as part of Google Test. This limited
|
||||||
|
// implementation should be enough most of the time when writing
|
||||||
|
// death tests; though it lacks many features you can find in PCRE
|
||||||
|
// or POSIX extended regex syntax. For example, we don't support
|
||||||
|
// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
|
||||||
|
// repetition count ("x{5,7}"), among others.
|
||||||
|
//
|
||||||
|
// Below is the syntax that we do support. We chose it to be a
|
||||||
|
// subset of both PCRE and POSIX extended regex, so it's easy to
|
||||||
|
// learn wherever you come from. In the following: 'A' denotes a
|
||||||
|
// literal character, period (.), or a single \\ escape sequence;
|
||||||
|
// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
|
||||||
|
// natural numbers.
|
||||||
|
//
|
||||||
|
// c matches any literal character c
|
||||||
|
// \\d matches any decimal digit
|
||||||
|
// \\D matches any character that's not a decimal digit
|
||||||
|
// \\f matches \f
|
||||||
|
// \\n matches \n
|
||||||
|
// \\r matches \r
|
||||||
|
// \\s matches any ASCII whitespace, including \n
|
||||||
|
// \\S matches any character that's not a whitespace
|
||||||
|
// \\t matches \t
|
||||||
|
// \\v matches \v
|
||||||
|
// \\w matches any letter, _, or decimal digit
|
||||||
|
// \\W matches any character that \\w doesn't match
|
||||||
|
// \\c matches any literal character c, which must be a punctuation
|
||||||
|
// . matches any single character except \n
|
||||||
|
// A? matches 0 or 1 occurrences of A
|
||||||
|
// A* matches 0 or many occurrences of A
|
||||||
|
// A+ matches 1 or many occurrences of A
|
||||||
|
// ^ matches the beginning of a string (not that of each line)
|
||||||
|
// $ matches the end of a string (not that of each line)
|
||||||
|
// xy matches x followed by y
|
||||||
|
//
|
||||||
|
// If you accidentally use PCRE or POSIX extended regex features
|
||||||
|
// not implemented by us, you will get a run-time failure. In that
|
||||||
|
// case, please try to rewrite your regular expression within the
|
||||||
|
// above syntax.
|
||||||
|
//
|
||||||
|
// This implementation is *not* meant to be as highly tuned or robust
|
||||||
|
// as a compiled regex library, but should perform well enough for a
|
||||||
|
// death test, which already incurs significant overhead by launching
|
||||||
|
// a child process.
|
||||||
|
//
|
||||||
|
// Known caveats:
|
||||||
|
//
|
||||||
|
// A "threadsafe" style death test obtains the path to the test
|
||||||
|
// program from argv[0] and re-executes it in the sub-process. For
|
||||||
|
// simplicity, the current implementation doesn't search the PATH
|
||||||
|
// when launching the sub-process. This means that the user must
|
||||||
|
// invoke the test program via a path that contains at least one
|
||||||
|
// path separator (e.g. path/to/foo_test and
|
||||||
|
// /absolute/path/to/bar_test are fine, but foo_test is not). This
|
||||||
|
// is rarely a problem as people usually don't put the test binary
|
||||||
|
// directory in PATH.
|
||||||
|
//
|
||||||
|
// TODO(wan@google.com): 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_)
|
||||||
|
|
||||||
|
// 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_)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
||||||
|
|
||||||
|
// Tests that an exit code describes a normal exit with a given exit code.
|
||||||
|
class GTEST_API_ ExitedWithCode {
|
||||||
|
public:
|
||||||
|
explicit ExitedWithCode(int exit_code);
|
||||||
|
bool operator()(int exit_status) const;
|
||||||
|
private:
|
||||||
|
// No implementation - assignment is unsupported.
|
||||||
|
void operator=(const ExitedWithCode& other);
|
||||||
|
|
||||||
|
const int exit_code_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !GTEST_OS_WINDOWS
|
||||||
|
// Tests that an exit code describes an exit due to termination by a
|
||||||
|
// given signal.
|
||||||
|
class GTEST_API_ KilledBySignal {
|
||||||
|
public:
|
||||||
|
explicit KilledBySignal(int signum);
|
||||||
|
bool operator()(int exit_status) const;
|
||||||
|
private:
|
||||||
|
const int signum_;
|
||||||
|
};
|
||||||
|
#endif // !GTEST_OS_WINDOWS
|
||||||
|
|
||||||
|
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
|
||||||
|
// The death testing framework causes this to have interesting semantics,
|
||||||
|
// since the sideeffects of the call are only visible in opt mode, and not
|
||||||
|
// in debug mode.
|
||||||
|
//
|
||||||
|
// In practice, this can be used to test functions that utilize the
|
||||||
|
// LOG(DFATAL) macro using the following style:
|
||||||
|
//
|
||||||
|
// int DieInDebugOr12(int* sideeffect) {
|
||||||
|
// if (sideeffect) {
|
||||||
|
// *sideeffect = 12;
|
||||||
|
// }
|
||||||
|
// LOG(DFATAL) << "death";
|
||||||
|
// return 12;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
|
||||||
|
// int sideeffect = 0;
|
||||||
|
// // Only asserts in dbg.
|
||||||
|
// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
|
||||||
|
//
|
||||||
|
// #ifdef NDEBUG
|
||||||
|
// // opt-mode has sideeffect visible.
|
||||||
|
// EXPECT_EQ(12, sideeffect);
|
||||||
|
// #else
|
||||||
|
// // dbg-mode no visible sideeffect.
|
||||||
|
// EXPECT_EQ(0, sideeffect);
|
||||||
|
// #endif
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// This will assert that DieInDebugReturn12InOpt() crashes in debug
|
||||||
|
// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
|
||||||
|
// appropriate fallback value (12 in this case) in opt mode. If you
|
||||||
|
// need to test that a function has appropriate side-effects in opt
|
||||||
|
// mode, include assertions against the side-effects. A general
|
||||||
|
// pattern for this is:
|
||||||
|
//
|
||||||
|
// EXPECT_DEBUG_DEATH({
|
||||||
|
// // Side-effects here will have an effect after this statement in
|
||||||
|
// // opt mode, but none in debug mode.
|
||||||
|
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
|
||||||
|
// }, "death");
|
||||||
|
//
|
||||||
|
#ifdef NDEBUG
|
||||||
|
|
||||||
|
#define EXPECT_DEBUG_DEATH(statement, regex) \
|
||||||
|
do { statement; } while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
|
#define ASSERT_DEBUG_DEATH(statement, regex) \
|
||||||
|
do { statement; } while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define EXPECT_DEBUG_DEATH(statement, regex) \
|
||||||
|
EXPECT_DEATH(statement, regex)
|
||||||
|
|
||||||
|
#define ASSERT_DEBUG_DEATH(statement, regex) \
|
||||||
|
ASSERT_DEATH(statement, regex)
|
||||||
|
|
||||||
|
#endif // NDEBUG for EXPECT_DEBUG_DEATH
|
||||||
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
|
||||||
|
// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
|
||||||
|
// death tests are supported; otherwise they just issue a warning. This is
|
||||||
|
// useful when you are combining death test assertions with normal test
|
||||||
|
// assertions in one test.
|
||||||
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
|
EXPECT_DEATH(statement, regex)
|
||||||
|
#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
|
ASSERT_DEATH(statement, regex)
|
||||||
|
#else
|
||||||
|
#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
|
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
|
||||||
|
#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
|
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
|
@ -0,0 +1,230 @@
|
||||||
|
// Copyright 2005, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
//
|
||||||
|
// The Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This header file defines the Message class.
|
||||||
|
//
|
||||||
|
// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
|
||||||
|
// leave some internal implementation details in this header file.
|
||||||
|
// They are clearly marked by comments like this:
|
||||||
|
//
|
||||||
|
// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
|
//
|
||||||
|
// Such code is NOT meant to be used by a user directly, and is subject
|
||||||
|
// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
|
||||||
|
// program!
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-string.h>
|
||||||
|
#include <gtest/internal/gtest-internal.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// The Message class works like an ostream repeater.
|
||||||
|
//
|
||||||
|
// Typical usage:
|
||||||
|
//
|
||||||
|
// 1. You stream a bunch of values to a Message object.
|
||||||
|
// It will remember the text in a StrStream.
|
||||||
|
// 2. Then you stream the Message object to an ostream.
|
||||||
|
// This causes the text in the Message to be streamed
|
||||||
|
// to the ostream.
|
||||||
|
//
|
||||||
|
// For example;
|
||||||
|
//
|
||||||
|
// testing::Message foo;
|
||||||
|
// foo << 1 << " != " << 2;
|
||||||
|
// std::cout << foo;
|
||||||
|
//
|
||||||
|
// will print "1 != 2".
|
||||||
|
//
|
||||||
|
// Message is not intended to be inherited from. In particular, its
|
||||||
|
// destructor is not virtual.
|
||||||
|
//
|
||||||
|
// Note that StrStream behaves differently in gcc and in MSVC. You
|
||||||
|
// can stream a NULL char pointer to it in the former, but not in the
|
||||||
|
// latter (it causes an access violation if you do). The Message
|
||||||
|
// class hides this difference by treating a NULL char pointer as
|
||||||
|
// "(null)".
|
||||||
|
class GTEST_API_ Message {
|
||||||
|
private:
|
||||||
|
// The type of basic IO manipulators (endl, ends, and flush) for
|
||||||
|
// narrow streams.
|
||||||
|
typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructs an empty Message.
|
||||||
|
// We allocate the StrStream separately because it otherwise each use of
|
||||||
|
// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
|
||||||
|
// stack frame leading to huge stack frames in some cases; gcc does not reuse
|
||||||
|
// the stack space.
|
||||||
|
Message() : ss_(new internal::StrStream) {
|
||||||
|
// By default, we want there to be enough precision when printing
|
||||||
|
// a double to a Message.
|
||||||
|
*ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy constructor.
|
||||||
|
Message(const Message& msg) : ss_(new internal::StrStream) { // NOLINT
|
||||||
|
*ss_ << msg.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a Message from a C-string.
|
||||||
|
explicit Message(const char* str) : ss_(new internal::StrStream) {
|
||||||
|
*ss_ << str;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Message() { delete ss_; }
|
||||||
|
#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) {
|
||||||
|
::GTestStreamToHelper(ss_, val);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Streams a pointer value to this object.
|
||||||
|
//
|
||||||
|
// This function is an overload of the previous one. When you
|
||||||
|
// stream a pointer to a Message, this definition will be used as it
|
||||||
|
// is more specialized. (The C++ Standard, section
|
||||||
|
// [temp.func.order].) If you stream a non-pointer, then the
|
||||||
|
// previous definition will be used.
|
||||||
|
//
|
||||||
|
// The reason for this overload is that streaming a NULL pointer to
|
||||||
|
// ostream is undefined behavior. Depending on the compiler, you
|
||||||
|
// may get "0", "(nil)", "(null)", or an access violation. To
|
||||||
|
// ensure consistent result across compilers, we always treat NULL
|
||||||
|
// as "(null)".
|
||||||
|
template <typename T>
|
||||||
|
inline Message& operator <<(T* const& pointer) { // NOLINT
|
||||||
|
if (pointer == NULL) {
|
||||||
|
*ss_ << "(null)";
|
||||||
|
} else {
|
||||||
|
::GTestStreamToHelper(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
|
||||||
|
// of operator <<, even though its body is the same as the
|
||||||
|
// templatized version above. Without this definition, streaming
|
||||||
|
// endl or other basic IO manipulators to Message will confuse the
|
||||||
|
// compiler.
|
||||||
|
Message& operator <<(BasicNarrowIoManip val) {
|
||||||
|
*ss_ << val;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instead of 1/0, we want to see true/false for bool values.
|
||||||
|
Message& operator <<(bool b) {
|
||||||
|
return *this << (b ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
// These two overloads allow streaming a wide C string to a Message
|
||||||
|
// using the UTF-8 encoding.
|
||||||
|
Message& operator <<(const wchar_t* wide_c_str) {
|
||||||
|
return *this << internal::String::ShowWideCString(wide_c_str);
|
||||||
|
}
|
||||||
|
Message& operator <<(wchar_t* wide_c_str) {
|
||||||
|
return *this << internal::String::ShowWideCString(wide_c_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GTEST_HAS_STD_WSTRING
|
||||||
|
// Converts the given wide string to a narrow string using the UTF-8
|
||||||
|
// encoding, and streams the result to this Message object.
|
||||||
|
Message& operator <<(const ::std::wstring& wstr);
|
||||||
|
#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 a String.
|
||||||
|
// Each '\0' character in the buffer is replaced with "\\0".
|
||||||
|
//
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
|
internal::String GetString() const {
|
||||||
|
return internal::StrStreamToString(ss_);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 /*dummy*/, T* pointer) {
|
||||||
|
if (pointer == NULL) {
|
||||||
|
*ss_ << "(null)";
|
||||||
|
} else {
|
||||||
|
::GTestStreamToHelper(ss_, pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
|
||||||
|
::GTestStreamToHelper(ss_, value);
|
||||||
|
}
|
||||||
|
#endif // GTEST_OS_SYMBIAN
|
||||||
|
|
||||||
|
// We'll hold the text streamed to this object here.
|
||||||
|
internal::StrStream* const ss_;
|
||||||
|
|
||||||
|
// We declare (but don't implement) this to prevent the compiler
|
||||||
|
// from implementing the assignment operator.
|
||||||
|
void operator=(const Message&);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Streams a Message to an ostream.
|
||||||
|
inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
|
||||||
|
return os << sb.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,457 @@
|
||||||
|
$$ -*- 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.
|
||||||
|
//
|
||||||
|
// Authors: vladl@google.com (Vlad Losev)
|
||||||
|
//
|
||||||
|
// Macros and functions for implementing parameterized tests
|
||||||
|
// in Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||||
|
//
|
||||||
|
#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 must be derived from testing::TestWithParam<T>, where T is
|
||||||
|
// the type of your parameter values. TestWithParam<T> is itself derived
|
||||||
|
// from testing::Test. T can be any copyable type. If it's a raw pointer,
|
||||||
|
// you are responsible for managing the lifespan of the pointed values.
|
||||||
|
|
||||||
|
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 are evaluated in
|
||||||
|
// RUN_ALL_TESTS(), after main() has started. This allows evaluation of
|
||||||
|
// parameter list based on command line parameters.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
|
||||||
|
#if !GTEST_OS_SYMBIAN
|
||||||
|
#include <utility>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||||
|
// *unconditionally*. Therefore these #includes cannot be moved
|
||||||
|
// inside #if GTEST_HAS_PARAM_TEST.
|
||||||
|
#include <gtest/internal/gtest-internal.h>
|
||||||
|
#include <gtest/internal/gtest-param-util.h>
|
||||||
|
#include <gtest/internal/gtest-param-util-generated.h>
|
||||||
|
|
||||||
|
#if GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Functions producing parameter generators.
|
||||||
|
//
|
||||||
|
// 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, SrtingTest, 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 ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
|
||||||
|
ForwardIterator begin,
|
||||||
|
ForwardIterator end) {
|
||||||
|
typedef typename ::std::iterator_traits<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, __FILE__, __LINE__)->AddTestPattern(\
|
||||||
|
#test_case_name, \
|
||||||
|
#test_name, \
|
||||||
|
new ::testing::internal::TestMetaFactory< \
|
||||||
|
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
static int gtest_registering_dummy_; \
|
||||||
|
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()
|
||||||
|
|
||||||
|
#define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
|
||||||
|
::testing::internal::ParamGenerator<test_case_name::ParamType> \
|
||||||
|
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
|
||||||
|
int gtest_##prefix##test_case_name##_dummy_ = \
|
||||||
|
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
|
||||||
|
GetTestCasePatternHolder<test_case_name>(\
|
||||||
|
#test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
|
||||||
|
#prefix, \
|
||||||
|
>est_##prefix##test_case_name##_EvalGenerator_, \
|
||||||
|
__FILE__, __LINE__)
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
|
@ -0,0 +1,232 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
//
|
||||||
|
// Utilities for testing Google Test itself and code that uses Google Test
|
||||||
|
// (e.g. frameworks built on top of Google Test).
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// This helper class can be used to mock out Google Test failure reporting
|
||||||
|
// so that we can test Google Test or code that builds on Google Test.
|
||||||
|
//
|
||||||
|
// An object of this class appends a TestPartResult object to the
|
||||||
|
// TestPartResultArray object given in the constructor whenever a Google Test
|
||||||
|
// failure is reported. It can either intercept only failures that are
|
||||||
|
// generated in the same thread that created this object or it can intercept
|
||||||
|
// all generated failures. The scope of this mock object can be controlled with
|
||||||
|
// the second argument to the two arguments constructor.
|
||||||
|
class GTEST_API_ ScopedFakeTestPartResultReporter
|
||||||
|
: public TestPartResultReporterInterface {
|
||||||
|
public:
|
||||||
|
// The two possible mocking modes of this object.
|
||||||
|
enum InterceptMode {
|
||||||
|
INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
|
||||||
|
INTERCEPT_ALL_THREADS // Intercepts all failures.
|
||||||
|
};
|
||||||
|
|
||||||
|
// The c'tor sets this object as the test part result reporter used
|
||||||
|
// by Google Test. The 'result' parameter specifies where to report the
|
||||||
|
// results. This reporter will only catch failures generated in the current
|
||||||
|
// thread. DEPRECATED
|
||||||
|
explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
|
||||||
|
|
||||||
|
// Same as above, but you can choose the interception scope of this object.
|
||||||
|
ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
|
||||||
|
TestPartResultArray* result);
|
||||||
|
|
||||||
|
// The d'tor restores the previous test part result reporter.
|
||||||
|
virtual ~ScopedFakeTestPartResultReporter();
|
||||||
|
|
||||||
|
// Appends the TestPartResult object to the TestPartResultArray
|
||||||
|
// received in the constructor.
|
||||||
|
//
|
||||||
|
// This method is from the TestPartResultReporterInterface
|
||||||
|
// interface.
|
||||||
|
virtual void ReportTestPartResult(const TestPartResult& result);
|
||||||
|
private:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
const InterceptMode intercept_mode_;
|
||||||
|
TestPartResultReporterInterface* old_reporter_;
|
||||||
|
TestPartResultArray* const result_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// A helper class for implementing EXPECT_FATAL_FAILURE() and
|
||||||
|
// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
|
||||||
|
// TestPartResultArray contains exactly one failure that has the given
|
||||||
|
// type and contains the given substring. If that's not the case, a
|
||||||
|
// non-fatal failure will be generated.
|
||||||
|
class GTEST_API_ SingleFailureChecker {
|
||||||
|
public:
|
||||||
|
// The constructor remembers the arguments.
|
||||||
|
SingleFailureChecker(const TestPartResultArray* results,
|
||||||
|
TestPartResult::Type type,
|
||||||
|
const char* substr);
|
||||||
|
~SingleFailureChecker();
|
||||||
|
private:
|
||||||
|
const TestPartResultArray* const results_;
|
||||||
|
const TestPartResult::Type type_;
|
||||||
|
const String substr_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
// A set of macros for testing Google Test assertions or code that's expected
|
||||||
|
// to generate Google Test fatal failures. It verifies that the given
|
||||||
|
// statement will cause exactly one fatal Google Test failure with 'substr'
|
||||||
|
// being part of the failure message.
|
||||||
|
//
|
||||||
|
// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
|
||||||
|
// affects and considers failures generated in the current thread and
|
||||||
|
// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
|
||||||
|
//
|
||||||
|
// The verification of the assertion is done correctly even when the statement
|
||||||
|
// throws an exception or aborts the current function.
|
||||||
|
//
|
||||||
|
// Known restrictions:
|
||||||
|
// - 'statement' cannot reference local non-static variables or
|
||||||
|
// non-static members of the current object.
|
||||||
|
// - 'statement' cannot return a value.
|
||||||
|
// - You cannot stream a failure message to this macro.
|
||||||
|
//
|
||||||
|
// Note that even though the implementations of the following two
|
||||||
|
// macros are much alike, we cannot refactor them to use a common
|
||||||
|
// helper macro, due to some peculiarity in how the preprocessor
|
||||||
|
// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
|
||||||
|
// gtest_unittest.cc will fail to compile if we do that.
|
||||||
|
#define EXPECT_FATAL_FAILURE(statement, substr) \
|
||||||
|
do { \
|
||||||
|
class GTestExpectFatalFailureHelper {\
|
||||||
|
public:\
|
||||||
|
static void Execute() { statement; }\
|
||||||
|
};\
|
||||||
|
::testing::TestPartResultArray gtest_failures;\
|
||||||
|
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||||
|
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
||||||
|
{\
|
||||||
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||||
|
::testing::ScopedFakeTestPartResultReporter:: \
|
||||||
|
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
||||||
|
GTestExpectFatalFailureHelper::Execute();\
|
||||||
|
}\
|
||||||
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
|
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||||
|
do { \
|
||||||
|
class GTestExpectFatalFailureHelper {\
|
||||||
|
public:\
|
||||||
|
static void Execute() { statement; }\
|
||||||
|
};\
|
||||||
|
::testing::TestPartResultArray gtest_failures;\
|
||||||
|
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||||
|
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
||||||
|
{\
|
||||||
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||||
|
::testing::ScopedFakeTestPartResultReporter:: \
|
||||||
|
INTERCEPT_ALL_THREADS, >est_failures);\
|
||||||
|
GTestExpectFatalFailureHelper::Execute();\
|
||||||
|
}\
|
||||||
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
|
// A macro for testing Google Test assertions or code that's expected to
|
||||||
|
// generate Google Test non-fatal failures. It asserts that the given
|
||||||
|
// statement will cause exactly one non-fatal Google Test failure with 'substr'
|
||||||
|
// being part of the failure message.
|
||||||
|
//
|
||||||
|
// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
|
||||||
|
// affects and considers failures generated in the current thread and
|
||||||
|
// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
|
||||||
|
//
|
||||||
|
// 'statement' is allowed to reference local variables and members of
|
||||||
|
// the current object.
|
||||||
|
//
|
||||||
|
// The verification of the assertion is done correctly even when the statement
|
||||||
|
// throws an exception or aborts the current function.
|
||||||
|
//
|
||||||
|
// Known restrictions:
|
||||||
|
// - You cannot stream a failure message to this macro.
|
||||||
|
//
|
||||||
|
// Note that even though the implementations of the following two
|
||||||
|
// macros are much alike, we cannot refactor them to use a common
|
||||||
|
// helper macro, due to some peculiarity in how the preprocessor
|
||||||
|
// works. If we do that, the code won't compile when the user gives
|
||||||
|
// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
|
||||||
|
// expands to code containing an unprotected comma. The
|
||||||
|
// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
|
||||||
|
// catches that.
|
||||||
|
//
|
||||||
|
// For the same reason, we have to write
|
||||||
|
// if (::testing::internal::AlwaysTrue()) { statement; }
|
||||||
|
// instead of
|
||||||
|
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
||||||
|
// to avoid an MSVC warning on unreachable code.
|
||||||
|
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
|
||||||
|
do {\
|
||||||
|
::testing::TestPartResultArray gtest_failures;\
|
||||||
|
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||||
|
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||||
|
(substr));\
|
||||||
|
{\
|
||||||
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||||
|
::testing::ScopedFakeTestPartResultReporter:: \
|
||||||
|
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
||||||
|
if (::testing::internal::AlwaysTrue()) { statement; }\
|
||||||
|
}\
|
||||||
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
|
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||||
|
do {\
|
||||||
|
::testing::TestPartResultArray gtest_failures;\
|
||||||
|
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||||
|
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||||
|
(substr));\
|
||||||
|
{\
|
||||||
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||||
|
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\
|
||||||
|
>est_failures);\
|
||||||
|
if (::testing::internal::AlwaysTrue()) { statement; }\
|
||||||
|
}\
|
||||||
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
|
@ -0,0 +1,176 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: mheule@google.com (Markus Heule)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <vector>
|
||||||
|
#include <gtest/internal/gtest-internal.h>
|
||||||
|
#include <gtest/internal/gtest-string.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// A copyable object representing the result of a test part (i.e. an
|
||||||
|
// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
|
||||||
|
//
|
||||||
|
// Don't inherit from TestPartResult as its destructor is not virtual.
|
||||||
|
class GTEST_API_ TestPartResult {
|
||||||
|
public:
|
||||||
|
// The possible outcomes of a test part (i.e. an assertion or an
|
||||||
|
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
|
||||||
|
enum Type {
|
||||||
|
kSuccess, // Succeeded.
|
||||||
|
kNonFatalFailure, // Failed but the test can continue.
|
||||||
|
kFatalFailure // Failed and the test should be terminated.
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
const char* a_message)
|
||||||
|
: type_(a_type),
|
||||||
|
file_name_(a_file_name),
|
||||||
|
line_number_(a_line_number),
|
||||||
|
summary_(ExtractSummary(a_message)),
|
||||||
|
message_(a_message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the outcome of the test part.
|
||||||
|
Type type() const { return type_; }
|
||||||
|
|
||||||
|
// 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_.c_str(); }
|
||||||
|
|
||||||
|
// Gets the line in the source file where the test part took place,
|
||||||
|
// or -1 if it's unknown.
|
||||||
|
int line_number() const { return line_number_; }
|
||||||
|
|
||||||
|
// Gets the summary of the failure message.
|
||||||
|
const char* summary() const { return summary_.c_str(); }
|
||||||
|
|
||||||
|
// Gets the message associated with the test part.
|
||||||
|
const char* message() const { return message_.c_str(); }
|
||||||
|
|
||||||
|
// Returns true iff 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.
|
||||||
|
bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
|
||||||
|
|
||||||
|
// Returns true iff the test part fatally failed.
|
||||||
|
bool fatally_failed() const { return type_ == kFatalFailure; }
|
||||||
|
private:
|
||||||
|
Type type_;
|
||||||
|
|
||||||
|
// Gets the summary of the failure message by omitting the stack
|
||||||
|
// trace in it.
|
||||||
|
static internal::String ExtractSummary(const char* message);
|
||||||
|
|
||||||
|
// The name of the source file where the test part took place, or
|
||||||
|
// NULL if the source file is unknown.
|
||||||
|
internal::String file_name_;
|
||||||
|
// The line in the source file where the test part took place, or -1
|
||||||
|
// if the line number is unknown.
|
||||||
|
int line_number_;
|
||||||
|
internal::String summary_; // The test failure summary.
|
||||||
|
internal::String message_; // The test failure message.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prints a TestPartResult object.
|
||||||
|
std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
|
||||||
|
|
||||||
|
// An array of TestPartResult objects.
|
||||||
|
//
|
||||||
|
// Don't inherit from TestPartResultArray as its destructor is not
|
||||||
|
// virtual.
|
||||||
|
class GTEST_API_ TestPartResultArray {
|
||||||
|
public:
|
||||||
|
TestPartResultArray() {}
|
||||||
|
|
||||||
|
// Appends the given TestPartResult to the array.
|
||||||
|
void Append(const TestPartResult& result);
|
||||||
|
|
||||||
|
// Returns the TestPartResult at the given index (0-based).
|
||||||
|
const TestPartResult& GetTestPartResult(int index) const;
|
||||||
|
|
||||||
|
// Returns the number of TestPartResult objects in the array.
|
||||||
|
int size() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<TestPartResult> array_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
|
||||||
|
};
|
||||||
|
|
||||||
|
// This interface knows how to report a test part result.
|
||||||
|
class TestPartResultReporterInterface {
|
||||||
|
public:
|
||||||
|
virtual ~TestPartResultReporterInterface() {}
|
||||||
|
|
||||||
|
virtual void ReportTestPartResult(const TestPartResult& result) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
|
||||||
|
// statement generates new fatal failures. To do so it registers itself as the
|
||||||
|
// current test part result reporter. Besides checking if fatal failures were
|
||||||
|
// reported, it only delegates the reporting to the former result reporter.
|
||||||
|
// The original result reporter is restored in the destructor.
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
|
class GTEST_API_ HasNewFatalFailureHelper
|
||||||
|
: public TestPartResultReporterInterface {
|
||||||
|
public:
|
||||||
|
HasNewFatalFailureHelper();
|
||||||
|
virtual ~HasNewFatalFailureHelper();
|
||||||
|
virtual void ReportTestPartResult(const TestPartResult& result);
|
||||||
|
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
||||||
|
private:
|
||||||
|
bool has_new_fatal_failure_;
|
||||||
|
TestPartResultReporterInterface* original_reporter_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
|
@ -0,0 +1,259 @@
|
||||||
|
// Copyright 2008 Google Inc.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||||
|
|
||||||
|
// This header implements typed tests and type-parameterized tests.
|
||||||
|
|
||||||
|
// Typed (aka type-driven) tests repeat the same test for types in a
|
||||||
|
// list. You must know which types you want to test with when writing
|
||||||
|
// typed tests. Here's how you do it:
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
// First, define a fixture class template. It should be parameterized
|
||||||
|
// by a type. Remember to derive it from testing::Test.
|
||||||
|
template <typename T>
|
||||||
|
class FooTest : public testing::Test {
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
typedef std::list<T> List;
|
||||||
|
static T shared_;
|
||||||
|
T value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Next, associate a list of types with the test case, 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);
|
||||||
|
|
||||||
|
// If the type list contains only one type, you can write that type
|
||||||
|
// directly without Types<...>:
|
||||||
|
// TYPED_TEST_CASE(FooTest, int);
|
||||||
|
|
||||||
|
// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
|
||||||
|
// tests for this test case 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'.
|
||||||
|
TypeParam n = this->value_;
|
||||||
|
|
||||||
|
// To visit static members of the fixture, add the TestFixture::
|
||||||
|
// prefix.
|
||||||
|
n += TestFixture::shared_;
|
||||||
|
|
||||||
|
// To refer to typedefs in the fixture, add the "typename
|
||||||
|
// TestFixture::" prefix.
|
||||||
|
typename TestFixture::List values;
|
||||||
|
values.push_back(n);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(FooTest, HasPropertyA) { ... }
|
||||||
|
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
// Type-parameterized tests are abstract test patterns parameterized
|
||||||
|
// by a type. Compared with typed tests, type-parameterized tests
|
||||||
|
// allow you to define the test pattern without knowing what the type
|
||||||
|
// parameters are. The defined pattern can be instantiated with
|
||||||
|
// different types any number of times, in any number of translation
|
||||||
|
// units.
|
||||||
|
//
|
||||||
|
// If you are designing an interface or concept, you can define a
|
||||||
|
// suite of type-parameterized tests to verify properties that any
|
||||||
|
// valid implementation of the interface/concept should have. Then,
|
||||||
|
// each implementation can easily instantiate the test suite to verify
|
||||||
|
// that it conforms to the requirements, without having to write
|
||||||
|
// similar tests repeatedly. Here's an example:
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
// First, define a fixture class template. It should be parameterized
|
||||||
|
// by a type. Remember to derive it from testing::Test.
|
||||||
|
template <typename T>
|
||||||
|
class FooTest : public testing::Test {
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
// Next, declare that you will define a type-parameterized test case
|
||||||
|
// (the _P suffix is for "parameterized" or "pattern", whichever you
|
||||||
|
// prefer):
|
||||||
|
TYPED_TEST_CASE_P(FooTest);
|
||||||
|
|
||||||
|
// Then, use TYPED_TEST_P() to define as many type-parameterized tests
|
||||||
|
// for this type-parameterized test case as you want.
|
||||||
|
TYPED_TEST_P(FooTest, DoesBlah) {
|
||||||
|
// Inside a test, refer to TypeParam to get the type parameter.
|
||||||
|
TypeParam n = 0;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
// case.
|
||||||
|
REGISTER_TYPED_TEST_CASE_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
|
||||||
|
// it in multiple C++ source files and instantiate it multiple times.
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// different instances.
|
||||||
|
typedef testing::Types<char, int, unsigned int> MyTypes;
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_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);
|
||||||
|
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
#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##_
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#define TYPED_TEST(CaseName, TestName) \
|
||||||
|
template <typename gtest_TypeParam_> \
|
||||||
|
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||||
|
: public CaseName<gtest_TypeParam_> { \
|
||||||
|
private: \
|
||||||
|
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||||
|
typedef gtest_TypeParam_ TypeParam; \
|
||||||
|
virtual void TestBody(); \
|
||||||
|
}; \
|
||||||
|
bool gtest_##CaseName##_##TestName##_registered_ = \
|
||||||
|
::testing::internal::TypeParameterizedTest< \
|
||||||
|
CaseName, \
|
||||||
|
::testing::internal::TemplateSel< \
|
||||||
|
GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
|
||||||
|
GTEST_TYPE_PARAMS_(CaseName)>::Register(\
|
||||||
|
"", #CaseName, #TestName, 0); \
|
||||||
|
template <typename gtest_TypeParam_> \
|
||||||
|
void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_TYPED_TEST
|
||||||
|
|
||||||
|
// Implements type-parameterized tests.
|
||||||
|
|
||||||
|
#if GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
//
|
||||||
|
// Expands to the namespace name that the type-parameterized tests for
|
||||||
|
// the given type-parameterized test case are defined in. The exact
|
||||||
|
// name of the namespace is subject to change without notice.
|
||||||
|
#define GTEST_CASE_NAMESPACE_(TestCaseName) \
|
||||||
|
gtest_case_##TestCaseName##_
|
||||||
|
|
||||||
|
// 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##_
|
||||||
|
|
||||||
|
// 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 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_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_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
|
||||||
|
__FILE__, __LINE__, #CaseName, #TestName); \
|
||||||
|
} \
|
||||||
|
template <typename gtest_TypeParam_> \
|
||||||
|
void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
|
||||||
|
|
||||||
|
#define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
|
||||||
|
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
||||||
|
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
|
||||||
|
} \
|
||||||
|
static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
|
||||||
|
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
|
||||||
|
__FILE__, __LINE__, #__VA_ARGS__)
|
||||||
|
|
||||||
|
// The 'Types' template argument below must have spaces around it
|
||||||
|
// since some compilers may choke on '>>' when passing a template
|
||||||
|
// instance (e.g. Types<int>)
|
||||||
|
#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
|
||||||
|
bool gtest_##Prefix##_##CaseName = \
|
||||||
|
::testing::internal::TypeParameterizedTestCase<CaseName, \
|
||||||
|
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
|
||||||
|
::testing::internal::TypeList< Types >::type>::Register(\
|
||||||
|
#Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,368 @@
|
||||||
|
// Copyright 2006, 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.
|
||||||
|
|
||||||
|
// This file is AUTOMATICALLY GENERATED on 10/02/2008 by command
|
||||||
|
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
|
||||||
|
//
|
||||||
|
// Implements a family of generic predicate assertion macros.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
|
|
||||||
|
// Makes sure this header is not included before gtest.h.
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
|
||||||
|
#error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
|
||||||
|
|
||||||
|
// This header implements a family of generic predicate assertion
|
||||||
|
// macros:
|
||||||
|
//
|
||||||
|
// ASSERT_PRED_FORMAT1(pred_format, v1)
|
||||||
|
// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// where pred_format is a function or functor that takes n (in the
|
||||||
|
// case of ASSERT_PRED_FORMATn) values and their source expression
|
||||||
|
// text, and returns a testing::AssertionResult. See the definition
|
||||||
|
// of ASSERT_EQ in gtest.h for an example.
|
||||||
|
//
|
||||||
|
// If you don't care about formatting, you can use the more
|
||||||
|
// restrictive version:
|
||||||
|
//
|
||||||
|
// ASSERT_PRED1(pred, v1)
|
||||||
|
// ASSERT_PRED2(pred, v1, v2)
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// where pred is an n-ary function or functor that returns bool,
|
||||||
|
// and the values v1, v2, ..., must support the << operator for
|
||||||
|
// streaming to std::ostream.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#define GTEST_ASSERT_(expression, on_failure) \
|
||||||
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
if (const ::testing::AssertionResult gtest_ar = (expression)) \
|
||||||
|
; \
|
||||||
|
else \
|
||||||
|
on_failure(gtest_ar.failure_message())
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
||||||
|
// this in your code.
|
||||||
|
template <typename Pred,
|
||||||
|
typename T1>
|
||||||
|
AssertionResult AssertPred1Helper(const char* pred_text,
|
||||||
|
const char* e1,
|
||||||
|
Pred pred,
|
||||||
|
const T1& v1) {
|
||||||
|
if (pred(v1)) return AssertionSuccess();
|
||||||
|
|
||||||
|
Message msg;
|
||||||
|
msg << pred_text << "("
|
||||||
|
<< e1 << ") evaluates to false, where"
|
||||||
|
<< "\n" << e1 << " evaluates to " << v1;
|
||||||
|
return AssertionFailure(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
||||||
|
// Don't use this in your code.
|
||||||
|
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
|
||||||
|
GTEST_ASSERT_(pred_format(#v1, v1),\
|
||||||
|
on_failure)
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
||||||
|
// this in your code.
|
||||||
|
#define GTEST_PRED1_(pred, v1, on_failure)\
|
||||||
|
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
|
||||||
|
#v1, \
|
||||||
|
pred, \
|
||||||
|
v1), on_failure)
|
||||||
|
|
||||||
|
// Unary predicate assertion macros.
|
||||||
|
#define EXPECT_PRED_FORMAT1(pred_format, v1) \
|
||||||
|
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define EXPECT_PRED1(pred, v1) \
|
||||||
|
GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED_FORMAT1(pred_format, v1) \
|
||||||
|
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED1(pred, v1) \
|
||||||
|
GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
||||||
|
// this in your code.
|
||||||
|
template <typename Pred,
|
||||||
|
typename T1,
|
||||||
|
typename T2>
|
||||||
|
AssertionResult AssertPred2Helper(const char* pred_text,
|
||||||
|
const char* e1,
|
||||||
|
const char* e2,
|
||||||
|
Pred pred,
|
||||||
|
const T1& v1,
|
||||||
|
const T2& v2) {
|
||||||
|
if (pred(v1, v2)) return AssertionSuccess();
|
||||||
|
|
||||||
|
Message msg;
|
||||||
|
msg << pred_text << "("
|
||||||
|
<< e1 << ", "
|
||||||
|
<< e2 << ") evaluates to false, where"
|
||||||
|
<< "\n" << e1 << " evaluates to " << v1
|
||||||
|
<< "\n" << e2 << " evaluates to " << v2;
|
||||||
|
return AssertionFailure(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
||||||
|
// Don't use this in your code.
|
||||||
|
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
|
||||||
|
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2),\
|
||||||
|
on_failure)
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
||||||
|
// this in your code.
|
||||||
|
#define GTEST_PRED2_(pred, v1, v2, on_failure)\
|
||||||
|
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
|
||||||
|
#v1, \
|
||||||
|
#v2, \
|
||||||
|
pred, \
|
||||||
|
v1, \
|
||||||
|
v2), on_failure)
|
||||||
|
|
||||||
|
// Binary predicate assertion macros.
|
||||||
|
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
|
||||||
|
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define EXPECT_PRED2(pred, v1, v2) \
|
||||||
|
GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
|
||||||
|
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED2(pred, v1, v2) \
|
||||||
|
GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
||||||
|
// this in your code.
|
||||||
|
template <typename Pred,
|
||||||
|
typename T1,
|
||||||
|
typename T2,
|
||||||
|
typename T3>
|
||||||
|
AssertionResult AssertPred3Helper(const char* pred_text,
|
||||||
|
const char* e1,
|
||||||
|
const char* e2,
|
||||||
|
const char* e3,
|
||||||
|
Pred pred,
|
||||||
|
const T1& v1,
|
||||||
|
const T2& v2,
|
||||||
|
const T3& v3) {
|
||||||
|
if (pred(v1, v2, v3)) return AssertionSuccess();
|
||||||
|
|
||||||
|
Message msg;
|
||||||
|
msg << 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(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
||||||
|
// Don't use this in your code.
|
||||||
|
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
|
||||||
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3),\
|
||||||
|
on_failure)
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
||||||
|
// this in your code.
|
||||||
|
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
|
||||||
|
GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
|
||||||
|
#v1, \
|
||||||
|
#v2, \
|
||||||
|
#v3, \
|
||||||
|
pred, \
|
||||||
|
v1, \
|
||||||
|
v2, \
|
||||||
|
v3), on_failure)
|
||||||
|
|
||||||
|
// Ternary predicate assertion macros.
|
||||||
|
#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
||||||
|
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define EXPECT_PRED3(pred, v1, v2, v3) \
|
||||||
|
GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
||||||
|
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED3(pred, v1, v2, v3) \
|
||||||
|
GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
||||||
|
// this in your code.
|
||||||
|
template <typename Pred,
|
||||||
|
typename T1,
|
||||||
|
typename T2,
|
||||||
|
typename T3,
|
||||||
|
typename T4>
|
||||||
|
AssertionResult AssertPred4Helper(const char* pred_text,
|
||||||
|
const char* e1,
|
||||||
|
const char* e2,
|
||||||
|
const char* e3,
|
||||||
|
const char* e4,
|
||||||
|
Pred pred,
|
||||||
|
const T1& v1,
|
||||||
|
const T2& v2,
|
||||||
|
const T3& v3,
|
||||||
|
const T4& v4) {
|
||||||
|
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
|
||||||
|
|
||||||
|
Message msg;
|
||||||
|
msg << 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(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
||||||
|
// Don't use this in your code.
|
||||||
|
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
|
||||||
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4),\
|
||||||
|
on_failure)
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
||||||
|
// this in your code.
|
||||||
|
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
|
||||||
|
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
|
||||||
|
#v1, \
|
||||||
|
#v2, \
|
||||||
|
#v3, \
|
||||||
|
#v4, \
|
||||||
|
pred, \
|
||||||
|
v1, \
|
||||||
|
v2, \
|
||||||
|
v3, \
|
||||||
|
v4), on_failure)
|
||||||
|
|
||||||
|
// 4-ary predicate assertion macros.
|
||||||
|
#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
||||||
|
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
|
||||||
|
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
||||||
|
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
|
||||||
|
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
||||||
|
// this in your code.
|
||||||
|
template <typename Pred,
|
||||||
|
typename T1,
|
||||||
|
typename T2,
|
||||||
|
typename T3,
|
||||||
|
typename T4,
|
||||||
|
typename T5>
|
||||||
|
AssertionResult AssertPred5Helper(const char* pred_text,
|
||||||
|
const char* e1,
|
||||||
|
const char* e2,
|
||||||
|
const char* e3,
|
||||||
|
const char* e4,
|
||||||
|
const char* e5,
|
||||||
|
Pred pred,
|
||||||
|
const T1& v1,
|
||||||
|
const T2& v2,
|
||||||
|
const T3& v3,
|
||||||
|
const T4& v4,
|
||||||
|
const T5& v5) {
|
||||||
|
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
|
||||||
|
|
||||||
|
Message msg;
|
||||||
|
msg << 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(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
||||||
|
// Don't use this in your code.
|
||||||
|
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
|
||||||
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5),\
|
||||||
|
on_failure)
|
||||||
|
|
||||||
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
||||||
|
// this in your code.
|
||||||
|
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
|
||||||
|
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
|
||||||
|
#v1, \
|
||||||
|
#v2, \
|
||||||
|
#v3, \
|
||||||
|
#v4, \
|
||||||
|
#v5, \
|
||||||
|
pred, \
|
||||||
|
v1, \
|
||||||
|
v2, \
|
||||||
|
v3, \
|
||||||
|
v4, \
|
||||||
|
v5), on_failure)
|
||||||
|
|
||||||
|
// 5-ary predicate assertion macros.
|
||||||
|
#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
||||||
|
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
|
||||||
|
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
||||||
|
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
||||||
|
#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
|
||||||
|
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright 2006, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
//
|
||||||
|
// Google C++ Testing Framework definitions useful in production code.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||||
|
#define GTEST_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
|
||||||
|
// class. For example:
|
||||||
|
//
|
||||||
|
// class MyClass {
|
||||||
|
// private:
|
||||||
|
// void MyMethod();
|
||||||
|
// FRIEND_TEST(MyClassTest, MyMethod);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// class MyClassTest : public testing::Test {
|
||||||
|
// // ...
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// TEST_F(MyClassTest, MyMethod) {
|
||||||
|
// // Can call MyClass::MyMethod() here.
|
||||||
|
// }
|
||||||
|
|
||||||
|
#define FRIEND_TEST(test_case_name, test_name)\
|
||||||
|
friend class test_case_name##_##test_name##_Test
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
|
@ -0,0 +1,275 @@
|
||||||
|
// Copyright 2005, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
|
||||||
|
//
|
||||||
|
// The Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This header file defines internal utilities needed for implementing
|
||||||
|
// death tests. They are subject to change without notice.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-internal.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
GTEST_DECLARE_string_(internal_run_death_test);
|
||||||
|
|
||||||
|
// Names of the flags (needed for parsing Google Test flags).
|
||||||
|
const char kDeathTestStyleFlag[] = "death_test_style";
|
||||||
|
const char kDeathTestUseFork[] = "death_test_use_fork";
|
||||||
|
const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
|
||||||
|
|
||||||
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
// DeathTest is a class that hides much of the complexity of the
|
||||||
|
// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
|
||||||
|
// returns a concrete class that depends on the prevailing death test
|
||||||
|
// style, as defined by the --gtest_death_test_style and/or
|
||||||
|
// --gtest_internal_run_death_test flags.
|
||||||
|
|
||||||
|
// In describing the results of death tests, these terms are used with
|
||||||
|
// the corresponding definitions:
|
||||||
|
//
|
||||||
|
// exit status: The integer exit information in the format specified
|
||||||
|
// by wait(2)
|
||||||
|
// exit code: The integer code passed to exit(3), _exit(2), or
|
||||||
|
// returned from main()
|
||||||
|
class GTEST_API_ DeathTest {
|
||||||
|
public:
|
||||||
|
// Create returns false if there was an error determining the
|
||||||
|
// appropriate action to take for the current death test; for example,
|
||||||
|
// if the gtest_death_test_style flag is set to an invalid value.
|
||||||
|
// The LastMessage method will return a more detailed message in that
|
||||||
|
// case. Otherwise, the DeathTest pointer pointed to by the "test"
|
||||||
|
// 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,
|
||||||
|
const char* file, int line, DeathTest** test);
|
||||||
|
DeathTest();
|
||||||
|
virtual ~DeathTest() { }
|
||||||
|
|
||||||
|
// A helper class that aborts a death test when it's deleted.
|
||||||
|
class ReturnSentinel {
|
||||||
|
public:
|
||||||
|
explicit ReturnSentinel(DeathTest* test) : test_(test) { }
|
||||||
|
~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
|
||||||
|
private:
|
||||||
|
DeathTest* const test_;
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
|
||||||
|
} GTEST_ATTRIBUTE_UNUSED_;
|
||||||
|
|
||||||
|
// An enumeration of possible roles that may be taken when a death
|
||||||
|
// test is encountered. EXECUTE means that the death test logic should
|
||||||
|
// be executed immediately. OVERSEE means that the program should prepare
|
||||||
|
// the appropriate environment for a child process to execute the death
|
||||||
|
// test, then wait for it to complete.
|
||||||
|
enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
|
||||||
|
|
||||||
|
// An enumeration of the two reasons that a test might be aborted.
|
||||||
|
enum AbortReason { TEST_ENCOUNTERED_RETURN_STATEMENT, TEST_DID_NOT_DIE };
|
||||||
|
|
||||||
|
// Assumes one of the above roles.
|
||||||
|
virtual TestRole AssumeRole() = 0;
|
||||||
|
|
||||||
|
// Waits for the death test to finish and returns its status.
|
||||||
|
virtual int Wait() = 0;
|
||||||
|
|
||||||
|
// Returns true if the death test passed; that is, the test process
|
||||||
|
// exited during the test, its exit status matches a user-supplied
|
||||||
|
// predicate, and its stderr output matches a user-supplied regular
|
||||||
|
// expression.
|
||||||
|
// The user-supplied predicate may be a macro expression rather
|
||||||
|
// than a function pointer or functor, or else Wait and Passed could
|
||||||
|
// be combined.
|
||||||
|
virtual bool Passed(bool exit_status_ok) = 0;
|
||||||
|
|
||||||
|
// Signals that the death test did not die as expected.
|
||||||
|
virtual void Abort(AbortReason reason) = 0;
|
||||||
|
|
||||||
|
// Returns a human-readable outcome message regarding the outcome of
|
||||||
|
// the last death test.
|
||||||
|
static const char* LastMessage();
|
||||||
|
|
||||||
|
static void set_last_death_test_message(const String& message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// A string containing a description of the outcome of the last death test.
|
||||||
|
static String last_death_test_message_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Factory interface for death tests. May be mocked out for testing.
|
||||||
|
class DeathTestFactory {
|
||||||
|
public:
|
||||||
|
virtual ~DeathTestFactory() { }
|
||||||
|
virtual bool Create(const char* statement, const RE* regex,
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
|
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
||||||
|
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.
|
||||||
|
|
||||||
|
// A class representing the parsed contents of the
|
||||||
|
// --gtest_internal_run_death_test flag, as it existed when
|
||||||
|
// RUN_ALL_TESTS was called.
|
||||||
|
class InternalRunDeathTestFlag {
|
||||||
|
public:
|
||||||
|
InternalRunDeathTestFlag(const String& a_file,
|
||||||
|
int a_line,
|
||||||
|
int an_index,
|
||||||
|
int a_write_fd)
|
||||||
|
: file_(a_file), line_(a_line), index_(an_index),
|
||||||
|
write_fd_(a_write_fd) {}
|
||||||
|
|
||||||
|
~InternalRunDeathTestFlag() {
|
||||||
|
if (write_fd_ >= 0)
|
||||||
|
posix::Close(write_fd_);
|
||||||
|
}
|
||||||
|
|
||||||
|
String file() const { return file_; }
|
||||||
|
int line() const { return line_; }
|
||||||
|
int index() const { return index_; }
|
||||||
|
int write_fd() const { return write_fd_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
String file_;
|
||||||
|
int line_;
|
||||||
|
int index_;
|
||||||
|
int write_fd_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a newly created InternalRunDeathTestFlag object with fields
|
||||||
|
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
||||||
|
// the flag is specified; otherwise returns NULL.
|
||||||
|
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
|
||||||
|
|
||||||
|
#else // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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
|
||||||
|
// this macro only accepts expressions that a macro such as
|
||||||
|
// EXPECT_DEATH would accept.
|
||||||
|
// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
|
||||||
|
// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
|
||||||
|
// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
|
||||||
|
// compile inside functions where ASSERT_DEATH doesn't
|
||||||
|
// compile.
|
||||||
|
//
|
||||||
|
// The branch that has an always false condition is used to ensure that
|
||||||
|
// statement and regex are compiled (and thus syntactically correct) but
|
||||||
|
// never executed. The unreachable code macro protects the terminator
|
||||||
|
// statement from generating an 'unreachable code' warning in case
|
||||||
|
// statement unconditionally returns or throws. The Message constructor at
|
||||||
|
// the end allows the syntax of streaming additional messages into the
|
||||||
|
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
|
||||||
|
#define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
|
||||||
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
|
GTEST_LOG_(WARNING) \
|
||||||
|
<< "Death tests are not supported on this platform.\n" \
|
||||||
|
<< "Statement '" #statement "' cannot be verified."; \
|
||||||
|
} else if (::testing::internal::AlwaysFalse()) { \
|
||||||
|
::testing::internal::RE::PartialMatch(".*", (regex)); \
|
||||||
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
|
terminator; \
|
||||||
|
} else \
|
||||||
|
::testing::Message()
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
|
@ -0,0 +1,210 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: keith.ray@gmail.com (Keith Ray)
|
||||||
|
//
|
||||||
|
// Google Test filepath utilities
|
||||||
|
//
|
||||||
|
// This header file declares classes and functions used internally by
|
||||||
|
// Google Test. They are subject to change without notice.
|
||||||
|
//
|
||||||
|
// This file is #included in <gtest/internal/gtest-internal.h>.
|
||||||
|
// Do not include this header file separately!
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-string.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// FilePath - a class for file and directory pathname manipulation which
|
||||||
|
// handles platform-specific conventions (like the pathname separator).
|
||||||
|
// Used for helper functions for naming files in a directory for xml output.
|
||||||
|
// Except for Set methods, all methods are const or static, which provides an
|
||||||
|
// "immutable value object" -- useful for peace of mind.
|
||||||
|
// A FilePath with a value ending in a path separator ("like/this/") represents
|
||||||
|
// a directory, otherwise it is assumed to represent a file. In either case,
|
||||||
|
// it may or may not represent an actual file or directory in the file system.
|
||||||
|
// Names are NOT checked for syntax correctness -- no checking for illegal
|
||||||
|
// characters, malformed paths, etc.
|
||||||
|
|
||||||
|
class GTEST_API_ FilePath {
|
||||||
|
public:
|
||||||
|
FilePath() : pathname_("") { }
|
||||||
|
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
|
||||||
|
|
||||||
|
explicit FilePath(const char* pathname) : pathname_(pathname) {
|
||||||
|
Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit FilePath(const String& pathname) : pathname_(pathname) {
|
||||||
|
Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath& operator=(const FilePath& rhs) {
|
||||||
|
Set(rhs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set(const FilePath& rhs) {
|
||||||
|
pathname_ = rhs.pathname_;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ToString() const { return pathname_; }
|
||||||
|
const char* c_str() const { return pathname_.c_str(); }
|
||||||
|
|
||||||
|
// Returns the current working directory, or "" if unsuccessful.
|
||||||
|
static FilePath GetCurrentDir();
|
||||||
|
|
||||||
|
// Given directory = "dir", base_name = "test", number = 0,
|
||||||
|
// extension = "xml", returns "dir/test.xml". If number is greater
|
||||||
|
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||||
|
// On Windows platform, uses \ as the separator rather than /.
|
||||||
|
static FilePath MakeFileName(const FilePath& directory,
|
||||||
|
const FilePath& base_name,
|
||||||
|
int number,
|
||||||
|
const char* extension);
|
||||||
|
|
||||||
|
// Given directory = "dir", relative_path = "test.xml",
|
||||||
|
// returns "dir/test.xml".
|
||||||
|
// On Windows, uses \ as the separator rather than /.
|
||||||
|
static FilePath ConcatPaths(const FilePath& directory,
|
||||||
|
const FilePath& relative_path);
|
||||||
|
|
||||||
|
// Returns a pathname for a file that does not currently exist. The pathname
|
||||||
|
// will be directory/base_name.extension or
|
||||||
|
// directory/base_name_<number>.extension if directory/base_name.extension
|
||||||
|
// already exists. The number will be incremented until a pathname is found
|
||||||
|
// that does not already exist.
|
||||||
|
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
|
||||||
|
// There could be a race condition if two or more processes are calling this
|
||||||
|
// function at the same time -- they could both pick the same filename.
|
||||||
|
static FilePath GenerateUniqueFileName(const FilePath& directory,
|
||||||
|
const FilePath& base_name,
|
||||||
|
const char* extension);
|
||||||
|
|
||||||
|
// Returns true iff the path is NULL or "".
|
||||||
|
bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; }
|
||||||
|
|
||||||
|
// If input name has a trailing separator character, removes it and returns
|
||||||
|
// the name, otherwise return the name string unmodified.
|
||||||
|
// On Windows platform, uses \ as the separator, other platforms use /.
|
||||||
|
FilePath RemoveTrailingPathSeparator() const;
|
||||||
|
|
||||||
|
// Returns a copy of the FilePath with the directory part removed.
|
||||||
|
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
||||||
|
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
||||||
|
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
|
||||||
|
// returns an empty FilePath ("").
|
||||||
|
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||||
|
FilePath RemoveDirectoryName() const;
|
||||||
|
|
||||||
|
// RemoveFileName returns the directory path with the filename removed.
|
||||||
|
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
|
||||||
|
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
|
||||||
|
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
|
||||||
|
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
||||||
|
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||||
|
FilePath RemoveFileName() const;
|
||||||
|
|
||||||
|
// Returns a copy of the FilePath with the case-insensitive extension removed.
|
||||||
|
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
|
||||||
|
// FilePath("dir/file"). If a case-insensitive extension is not
|
||||||
|
// found, returns a copy of the original FilePath.
|
||||||
|
FilePath RemoveExtension(const char* extension) const;
|
||||||
|
|
||||||
|
// Creates directories so that path exists. Returns true if successful or if
|
||||||
|
// the directories already exist; returns false if unable to create
|
||||||
|
// directories for any reason. Will also return false if the FilePath does
|
||||||
|
// not represent a directory (that is, it doesn't end with a path separator).
|
||||||
|
bool CreateDirectoriesRecursively() const;
|
||||||
|
|
||||||
|
// Create the directory so that path exists. Returns true if successful or
|
||||||
|
// if the directory already exists; returns false if unable to create the
|
||||||
|
// directory for any reason, including if the parent directory does not
|
||||||
|
// exist. Not named "CreateDirectory" because that's a macro on Windows.
|
||||||
|
bool CreateFolder() const;
|
||||||
|
|
||||||
|
// Returns true if FilePath describes something in the file-system,
|
||||||
|
// either a file, directory, or whatever, and that something exists.
|
||||||
|
bool FileOrDirectoryExists() const;
|
||||||
|
|
||||||
|
// Returns true if pathname describes a directory in the file-system
|
||||||
|
// that exists.
|
||||||
|
bool DirectoryExists() const;
|
||||||
|
|
||||||
|
// Returns true if FilePath ends with a path separator, which indicates that
|
||||||
|
// it is intended to represent a directory. Returns false otherwise.
|
||||||
|
// This does NOT check that a directory (or file) actually exists.
|
||||||
|
bool IsDirectory() const;
|
||||||
|
|
||||||
|
// Returns true if pathname describes a root directory. (Windows has one
|
||||||
|
// root directory per disk drive.)
|
||||||
|
bool IsRootDirectory() const;
|
||||||
|
|
||||||
|
// Returns true if pathname describes an absolute path.
|
||||||
|
bool IsAbsolutePath() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Replaces multiple consecutive separators with a single separator.
|
||||||
|
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||||
|
// redundancies that might be in a pathname involving "." or "..".
|
||||||
|
//
|
||||||
|
// A pathname with multiple consecutive separators may occur either through
|
||||||
|
// user error or as a result of some scripts or APIs that generate a pathname
|
||||||
|
// with a trailing separator. On other platforms the same API or script
|
||||||
|
// may NOT generate a pathname with a trailing "/". Then elsewhere that
|
||||||
|
// pathname may have another "/" and pathname components added to it,
|
||||||
|
// without checking for the separator already being there.
|
||||||
|
// The script language and operating system may allow paths like "foo//bar"
|
||||||
|
// but some of the functions in FilePath will not handle that correctly. In
|
||||||
|
// particular, RemoveTrailingPathSeparator() only removes one separator, and
|
||||||
|
// it is called in CreateDirectoriesRecursively() assuming that it will change
|
||||||
|
// a pathname from directory syntax (trailing separator) to filename syntax.
|
||||||
|
//
|
||||||
|
// On Windows this method also replaces the alternate path separator '/' with
|
||||||
|
// the primary path separator '\\', so that for example "bar\\/\\foo" becomes
|
||||||
|
// "bar\\foo".
|
||||||
|
|
||||||
|
void Normalize();
|
||||||
|
|
||||||
|
// Returns a pointer to the last occurence of a valid path separator in
|
||||||
|
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||||
|
// separators. Returns NULL if no path separator was found.
|
||||||
|
const char* FindLastPathSeparator() const;
|
||||||
|
|
||||||
|
String pathname_;
|
||||||
|
}; // class FilePath
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
|
@ -0,0 +1,923 @@
|
||||||
|
// Copyright 2005, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
|
||||||
|
//
|
||||||
|
// The Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This header file declares functions and macros used internally by
|
||||||
|
// Google Test. They are subject to change without notice.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
|
||||||
|
#if GTEST_OS_LINUX
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif // GTEST_OS_LINUX
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <limits>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-string.h>
|
||||||
|
#include <gtest/internal/gtest-filepath.h>
|
||||||
|
#include <gtest/internal/gtest-type-util.h>
|
||||||
|
|
||||||
|
// Due to C++ preprocessor weirdness, we need double indirection to
|
||||||
|
// concatenate two tokens when one of them is __LINE__. Writing
|
||||||
|
//
|
||||||
|
// foo ## __LINE__
|
||||||
|
//
|
||||||
|
// will result in the token foo__LINE__, instead of foo followed by
|
||||||
|
// the current line number. For more details, see
|
||||||
|
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
|
||||||
|
#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
|
||||||
|
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
|
||||||
|
|
||||||
|
// Google Test defines the testing::Message class to allow construction of
|
||||||
|
// test messages via the << operator. The idea is that anything
|
||||||
|
// streamable to std::ostream can be streamed to a testing::Message.
|
||||||
|
// This allows a user to use his own types in Google Test assertions by
|
||||||
|
// overloading the << operator.
|
||||||
|
//
|
||||||
|
// util/gtl/stl_logging-inl.h overloads << for STL containers. These
|
||||||
|
// overloads cannot be defined in the std namespace, as that will be
|
||||||
|
// undefined behavior. Therefore, they are defined in the global
|
||||||
|
// namespace instead.
|
||||||
|
//
|
||||||
|
// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
|
||||||
|
// overloads are visible in either the std namespace or the global
|
||||||
|
// namespace, but not other namespaces, including the testing
|
||||||
|
// namespace which Google Test's Message class is in.
|
||||||
|
//
|
||||||
|
// To allow STL containers (and other types that has a << operator
|
||||||
|
// defined in the global namespace) to be used in Google Test assertions,
|
||||||
|
// testing::Message must access the custom << operator from the global
|
||||||
|
// namespace. Hence this helper function.
|
||||||
|
//
|
||||||
|
// Note: Jeffrey Yasskin suggested an alternative fix by "using
|
||||||
|
// ::operator<<;" in the definition of Message's operator<<. That fix
|
||||||
|
// doesn't require a helper function, but unfortunately doesn't
|
||||||
|
// compile with MSVC.
|
||||||
|
template <typename T>
|
||||||
|
inline void GTestStreamToHelper(std::ostream* os, const T& val) {
|
||||||
|
*os << val;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Forward declaration of classes.
|
||||||
|
|
||||||
|
class AssertionResult; // Result of an assertion.
|
||||||
|
class Message; // Represents a failure message.
|
||||||
|
class Test; // Represents a test.
|
||||||
|
class TestInfo; // Information about a test.
|
||||||
|
class TestPartResult; // Result of a test part.
|
||||||
|
class UnitTest; // A collection of test cases.
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
struct TraceInfo; // Information about a trace point.
|
||||||
|
class ScopedTrace; // Implements scoped trace.
|
||||||
|
class TestInfoImpl; // Opaque implementation of TestInfo
|
||||||
|
class UnitTestImpl; // Opaque implementation of UnitTest
|
||||||
|
|
||||||
|
// How many times InitGoogleTest() has been called.
|
||||||
|
extern int g_init_gtest_count;
|
||||||
|
|
||||||
|
// The text used in failure messages to indicate the start of the
|
||||||
|
// stack trace.
|
||||||
|
GTEST_API_ extern const char kStackTraceMarker[];
|
||||||
|
|
||||||
|
// A secret type that Google Test users don't know about. It has no
|
||||||
|
// definition on purpose. Therefore it's impossible to create a
|
||||||
|
// Secret object, which is what we want.
|
||||||
|
class Secret;
|
||||||
|
|
||||||
|
// Two overloaded helpers for checking at compile time whether an
|
||||||
|
// expression is a null pointer literal (i.e. NULL or any 0-valued
|
||||||
|
// compile-time integral constant). Their return values have
|
||||||
|
// different sizes, so we can use sizeof() to test which version is
|
||||||
|
// picked by the compiler. These helpers have no implementations, as
|
||||||
|
// we only need their signatures.
|
||||||
|
//
|
||||||
|
// Given IsNullLiteralHelper(x), the compiler will pick the first
|
||||||
|
// version if x can be implicitly converted to Secret*, and pick the
|
||||||
|
// second version otherwise. Since Secret is a secret and incomplete
|
||||||
|
// type, the only expression a user can write that has type Secret* is
|
||||||
|
// a null pointer literal. Therefore, we know that x is a null
|
||||||
|
// pointer literal if and only if the first version is picked by the
|
||||||
|
// compiler.
|
||||||
|
char IsNullLiteralHelper(Secret* p);
|
||||||
|
char (&IsNullLiteralHelper(...))[2]; // NOLINT
|
||||||
|
|
||||||
|
// A compile-time bool constant that is true if and only if x is a
|
||||||
|
// null pointer literal (i.e. NULL or any 0-valued compile-time
|
||||||
|
// integral constant).
|
||||||
|
#ifdef GTEST_ELLIPSIS_NEEDS_POD_
|
||||||
|
// We lose support for NULL detection where the compiler doesn't like
|
||||||
|
// passing non-POD classes through ellipsis (...).
|
||||||
|
#define GTEST_IS_NULL_LITERAL_(x) false
|
||||||
|
#else
|
||||||
|
#define GTEST_IS_NULL_LITERAL_(x) \
|
||||||
|
(sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
|
||||||
|
#endif // GTEST_ELLIPSIS_NEEDS_POD_
|
||||||
|
|
||||||
|
// Appends the user-supplied message to the Google-Test-generated message.
|
||||||
|
GTEST_API_ String AppendUserMessage(const String& gtest_msg,
|
||||||
|
const Message& user_msg);
|
||||||
|
|
||||||
|
// A helper class for creating scoped traces in user programs.
|
||||||
|
class GTEST_API_ ScopedTrace {
|
||||||
|
public:
|
||||||
|
// The c'tor pushes the given source file location and message onto
|
||||||
|
// a trace stack maintained by Google Test.
|
||||||
|
ScopedTrace(const char* file, int line, const Message& message);
|
||||||
|
|
||||||
|
// The d'tor pops the info pushed by the c'tor.
|
||||||
|
//
|
||||||
|
// Note that the d'tor is not virtual in order to be efficient.
|
||||||
|
// Don't inherit from ScopedTrace!
|
||||||
|
~ScopedTrace();
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
|
||||||
|
} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its
|
||||||
|
// c'tor and d'tor. Therefore it doesn't
|
||||||
|
// need to be used otherwise.
|
||||||
|
|
||||||
|
// Converts a streamable value to a String. A NULL pointer is
|
||||||
|
// converted to "(null)". When the input value is a ::string,
|
||||||
|
// ::std::string, ::wstring, or ::std::wstring object, each NUL
|
||||||
|
// character in it is replaced with "\\0".
|
||||||
|
// Declared here but defined in gtest.h, so that it has access
|
||||||
|
// to the definition of the Message class, required by the ARM
|
||||||
|
// compiler.
|
||||||
|
template <typename T>
|
||||||
|
String StreamableToString(const T& streamable);
|
||||||
|
|
||||||
|
// Formats a value to be used in a failure message.
|
||||||
|
|
||||||
|
#ifdef GTEST_NEEDS_IS_POINTER_
|
||||||
|
|
||||||
|
// These are needed as the Nokia Symbian and IBM XL C/C++ compilers
|
||||||
|
// cannot decide between const T& and const T* in a function template.
|
||||||
|
// These compilers _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.
|
||||||
|
|
||||||
|
// This overload makes sure that all pointers (including
|
||||||
|
// those to char or wchar_t) are printed as raw pointers.
|
||||||
|
template <typename T>
|
||||||
|
inline String FormatValueForFailureMessage(internal::true_type /*dummy*/,
|
||||||
|
T* pointer) {
|
||||||
|
return StreamableToString(static_cast<const void*>(pointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline String FormatValueForFailureMessage(internal::false_type /*dummy*/,
|
||||||
|
const T& value) {
|
||||||
|
return StreamableToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline String FormatForFailureMessage(const T& value) {
|
||||||
|
return FormatValueForFailureMessage(
|
||||||
|
typename internal::is_pointer<T>::type(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// These are needed as the above solution using is_pointer has the
|
||||||
|
// limitation that T cannot be a type without external linkage, when
|
||||||
|
// compiled using MSVC.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline String FormatForFailureMessage(const T& value) {
|
||||||
|
return StreamableToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This overload makes sure that all pointers (including
|
||||||
|
// those to char or wchar_t) are printed as raw pointers.
|
||||||
|
template <typename T>
|
||||||
|
inline String FormatForFailureMessage(T* pointer) {
|
||||||
|
return StreamableToString(static_cast<const void*>(pointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GTEST_NEEDS_IS_POINTER_
|
||||||
|
|
||||||
|
// These overloaded versions handle narrow and wide characters.
|
||||||
|
GTEST_API_ String FormatForFailureMessage(char ch);
|
||||||
|
GTEST_API_ String FormatForFailureMessage(wchar_t wchar);
|
||||||
|
|
||||||
|
// When this operand is a const char* or char*, and the other operand
|
||||||
|
// is a ::std::string or ::string, we print this operand as a C string
|
||||||
|
// rather than a pointer. We do the same for wide strings.
|
||||||
|
|
||||||
|
// This internal macro is used to avoid duplicated code.
|
||||||
|
#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\
|
||||||
|
inline String FormatForComparisonFailureMessage(\
|
||||||
|
operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
|
||||||
|
return operand1_printer(str);\
|
||||||
|
}\
|
||||||
|
inline String FormatForComparisonFailureMessage(\
|
||||||
|
const operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
|
||||||
|
return operand1_printer(str);\
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted)
|
||||||
|
#if GTEST_HAS_STD_WSTRING
|
||||||
|
GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted)
|
||||||
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
GTEST_FORMAT_IMPL_(::string, String::ShowCStringQuoted)
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
#if GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted)
|
||||||
|
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
|
||||||
|
#undef GTEST_FORMAT_IMPL_
|
||||||
|
|
||||||
|
// Constructs and returns the message for an equality assertion
|
||||||
|
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
|
||||||
|
//
|
||||||
|
// The first four parameters are the expressions used in the assertion
|
||||||
|
// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
|
||||||
|
// where foo is 5 and bar is 6, we have:
|
||||||
|
//
|
||||||
|
// expected_expression: "foo"
|
||||||
|
// actual_expression: "bar"
|
||||||
|
// expected_value: "5"
|
||||||
|
// actual_value: "6"
|
||||||
|
//
|
||||||
|
// The ignoring_case parameter is true iff the assertion is a
|
||||||
|
// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
|
||||||
|
// be inserted into the message.
|
||||||
|
GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
|
||||||
|
const char* actual_expression,
|
||||||
|
const String& expected_value,
|
||||||
|
const String& actual_value,
|
||||||
|
bool ignoring_case);
|
||||||
|
|
||||||
|
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
|
||||||
|
GTEST_API_ String GetBoolAssertionFailureMessage(
|
||||||
|
const AssertionResult& assertion_result,
|
||||||
|
const char* expression_text,
|
||||||
|
const char* actual_predicate_value,
|
||||||
|
const char* expected_predicate_value);
|
||||||
|
|
||||||
|
// This template class represents an IEEE floating-point number
|
||||||
|
// (either single-precision or double-precision, depending on the
|
||||||
|
// template parameters).
|
||||||
|
//
|
||||||
|
// The purpose of this class is to do more sophisticated number
|
||||||
|
// comparison. (Due to round-off error, etc, it's very unlikely that
|
||||||
|
// two floating-points will be equal exactly. Hence a naive
|
||||||
|
// comparison by the == operation often doesn't work.)
|
||||||
|
//
|
||||||
|
// Format of IEEE floating-point:
|
||||||
|
//
|
||||||
|
// The most-significant bit being the leftmost, an IEEE
|
||||||
|
// floating-point looks like
|
||||||
|
//
|
||||||
|
// sign_bit exponent_bits fraction_bits
|
||||||
|
//
|
||||||
|
// Here, sign_bit is a single bit that designates the sign of the
|
||||||
|
// number.
|
||||||
|
//
|
||||||
|
// For float, there are 8 exponent bits and 23 fraction bits.
|
||||||
|
//
|
||||||
|
// For double, there are 11 exponent bits and 52 fraction bits.
|
||||||
|
//
|
||||||
|
// More details can be found at
|
||||||
|
// http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
|
||||||
|
//
|
||||||
|
// Template parameter:
|
||||||
|
//
|
||||||
|
// RawType: the raw floating-point type (either float or double)
|
||||||
|
template <typename RawType>
|
||||||
|
class FloatingPoint {
|
||||||
|
public:
|
||||||
|
// Defines the unsigned integer type that has the same size as the
|
||||||
|
// floating point number.
|
||||||
|
typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
|
||||||
|
|
||||||
|
// Constants.
|
||||||
|
|
||||||
|
// # of bits in a number.
|
||||||
|
static const size_t kBitCount = 8*sizeof(RawType);
|
||||||
|
|
||||||
|
// # of fraction bits in a number.
|
||||||
|
static const size_t kFractionBitCount =
|
||||||
|
std::numeric_limits<RawType>::digits - 1;
|
||||||
|
|
||||||
|
// # of exponent bits in a number.
|
||||||
|
static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
|
||||||
|
|
||||||
|
// The mask for the sign bit.
|
||||||
|
static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
|
||||||
|
|
||||||
|
// The mask for the fraction bits.
|
||||||
|
static const Bits kFractionBitMask =
|
||||||
|
~static_cast<Bits>(0) >> (kExponentBitCount + 1);
|
||||||
|
|
||||||
|
// The mask for the exponent bits.
|
||||||
|
static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
|
||||||
|
|
||||||
|
// How many ULP's (Units in the Last Place) we want to tolerate when
|
||||||
|
// comparing two numbers. The larger the value, the more error we
|
||||||
|
// allow. A 0 value means that two numbers must be exactly the same
|
||||||
|
// to be considered equal.
|
||||||
|
//
|
||||||
|
// The maximum error of a single floating-point operation is 0.5
|
||||||
|
// units in the last place. On Intel CPU's, all floating-point
|
||||||
|
// calculations are done with 80-bit precision, while double has 64
|
||||||
|
// bits. Therefore, 4 should be enough for ordinary use.
|
||||||
|
//
|
||||||
|
// See the following article for more details on ULP:
|
||||||
|
// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.
|
||||||
|
static const size_t kMaxUlps = 4;
|
||||||
|
|
||||||
|
// Constructs a FloatingPoint from a raw floating-point number.
|
||||||
|
//
|
||||||
|
// On an Intel CPU, passing a non-normalized NAN (Not a Number)
|
||||||
|
// around may change its bits, although the new value is guaranteed
|
||||||
|
// to be also a NAN. Therefore, don't expect this constructor to
|
||||||
|
// preserve the bits in x when x is a NAN.
|
||||||
|
explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
|
||||||
|
|
||||||
|
// Static methods
|
||||||
|
|
||||||
|
// Reinterprets a bit pattern as a floating-point number.
|
||||||
|
//
|
||||||
|
// This function is needed to test the AlmostEquals() method.
|
||||||
|
static RawType ReinterpretBits(const Bits bits) {
|
||||||
|
FloatingPoint fp(0);
|
||||||
|
fp.u_.bits_ = bits;
|
||||||
|
return fp.u_.value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the floating-point number that represent positive infinity.
|
||||||
|
static RawType Infinity() {
|
||||||
|
return ReinterpretBits(kExponentBitMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-static methods
|
||||||
|
|
||||||
|
// Returns the bits that represents this number.
|
||||||
|
const Bits &bits() const { return u_.bits_; }
|
||||||
|
|
||||||
|
// Returns the exponent bits of this number.
|
||||||
|
Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
|
||||||
|
|
||||||
|
// Returns the fraction bits of this number.
|
||||||
|
Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
|
||||||
|
|
||||||
|
// Returns the sign bit of this number.
|
||||||
|
Bits sign_bit() const { return kSignBitMask & u_.bits_; }
|
||||||
|
|
||||||
|
// Returns true iff this is NAN (not a number).
|
||||||
|
bool is_nan() const {
|
||||||
|
// It's a NAN if the exponent bits are all ones and the fraction
|
||||||
|
// bits are not entirely zeros.
|
||||||
|
return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff this number is at most kMaxUlps ULP's away from
|
||||||
|
// rhs. In particular, this function:
|
||||||
|
//
|
||||||
|
// - returns false if either number is (or both are) NAN.
|
||||||
|
// - treats really large numbers as almost equal to infinity.
|
||||||
|
// - thinks +0.0 and -0.0 are 0 DLP's apart.
|
||||||
|
bool AlmostEquals(const FloatingPoint& rhs) const {
|
||||||
|
// The IEEE standard says that any comparison operation involving
|
||||||
|
// a NAN must return false.
|
||||||
|
if (is_nan() || rhs.is_nan()) return false;
|
||||||
|
|
||||||
|
return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
|
||||||
|
<= kMaxUlps;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The data type used to store the actual floating-point number.
|
||||||
|
union FloatingPointUnion {
|
||||||
|
RawType value_; // The raw floating-point number.
|
||||||
|
Bits bits_; // The bits that represent the number.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Converts an integer from the sign-and-magnitude representation to
|
||||||
|
// the biased representation. More precisely, let N be 2 to the
|
||||||
|
// power of (kBitCount - 1), an integer x is represented by the
|
||||||
|
// unsigned number x + N.
|
||||||
|
//
|
||||||
|
// For instance,
|
||||||
|
//
|
||||||
|
// -N + 1 (the most negative number representable using
|
||||||
|
// sign-and-magnitude) is represented by 1;
|
||||||
|
// 0 is represented by N; and
|
||||||
|
// N - 1 (the biggest number representable using
|
||||||
|
// sign-and-magnitude) is represented by 2N - 1.
|
||||||
|
//
|
||||||
|
// Read http://en.wikipedia.org/wiki/Signed_number_representations
|
||||||
|
// for more details on signed number representations.
|
||||||
|
static Bits SignAndMagnitudeToBiased(const Bits &sam) {
|
||||||
|
if (kSignBitMask & sam) {
|
||||||
|
// sam represents a negative number.
|
||||||
|
return ~sam + 1;
|
||||||
|
} else {
|
||||||
|
// sam represents a positive number.
|
||||||
|
return kSignBitMask | sam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given two numbers in the sign-and-magnitude representation,
|
||||||
|
// returns the distance between them as an unsigned number.
|
||||||
|
static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
|
||||||
|
const Bits &sam2) {
|
||||||
|
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
|
||||||
|
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
|
||||||
|
return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FloatingPointUnion u_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typedefs the instances of the FloatingPoint template class that we
|
||||||
|
// care to use.
|
||||||
|
typedef FloatingPoint<float> Float;
|
||||||
|
typedef FloatingPoint<double> Double;
|
||||||
|
|
||||||
|
// In order to catch the mistake of putting tests that use different
|
||||||
|
// test fixture classes in the same test case, we need to assign
|
||||||
|
// unique IDs to fixture classes and compare them. The TypeId type is
|
||||||
|
// used to hold such IDs. The user should treat TypeId as an opaque
|
||||||
|
// type: the only operation allowed on TypeId values is to compare
|
||||||
|
// them for equality using the == operator.
|
||||||
|
typedef const void* TypeId;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class TypeIdHelper {
|
||||||
|
public:
|
||||||
|
// dummy_ must not have a const type. Otherwise an overly eager
|
||||||
|
// compiler (e.g. MSVC 7.1 & 8.0) may try to merge
|
||||||
|
// TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
|
||||||
|
static bool dummy_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool TypeIdHelper<T>::dummy_ = false;
|
||||||
|
|
||||||
|
// GetTypeId<T>() returns the ID of type T. Different values will be
|
||||||
|
// returned for different types. Calling the function twice with the
|
||||||
|
// same type argument is guaranteed to return the same ID.
|
||||||
|
template <typename T>
|
||||||
|
TypeId GetTypeId() {
|
||||||
|
// The compiler is required to allocate a different
|
||||||
|
// TypeIdHelper<T>::dummy_ variable for each T used to instantiate
|
||||||
|
// the template. Therefore, the address of dummy_ is guaranteed to
|
||||||
|
// be unique.
|
||||||
|
return &(TypeIdHelper<T>::dummy_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the type ID of ::testing::Test. Always call this instead
|
||||||
|
// of GetTypeId< ::testing::Test>() to get the type ID of
|
||||||
|
// ::testing::Test, as the latter may give the wrong result due to a
|
||||||
|
// suspected linker bug when compiling Google Test as a Mac OS X
|
||||||
|
// framework.
|
||||||
|
GTEST_API_ TypeId GetTestTypeId();
|
||||||
|
|
||||||
|
// Defines the abstract factory interface that creates instances
|
||||||
|
// of a Test object.
|
||||||
|
class TestFactoryBase {
|
||||||
|
public:
|
||||||
|
virtual ~TestFactoryBase() {}
|
||||||
|
|
||||||
|
// Creates a test instance to run. The instance is both created and destroyed
|
||||||
|
// within TestInfoImpl::Run()
|
||||||
|
virtual Test* CreateTest() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TestFactoryBase() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class provides implementation of TeastFactoryBase interface.
|
||||||
|
// It is used in TEST and TEST_F macros.
|
||||||
|
template <class TestClass>
|
||||||
|
class TestFactoryImpl : public TestFactoryBase {
|
||||||
|
public:
|
||||||
|
virtual Test* CreateTest() { return new TestClass; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS
|
||||||
|
|
||||||
|
// Predicate-formatters for implementing the HRESULT checking macros
|
||||||
|
// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
|
||||||
|
// We pass a long instead of HRESULT to avoid causing an
|
||||||
|
// include dependency for the HRESULT type.
|
||||||
|
GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
|
||||||
|
long hr); // NOLINT
|
||||||
|
GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
|
||||||
|
long hr); // NOLINT
|
||||||
|
|
||||||
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
|
// Formats a source file path and a line number as they would appear
|
||||||
|
// in a compiler error message.
|
||||||
|
inline String FormatFileLocation(const char* file, int line) {
|
||||||
|
const char* const file_name = file == NULL ? "unknown file" : file;
|
||||||
|
if (line < 0) {
|
||||||
|
return String::Format("%s:", file_name);
|
||||||
|
}
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return String::Format("%s(%d):", file_name, line);
|
||||||
|
#else
|
||||||
|
return String::Format("%s:%d:", file_name, line);
|
||||||
|
#endif // _MSC_VER
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types of SetUpTestCase() and TearDownTestCase() functions.
|
||||||
|
typedef void (*SetUpTestCaseFunc)();
|
||||||
|
typedef void (*TearDownTestCaseFunc)();
|
||||||
|
|
||||||
|
// Creates a new TestInfo object and registers it with Google Test;
|
||||||
|
// returns the created object.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
//
|
||||||
|
// test_case_name: name of the test case
|
||||||
|
// name: name of the test
|
||||||
|
// test_case_comment: a comment on the test case that will be included in
|
||||||
|
// the test output
|
||||||
|
// comment: a comment on the test that will be included in the
|
||||||
|
// test output
|
||||||
|
// fixture_class_id: ID of the test fixture class
|
||||||
|
// 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
|
||||||
|
// factory: pointer to the factory that creates a test object.
|
||||||
|
// The newly created TestInfo instance will assume
|
||||||
|
// ownership of the factory object.
|
||||||
|
GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
|
||||||
|
const char* test_case_name, const char* name,
|
||||||
|
const char* test_case_comment, const char* comment,
|
||||||
|
TypeId fixture_class_id,
|
||||||
|
SetUpTestCaseFunc set_up_tc,
|
||||||
|
TearDownTestCaseFunc tear_down_tc,
|
||||||
|
TestFactoryBase* factory);
|
||||||
|
|
||||||
|
// If *pstr starts with the given prefix, modifies *pstr to be right
|
||||||
|
// past the prefix and returns true; otherwise leaves *pstr unchanged
|
||||||
|
// and returns false. None of pstr, *pstr, and prefix can be NULL.
|
||||||
|
bool SkipPrefix(const char* prefix, const char** pstr);
|
||||||
|
|
||||||
|
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
// State of the definition of a type-parameterized test case.
|
||||||
|
class GTEST_API_ TypedTestCasePState {
|
||||||
|
public:
|
||||||
|
TypedTestCasePState() : registered_(false) {}
|
||||||
|
|
||||||
|
// Adds the given test name to defined_test_names_ and return true
|
||||||
|
// if the test case hasn't been registered; otherwise aborts the
|
||||||
|
// program.
|
||||||
|
bool AddTestName(const char* file, int line, const char* case_name,
|
||||||
|
const char* test_name) {
|
||||||
|
if (registered_) {
|
||||||
|
fprintf(stderr, "%s Test %s must be defined before "
|
||||||
|
"REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
|
||||||
|
FormatFileLocation(file, line).c_str(), test_name, case_name);
|
||||||
|
fflush(stderr);
|
||||||
|
posix::Abort();
|
||||||
|
}
|
||||||
|
defined_test_names_.insert(test_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies that registered_tests match the test names in
|
||||||
|
// defined_test_names_; returns registered_tests if successful, or
|
||||||
|
// aborts the program otherwise.
|
||||||
|
const char* VerifyRegisteredTestNames(
|
||||||
|
const char* file, int line, const char* registered_tests);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool registered_;
|
||||||
|
::std::set<const char*> defined_test_names_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Skips to the first non-space char after the first comma in 'str';
|
||||||
|
// returns NULL if no comma is found in 'str'.
|
||||||
|
inline const char* SkipComma(const char* str) {
|
||||||
|
const char* comma = strchr(str, ',');
|
||||||
|
if (comma == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
while (isspace(*(++comma))) {}
|
||||||
|
return comma;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the prefix of 'str' before the first comma in it; returns
|
||||||
|
// the entire string if it contains no comma.
|
||||||
|
inline String GetPrefixUntilComma(const char* str) {
|
||||||
|
const char* comma = strchr(str, ',');
|
||||||
|
return comma == NULL ? String(str) : String(str, comma - str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
|
||||||
|
// registers a list of type-parameterized tests with Google Test. The
|
||||||
|
// return value is insignificant - we just need to return something
|
||||||
|
// such that we can call this function in a namespace scope.
|
||||||
|
//
|
||||||
|
// Implementation note: The GTEST_TEMPLATE_ macro declares a template
|
||||||
|
// template parameter. It's defined in gtest-type-util.h.
|
||||||
|
template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
|
||||||
|
class TypeParameterizedTest {
|
||||||
|
public:
|
||||||
|
// 'index' is the index of the test in the type list 'Types'
|
||||||
|
// specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
|
||||||
|
// Types). Valid values for 'index' are [0, N - 1] where N is the
|
||||||
|
// length of Types.
|
||||||
|
static bool Register(const char* prefix, const char* case_name,
|
||||||
|
const char* test_names, int index) {
|
||||||
|
typedef typename Types::Head Type;
|
||||||
|
typedef Fixture<Type> FixtureClass;
|
||||||
|
typedef typename GTEST_BIND_(TestSel, Type) TestClass;
|
||||||
|
|
||||||
|
// First, registers the first type-parameterized test in the type
|
||||||
|
// list.
|
||||||
|
MakeAndRegisterTestInfo(
|
||||||
|
String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/",
|
||||||
|
case_name, index).c_str(),
|
||||||
|
GetPrefixUntilComma(test_names).c_str(),
|
||||||
|
String::Format("TypeParam = %s", GetTypeName<Type>().c_str()).c_str(),
|
||||||
|
"",
|
||||||
|
GetTypeId<FixtureClass>(),
|
||||||
|
TestClass::SetUpTestCase,
|
||||||
|
TestClass::TearDownTestCase,
|
||||||
|
new TestFactoryImpl<TestClass>);
|
||||||
|
|
||||||
|
// Next, recurses (at compile time) with the tail of the type list.
|
||||||
|
return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
|
||||||
|
::Register(prefix, case_name, test_names, index + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The base case for the compile time recursion.
|
||||||
|
template <GTEST_TEMPLATE_ Fixture, class TestSel>
|
||||||
|
class TypeParameterizedTest<Fixture, TestSel, Types0> {
|
||||||
|
public:
|
||||||
|
static bool Register(const char* /*prefix*/, const char* /*case_name*/,
|
||||||
|
const char* /*test_names*/, int /*index*/) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
|
||||||
|
// registers *all combinations* of 'Tests' and 'Types' with Google
|
||||||
|
// Test. The return value is insignificant - we just need to return
|
||||||
|
// something such that we can call this function in a namespace scope.
|
||||||
|
template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
|
||||||
|
class TypeParameterizedTestCase {
|
||||||
|
public:
|
||||||
|
static bool Register(const char* prefix, const char* case_name,
|
||||||
|
const char* test_names) {
|
||||||
|
typedef typename Tests::Head Head;
|
||||||
|
|
||||||
|
// First, register the first test in 'Test' for each type in 'Types'.
|
||||||
|
TypeParameterizedTest<Fixture, Head, Types>::Register(
|
||||||
|
prefix, case_name, test_names, 0);
|
||||||
|
|
||||||
|
// Next, recurses (at compile time) with the tail of the test list.
|
||||||
|
return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
|
||||||
|
::Register(prefix, case_name, SkipComma(test_names));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The base case for the compile time recursion.
|
||||||
|
template <GTEST_TEMPLATE_ Fixture, typename Types>
|
||||||
|
class TypeParameterizedTestCase<Fixture, Templates0, Types> {
|
||||||
|
public:
|
||||||
|
static bool Register(const char* /*prefix*/, const char* /*case_name*/,
|
||||||
|
const char* /*test_names*/) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
// Returns the current OS stack trace as a String.
|
||||||
|
//
|
||||||
|
// The maximum number of stack frames to be included is specified by
|
||||||
|
// the gtest_stack_trace_depth flag. The skip_count parameter
|
||||||
|
// specifies the number of top frames to be skipped, which doesn't
|
||||||
|
// count against the number of frames to be included.
|
||||||
|
//
|
||||||
|
// For example, if Foo() calls Bar(), which in turn calls
|
||||||
|
// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
|
||||||
|
// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
|
||||||
|
GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test,
|
||||||
|
int skip_count);
|
||||||
|
|
||||||
|
// Helpers for suppressing warnings on unreachable code or constant
|
||||||
|
// condition.
|
||||||
|
|
||||||
|
// Always returns true.
|
||||||
|
GTEST_API_ bool AlwaysTrue();
|
||||||
|
|
||||||
|
// Always returns false.
|
||||||
|
inline bool AlwaysFalse() { return !AlwaysTrue(); }
|
||||||
|
|
||||||
|
// A simple Linear Congruential Generator for generating random
|
||||||
|
// numbers with a uniform distribution. Unlike rand() and srand(), it
|
||||||
|
// doesn't use global state (and therefore can't interfere with user
|
||||||
|
// code). Unlike rand_r(), it's portable. An LCG isn't very random,
|
||||||
|
// but it's good enough for our purposes.
|
||||||
|
class GTEST_API_ Random {
|
||||||
|
public:
|
||||||
|
static const UInt32 kMaxRange = 1u << 31;
|
||||||
|
|
||||||
|
explicit Random(UInt32 seed) : state_(seed) {}
|
||||||
|
|
||||||
|
void Reseed(UInt32 seed) { state_ = seed; }
|
||||||
|
|
||||||
|
// Generates a random number from [0, range). Crashes if 'range' is
|
||||||
|
// 0 or greater than kMaxRange.
|
||||||
|
UInt32 Generate(UInt32 range);
|
||||||
|
|
||||||
|
private:
|
||||||
|
UInt32 state_;
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#define GTEST_MESSAGE_(message, result_type) \
|
||||||
|
::testing::internal::AssertHelper(result_type, __FILE__, __LINE__, message) \
|
||||||
|
= ::testing::Message()
|
||||||
|
|
||||||
|
#define GTEST_FATAL_FAILURE_(message) \
|
||||||
|
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
|
||||||
|
|
||||||
|
#define GTEST_NONFATAL_FAILURE_(message) \
|
||||||
|
GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
|
||||||
|
|
||||||
|
#define GTEST_SUCCESS_(message) \
|
||||||
|
GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
|
||||||
|
|
||||||
|
// Suppresses MSVC warnings 4072 (unreachable code) for the code following
|
||||||
|
// statement if it returns or throws (or doesn't return or throw in some
|
||||||
|
// situations).
|
||||||
|
#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
|
||||||
|
if (::testing::internal::AlwaysTrue()) { statement; }
|
||||||
|
|
||||||
|
#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
|
||||||
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
if (const char* gtest_msg = "") { \
|
||||||
|
bool gtest_caught_expected = false; \
|
||||||
|
try { \
|
||||||
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
|
} \
|
||||||
|
catch (expected_exception const&) { \
|
||||||
|
gtest_caught_expected = true; \
|
||||||
|
} \
|
||||||
|
catch (...) { \
|
||||||
|
gtest_msg = "Expected: " #statement " throws an exception of type " \
|
||||||
|
#expected_exception ".\n Actual: it throws a different " \
|
||||||
|
"type."; \
|
||||||
|
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
|
||||||
|
} \
|
||||||
|
if (!gtest_caught_expected) { \
|
||||||
|
gtest_msg = "Expected: " #statement " throws an exception of type " \
|
||||||
|
#expected_exception ".\n Actual: it throws nothing."; \
|
||||||
|
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
|
||||||
|
} \
|
||||||
|
} else \
|
||||||
|
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
|
||||||
|
fail(gtest_msg)
|
||||||
|
|
||||||
|
#define GTEST_TEST_NO_THROW_(statement, fail) \
|
||||||
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
if (const char* gtest_msg = "") { \
|
||||||
|
try { \
|
||||||
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
|
} \
|
||||||
|
catch (...) { \
|
||||||
|
gtest_msg = "Expected: " #statement " doesn't throw an exception.\n" \
|
||||||
|
" Actual: it throws."; \
|
||||||
|
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
|
||||||
|
} \
|
||||||
|
} else \
|
||||||
|
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
|
||||||
|
fail(gtest_msg)
|
||||||
|
|
||||||
|
#define GTEST_TEST_ANY_THROW_(statement, fail) \
|
||||||
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
if (const char* gtest_msg = "") { \
|
||||||
|
bool gtest_caught_any = false; \
|
||||||
|
try { \
|
||||||
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
|
} \
|
||||||
|
catch (...) { \
|
||||||
|
gtest_caught_any = true; \
|
||||||
|
} \
|
||||||
|
if (!gtest_caught_any) { \
|
||||||
|
gtest_msg = "Expected: " #statement " throws an exception.\n" \
|
||||||
|
" Actual: it doesn't."; \
|
||||||
|
goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
|
||||||
|
} \
|
||||||
|
} else \
|
||||||
|
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
|
||||||
|
fail(gtest_msg)
|
||||||
|
|
||||||
|
|
||||||
|
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
|
||||||
|
// either a boolean expression or an AssertionResult. text is a textual
|
||||||
|
// represenation of expression as it was passed into the EXPECT_TRUE.
|
||||||
|
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
|
||||||
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
if (const ::testing::AssertionResult gtest_ar_ = \
|
||||||
|
::testing::AssertionResult(expression)) \
|
||||||
|
; \
|
||||||
|
else \
|
||||||
|
fail(::testing::internal::GetBoolAssertionFailureMessage(\
|
||||||
|
gtest_ar_, text, #actual, #expected).c_str())
|
||||||
|
|
||||||
|
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
|
||||||
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
if (const char* gtest_msg = "") { \
|
||||||
|
::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
|
||||||
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
|
if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
|
||||||
|
gtest_msg = "Expected: " #statement " doesn't generate new fatal " \
|
||||||
|
"failures in the current thread.\n" \
|
||||||
|
" Actual: it does."; \
|
||||||
|
goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
|
||||||
|
} \
|
||||||
|
} else \
|
||||||
|
GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
|
||||||
|
fail(gtest_msg)
|
||||||
|
|
||||||
|
// Expands to the name of the class that implements the given test.
|
||||||
|
#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
|
||||||
|
test_case_name##_##test_name##_Test
|
||||||
|
|
||||||
|
// Helper macro for defining tests.
|
||||||
|
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
|
||||||
|
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
|
||||||
|
public:\
|
||||||
|
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
|
||||||
|
private:\
|
||||||
|
virtual void TestBody();\
|
||||||
|
static ::testing::TestInfo* const test_info_;\
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
|
||||||
|
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
|
||||||
|
};\
|
||||||
|
\
|
||||||
|
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
|
||||||
|
::test_info_ =\
|
||||||
|
::testing::internal::MakeAndRegisterTestInfo(\
|
||||||
|
#test_case_name, #test_name, "", "", \
|
||||||
|
(parent_id), \
|
||||||
|
parent_class::SetUpTestCase, \
|
||||||
|
parent_class::TearDownTestCase, \
|
||||||
|
new ::testing::internal::TestFactoryImpl<\
|
||||||
|
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
|
||||||
|
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
|
@ -0,0 +1,242 @@
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Authors: Dan Egnor (egnor@google.com)
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
|
||||||
|
// confusion with normal linked_ptr.
|
||||||
|
|
||||||
|
#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.
|
||||||
|
// L < g_linked_ptr_mutex
|
||||||
|
void join(linked_ptr_internal const* ptr) {
|
||||||
|
MutexLock lock(&g_linked_ptr_mutex);
|
||||||
|
|
||||||
|
linked_ptr_internal const* p = ptr;
|
||||||
|
while (p->next_ != ptr) 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.
|
||||||
|
// L < g_linked_ptr_mutex
|
||||||
|
bool depart() {
|
||||||
|
MutexLock lock(&g_linked_ptr_mutex);
|
||||||
|
|
||||||
|
if (next_ == this) return true;
|
||||||
|
linked_ptr_internal const* p = next_;
|
||||||
|
while (p->next_ != this) 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_; }
|
||||||
|
// Release ownership of the pointed object and returns it.
|
||||||
|
// Sole ownership by this linked_ptr object is required.
|
||||||
|
T* release() {
|
||||||
|
bool last = link_.depart();
|
||||||
|
assert(last);
|
||||||
|
T* v = value_;
|
||||||
|
value_ = NULL;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(T* p) const { return value_ == p; }
|
||||||
|
bool operator!=(T* p) const { return value_ != p; }
|
||||||
|
template <typename U>
|
||||||
|
bool operator==(linked_ptr<U> const& ptr) const {
|
||||||
|
return value_ == ptr.get();
|
||||||
|
}
|
||||||
|
template <typename U>
|
||||||
|
bool operator!=(linked_ptr<U> const& ptr) const {
|
||||||
|
return value_ != ptr.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename U>
|
||||||
|
friend class linked_ptr;
|
||||||
|
|
||||||
|
T* value_;
|
||||||
|
linked_ptr_internal link_;
|
||||||
|
|
||||||
|
void depart() {
|
||||||
|
if (link_.depart()) delete value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void capture(T* ptr) {
|
||||||
|
value_ = ptr;
|
||||||
|
link_.join_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U> void copy(linked_ptr<U> const* ptr) {
|
||||||
|
value_ = ptr->get();
|
||||||
|
if (value_)
|
||||||
|
link_.join(&ptr->link_);
|
||||||
|
else
|
||||||
|
link_.join_new();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> inline
|
||||||
|
bool operator==(T* ptr, const linked_ptr<T>& x) {
|
||||||
|
return ptr == x.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> inline
|
||||||
|
bool operator!=(T* ptr, const linked_ptr<T>& x) {
|
||||||
|
return ptr != x.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// A function to convert T* into linked_ptr<T>
|
||||||
|
// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
|
||||||
|
// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
|
||||||
|
template <typename T>
|
||||||
|
linked_ptr<T> make_linked_ptr(T* ptr) {
|
||||||
|
return linked_ptr<T>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
File diff suppressed because it is too large
Load Diff
301
3rdparty/gmock/gtest/include/gtest/internal/gtest-param-util-generated.h.pump
vendored
Normal file
301
3rdparty/gmock/gtest/include/gtest/internal/gtest-param-util-generated.h.pump
vendored
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
$$ -*- 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.
|
||||||
|
//
|
||||||
|
// Author: vladl@google.com (Vlad Losev)
|
||||||
|
|
||||||
|
// 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 tr1::tuple which is
|
||||||
|
// currently set at $maxtuple.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||||
|
|
||||||
|
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||||
|
// *unconditionally*. Therefore these #includes cannot be moved
|
||||||
|
// inside #if GTEST_HAS_PARAM_TEST.
|
||||||
|
#include <gtest/internal/gtest-param-util.h>
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
|
||||||
|
#if GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Forward declarations of ValuesIn(), which is implemented in
|
||||||
|
// include/gtest/gtest-param-test.h.
|
||||||
|
template <typename ForwardIterator>
|
||||||
|
internal::ParamGenerator<
|
||||||
|
typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
|
||||||
|
ForwardIterator begin, ForwardIterator end);
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
|
||||||
|
|
||||||
|
template <class Container>
|
||||||
|
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
||||||
|
const Container& container);
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Used in the Values() function to provide polymorphic capabilities.
|
||||||
|
template <typename T1>
|
||||||
|
class ValueArray1 {
|
||||||
|
public:
|
||||||
|
explicit ValueArray1(T1 v1) : v1_(v1) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// No implementation - assignment is unsupported.
|
||||||
|
void operator=(const ValueArray1& other);
|
||||||
|
|
||||||
|
const T1 v1_;
|
||||||
|
};
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
|
||||||
|
template <$for j, [[typename T$j]]>
|
||||||
|
class ValueArray$i {
|
||||||
|
public:
|
||||||
|
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, [[v$(j)_]]};
|
||||||
|
return ValuesIn(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
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< ::std::tr1::tuple<$for j, [[T$j]]> > {
|
||||||
|
public:
|
||||||
|
typedef ::std::tr1::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 ¤t_value_; }
|
||||||
|
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_ = 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)_;
|
||||||
|
]]
|
||||||
|
|
||||||
|
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< ::std::tr1::tuple<$for j, [[T$j]]> >() const {
|
||||||
|
return ParamGenerator< ::std::tr1::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_HAS_PARAM_TEST
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
|
@ -0,0 +1,619 @@
|
||||||
|
// Copyright 2008 Google Inc.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: vladl@google.com (Vlad Losev)
|
||||||
|
|
||||||
|
// Type and function utilities for implementing parameterized tests.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||||
|
// *unconditionally*. Therefore these #includes cannot be moved
|
||||||
|
// inside #if GTEST_HAS_PARAM_TEST.
|
||||||
|
#include <gtest/internal/gtest-internal.h>
|
||||||
|
#include <gtest/internal/gtest-linked_ptr.h>
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
|
||||||
|
#if GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
//
|
||||||
|
// Outputs a message explaining invalid registration of different
|
||||||
|
// fixture class for the same test case. This may happen when
|
||||||
|
// TEST_P macro is used to define two tests with the same name
|
||||||
|
// but in different namespaces.
|
||||||
|
GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
|
||||||
|
const char* file, int line);
|
||||||
|
|
||||||
|
template <typename> class ParamGeneratorInterface;
|
||||||
|
template <typename> class ParamGenerator;
|
||||||
|
|
||||||
|
// Interface for iterating over elements provided by an implementation
|
||||||
|
// of ParamGeneratorInterface<T>.
|
||||||
|
template <typename T>
|
||||||
|
class ParamIteratorInterface {
|
||||||
|
public:
|
||||||
|
virtual ~ParamIteratorInterface() {}
|
||||||
|
// A pointer to the base generator instance.
|
||||||
|
// Used only for the purposes of iterator comparison
|
||||||
|
// to make sure that two iterators belong to the same generator.
|
||||||
|
virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
|
||||||
|
// Advances iterator to point to the next element
|
||||||
|
// provided by the generator. The caller is responsible
|
||||||
|
// for not calling Advance() on an iterator equal to
|
||||||
|
// BaseGenerator()->End().
|
||||||
|
virtual void Advance() = 0;
|
||||||
|
// Clones the iterator object. Used for implementing copy semantics
|
||||||
|
// of ParamIterator<T>.
|
||||||
|
virtual ParamIteratorInterface* Clone() const = 0;
|
||||||
|
// Dereferences the current iterator and provides (read-only) access
|
||||||
|
// to the pointed value. It is the caller's responsibility not to call
|
||||||
|
// Current() on an iterator equal to BaseGenerator()->End().
|
||||||
|
// Used for implementing ParamGenerator<T>::operator*().
|
||||||
|
virtual const T* Current() const = 0;
|
||||||
|
// Determines whether the given iterator and other point to the same
|
||||||
|
// element in the sequence generated by the generator.
|
||||||
|
// Used for implementing ParamGenerator<T>::operator==().
|
||||||
|
virtual bool Equals(const ParamIteratorInterface& other) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class iterating over elements provided by an implementation of
|
||||||
|
// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
|
||||||
|
// and implements the const forward iterator concept.
|
||||||
|
template <typename T>
|
||||||
|
class ParamIterator {
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
typedef const T& reference;
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
|
||||||
|
// ParamIterator assumes ownership of the impl_ pointer.
|
||||||
|
ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
|
||||||
|
ParamIterator& operator=(const ParamIterator& other) {
|
||||||
|
if (this != &other)
|
||||||
|
impl_.reset(other.impl_->Clone());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator*() const { return *impl_->Current(); }
|
||||||
|
const T* operator->() const { return impl_->Current(); }
|
||||||
|
// Prefix version of operator++.
|
||||||
|
ParamIterator& operator++() {
|
||||||
|
impl_->Advance();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// Postfix version of operator++.
|
||||||
|
ParamIterator operator++(int /*unused*/) {
|
||||||
|
ParamIteratorInterface<T>* clone = impl_->Clone();
|
||||||
|
impl_->Advance();
|
||||||
|
return ParamIterator(clone);
|
||||||
|
}
|
||||||
|
bool operator==(const ParamIterator& other) const {
|
||||||
|
return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
|
||||||
|
}
|
||||||
|
bool operator!=(const ParamIterator& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ParamGenerator<T>;
|
||||||
|
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
|
||||||
|
scoped_ptr<ParamIteratorInterface<T> > impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ParamGeneratorInterface<T> is the binary interface to access generators
|
||||||
|
// defined in other translation units.
|
||||||
|
template <typename T>
|
||||||
|
class ParamGeneratorInterface {
|
||||||
|
public:
|
||||||
|
typedef T ParamType;
|
||||||
|
|
||||||
|
virtual ~ParamGeneratorInterface() {}
|
||||||
|
|
||||||
|
// Generator interface definition
|
||||||
|
virtual ParamIteratorInterface<T>* Begin() const = 0;
|
||||||
|
virtual ParamIteratorInterface<T>* End() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wraps ParamGeneratorInterface<T> and provides general generator syntax
|
||||||
|
// compatible with the STL Container concept.
|
||||||
|
// This class implements copy initialization semantics and the contained
|
||||||
|
// ParamGeneratorInterface<T> instance is shared among all copies
|
||||||
|
// of the original object. This is possible because that instance is immutable.
|
||||||
|
template<typename T>
|
||||||
|
class ParamGenerator {
|
||||||
|
public:
|
||||||
|
typedef ParamIterator<T> iterator;
|
||||||
|
|
||||||
|
explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
|
||||||
|
ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
|
||||||
|
|
||||||
|
ParamGenerator& operator=(const ParamGenerator& other) {
|
||||||
|
impl_ = other.impl_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() const { return iterator(impl_->Begin()); }
|
||||||
|
iterator end() const { return iterator(impl_->End()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
::testing::internal::linked_ptr<const ParamGeneratorInterface<T> > impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generates values from a range of two comparable values. Can be used to
|
||||||
|
// generate sequences of user-defined types that implement operator+() and
|
||||||
|
// operator<().
|
||||||
|
// This class is used in the Range() function.
|
||||||
|
template <typename T, typename IncrementT>
|
||||||
|
class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
|
public:
|
||||||
|
RangeGenerator(T begin, T end, IncrementT step)
|
||||||
|
: begin_(begin), end_(end),
|
||||||
|
step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
|
||||||
|
virtual ~RangeGenerator() {}
|
||||||
|
|
||||||
|
virtual ParamIteratorInterface<T>* Begin() const {
|
||||||
|
return new Iterator(this, begin_, 0, step_);
|
||||||
|
}
|
||||||
|
virtual ParamIteratorInterface<T>* End() const {
|
||||||
|
return new Iterator(this, end_, end_index_, step_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Iterator : public ParamIteratorInterface<T> {
|
||||||
|
public:
|
||||||
|
Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
|
||||||
|
IncrementT step)
|
||||||
|
: base_(base), value_(value), index_(index), step_(step) {}
|
||||||
|
virtual ~Iterator() {}
|
||||||
|
|
||||||
|
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
|
||||||
|
return base_;
|
||||||
|
}
|
||||||
|
virtual void Advance() {
|
||||||
|
value_ = value_ + step_;
|
||||||
|
index_++;
|
||||||
|
}
|
||||||
|
virtual ParamIteratorInterface<T>* Clone() const {
|
||||||
|
return new Iterator(*this);
|
||||||
|
}
|
||||||
|
virtual const T* Current() const { return &value_; }
|
||||||
|
virtual bool Equals(const ParamIteratorInterface<T>& 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 int other_index =
|
||||||
|
CheckedDowncastToActualType<const Iterator>(&other)->index_;
|
||||||
|
return index_ == other_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Iterator(const Iterator& other)
|
||||||
|
: ParamIteratorInterface<T>(),
|
||||||
|
base_(other.base_), value_(other.value_), index_(other.index_),
|
||||||
|
step_(other.step_) {}
|
||||||
|
|
||||||
|
// No implementation - assignment is unsupported.
|
||||||
|
void operator=(const Iterator& other);
|
||||||
|
|
||||||
|
const ParamGeneratorInterface<T>* const base_;
|
||||||
|
T value_;
|
||||||
|
int index_;
|
||||||
|
const IncrementT step_;
|
||||||
|
}; // class RangeGenerator::Iterator
|
||||||
|
|
||||||
|
static int CalculateEndIndex(const T& begin,
|
||||||
|
const T& end,
|
||||||
|
const IncrementT& step) {
|
||||||
|
int end_index = 0;
|
||||||
|
for (T i = begin; i < end; i = i + step)
|
||||||
|
end_index++;
|
||||||
|
return end_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No implementation - assignment is unsupported.
|
||||||
|
void operator=(const RangeGenerator& other);
|
||||||
|
|
||||||
|
const T begin_;
|
||||||
|
const T end_;
|
||||||
|
const IncrementT step_;
|
||||||
|
// The index for the end() iterator. All the elements in the generated
|
||||||
|
// sequence are indexed (0-based) to aid iterator comparison.
|
||||||
|
const int end_index_;
|
||||||
|
}; // class RangeGenerator
|
||||||
|
|
||||||
|
|
||||||
|
// Generates values from a pair of STL-style iterators. Used in the
|
||||||
|
// ValuesIn() function. The elements are copied from the source range
|
||||||
|
// since the source can be located on the stack, and the generator
|
||||||
|
// is likely to persist beyond that stack frame.
|
||||||
|
template <typename T>
|
||||||
|
class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
|
public:
|
||||||
|
template <typename ForwardIterator>
|
||||||
|
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
|
||||||
|
: container_(begin, end) {}
|
||||||
|
virtual ~ValuesInIteratorRangeGenerator() {}
|
||||||
|
|
||||||
|
virtual ParamIteratorInterface<T>* Begin() const {
|
||||||
|
return new Iterator(this, container_.begin());
|
||||||
|
}
|
||||||
|
virtual ParamIteratorInterface<T>* End() const {
|
||||||
|
return new Iterator(this, container_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef typename ::std::vector<T> ContainerType;
|
||||||
|
|
||||||
|
class Iterator : public ParamIteratorInterface<T> {
|
||||||
|
public:
|
||||||
|
Iterator(const ParamGeneratorInterface<T>* base,
|
||||||
|
typename ContainerType::const_iterator iterator)
|
||||||
|
: base_(base), iterator_(iterator) {}
|
||||||
|
virtual ~Iterator() {}
|
||||||
|
|
||||||
|
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
|
||||||
|
return base_;
|
||||||
|
}
|
||||||
|
virtual void Advance() {
|
||||||
|
++iterator_;
|
||||||
|
value_.reset();
|
||||||
|
}
|
||||||
|
virtual ParamIteratorInterface<T>* Clone() const {
|
||||||
|
return new Iterator(*this);
|
||||||
|
}
|
||||||
|
// We need to use cached value referenced by iterator_ because *iterator_
|
||||||
|
// can return a temporary object (and of type other then T), so just
|
||||||
|
// having "return &*iterator_;" doesn't work.
|
||||||
|
// value_ is updated here and not in Advance() because Advance()
|
||||||
|
// 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_));
|
||||||
|
return value_.get();
|
||||||
|
}
|
||||||
|
virtual bool Equals(const ParamIteratorInterface<T>& 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;
|
||||||
|
return iterator_ ==
|
||||||
|
CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Iterator(const Iterator& other)
|
||||||
|
// The explicit constructor call suppresses a false warning
|
||||||
|
// emitted by gcc when supplied with the -Wextra option.
|
||||||
|
: ParamIteratorInterface<T>(),
|
||||||
|
base_(other.base_),
|
||||||
|
iterator_(other.iterator_) {}
|
||||||
|
|
||||||
|
const ParamGeneratorInterface<T>* const base_;
|
||||||
|
typename ContainerType::const_iterator iterator_;
|
||||||
|
// 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,
|
||||||
|
// which is bound by the lifespan of the iterator itself.
|
||||||
|
mutable scoped_ptr<const T> value_;
|
||||||
|
}; // class ValuesInIteratorRangeGenerator::Iterator
|
||||||
|
|
||||||
|
// No implementation - assignment is unsupported.
|
||||||
|
void operator=(const ValuesInIteratorRangeGenerator& other);
|
||||||
|
|
||||||
|
const ContainerType container_;
|
||||||
|
}; // class ValuesInIteratorRangeGenerator
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
//
|
||||||
|
// Stores a parameter value and later creates tests parameterized with that
|
||||||
|
// value.
|
||||||
|
template <class TestClass>
|
||||||
|
class ParameterizedTestFactory : public TestFactoryBase {
|
||||||
|
public:
|
||||||
|
typedef typename TestClass::ParamType ParamType;
|
||||||
|
explicit ParameterizedTestFactory(ParamType parameter) :
|
||||||
|
parameter_(parameter) {}
|
||||||
|
virtual Test* CreateTest() {
|
||||||
|
TestClass::SetParam(¶meter_);
|
||||||
|
return new TestClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ParamType parameter_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
|
||||||
|
};
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
//
|
||||||
|
// TestMetaFactoryBase is a base class for meta-factories that create
|
||||||
|
// test factories for passing into MakeAndRegisterTestInfo function.
|
||||||
|
template <class ParamType>
|
||||||
|
class TestMetaFactoryBase {
|
||||||
|
public:
|
||||||
|
virtual ~TestMetaFactoryBase() {}
|
||||||
|
|
||||||
|
virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// it for each Test/Parameter value combination. Thus it needs meta factory
|
||||||
|
// creator class.
|
||||||
|
template <class TestCase>
|
||||||
|
class TestMetaFactory
|
||||||
|
: public TestMetaFactoryBase<typename TestCase::ParamType> {
|
||||||
|
public:
|
||||||
|
typedef typename TestCase::ParamType ParamType;
|
||||||
|
|
||||||
|
TestMetaFactory() {}
|
||||||
|
|
||||||
|
virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
|
||||||
|
return new ParameterizedTestFactory<TestCase>(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
|
||||||
|
};
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
//
|
||||||
|
// ParameterizedTestCaseInfoBase is a generic interface
|
||||||
|
// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
|
||||||
|
// accumulates test information provided by TEST_P macro invocations
|
||||||
|
// and generators provided by INSTANTIATE_TEST_CASE_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
|
||||||
|
// and calls RegisterTests() on each of them when asked.
|
||||||
|
class ParameterizedTestCaseInfoBase {
|
||||||
|
public:
|
||||||
|
virtual ~ParameterizedTestCaseInfoBase() {}
|
||||||
|
|
||||||
|
// Base part of test case name for display purposes.
|
||||||
|
virtual const String& GetTestCaseName() const = 0;
|
||||||
|
// Test case id to verify identity.
|
||||||
|
virtual TypeId GetTestCaseTypeId() 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.
|
||||||
|
virtual void RegisterTests() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ParameterizedTestCaseInfoBase() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// generators when asked.
|
||||||
|
template <class TestCase>
|
||||||
|
class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
|
||||||
|
public:
|
||||||
|
// ParamType and GeneratorCreationFunc are private types but are required
|
||||||
|
// for declarations of public methods AddTestPattern() and
|
||||||
|
// AddTestCaseInstantiation().
|
||||||
|
typedef typename TestCase::ParamType ParamType;
|
||||||
|
// A function that returns an instance of appropriate generator type.
|
||||||
|
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
|
||||||
|
|
||||||
|
explicit ParameterizedTestCaseInfo(const char* name)
|
||||||
|
: test_case_name_(name) {}
|
||||||
|
|
||||||
|
// Test case base name for display purposes.
|
||||||
|
virtual const String& GetTestCaseName() const { return test_case_name_; }
|
||||||
|
// Test case id to verify identity.
|
||||||
|
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
|
||||||
|
// 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
|
||||||
|
// 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)));
|
||||||
|
}
|
||||||
|
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
|
||||||
|
// about a generator.
|
||||||
|
int AddTestCaseInstantiation(const char* instantiation_name,
|
||||||
|
GeneratorCreationFunc* func,
|
||||||
|
const char* /* file */,
|
||||||
|
int /* line */) {
|
||||||
|
instantiations_.push_back(::std::make_pair(instantiation_name, func));
|
||||||
|
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() {
|
||||||
|
for (typename TestInfoContainer::iterator test_it = tests_.begin();
|
||||||
|
test_it != tests_.end(); ++test_it) {
|
||||||
|
linked_ptr<TestInfo> test_info = *test_it;
|
||||||
|
for (typename InstantiationContainer::iterator gen_it =
|
||||||
|
instantiations_.begin(); gen_it != instantiations_.end();
|
||||||
|
++gen_it) {
|
||||||
|
const String& instantiation_name = gen_it->first;
|
||||||
|
ParamGenerator<ParamType> generator((*gen_it->second)());
|
||||||
|
|
||||||
|
Message test_case_name_stream;
|
||||||
|
if ( !instantiation_name.empty() )
|
||||||
|
test_case_name_stream << instantiation_name.c_str() << "/";
|
||||||
|
test_case_name_stream << test_info->test_case_base_name.c_str();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (typename ParamGenerator<ParamType>::iterator param_it =
|
||||||
|
generator.begin();
|
||||||
|
param_it != generator.end(); ++param_it, ++i) {
|
||||||
|
Message test_name_stream;
|
||||||
|
test_name_stream << test_info->test_base_name.c_str() << "/" << i;
|
||||||
|
::testing::internal::MakeAndRegisterTestInfo(
|
||||||
|
test_case_name_stream.GetString().c_str(),
|
||||||
|
test_name_stream.GetString().c_str(),
|
||||||
|
"", // test_case_comment
|
||||||
|
"", // comment; TODO(vladl@google.com): provide parameter value
|
||||||
|
// representation.
|
||||||
|
GetTestCaseTypeId(),
|
||||||
|
TestCase::SetUpTestCase,
|
||||||
|
TestCase::TearDownTestCase,
|
||||||
|
test_info->test_meta_factory->CreateTestFactory(*param_it));
|
||||||
|
} // for param_it
|
||||||
|
} // for gen_it
|
||||||
|
} // for test_it
|
||||||
|
} // 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) {}
|
||||||
|
|
||||||
|
const String test_case_base_name;
|
||||||
|
const String test_base_name;
|
||||||
|
const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
|
||||||
|
};
|
||||||
|
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
|
||||||
|
// Keeps pairs of <Instantiation name, Sequence generator creation function>
|
||||||
|
// received from INSTANTIATE_TEST_CASE_P macros.
|
||||||
|
typedef ::std::vector<std::pair<String, GeneratorCreationFunc*> >
|
||||||
|
InstantiationContainer;
|
||||||
|
|
||||||
|
const String test_case_name_;
|
||||||
|
TestInfoContainer tests_;
|
||||||
|
InstantiationContainer instantiations_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
|
||||||
|
}; // class ParameterizedTestCaseInfo
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
public:
|
||||||
|
ParameterizedTestCaseRegistry() {}
|
||||||
|
~ParameterizedTestCaseRegistry() {
|
||||||
|
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
|
||||||
|
it != test_case_infos_.end(); ++it) {
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
const char* file,
|
||||||
|
int line) {
|
||||||
|
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>()) {
|
||||||
|
// 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, file, line);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typed_test_info == NULL) {
|
||||||
|
typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
|
||||||
|
test_case_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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
|
||||||
|
|
||||||
|
TestCaseInfoContainer test_case_infos_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,350 @@
|
||||||
|
// Copyright 2005, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
|
||||||
|
//
|
||||||
|
// The Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This header file declares the String class and functions used internally by
|
||||||
|
// Google Test. They are subject to change without notice. They should not used
|
||||||
|
// by code external to Google Test.
|
||||||
|
//
|
||||||
|
// This header file is #included by <gtest/internal/gtest-internal.h>.
|
||||||
|
// It should not be #included by other files.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||||
|
|
||||||
|
#ifdef __BORLANDC__
|
||||||
|
// string.h is not guaranteed to provide strcpy on C++ Builder.
|
||||||
|
#include <mem.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// String - a UTF-8 string class.
|
||||||
|
//
|
||||||
|
// For historic reasons, we don't use std::string.
|
||||||
|
//
|
||||||
|
// TODO(wan@google.com): replace this class with std::string or
|
||||||
|
// implement it in terms of the latter.
|
||||||
|
//
|
||||||
|
// Note that String can represent both NULL and the empty string,
|
||||||
|
// while std::string cannot represent NULL.
|
||||||
|
//
|
||||||
|
// NULL and the empty string are considered different. NULL is less
|
||||||
|
// than anything (including the empty string) except itself.
|
||||||
|
//
|
||||||
|
// This class only provides minimum functionality necessary for
|
||||||
|
// implementing Google Test. We do not intend to implement a full-fledged
|
||||||
|
// string class here.
|
||||||
|
//
|
||||||
|
// Since the purpose of this class is to provide a substitute for
|
||||||
|
// std::string on platforms where it cannot be used, we define a copy
|
||||||
|
// constructor and assignment operators such that we don't need
|
||||||
|
// conditional compilation in a lot of places.
|
||||||
|
//
|
||||||
|
// In order to make the representation efficient, the d'tor of String
|
||||||
|
// is not virtual. Therefore DO NOT INHERIT FROM String.
|
||||||
|
class GTEST_API_ String {
|
||||||
|
public:
|
||||||
|
// Static utility methods
|
||||||
|
|
||||||
|
// Returns the input enclosed in double quotes if it's not NULL;
|
||||||
|
// otherwise returns "(null)". For example, "\"Hello\"" is returned
|
||||||
|
// for input "Hello".
|
||||||
|
//
|
||||||
|
// This is useful for printing a C string in the syntax of a literal.
|
||||||
|
//
|
||||||
|
// Known issue: escape sequences are not handled yet.
|
||||||
|
static String ShowCStringQuoted(const char* c_str);
|
||||||
|
|
||||||
|
// Clones a 0-terminated C string, allocating memory using new. The
|
||||||
|
// caller is responsible for deleting the return value using
|
||||||
|
// delete[]. Returns the cloned string, or NULL if the input is
|
||||||
|
// NULL.
|
||||||
|
//
|
||||||
|
// This is different from strdup() in string.h, which allocates
|
||||||
|
// memory using malloc().
|
||||||
|
static const char* CloneCString(const char* c_str);
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
// Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
|
||||||
|
// able to pass strings to Win32 APIs on CE we need to convert them
|
||||||
|
// to 'Unicode', UTF-16.
|
||||||
|
|
||||||
|
// Creates a UTF-16 wide string from the given ANSI string, allocating
|
||||||
|
// memory using new. The caller is responsible for deleting the return
|
||||||
|
// value using delete[]. Returns the wide string, or NULL if the
|
||||||
|
// input is NULL.
|
||||||
|
//
|
||||||
|
// The wide string is created using the ANSI codepage (CP_ACP) to
|
||||||
|
// match the behaviour of the ANSI versions of Win32 calls and the
|
||||||
|
// C runtime.
|
||||||
|
static LPCWSTR AnsiToUtf16(const char* c_str);
|
||||||
|
|
||||||
|
// Creates an ANSI string from the given wide string, allocating
|
||||||
|
// memory using new. The caller is responsible for deleting the return
|
||||||
|
// value using delete[]. Returns the ANSI string, or NULL if the
|
||||||
|
// input is NULL.
|
||||||
|
//
|
||||||
|
// The returned string is created using the ANSI codepage (CP_ACP) to
|
||||||
|
// match the behaviour of the ANSI versions of Win32 calls and the
|
||||||
|
// C runtime.
|
||||||
|
static const char* Utf16ToAnsi(LPCWSTR utf16_str);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Compares two C strings. Returns true iff 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,
|
||||||
|
// including the empty string.
|
||||||
|
static bool CStringEquals(const char* lhs, const char* rhs);
|
||||||
|
|
||||||
|
// Converts a wide C string to a String using the UTF-8 encoding.
|
||||||
|
// NULL will be converted to "(null)". If an error occurred during
|
||||||
|
// the conversion, "(failed to convert from wide string)" is
|
||||||
|
// returned.
|
||||||
|
static String ShowWideCString(const wchar_t* wide_c_str);
|
||||||
|
|
||||||
|
// Similar to ShowWideCString(), except that this function encloses
|
||||||
|
// the converted string in double quotes.
|
||||||
|
static String ShowWideCStringQuoted(const wchar_t* wide_c_str);
|
||||||
|
|
||||||
|
// Compares two wide C strings. Returns true iff 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.
|
||||||
|
//
|
||||||
|
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
||||||
|
// A NULL C string is considered different to any non-NULL C string,
|
||||||
|
// including the empty string.
|
||||||
|
static bool CaseInsensitiveCStringEquals(const char* lhs,
|
||||||
|
const char* rhs);
|
||||||
|
|
||||||
|
// Compares two wide C strings, ignoring case. Returns true iff 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,
|
||||||
|
// including the empty string.
|
||||||
|
// NB: The implementations on different platforms slightly differ.
|
||||||
|
// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
|
||||||
|
// environment variable. On GNU platform this method uses wcscasecmp
|
||||||
|
// which compares according to LC_CTYPE category of the current locale.
|
||||||
|
// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
|
||||||
|
// current locale.
|
||||||
|
static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
|
||||||
|
const wchar_t* rhs);
|
||||||
|
|
||||||
|
// Formats a list of arguments to a String, using the same format
|
||||||
|
// spec string as for printf.
|
||||||
|
//
|
||||||
|
// We do not use the StringPrintf class as it is not universally
|
||||||
|
// available.
|
||||||
|
//
|
||||||
|
// The result is limited to 4096 characters (including the tailing
|
||||||
|
// 0). If 4096 characters are not enough to format the input,
|
||||||
|
// "<buffer exceeded>" is returned.
|
||||||
|
static String Format(const char* format, ...);
|
||||||
|
|
||||||
|
// C'tors
|
||||||
|
|
||||||
|
// The default c'tor constructs a NULL string.
|
||||||
|
String() : c_str_(NULL), length_(0) {}
|
||||||
|
|
||||||
|
// Constructs a String by cloning a 0-terminated C string.
|
||||||
|
String(const char* a_c_str) { // NOLINT
|
||||||
|
if (a_c_str == NULL) {
|
||||||
|
c_str_ = NULL;
|
||||||
|
length_ = 0;
|
||||||
|
} else {
|
||||||
|
ConstructNonNull(a_c_str, strlen(a_c_str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a String by copying a given number of chars from a
|
||||||
|
// buffer. E.g. String("hello", 3) creates the string "hel",
|
||||||
|
// String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "",
|
||||||
|
// and String(NULL, 1) results in access violation.
|
||||||
|
String(const char* buffer, size_t a_length) {
|
||||||
|
ConstructNonNull(buffer, a_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The copy c'tor creates a new copy of the string. The two
|
||||||
|
// String objects do not share content.
|
||||||
|
String(const String& str) : c_str_(NULL), length_(0) { *this = str; }
|
||||||
|
|
||||||
|
// D'tor. String is intended to be a final class, so the d'tor
|
||||||
|
// doesn't need to be virtual.
|
||||||
|
~String() { delete[] c_str_; }
|
||||||
|
|
||||||
|
// Allows a String to be implicitly converted to an ::std::string or
|
||||||
|
// ::string, and vice versa. Converting a String containing a NULL
|
||||||
|
// pointer to ::std::string or ::string is undefined behavior.
|
||||||
|
// Converting a ::std::string or ::string containing an embedded NUL
|
||||||
|
// character to a String will result in the prefix up to the first
|
||||||
|
// NUL character.
|
||||||
|
String(const ::std::string& str) {
|
||||||
|
ConstructNonNull(str.c_str(), str.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
operator ::std::string() const { return ::std::string(c_str(), length()); }
|
||||||
|
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
String(const ::string& str) {
|
||||||
|
ConstructNonNull(str.c_str(), str.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
operator ::string() const { return ::string(c_str(), length()); }
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
|
// Returns true iff this is an empty string (i.e. "").
|
||||||
|
bool empty() const { return (c_str() != NULL) && (length() == 0); }
|
||||||
|
|
||||||
|
// Compares this with another String.
|
||||||
|
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
|
||||||
|
// if this is greater than rhs.
|
||||||
|
int Compare(const String& rhs) const;
|
||||||
|
|
||||||
|
// Returns true iff this String equals the given C string. A NULL
|
||||||
|
// string and a non-NULL string are considered not equal.
|
||||||
|
bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; }
|
||||||
|
|
||||||
|
// Returns true iff this String is less than the given String. A
|
||||||
|
// NULL string is considered less than "".
|
||||||
|
bool operator<(const String& rhs) const { return Compare(rhs) < 0; }
|
||||||
|
|
||||||
|
// Returns true iff this String doesn't equal the given C string. A NULL
|
||||||
|
// string and a non-NULL string are considered not equal.
|
||||||
|
bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); }
|
||||||
|
|
||||||
|
// Returns true iff this String ends with the given suffix. *Any*
|
||||||
|
// String is considered to end with a NULL or empty suffix.
|
||||||
|
bool EndsWith(const char* suffix) const;
|
||||||
|
|
||||||
|
// Returns true iff this String ends with the given suffix, not considering
|
||||||
|
// case. Any String is considered to end with a NULL or empty suffix.
|
||||||
|
bool EndsWithCaseInsensitive(const char* suffix) const;
|
||||||
|
|
||||||
|
// Returns the length of the encapsulated string, or 0 if the
|
||||||
|
// string is NULL.
|
||||||
|
size_t length() const { return length_; }
|
||||||
|
|
||||||
|
// Gets the 0-terminated C string this String object represents.
|
||||||
|
// The String object still owns the string. Therefore the caller
|
||||||
|
// should NOT delete the return value.
|
||||||
|
const char* c_str() const { return c_str_; }
|
||||||
|
|
||||||
|
// Assigns a C string to this object. Self-assignment works.
|
||||||
|
const String& operator=(const char* a_c_str) {
|
||||||
|
return *this = String(a_c_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assigns a String object to this object. Self-assignment works.
|
||||||
|
const String& operator=(const String& rhs) {
|
||||||
|
if (this != &rhs) {
|
||||||
|
delete[] c_str_;
|
||||||
|
if (rhs.c_str() == NULL) {
|
||||||
|
c_str_ = NULL;
|
||||||
|
length_ = 0;
|
||||||
|
} else {
|
||||||
|
ConstructNonNull(rhs.c_str(), rhs.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Constructs a non-NULL String from the given content. This
|
||||||
|
// function can only be called when data_ has not been allocated.
|
||||||
|
// ConstructNonNull(NULL, 0) results in an empty string ("").
|
||||||
|
// ConstructNonNull(NULL, non_zero) is undefined behavior.
|
||||||
|
void ConstructNonNull(const char* buffer, size_t a_length) {
|
||||||
|
char* const str = new char[a_length + 1];
|
||||||
|
memcpy(str, buffer, a_length);
|
||||||
|
str[a_length] = '\0';
|
||||||
|
c_str_ = str;
|
||||||
|
length_ = a_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* c_str_;
|
||||||
|
size_t length_;
|
||||||
|
}; // class String
|
||||||
|
|
||||||
|
// Streams a String to an ostream. Each '\0' character in the String
|
||||||
|
// is replaced with "\\0".
|
||||||
|
inline ::std::ostream& operator<<(::std::ostream& os, const String& str) {
|
||||||
|
if (str.c_str() == NULL) {
|
||||||
|
os << "(null)";
|
||||||
|
} else {
|
||||||
|
const char* const c_str = str.c_str();
|
||||||
|
for (size_t i = 0; i != str.length(); i++) {
|
||||||
|
if (c_str[i] == '\0') {
|
||||||
|
os << "\\0";
|
||||||
|
} else {
|
||||||
|
os << c_str[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the content of the StrStream's buffer as a String. Each '\0'
|
||||||
|
// character in the buffer is replaced with "\\0".
|
||||||
|
GTEST_API_ String StrStreamToString(StrStream* stream);
|
||||||
|
|
||||||
|
// Converts a streamable value to a String. A NULL pointer is
|
||||||
|
// converted to "(null)". When the input value is a ::string,
|
||||||
|
// ::std::string, ::wstring, or ::std::wstring object, each NUL
|
||||||
|
// character in it is replaced with "\\0".
|
||||||
|
|
||||||
|
// Declared here but defined in gtest.h, so that it has access
|
||||||
|
// to the definition of the Message class, required by the ARM
|
||||||
|
// compiler.
|
||||||
|
template <typename T>
|
||||||
|
String StreamableToString(const T& streamable);
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
|
@ -0,0 +1,968 @@
|
||||||
|
// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
|
||||||
|
|
||||||
|
#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
|
||||||
|
// hack bypasses the bug by declaring the members that should otherwise be
|
||||||
|
// private as public.
|
||||||
|
// Sun Studio versions < 12 also have the above bug.
|
||||||
|
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
|
||||||
|
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
|
||||||
|
#else
|
||||||
|
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
|
||||||
|
template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
|
||||||
|
private:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GTEST_n_TUPLE_(T) is the type of an n-tuple.
|
||||||
|
#define GTEST_0_TUPLE_(T) tuple<>
|
||||||
|
#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
|
||||||
|
void, void, void>
|
||||||
|
#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
|
||||||
|
void, void, void>
|
||||||
|
#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
|
||||||
|
void, void, void>
|
||||||
|
#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
|
||||||
|
void, void, void>
|
||||||
|
#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
|
||||||
|
void, void, void>
|
||||||
|
#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
|
||||||
|
void, void, void>
|
||||||
|
#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
|
||||||
|
void, void, void>
|
||||||
|
#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
|
||||||
|
T##7, void, void>
|
||||||
|
#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
|
||||||
|
T##7, T##8, void>
|
||||||
|
#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
|
||||||
|
T##7, T##8, T##9>
|
||||||
|
|
||||||
|
// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
|
||||||
|
#define GTEST_0_TYPENAMES_(T)
|
||||||
|
#define GTEST_1_TYPENAMES_(T) typename T##0
|
||||||
|
#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
|
||||||
|
#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
|
||||||
|
#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
|
||||||
|
typename T##3
|
||||||
|
#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
|
||||||
|
typename T##3, typename T##4
|
||||||
|
#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
|
||||||
|
typename T##3, typename T##4, typename T##5
|
||||||
|
#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
|
||||||
|
typename T##3, typename T##4, typename T##5, typename T##6
|
||||||
|
#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
|
||||||
|
typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
|
||||||
|
#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
|
||||||
|
typename T##3, typename T##4, typename T##5, typename T##6, \
|
||||||
|
typename T##7, typename T##8
|
||||||
|
#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
|
||||||
|
typename T##3, typename T##4, typename T##5, typename T##6, \
|
||||||
|
typename T##7, typename T##8, typename T##9
|
||||||
|
|
||||||
|
// 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 <typename T0 = void, typename T1 = void, typename T2 = void,
|
||||||
|
typename T3 = void, typename T4 = void, typename T5 = void,
|
||||||
|
typename T6 = void, typename T7 = void, typename T8 = void,
|
||||||
|
typename T9 = 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;
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 0, GTEST_10_TUPLE_(T)> { typedef T0 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 1, GTEST_10_TUPLE_(T)> { typedef T1 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 2, GTEST_10_TUPLE_(T)> { typedef T2 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 3, GTEST_10_TUPLE_(T)> { typedef T3 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 4, GTEST_10_TUPLE_(T)> { typedef T4 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 5, GTEST_10_TUPLE_(T)> { typedef T5 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 6, GTEST_10_TUPLE_(T)> { typedef T6 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 7, GTEST_10_TUPLE_(T)> { typedef T7 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 8, GTEST_10_TUPLE_(T)> { typedef T8 type; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct TupleElement<true, 9, GTEST_10_TUPLE_(T)> { typedef T9 type; };
|
||||||
|
|
||||||
|
} // namespace gtest_internal
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class tuple<> {
|
||||||
|
public:
|
||||||
|
tuple() {}
|
||||||
|
tuple(const tuple& /* t */) {}
|
||||||
|
tuple& operator=(const tuple& /* t */) { return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_1_TYPENAMES_(T)>
|
||||||
|
class GTEST_1_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_) {}
|
||||||
|
|
||||||
|
template <GTEST_1_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_1_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_1_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_2_TYPENAMES_(T)>
|
||||||
|
class GTEST_2_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
|
||||||
|
f1_(f1) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
|
||||||
|
|
||||||
|
template <GTEST_2_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
|
||||||
|
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_2_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
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_2_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_3_TYPENAMES_(T)>
|
||||||
|
class GTEST_3_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_(), f2_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||||
|
GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
|
||||||
|
|
||||||
|
template <GTEST_3_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_3_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_3_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
f2_ = t.f2_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
T2 f2_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_4_TYPENAMES_(T)>
|
||||||
|
class GTEST_4_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_(), f2_(), f3_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||||
|
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
|
||||||
|
f3_(f3) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
|
||||||
|
|
||||||
|
template <GTEST_4_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
|
||||||
|
f3_(t.f3_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_4_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_4_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
f2_ = t.f2_;
|
||||||
|
f3_ = t.f3_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
T2 f2_;
|
||||||
|
T3 f3_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_5_TYPENAMES_(T)>
|
||||||
|
class GTEST_5_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||||
|
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
|
||||||
|
GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
|
||||||
|
f4_(t.f4_) {}
|
||||||
|
|
||||||
|
template <GTEST_5_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
|
||||||
|
f3_(t.f3_), f4_(t.f4_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_5_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_5_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
f2_ = t.f2_;
|
||||||
|
f3_ = t.f3_;
|
||||||
|
f4_ = t.f4_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
T2 f2_;
|
||||||
|
T3 f3_;
|
||||||
|
T4 f4_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_6_TYPENAMES_(T)>
|
||||||
|
class GTEST_6_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||||
|
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||||
|
GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
|
||||||
|
f5_(f5) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
|
||||||
|
f4_(t.f4_), f5_(t.f5_) {}
|
||||||
|
|
||||||
|
template <GTEST_6_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
|
||||||
|
f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_6_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_6_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
f2_ = t.f2_;
|
||||||
|
f3_ = t.f3_;
|
||||||
|
f4_ = t.f4_;
|
||||||
|
f5_ = t.f5_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
T2 f2_;
|
||||||
|
T3 f3_;
|
||||||
|
T4 f4_;
|
||||||
|
T5 f5_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_7_TYPENAMES_(T)>
|
||||||
|
class GTEST_7_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||||
|
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||||
|
GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
|
||||||
|
f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
|
||||||
|
f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
|
||||||
|
|
||||||
|
template <GTEST_7_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
|
||||||
|
f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_7_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_7_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
f2_ = t.f2_;
|
||||||
|
f3_ = t.f3_;
|
||||||
|
f4_ = t.f4_;
|
||||||
|
f5_ = t.f5_;
|
||||||
|
f6_ = t.f6_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
T2 f2_;
|
||||||
|
T3 f3_;
|
||||||
|
T4 f4_;
|
||||||
|
T5 f5_;
|
||||||
|
T6 f6_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_8_TYPENAMES_(T)>
|
||||||
|
class GTEST_8_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||||
|
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||||
|
GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
|
||||||
|
GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
|
||||||
|
f5_(f5), f6_(f6), f7_(f7) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
|
||||||
|
f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
|
||||||
|
|
||||||
|
template <GTEST_8_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
|
||||||
|
f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_8_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_8_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
f2_ = t.f2_;
|
||||||
|
f3_ = t.f3_;
|
||||||
|
f4_ = t.f4_;
|
||||||
|
f5_ = t.f5_;
|
||||||
|
f6_ = t.f6_;
|
||||||
|
f7_ = t.f7_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
T2 f2_;
|
||||||
|
T3 f3_;
|
||||||
|
T4 f4_;
|
||||||
|
T5 f5_;
|
||||||
|
T6 f6_;
|
||||||
|
T7 f7_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_9_TYPENAMES_(T)>
|
||||||
|
class GTEST_9_TUPLE_(T) {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||||
|
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||||
|
GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
|
||||||
|
GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
|
||||||
|
f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
|
||||||
|
f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
|
||||||
|
|
||||||
|
template <GTEST_9_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
|
||||||
|
f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_9_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_9_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
f2_ = t.f2_;
|
||||||
|
f3_ = t.f3_;
|
||||||
|
f4_ = t.f4_;
|
||||||
|
f5_ = t.f5_;
|
||||||
|
f6_ = t.f6_;
|
||||||
|
f7_ = t.f7_;
|
||||||
|
f8_ = t.f8_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
T2 f2_;
|
||||||
|
T3 f3_;
|
||||||
|
T4 f4_;
|
||||||
|
T5 f5_;
|
||||||
|
T6 f6_;
|
||||||
|
T7 f7_;
|
||||||
|
T8 f8_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
class tuple {
|
||||||
|
public:
|
||||||
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
|
||||||
|
f9_() {}
|
||||||
|
|
||||||
|
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
|
||||||
|
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
|
||||||
|
GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
|
||||||
|
GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
|
||||||
|
f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
|
||||||
|
|
||||||
|
tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
|
||||||
|
f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(U)>
|
||||||
|
tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
|
||||||
|
f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
|
||||||
|
f9_(t.f9_) {}
|
||||||
|
|
||||||
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(U)>
|
||||||
|
tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
|
||||||
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(U)>
|
||||||
|
tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
|
||||||
|
f0_ = t.f0_;
|
||||||
|
f1_ = t.f1_;
|
||||||
|
f2_ = t.f2_;
|
||||||
|
f3_ = t.f3_;
|
||||||
|
f4_ = t.f4_;
|
||||||
|
f5_ = t.f5_;
|
||||||
|
f6_ = t.f6_;
|
||||||
|
f7_ = t.f7_;
|
||||||
|
f8_ = t.f8_;
|
||||||
|
f9_ = t.f9_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T0 f0_;
|
||||||
|
T1 f1_;
|
||||||
|
T2 f2_;
|
||||||
|
T3 f3_;
|
||||||
|
T4 f4_;
|
||||||
|
T5 f5_;
|
||||||
|
T6 f6_;
|
||||||
|
T7 f7_;
|
||||||
|
T8 f8_;
|
||||||
|
T9 f9_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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<>(); }
|
||||||
|
|
||||||
|
template <GTEST_1_TYPENAMES_(T)>
|
||||||
|
inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
|
||||||
|
return GTEST_1_TUPLE_(T)(f0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_2_TYPENAMES_(T)>
|
||||||
|
inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
|
||||||
|
return GTEST_2_TUPLE_(T)(f0, f1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_3_TYPENAMES_(T)>
|
||||||
|
inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
|
||||||
|
return GTEST_3_TUPLE_(T)(f0, f1, f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_4_TYPENAMES_(T)>
|
||||||
|
inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
|
||||||
|
const T3& f3) {
|
||||||
|
return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_5_TYPENAMES_(T)>
|
||||||
|
inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
|
||||||
|
const T3& f3, const T4& f4) {
|
||||||
|
return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_6_TYPENAMES_(T)>
|
||||||
|
inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
|
||||||
|
const T3& f3, const T4& f4, const T5& f5) {
|
||||||
|
return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_7_TYPENAMES_(T)>
|
||||||
|
inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
|
||||||
|
const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
|
||||||
|
return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_8_TYPENAMES_(T)>
|
||||||
|
inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
|
||||||
|
const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
|
||||||
|
return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_9_TYPENAMES_(T)>
|
||||||
|
inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
|
||||||
|
const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
|
||||||
|
const T8& f8) {
|
||||||
|
return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
|
||||||
|
const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
|
||||||
|
const T8& f8, const T9& f9) {
|
||||||
|
return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6.1.3.3 Tuple helper classes.
|
||||||
|
|
||||||
|
template <typename Tuple> struct tuple_size;
|
||||||
|
|
||||||
|
template <GTEST_0_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_0_TUPLE_(T)> { static const int value = 0; };
|
||||||
|
|
||||||
|
template <GTEST_1_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_1_TUPLE_(T)> { static const int value = 1; };
|
||||||
|
|
||||||
|
template <GTEST_2_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_2_TUPLE_(T)> { static const int value = 2; };
|
||||||
|
|
||||||
|
template <GTEST_3_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_3_TUPLE_(T)> { static const int value = 3; };
|
||||||
|
|
||||||
|
template <GTEST_4_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_4_TUPLE_(T)> { static const int value = 4; };
|
||||||
|
|
||||||
|
template <GTEST_5_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_5_TUPLE_(T)> { static const int value = 5; };
|
||||||
|
|
||||||
|
template <GTEST_6_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_6_TUPLE_(T)> { static const int value = 6; };
|
||||||
|
|
||||||
|
template <GTEST_7_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_7_TUPLE_(T)> { static const int value = 7; };
|
||||||
|
|
||||||
|
template <GTEST_8_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_8_TUPLE_(T)> { static const int value = 8; };
|
||||||
|
|
||||||
|
template <GTEST_9_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_9_TUPLE_(T)> { static const int value = 9; };
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_10_TUPLE_(T)> { static const int value = 10; };
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<0> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f0_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f0_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<1> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f1_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f1_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<2> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f2_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f2_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<3> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f3_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f3_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<4> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f4_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f4_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<5> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f5_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f5_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<6> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f6_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f6_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<7> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f7_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f7_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<8> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f8_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f8_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Get<9> {
|
||||||
|
public:
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f9_; } // NOLINT
|
||||||
|
|
||||||
|
template <class Tuple>
|
||||||
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
|
||||||
|
ConstField(const Tuple& t) { return t.f9_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gtest_internal
|
||||||
|
|
||||||
|
template <int k, GTEST_10_TYPENAMES_(T)>
|
||||||
|
GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
|
||||||
|
get(GTEST_10_TUPLE_(T)& t) {
|
||||||
|
return gtest_internal::Get<k>::Field(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int k, GTEST_10_TYPENAMES_(T)>
|
||||||
|
GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
|
||||||
|
get(const GTEST_10_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_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
|
||||||
|
inline bool operator==(const GTEST_10_TUPLE_(T)& t,
|
||||||
|
const GTEST_10_TUPLE_(U)& u) {
|
||||||
|
return gtest_internal::SameSizeTuplePrefixComparator<
|
||||||
|
tuple_size<GTEST_10_TUPLE_(T)>::value,
|
||||||
|
tuple_size<GTEST_10_TUPLE_(U)>::value>::Eq(t, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
|
||||||
|
inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
|
||||||
|
const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
|
||||||
|
|
||||||
|
// 6.1.4 Pairs.
|
||||||
|
// Unimplemented.
|
||||||
|
|
||||||
|
} // namespace tr1
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
#undef GTEST_0_TUPLE_
|
||||||
|
#undef GTEST_1_TUPLE_
|
||||||
|
#undef GTEST_2_TUPLE_
|
||||||
|
#undef GTEST_3_TUPLE_
|
||||||
|
#undef GTEST_4_TUPLE_
|
||||||
|
#undef GTEST_5_TUPLE_
|
||||||
|
#undef GTEST_6_TUPLE_
|
||||||
|
#undef GTEST_7_TUPLE_
|
||||||
|
#undef GTEST_8_TUPLE_
|
||||||
|
#undef GTEST_9_TUPLE_
|
||||||
|
#undef GTEST_10_TUPLE_
|
||||||
|
|
||||||
|
#undef GTEST_0_TYPENAMES_
|
||||||
|
#undef GTEST_1_TYPENAMES_
|
||||||
|
#undef GTEST_2_TYPENAMES_
|
||||||
|
#undef GTEST_3_TYPENAMES_
|
||||||
|
#undef GTEST_4_TYPENAMES_
|
||||||
|
#undef GTEST_5_TYPENAMES_
|
||||||
|
#undef GTEST_6_TYPENAMES_
|
||||||
|
#undef GTEST_7_TYPENAMES_
|
||||||
|
#undef GTEST_8_TYPENAMES_
|
||||||
|
#undef GTEST_9_TYPENAMES_
|
||||||
|
#undef GTEST_10_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_
|
|
@ -0,0 +1,336 @@
|
||||||
|
$$ -*- 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.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
|
||||||
|
|
||||||
|
#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
|
||||||
|
// hack bypasses the bug by declaring the members that should otherwise be
|
||||||
|
// private as public.
|
||||||
|
// Sun Studio versions < 12 also have the above bug.
|
||||||
|
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
|
||||||
|
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
|
||||||
|
#else
|
||||||
|
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
|
||||||
|
template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
|
||||||
|
private:
|
||||||
|
#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_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,287 @@
|
||||||
|
$$ -*- 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.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
#include <gtest/internal/gtest-string.h>
|
||||||
|
|
||||||
|
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
||||||
|
// libstdc++ (which is where cxxabi.h comes from).
|
||||||
|
#ifdef __GLIBCXX__
|
||||||
|
#include <cxxabi.h>
|
||||||
|
#endif // __GLIBCXX__
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// GetTypeName<T>() returns a human-readable name of type T.
|
||||||
|
template <typename T>
|
||||||
|
String GetTypeName() {
|
||||||
|
#if GTEST_HAS_RTTI
|
||||||
|
|
||||||
|
const char* const name = typeid(T).name();
|
||||||
|
#ifdef __GLIBCXX__
|
||||||
|
int status = 0;
|
||||||
|
// gcc's implementation of typeid(T).name() mangles the type name,
|
||||||
|
// so we have to demangle it.
|
||||||
|
char* const readable_name = abi::__cxa_demangle(name, 0, 0, &status);
|
||||||
|
const String name_str(status == 0 ? readable_name : name);
|
||||||
|
free(readable_name);
|
||||||
|
return name_str;
|
||||||
|
#else
|
||||||
|
return name;
|
||||||
|
#endif // __GLIBCXX__
|
||||||
|
|
||||||
|
#else
|
||||||
|
return "<type>";
|
||||||
|
#endif // GTEST_HAS_RTTI
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: mheule@google.com (Markus Heule)
|
||||||
|
//
|
||||||
|
// Google C++ Testing Framework (Google Test)
|
||||||
|
//
|
||||||
|
// Sometimes it's desirable to build Google Test by compiling a single file.
|
||||||
|
// This file serves this purpose.
|
||||||
|
|
||||||
|
// This line ensures that gtest.h can be compiled on its own, even
|
||||||
|
// when it's fused.
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
// The following lines pull in the real gtest *.cc files.
|
||||||
|
#include "src/gtest.cc"
|
||||||
|
#include "src/gtest-death-test.cc"
|
||||||
|
#include "src/gtest-filepath.cc"
|
||||||
|
#include "src/gtest-port.cc"
|
||||||
|
#include "src/gtest-test-part.cc"
|
||||||
|
#include "src/gtest-typed-test.cc"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,380 @@
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Authors: keith.ray@gmail.com (Keith Ray)
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-filepath.h>
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
#include <windows.h>
|
||||||
|
#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.
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS
|
||||||
|
#define GTEST_PATH_MAX_ _MAX_PATH
|
||||||
|
#elif defined(PATH_MAX)
|
||||||
|
#define GTEST_PATH_MAX_ PATH_MAX
|
||||||
|
#elif defined(_XOPEN_PATH_MAX)
|
||||||
|
#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
|
||||||
|
#else
|
||||||
|
#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
||||||
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-string.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS
|
||||||
|
// On Windows, '\\' is the standard path separator, but many tools and the
|
||||||
|
// Windows API also accept '/' as an alternate path separator. Unless otherwise
|
||||||
|
// noted, a file path can contain either kind of path separators, or a mixture
|
||||||
|
// of them.
|
||||||
|
const char kPathSeparator = '\\';
|
||||||
|
const char kAlternatePathSeparator = '/';
|
||||||
|
const char kPathSeparatorString[] = "\\";
|
||||||
|
const char kAlternatePathSeparatorString[] = "/";
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
// Windows CE doesn't have a current directory. You should not use
|
||||||
|
// the current directory in tests on Windows CE, but this at least
|
||||||
|
// provides a reasonable fallback.
|
||||||
|
const char kCurrentDirectoryString[] = "\\";
|
||||||
|
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
|
||||||
|
const DWORD kInvalidFileAttributes = 0xffffffff;
|
||||||
|
#else
|
||||||
|
const char kCurrentDirectoryString[] = ".\\";
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
#else
|
||||||
|
const char kPathSeparator = '/';
|
||||||
|
const char kPathSeparatorString[] = "/";
|
||||||
|
const char kCurrentDirectoryString[] = "./";
|
||||||
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
|
// Returns whether the given character is a valid path separator.
|
||||||
|
static bool IsPathSeparator(char c) {
|
||||||
|
#if GTEST_HAS_ALT_PATH_SEP_
|
||||||
|
return (c == kPathSeparator) || (c == kAlternatePathSeparator);
|
||||||
|
#else
|
||||||
|
return c == kPathSeparator;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the current working directory, or "" if unsuccessful.
|
||||||
|
FilePath FilePath::GetCurrentDir() {
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
// Windows CE doesn't 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);
|
||||||
|
#else
|
||||||
|
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||||
|
return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a copy of the FilePath with the case-insensitive extension removed.
|
||||||
|
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
|
||||||
|
// FilePath("dir/file"). If a case-insensitive extension is not
|
||||||
|
// found, returns a copy of the original FilePath.
|
||||||
|
FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||||
|
String dot_extension(String::Format(".%s", extension));
|
||||||
|
if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
|
||||||
|
return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a pointer to the last occurence of a valid path separator in
|
||||||
|
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||||
|
// separators. Returns NULL if no path separator was found.
|
||||||
|
const char* FilePath::FindLastPathSeparator() const {
|
||||||
|
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||||
|
#if GTEST_HAS_ALT_PATH_SEP_
|
||||||
|
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
||||||
|
// Comparing two pointers of which only one is NULL is undefined.
|
||||||
|
if (last_alt_sep != NULL &&
|
||||||
|
(last_sep == NULL || last_alt_sep > last_sep)) {
|
||||||
|
return last_alt_sep;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return last_sep;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a copy of the FilePath with the directory part removed.
|
||||||
|
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
||||||
|
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
||||||
|
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
|
||||||
|
// returns an empty FilePath ("").
|
||||||
|
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||||
|
FilePath FilePath::RemoveDirectoryName() const {
|
||||||
|
const char* const last_sep = FindLastPathSeparator();
|
||||||
|
return last_sep ? FilePath(String(last_sep + 1)) : *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveFileName returns the directory path with the filename removed.
|
||||||
|
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
|
||||||
|
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
|
||||||
|
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
|
||||||
|
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
||||||
|
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||||
|
FilePath FilePath::RemoveFileName() const {
|
||||||
|
const char* const last_sep = FindLastPathSeparator();
|
||||||
|
String dir;
|
||||||
|
if (last_sep) {
|
||||||
|
dir = String(c_str(), last_sep + 1 - c_str());
|
||||||
|
} else {
|
||||||
|
dir = kCurrentDirectoryString;
|
||||||
|
}
|
||||||
|
return FilePath(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions for naming files in a directory for xml output.
|
||||||
|
|
||||||
|
// Given directory = "dir", base_name = "test", number = 0,
|
||||||
|
// extension = "xml", returns "dir/test.xml". If number is greater
|
||||||
|
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||||
|
// On Windows platform, uses \ as the separator rather than /.
|
||||||
|
FilePath FilePath::MakeFileName(const FilePath& directory,
|
||||||
|
const FilePath& base_name,
|
||||||
|
int number,
|
||||||
|
const char* extension) {
|
||||||
|
String file;
|
||||||
|
if (number == 0) {
|
||||||
|
file = String::Format("%s.%s", base_name.c_str(), extension);
|
||||||
|
} else {
|
||||||
|
file = String::Format("%s_%d.%s", base_name.c_str(), number, extension);
|
||||||
|
}
|
||||||
|
return ConcatPaths(directory, FilePath(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
|
||||||
|
// On Windows, uses \ as the separator rather than /.
|
||||||
|
FilePath FilePath::ConcatPaths(const FilePath& directory,
|
||||||
|
const FilePath& relative_path) {
|
||||||
|
if (directory.IsEmpty())
|
||||||
|
return relative_path;
|
||||||
|
const FilePath dir(directory.RemoveTrailingPathSeparator());
|
||||||
|
return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator,
|
||||||
|
relative_path.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if pathname describes something findable in the file-system,
|
||||||
|
// either a file, directory, or whatever.
|
||||||
|
bool FilePath::FileOrDirectoryExists() const {
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
|
||||||
|
const DWORD attributes = GetFileAttributes(unicode);
|
||||||
|
delete [] unicode;
|
||||||
|
return attributes != kInvalidFileAttributes;
|
||||||
|
#else
|
||||||
|
posix::StatStruct file_stat;
|
||||||
|
return posix::Stat(pathname_.c_str(), &file_stat) == 0;
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if pathname describes a directory in the file-system
|
||||||
|
// that exists.
|
||||||
|
bool FilePath::DirectoryExists() const {
|
||||||
|
bool result = false;
|
||||||
|
#if GTEST_OS_WINDOWS
|
||||||
|
// Don't strip off trailing separator if path is a root directory on
|
||||||
|
// Windows (like "C:\\").
|
||||||
|
const FilePath& path(IsRootDirectory() ? *this :
|
||||||
|
RemoveTrailingPathSeparator());
|
||||||
|
#else
|
||||||
|
const FilePath& path(*this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
|
||||||
|
const DWORD attributes = GetFileAttributes(unicode);
|
||||||
|
delete [] unicode;
|
||||||
|
if ((attributes != kInvalidFileAttributes) &&
|
||||||
|
(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
posix::StatStruct file_stat;
|
||||||
|
result = posix::Stat(path.c_str(), &file_stat) == 0 &&
|
||||||
|
posix::IsDir(file_stat);
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if pathname describes a root directory. (Windows has one
|
||||||
|
// root directory per disk drive.)
|
||||||
|
bool FilePath::IsRootDirectory() const {
|
||||||
|
#if GTEST_OS_WINDOWS
|
||||||
|
// TODO(wan@google.com): 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]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if pathname describes an absolute path.
|
||||||
|
bool FilePath::IsAbsolutePath() const {
|
||||||
|
const char* const name = pathname_.c_str();
|
||||||
|
#if GTEST_OS_WINDOWS
|
||||||
|
return pathname_.length() >= 3 &&
|
||||||
|
((name[0] >= 'a' && name[0] <= 'z') ||
|
||||||
|
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
||||||
|
name[1] == ':' &&
|
||||||
|
IsPathSeparator(name[2]);
|
||||||
|
#else
|
||||||
|
return IsPathSeparator(name[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a pathname for a file that does not currently exist. The pathname
|
||||||
|
// will be directory/base_name.extension or
|
||||||
|
// directory/base_name_<number>.extension if directory/base_name.extension
|
||||||
|
// already exists. The number will be incremented until a pathname is found
|
||||||
|
// that does not already exist.
|
||||||
|
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
|
||||||
|
// There could be a race condition if two or more processes are calling this
|
||||||
|
// function at the same time -- they could both pick the same filename.
|
||||||
|
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
|
||||||
|
const FilePath& base_name,
|
||||||
|
const char* extension) {
|
||||||
|
FilePath full_pathname;
|
||||||
|
int number = 0;
|
||||||
|
do {
|
||||||
|
full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
|
||||||
|
} while (full_pathname.FileOrDirectoryExists());
|
||||||
|
return full_pathname;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if FilePath ends with a path separator, which indicates that
|
||||||
|
// it is intended to represent a directory. Returns false otherwise.
|
||||||
|
// This does NOT check that a directory (or file) actually exists.
|
||||||
|
bool FilePath::IsDirectory() const {
|
||||||
|
return !pathname_.empty() &&
|
||||||
|
IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create directories so that path exists. Returns true if successful or if
|
||||||
|
// the directories already exist; returns false if unable to create directories
|
||||||
|
// for any reason.
|
||||||
|
bool FilePath::CreateDirectoriesRecursively() const {
|
||||||
|
if (!this->IsDirectory()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathname_.length() == 0 || this->DirectoryExists()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
|
||||||
|
return parent.CreateDirectoriesRecursively() && this->CreateFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the directory so that path exists. Returns true if successful or
|
||||||
|
// if the directory already exists; returns false if unable to create the
|
||||||
|
// directory for any reason, including if the parent directory does not
|
||||||
|
// exist. Not named "CreateDirectory" because that's a macro on Windows.
|
||||||
|
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;
|
||||||
|
delete [] unicode;
|
||||||
|
#elif GTEST_OS_WINDOWS
|
||||||
|
int result = _mkdir(pathname_.c_str());
|
||||||
|
#else
|
||||||
|
int result = mkdir(pathname_.c_str(), 0777);
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
|
if (result == -1) {
|
||||||
|
return this->DirectoryExists(); // An error is OK if the directory exists.
|
||||||
|
}
|
||||||
|
return true; // No error.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If input name has a trailing separator character, remove it and return the
|
||||||
|
// name, otherwise return the name string unmodified.
|
||||||
|
// On Windows platform, uses \ as the separator, other platforms use /.
|
||||||
|
FilePath FilePath::RemoveTrailingPathSeparator() const {
|
||||||
|
return IsDirectory()
|
||||||
|
? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
|
||||||
|
: *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes any redundant separators that might be in the pathname.
|
||||||
|
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||||
|
// redundancies that might be in a pathname involving "." or "..".
|
||||||
|
// TODO(wan@google.com): 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);
|
||||||
|
|
||||||
|
while (*src != '\0') {
|
||||||
|
*dest_ptr = *src;
|
||||||
|
if (!IsPathSeparator(*src)) {
|
||||||
|
src++;
|
||||||
|
} else {
|
||||||
|
#if GTEST_HAS_ALT_PATH_SEP_
|
||||||
|
if (*dest_ptr == kAlternatePathSeparator) {
|
||||||
|
*dest_ptr = kPathSeparator;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
while (IsPathSeparator(*src))
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
dest_ptr++;
|
||||||
|
}
|
||||||
|
*dest_ptr = '\0';
|
||||||
|
pathname_ = dest;
|
||||||
|
delete[] dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,711 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
#include <windows.h> // For TerminateProcess()
|
||||||
|
#elif GTEST_OS_WINDOWS
|
||||||
|
#include <io.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
|
#if GTEST_OS_MAC
|
||||||
|
#include <mach/mach_init.h>
|
||||||
|
#include <mach/task.h>
|
||||||
|
#include <mach/vm_map.h>
|
||||||
|
#endif // GTEST_OS_MAC
|
||||||
|
|
||||||
|
#include <gtest/gtest-spi.h>
|
||||||
|
#include <gtest/gtest-message.h>
|
||||||
|
#include <gtest/internal/gtest-string.h>
|
||||||
|
|
||||||
|
// Indicates that this translation unit is part of Google Test's
|
||||||
|
// implementation. It must come before gtest-internal-inl.h is
|
||||||
|
// included, or there will be a compiler error. This trick is to
|
||||||
|
// prevent a user from accidentally including gtest-internal-inl.h in
|
||||||
|
// his code.
|
||||||
|
#define GTEST_IMPLEMENTATION_ 1
|
||||||
|
#include "src/gtest-internal-inl.h"
|
||||||
|
#undef GTEST_IMPLEMENTATION_
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||||
|
// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
|
||||||
|
const int kStdOutFileno = 1;
|
||||||
|
const int kStdErrFileno = 2;
|
||||||
|
#else
|
||||||
|
const int kStdOutFileno = STDOUT_FILENO;
|
||||||
|
const int kStdErrFileno = STDERR_FILENO;
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
#if GTEST_OS_MAC
|
||||||
|
|
||||||
|
// Returns the number of threads running in the process, or 0 to indicate that
|
||||||
|
// we cannot detect it.
|
||||||
|
size_t GetThreadCount() {
|
||||||
|
const task_t task = mach_task_self();
|
||||||
|
mach_msg_type_number_t thread_count;
|
||||||
|
thread_act_array_t thread_list;
|
||||||
|
const kern_return_t status = task_threads(task, &thread_list, &thread_count);
|
||||||
|
if (status == KERN_SUCCESS) {
|
||||||
|
// task_threads allocates resources in thread_list and we need to free them
|
||||||
|
// to avoid leaks.
|
||||||
|
vm_deallocate(task,
|
||||||
|
reinterpret_cast<vm_address_t>(thread_list),
|
||||||
|
sizeof(thread_t) * thread_count);
|
||||||
|
return static_cast<size_t>(thread_count);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
size_t GetThreadCount() {
|
||||||
|
// There's no portable way to detect the number of threads, so we just
|
||||||
|
// return 0 to indicate that we cannot detect it.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GTEST_OS_MAC
|
||||||
|
|
||||||
|
#if GTEST_USES_POSIX_RE
|
||||||
|
|
||||||
|
// Implements RE. Currently only needed for death tests.
|
||||||
|
|
||||||
|
RE::~RE() {
|
||||||
|
if (is_valid_) {
|
||||||
|
// regfree'ing an invalid regex might crash because the content
|
||||||
|
// of the regex is undefined. Since the regex's are essentially
|
||||||
|
// the same, one cannot be valid (or invalid) without the other
|
||||||
|
// being so too.
|
||||||
|
regfree(&partial_regex_);
|
||||||
|
regfree(&full_regex_);
|
||||||
|
}
|
||||||
|
free(const_cast<char*>(pattern_));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff regular expression re matches the entire str.
|
||||||
|
bool RE::FullMatch(const char* str, const RE& re) {
|
||||||
|
if (!re.is_valid_) return false;
|
||||||
|
|
||||||
|
regmatch_t match;
|
||||||
|
return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff 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;
|
||||||
|
|
||||||
|
regmatch_t match;
|
||||||
|
return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initializes an RE from its string representation.
|
||||||
|
void RE::Init(const char* regex) {
|
||||||
|
pattern_ = posix::StrDup(regex);
|
||||||
|
|
||||||
|
// Reserves enough bytes to hold the regular expression used for a
|
||||||
|
// full match.
|
||||||
|
const size_t full_regex_len = strlen(regex) + 10;
|
||||||
|
char* const full_pattern = new char[full_regex_len];
|
||||||
|
|
||||||
|
snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
|
||||||
|
is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
|
||||||
|
// We want to call regcomp(&partial_regex_, ...) even if the
|
||||||
|
// previous expression returns false. Otherwise partial_regex_ may
|
||||||
|
// not be properly initialized can may cause trouble when it's
|
||||||
|
// freed.
|
||||||
|
//
|
||||||
|
// Some implementation of POSIX regex (e.g. on at least some
|
||||||
|
// versions of Cygwin) doesn't accept the empty string as a valid
|
||||||
|
// regex. We change it to an equivalent form "()" to be safe.
|
||||||
|
if (is_valid_) {
|
||||||
|
const char* const partial_regex = (*regex == '\0') ? "()" : regex;
|
||||||
|
is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(is_valid_)
|
||||||
|
<< "Regular expression \"" << regex
|
||||||
|
<< "\" is not a valid POSIX Extended regular expression.";
|
||||||
|
|
||||||
|
delete[] full_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif GTEST_USES_SIMPLE_RE
|
||||||
|
|
||||||
|
// Returns true iff ch appears anywhere in str (excluding the
|
||||||
|
// terminating '\0' character).
|
||||||
|
bool IsInSet(char ch, const char* str) {
|
||||||
|
return ch != '\0' && strchr(str, ch) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff ch belongs to the given classification. Unlike
|
||||||
|
// similar functions in <ctype.h>, these aren't affected by the
|
||||||
|
// current locale.
|
||||||
|
bool IsDigit(char ch) { return '0' <= ch && ch <= '9'; }
|
||||||
|
bool IsPunct(char ch) {
|
||||||
|
return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
|
||||||
|
}
|
||||||
|
bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
|
||||||
|
bool IsWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
|
||||||
|
bool IsWordChar(char ch) {
|
||||||
|
return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
|
||||||
|
('0' <= ch && ch <= '9') || ch == '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff "\\c" is a supported escape sequence.
|
||||||
|
bool IsValidEscape(char c) {
|
||||||
|
return (IsPunct(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.
|
||||||
|
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
||||||
|
if (escaped) { // "\\p" where p is pattern_char.
|
||||||
|
switch (pattern_char) {
|
||||||
|
case 'd': return IsDigit(ch);
|
||||||
|
case 'D': return !IsDigit(ch);
|
||||||
|
case 'f': return ch == '\f';
|
||||||
|
case 'n': return ch == '\n';
|
||||||
|
case 'r': return ch == '\r';
|
||||||
|
case 's': return IsWhiteSpace(ch);
|
||||||
|
case 'S': return !IsWhiteSpace(ch);
|
||||||
|
case 't': return ch == '\t';
|
||||||
|
case 'v': return ch == '\v';
|
||||||
|
case 'w': return IsWordChar(ch);
|
||||||
|
case 'W': return !IsWordChar(ch);
|
||||||
|
}
|
||||||
|
return IsPunct(pattern_char) && pattern_char == ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function used by ValidateRegex() to format error messages.
|
||||||
|
String FormatRegexSyntaxError(const char* regex, int index) {
|
||||||
|
return (Message() << "Syntax error at index " << index
|
||||||
|
<< " in simple regular expression \"" << regex << "\": ").GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates non-fatal failures and returns false if regex is invalid;
|
||||||
|
// otherwise returns true.
|
||||||
|
bool ValidateRegex(const char* regex) {
|
||||||
|
if (regex == NULL) {
|
||||||
|
// TODO(wan@google.com): fix the source file location in the
|
||||||
|
// assertion failures to match where the regex is used in user
|
||||||
|
// code.
|
||||||
|
ADD_FAILURE() << "NULL is not a valid simple regular expression.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_valid = true;
|
||||||
|
|
||||||
|
// True iff ?, *, or + can follow the previous atom.
|
||||||
|
bool prev_repeatable = false;
|
||||||
|
for (int i = 0; regex[i]; i++) {
|
||||||
|
if (regex[i] == '\\') { // An escape sequence
|
||||||
|
i++;
|
||||||
|
if (regex[i] == '\0') {
|
||||||
|
ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
|
||||||
|
<< "'\\' cannot appear at the end.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsValidEscape(regex[i])) {
|
||||||
|
ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
|
||||||
|
<< "invalid escape sequence \"\\" << regex[i] << "\".";
|
||||||
|
is_valid = false;
|
||||||
|
}
|
||||||
|
prev_repeatable = true;
|
||||||
|
} else { // Not an escape sequence.
|
||||||
|
const char ch = regex[i];
|
||||||
|
|
||||||
|
if (ch == '^' && i > 0) {
|
||||||
|
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
|
||||||
|
<< "'^' can only appear at the beginning.";
|
||||||
|
is_valid = false;
|
||||||
|
} else if (ch == '$' && regex[i + 1] != '\0') {
|
||||||
|
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
|
||||||
|
<< "'$' can only appear at the end.";
|
||||||
|
is_valid = false;
|
||||||
|
} else if (IsInSet(ch, "()[]{}|")) {
|
||||||
|
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
|
||||||
|
<< "'" << ch << "' is unsupported.";
|
||||||
|
is_valid = false;
|
||||||
|
} else if (IsRepeat(ch) && !prev_repeatable) {
|
||||||
|
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
|
||||||
|
<< "'" << ch << "' can only follow a repeatable token.";
|
||||||
|
is_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_repeatable = !IsInSet(ch, "^$?*+");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches a repeated regex atom followed by a valid simple regular
|
||||||
|
// expression. The regex atom is defined as c if escaped is false,
|
||||||
|
// or \c otherwise. repeat is the repetition meta character (?, *,
|
||||||
|
// or +). The behavior is undefined if str contains too many
|
||||||
|
// characters to be indexable by size_t, in which case the test will
|
||||||
|
// probably time out anyway. We are fine with this limitation as
|
||||||
|
// std::string has it too.
|
||||||
|
bool MatchRepetitionAndRegexAtHead(
|
||||||
|
bool escaped, char c, char repeat, const char* regex,
|
||||||
|
const char* str) {
|
||||||
|
const size_t min_count = (repeat == '+') ? 1 : 0;
|
||||||
|
const size_t max_count = (repeat == '?') ? 1 :
|
||||||
|
static_cast<size_t>(-1) - 1;
|
||||||
|
// We cannot call numeric_limits::max() as it conflicts with the
|
||||||
|
// max() macro on Windows.
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= max_count; ++i) {
|
||||||
|
// We know that the atom matches each of the first i characters in str.
|
||||||
|
if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
|
||||||
|
// We have enough matches at the head, and the tail matches too.
|
||||||
|
// Since we only care about *whether* the pattern matches str
|
||||||
|
// (as opposed to *how* it matches), there is no need to find a
|
||||||
|
// greedy match.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
// result is undefined.
|
||||||
|
bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||||
|
if (*regex == '\0') // An empty regex matches a prefix of anything.
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// "$" only matches the end of a string. Note that regex being
|
||||||
|
// valid guarantees that there's nothing after "$" in it.
|
||||||
|
if (*regex == '$')
|
||||||
|
return *str == '\0';
|
||||||
|
|
||||||
|
// Is the first thing in regex an escape sequence?
|
||||||
|
const bool escaped = *regex == '\\';
|
||||||
|
if (escaped)
|
||||||
|
++regex;
|
||||||
|
if (IsRepeat(regex[1])) {
|
||||||
|
// MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
|
||||||
|
// here's an indirect recursion. It terminates as the regex gets
|
||||||
|
// shorter in each recursion.
|
||||||
|
return MatchRepetitionAndRegexAtHead(
|
||||||
|
escaped, regex[0], regex[1], regex + 2, str);
|
||||||
|
} else {
|
||||||
|
// regex isn't empty, isn't "$", and doesn't start with a
|
||||||
|
// repetition. We match the first atom of regex with the first
|
||||||
|
// character of str and recurse.
|
||||||
|
return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
|
||||||
|
MatchRegexAtHead(regex + 1, str + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff 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
|
||||||
|
// stack space normally. In rare cases the time complexity can be
|
||||||
|
// 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 == '^')
|
||||||
|
return MatchRegexAtHead(regex + 1, str);
|
||||||
|
|
||||||
|
// A successful match can be anywhere in str.
|
||||||
|
do {
|
||||||
|
if (MatchRegexAtHead(regex, str))
|
||||||
|
return true;
|
||||||
|
} while (*str++ != '\0');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the RE class.
|
||||||
|
|
||||||
|
RE::~RE() {
|
||||||
|
free(const_cast<char*>(pattern_));
|
||||||
|
free(const_cast<char*>(full_pattern_));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff 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).
|
||||||
|
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_ = posix::StrDup(regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_valid_ = ValidateRegex(regex);
|
||||||
|
if (!is_valid_) {
|
||||||
|
// No need to calculate the full pattern when the regex is invalid.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t len = strlen(regex);
|
||||||
|
// Reserves enough bytes to hold the regular expression used for a
|
||||||
|
// full match: we need space to prepend a '^', append a '$', and
|
||||||
|
// terminate the string with '\0'.
|
||||||
|
char* buffer = static_cast<char*>(malloc(len + 3));
|
||||||
|
full_pattern_ = buffer;
|
||||||
|
|
||||||
|
if (*regex != '^')
|
||||||
|
*buffer++ = '^'; // Makes sure full_pattern_ starts with '^'.
|
||||||
|
|
||||||
|
// We don't use snprintf or strncpy, as they trigger a warning when
|
||||||
|
// compiled with VC++ 8.0.
|
||||||
|
memcpy(buffer, regex, len);
|
||||||
|
buffer += len;
|
||||||
|
|
||||||
|
if (len == 0 || regex[len - 1] != '$')
|
||||||
|
*buffer++ = '$'; // Makes sure full_pattern_ ends with '$'.
|
||||||
|
|
||||||
|
*buffer = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GTEST_USES_POSIX_RE
|
||||||
|
|
||||||
|
|
||||||
|
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
|
||||||
|
: severity_(severity) {
|
||||||
|
const char* const marker =
|
||||||
|
severity == GTEST_INFO ? "[ INFO ]" :
|
||||||
|
severity == GTEST_WARNING ? "[WARNING]" :
|
||||||
|
severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
|
||||||
|
GetStream() << ::std::endl << marker << " "
|
||||||
|
<< FormatFileLocation(file, line).c_str() << ": ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
|
||||||
|
GTestLog::~GTestLog() {
|
||||||
|
GetStream() << ::std::endl;
|
||||||
|
if (severity_ == GTEST_FATAL) {
|
||||||
|
fflush(stderr);
|
||||||
|
posix::Abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Disable Microsoft deprecation warnings for POSIX functions called from
|
||||||
|
// this class (creat, dup, dup2, and close)
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4996)
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
#if GTEST_HAS_STREAM_REDIRECTION_
|
||||||
|
|
||||||
|
// Object that captures an output stream (stdout/stderr).
|
||||||
|
class CapturedStream {
|
||||||
|
public:
|
||||||
|
// The ctor redirects the stream to a temporary file.
|
||||||
|
CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
|
||||||
|
#if GTEST_OS_WINDOWS
|
||||||
|
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
||||||
|
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
||||||
|
|
||||||
|
::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
|
||||||
|
const UINT success = ::GetTempFileNameA(temp_dir_path,
|
||||||
|
"gtest_redir",
|
||||||
|
0, // Generate unique file name.
|
||||||
|
temp_file_path);
|
||||||
|
GTEST_CHECK_(success != 0)
|
||||||
|
<< "Unable to create a temporary file in " << temp_dir_path;
|
||||||
|
const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
|
||||||
|
GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
|
||||||
|
<< temp_file_path;
|
||||||
|
filename_ = temp_file_path;
|
||||||
|
#else
|
||||||
|
// There's no guarantee that a test has write access to the
|
||||||
|
// current directory, so we create the temporary file in the /tmp
|
||||||
|
// directory instead.
|
||||||
|
char name_template[] = "/tmp/captured_stream.XXXXXX";
|
||||||
|
const int captured_fd = mkstemp(name_template);
|
||||||
|
filename_ = name_template;
|
||||||
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
fflush(NULL);
|
||||||
|
dup2(captured_fd, fd_);
|
||||||
|
close(captured_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CapturedStream() {
|
||||||
|
remove(filename_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
String GetCapturedString() {
|
||||||
|
if (uncaptured_fd_ != -1) {
|
||||||
|
// Restores the original stream.
|
||||||
|
fflush(NULL);
|
||||||
|
dup2(uncaptured_fd_, fd_);
|
||||||
|
close(uncaptured_fd_);
|
||||||
|
uncaptured_fd_ = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* const file = posix::FOpen(filename_.c_str(), "r");
|
||||||
|
const String content = ReadEntireFile(file);
|
||||||
|
posix::FClose(file);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Reads the entire content of a file as a String.
|
||||||
|
static String ReadEntireFile(FILE* file);
|
||||||
|
|
||||||
|
// Returns the size (in bytes) of a file.
|
||||||
|
static size_t GetFileSize(FILE* file);
|
||||||
|
|
||||||
|
const int fd_; // A stream to capture.
|
||||||
|
int uncaptured_fd_;
|
||||||
|
// Name of the temporary file holding the stderr output.
|
||||||
|
::std::string filename_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the size (in bytes) of a file.
|
||||||
|
size_t CapturedStream::GetFileSize(FILE* file) {
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
return static_cast<size_t>(ftell(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads the entire content of a file as a string.
|
||||||
|
String CapturedStream::ReadEntireFile(FILE* file) {
|
||||||
|
const size_t file_size = GetFileSize(file);
|
||||||
|
char* const buffer = new char[file_size];
|
||||||
|
|
||||||
|
size_t bytes_last_read = 0; // # of bytes read in the last fread()
|
||||||
|
size_t bytes_read = 0; // # of bytes read so far
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
// Keeps reading the file until we cannot read further or the
|
||||||
|
// pre-determined file size is reached.
|
||||||
|
do {
|
||||||
|
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
|
||||||
|
bytes_read += bytes_last_read;
|
||||||
|
} while (bytes_last_read > 0 && bytes_read < file_size);
|
||||||
|
|
||||||
|
const String content(buffer, bytes_read);
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
static CapturedStream* g_captured_stderr = NULL;
|
||||||
|
static CapturedStream* g_captured_stdout = NULL;
|
||||||
|
|
||||||
|
// Starts capturing an output stream (stdout/stderr).
|
||||||
|
void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
|
||||||
|
if (*stream != NULL) {
|
||||||
|
GTEST_LOG_(FATAL) << "Only one " << stream_name
|
||||||
|
<< " capturer can exist at a time.";
|
||||||
|
}
|
||||||
|
*stream = new CapturedStream(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stops capturing the output stream and returns the captured string.
|
||||||
|
String GetCapturedStream(CapturedStream** captured_stream) {
|
||||||
|
const String content = (*captured_stream)->GetCapturedString();
|
||||||
|
|
||||||
|
delete *captured_stream;
|
||||||
|
*captured_stream = NULL;
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starts capturing stdout.
|
||||||
|
void CaptureStdout() {
|
||||||
|
CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starts capturing stderr.
|
||||||
|
void CaptureStderr() {
|
||||||
|
CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stops capturing stdout and returns the captured string.
|
||||||
|
String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
|
||||||
|
|
||||||
|
// Stops capturing stderr and returns the captured string.
|
||||||
|
String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_STREAM_REDIRECTION_
|
||||||
|
|
||||||
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
// A copy of all command line arguments. Set by InitGoogleTest().
|
||||||
|
::std::vector<String> g_argvs;
|
||||||
|
|
||||||
|
// Returns the command line as a vector of strings.
|
||||||
|
const ::std::vector<String>& GetArgvs() { return g_argvs; }
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
namespace posix {
|
||||||
|
void Abort() {
|
||||||
|
DebugBreak();
|
||||||
|
TerminateProcess(GetCurrentProcess(), 1);
|
||||||
|
}
|
||||||
|
} // namespace posix
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
|
// Returns the name of the environment variable corresponding to the
|
||||||
|
// given flag. For example, FlagToEnvVar("foo") will return
|
||||||
|
// "GTEST_FOO" in the open-source version.
|
||||||
|
static String FlagToEnvVar(const char* flag) {
|
||||||
|
const String full_flag =
|
||||||
|
(Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
|
||||||
|
|
||||||
|
Message env_var;
|
||||||
|
for (size_t i = 0; i != full_flag.length(); i++) {
|
||||||
|
env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return env_var.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
// Parses the environment variable as a decimal integer.
|
||||||
|
char* end = NULL;
|
||||||
|
const long long_value = strtol(str, &end, 10); // NOLINT
|
||||||
|
|
||||||
|
// Has strtol() consumed all characters in the string?
|
||||||
|
if (*end != '\0') {
|
||||||
|
// No - an invalid character was encountered.
|
||||||
|
Message msg;
|
||||||
|
msg << "WARNING: " << src_text
|
||||||
|
<< " is expected to be a 32-bit integer, but actually"
|
||||||
|
<< " has value \"" << str << "\".\n";
|
||||||
|
printf("%s", msg.GetString().c_str());
|
||||||
|
fflush(stdout);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the parsed value in the range of an Int32?
|
||||||
|
const Int32 result = static_cast<Int32>(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.
|
||||||
|
) {
|
||||||
|
Message msg;
|
||||||
|
msg << "WARNING: " << src_text
|
||||||
|
<< " is expected to be a 32-bit integer, but actually"
|
||||||
|
<< " has value " << str << ", which overflows.\n";
|
||||||
|
printf("%s", msg.GetString().c_str());
|
||||||
|
fflush(stdout);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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".
|
||||||
|
bool BoolFromGTestEnv(const char* flag, bool default_value) {
|
||||||
|
const 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
const String env_var = FlagToEnvVar(flag);
|
||||||
|
const char* const string_value = posix::GetEnv(env_var.c_str());
|
||||||
|
if (string_value == NULL) {
|
||||||
|
// The environment variable is not set.
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Int32 result = default_value;
|
||||||
|
if (!ParseInt32(Message() << "Environment variable " << env_var,
|
||||||
|
string_value, &result)) {
|
||||||
|
printf("The default value %s is used.\n",
|
||||||
|
(Message() << default_value).GetString().c_str());
|
||||||
|
fflush(stdout);
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads and returns the string environment variable corresponding to
|
||||||
|
// the given flag; if it's not set, returns default_value.
|
||||||
|
const char* StringFromGTestEnv(const char* flag, const char* default_value) {
|
||||||
|
const String env_var = FlagToEnvVar(flag);
|
||||||
|
const char* const value = posix::GetEnv(env_var.c_str());
|
||||||
|
return value == NULL ? default_value : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
|
@ -0,0 +1,110 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: mheule@google.com (Markus Heule)
|
||||||
|
//
|
||||||
|
// The Google C++ Testing Framework (Google Test)
|
||||||
|
|
||||||
|
#include <gtest/gtest-test-part.h>
|
||||||
|
|
||||||
|
// Indicates that this translation unit is part of Google Test's
|
||||||
|
// implementation. It must come before gtest-internal-inl.h is
|
||||||
|
// included, or there will be a compiler error. This trick is to
|
||||||
|
// prevent a user from accidentally including gtest-internal-inl.h in
|
||||||
|
// his code.
|
||||||
|
#define GTEST_IMPLEMENTATION_ 1
|
||||||
|
#include "src/gtest-internal-inl.h"
|
||||||
|
#undef GTEST_IMPLEMENTATION_
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
using internal::GetUnitTestImpl;
|
||||||
|
|
||||||
|
// Gets the summary of the failure message by omitting the stack trace
|
||||||
|
// in it.
|
||||||
|
internal::String TestPartResult::ExtractSummary(const char* message) {
|
||||||
|
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
|
||||||
|
return stack_trace == NULL ? internal::String(message) :
|
||||||
|
internal::String(message, stack_trace - message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appends a TestPartResult to the array.
|
||||||
|
void TestPartResultArray::Append(const TestPartResult& result) {
|
||||||
|
array_.push_back(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the TestPartResult at the given index (0-based).
|
||||||
|
const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
|
||||||
|
if (index < 0 || index >= size()) {
|
||||||
|
printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
|
||||||
|
internal::posix::Abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the number of TestPartResult objects in the array.
|
||||||
|
int TestPartResultArray::size() const {
|
||||||
|
return static_cast<int>(array_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
|
||||||
|
: has_new_fatal_failure_(false),
|
||||||
|
original_reporter_(GetUnitTestImpl()->
|
||||||
|
GetTestPartResultReporterForCurrentThread()) {
|
||||||
|
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
|
||||||
|
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
|
||||||
|
original_reporter_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HasNewFatalFailureHelper::ReportTestPartResult(
|
||||||
|
const TestPartResult& result) {
|
||||||
|
if (result.fatally_failed())
|
||||||
|
has_new_fatal_failure_ = true;
|
||||||
|
original_reporter_->ReportTestPartResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace testing
|
|
@ -0,0 +1,110 @@
|
||||||
|
// Copyright 2008 Google Inc.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
#include <gtest/gtest-typed-test.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
#if GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
// Skips to the first non-space char in str. Returns an empty string if str
|
||||||
|
// contains only whitespace characters.
|
||||||
|
static const char* SkipSpaces(const char* str) {
|
||||||
|
while (isspace(*str))
|
||||||
|
str++;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies that registered_tests match the test names in
|
||||||
|
// defined_test_names_; returns registered_tests if successful, or
|
||||||
|
// aborts the program otherwise.
|
||||||
|
const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||||
|
const char* file, int line, const char* registered_tests) {
|
||||||
|
typedef ::std::set<const char*>::const_iterator DefinedTestIter;
|
||||||
|
registered_ = true;
|
||||||
|
|
||||||
|
// Skip initial whitespace in registered_tests since some
|
||||||
|
// preprocessors prefix stringizied literals with whitespace.
|
||||||
|
registered_tests = SkipSpaces(registered_tests);
|
||||||
|
|
||||||
|
Message errors;
|
||||||
|
::std::set<String> tests;
|
||||||
|
for (const char* names = registered_tests; names != NULL;
|
||||||
|
names = SkipComma(names)) {
|
||||||
|
const String name = GetPrefixUntilComma(names);
|
||||||
|
if (tests.count(name) != 0) {
|
||||||
|
errors << "Test " << name << " is listed more than once.\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (DefinedTestIter it = defined_test_names_.begin();
|
||||||
|
it != defined_test_names_.end();
|
||||||
|
++it) {
|
||||||
|
if (name == *it) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
tests.insert(name);
|
||||||
|
} else {
|
||||||
|
errors << "No test named " << name
|
||||||
|
<< " can be found in this test case.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DefinedTestIter it = defined_test_names_.begin();
|
||||||
|
it != defined_test_names_.end();
|
||||||
|
++it) {
|
||||||
|
if (tests.count(*it) == 0) {
|
||||||
|
errors << "You forgot to list test " << *it << ".\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const String& errors_str = errors.GetString();
|
||||||
|
if (errors_str != "") {
|
||||||
|
fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
|
||||||
|
errors_str.c_str());
|
||||||
|
fflush(stderr);
|
||||||
|
posix::Abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return registered_tests;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2006, 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.
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
std::cout << "Running main() from gtest_main.cc\n";
|
||||||
|
|
||||||
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,146 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some commonly used cardinalities. More
|
||||||
|
// cardinalities can be defined by the user implementing the
|
||||||
|
// CardinalityInterface interface if necessary.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// To implement a cardinality Foo, define:
|
||||||
|
// 1. a class FooCardinality that implements the
|
||||||
|
// CardinalityInterface interface, and
|
||||||
|
// 2. a factory function that creates a Cardinality object from a
|
||||||
|
// const FooCardinality*.
|
||||||
|
//
|
||||||
|
// The two-level delegation design follows that of Matcher, providing
|
||||||
|
// consistency for extension developers. It also eases ownership
|
||||||
|
// management as Cardinality objects can now be copied like plain values.
|
||||||
|
|
||||||
|
// The implementation of a cardinality.
|
||||||
|
class CardinalityInterface {
|
||||||
|
public:
|
||||||
|
virtual ~CardinalityInterface() {}
|
||||||
|
|
||||||
|
// Conservative estimate on the lower/upper bound of the number of
|
||||||
|
// calls allowed.
|
||||||
|
virtual int ConservativeLowerBound() const { return 0; }
|
||||||
|
virtual int ConservativeUpperBound() const { return INT_MAX; }
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will satisfy this cardinality.
|
||||||
|
virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will saturate this cardinality.
|
||||||
|
virtual bool IsSaturatedByCallCount(int call_count) const = 0;
|
||||||
|
|
||||||
|
// Describes self to an ostream.
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A Cardinality is a copyable and IMMUTABLE (except by assignment)
|
||||||
|
// object that specifies how many times a mock function is expected to
|
||||||
|
// be called. The implementation of Cardinality is just a linked_ptr
|
||||||
|
// to const CardinalityInterface, so copying is fairly cheap.
|
||||||
|
// Don't inherit from Cardinality!
|
||||||
|
class Cardinality {
|
||||||
|
public:
|
||||||
|
// Constructs a null cardinality. Needed for storing Cardinality
|
||||||
|
// objects in STL containers.
|
||||||
|
Cardinality() {}
|
||||||
|
|
||||||
|
// Constructs a Cardinality from its implementation.
|
||||||
|
explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {}
|
||||||
|
|
||||||
|
// Conservative estimate on the lower/upper bound of the number of
|
||||||
|
// calls allowed.
|
||||||
|
int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); }
|
||||||
|
int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); }
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will satisfy this cardinality.
|
||||||
|
bool IsSatisfiedByCallCount(int call_count) const {
|
||||||
|
return impl_->IsSatisfiedByCallCount(call_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will saturate this cardinality.
|
||||||
|
bool IsSaturatedByCallCount(int call_count) const {
|
||||||
|
return impl_->IsSaturatedByCallCount(call_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will over-saturate this
|
||||||
|
// cardinality, i.e. exceed the maximum number of allowed calls.
|
||||||
|
bool IsOverSaturatedByCallCount(int call_count) const {
|
||||||
|
return impl_->IsSaturatedByCallCount(call_count) &&
|
||||||
|
!impl_->IsSatisfiedByCallCount(call_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes self to an ostream
|
||||||
|
void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
|
||||||
|
|
||||||
|
// Describes the given actual call count to an ostream.
|
||||||
|
static void DescribeActualCallCountTo(int actual_call_count,
|
||||||
|
::std::ostream* os);
|
||||||
|
private:
|
||||||
|
internal::linked_ptr<const CardinalityInterface> impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates a cardinality that allows at least n calls.
|
||||||
|
Cardinality AtLeast(int n);
|
||||||
|
|
||||||
|
// Creates a cardinality that allows at most n calls.
|
||||||
|
Cardinality AtMost(int n);
|
||||||
|
|
||||||
|
// Creates a cardinality that allows any number of calls.
|
||||||
|
Cardinality AnyNumber();
|
||||||
|
|
||||||
|
// Creates a cardinality that allows between min and max calls.
|
||||||
|
Cardinality Between(int min, int max);
|
||||||
|
|
||||||
|
// Creates a cardinality that allows exactly n calls.
|
||||||
|
Cardinality Exactly(int n);
|
||||||
|
|
||||||
|
// Creates a cardinality from its implementation.
|
||||||
|
inline Cardinality MakeCardinality(const CardinalityInterface* c) {
|
||||||
|
return Cardinality(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,825 @@
|
||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-actions.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
$$}} This meta comment fixes auto-indentation in editors.
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some commonly used variadic actions.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||||
|
|
||||||
|
#include <gmock/gmock-actions.h>
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary
|
||||||
|
// function or method with the unpacked values, where F is a function
|
||||||
|
// type that takes N arguments.
|
||||||
|
template <typename Result, typename ArgumentTuple>
|
||||||
|
class InvokeHelper;
|
||||||
|
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var types = [[$for j [[, typename A$j]]]]
|
||||||
|
$var as = [[$for j, [[A$j]]]]
|
||||||
|
$var args = [[$if i==0 [[]] $else [[ args]]]]
|
||||||
|
$var import = [[$if i==0 [[]] $else [[
|
||||||
|
using ::std::tr1::get;
|
||||||
|
|
||||||
|
]]]]
|
||||||
|
$var gets = [[$for j, [[get<$(j - 1)>(args)]]]]
|
||||||
|
template <typename R$types>
|
||||||
|
class InvokeHelper<R, ::std::tr1::tuple<$as> > {
|
||||||
|
public:
|
||||||
|
template <typename Function>
|
||||||
|
static R Invoke(Function function, const ::std::tr1::tuple<$as>&$args) {
|
||||||
|
$import return function($gets);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Class, typename MethodPtr>
|
||||||
|
static R InvokeMethod(Class* obj_ptr,
|
||||||
|
MethodPtr method_ptr,
|
||||||
|
const ::std::tr1::tuple<$as>&$args) {
|
||||||
|
$import return (obj_ptr->*method_ptr)($gets);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
// CallableHelper has static methods for invoking "callables",
|
||||||
|
// i.e. function pointers and functors. It uses overloading to
|
||||||
|
// provide a uniform interface for invoking different kinds of
|
||||||
|
// callables. In particular, you can use:
|
||||||
|
//
|
||||||
|
// CallableHelper<R>::Call(callable, a1, a2, ..., an)
|
||||||
|
//
|
||||||
|
// to invoke an n-ary callable, where R is its return type. If an
|
||||||
|
// argument, say a2, needs to be passed by reference, you should write
|
||||||
|
// ByRef(a2) instead of a2 in the above expression.
|
||||||
|
template <typename R>
|
||||||
|
class CallableHelper {
|
||||||
|
public:
|
||||||
|
// Calls a nullary callable.
|
||||||
|
template <typename Function>
|
||||||
|
static R Call(Function function) { return function(); }
|
||||||
|
|
||||||
|
// Calls a unary callable.
|
||||||
|
|
||||||
|
// We deliberately pass a1 by value instead of const reference here
|
||||||
|
// in case it is a C-string literal. If we had declared the
|
||||||
|
// parameter as 'const A1& a1' and write Call(function, "Hi"), the
|
||||||
|
// compiler would've thought A1 is 'char[3]', which causes trouble
|
||||||
|
// when you need to copy a value of type A1. By declaring the
|
||||||
|
// parameter as 'A1 a1', the compiler will correctly infer that A1
|
||||||
|
// is 'const char*' when it sees Call(function, "Hi").
|
||||||
|
//
|
||||||
|
// Since this function is defined inline, the compiler can get rid
|
||||||
|
// of the copying of the arguments. Therefore the performance won't
|
||||||
|
// be hurt.
|
||||||
|
template <typename Function, typename A1>
|
||||||
|
static R Call(Function function, A1 a1) { return function(a1); }
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i
|
||||||
|
[[
|
||||||
|
$var arity = [[$if i==2 [[binary]] $elif i==3 [[ternary]] $else [[$i-ary]]]]
|
||||||
|
|
||||||
|
// Calls a $arity callable.
|
||||||
|
|
||||||
|
$range j 1..i
|
||||||
|
$var typename_As = [[$for j, [[typename A$j]]]]
|
||||||
|
$var Aas = [[$for j, [[A$j a$j]]]]
|
||||||
|
$var as = [[$for j, [[a$j]]]]
|
||||||
|
$var typename_Ts = [[$for j, [[typename T$j]]]]
|
||||||
|
$var Ts = [[$for j, [[T$j]]]]
|
||||||
|
template <typename Function, $typename_As>
|
||||||
|
static R Call(Function function, $Aas) {
|
||||||
|
return function($as);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
}; // class CallableHelper
|
||||||
|
|
||||||
|
// An INTERNAL macro for extracting the type of a tuple field. It's
|
||||||
|
// subject to change without notice - DO NOT USE IN USER CODE!
|
||||||
|
#define GMOCK_FIELD_(Tuple, N) \
|
||||||
|
typename ::std::tr1::tuple_element<N, Tuple>::type
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
|
||||||
|
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
|
||||||
|
// type of an n-ary function whose i-th (1-based) argument type is the
|
||||||
|
// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
|
||||||
|
// type, and whose return type is Result. For example,
|
||||||
|
// SelectArgs<int, ::std::tr1::tuple<bool, char, double, long>, 0, 3>::type
|
||||||
|
// is int(bool, long).
|
||||||
|
//
|
||||||
|
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
|
||||||
|
// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
|
||||||
|
// For example,
|
||||||
|
// SelectArgs<int, ::std::tr1::tuple<bool, char, double>, 2, 0>::Select(
|
||||||
|
// ::std::tr1::make_tuple(true, 'a', 2.5))
|
||||||
|
// returns ::std::tr1::tuple (2.5, true).
|
||||||
|
//
|
||||||
|
// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
|
||||||
|
// in the range [0, $n]. Duplicates are allowed and they don't have
|
||||||
|
// to be in an ascending or descending order.
|
||||||
|
|
||||||
|
template <typename Result, typename ArgumentTuple, $for i, [[int k$i]]>
|
||||||
|
class SelectArgs {
|
||||||
|
public:
|
||||||
|
typedef Result type($for i, [[GMOCK_FIELD_(ArgumentTuple, k$i)]]);
|
||||||
|
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||||
|
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return SelectedArgs($for i, [[get<k$i>(args)]]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 1..n
|
||||||
|
$range j1 1..i-1
|
||||||
|
template <typename Result, typename ArgumentTuple$for j1[[, int k$j1]]>
|
||||||
|
class SelectArgs<Result, ArgumentTuple,
|
||||||
|
$for j, [[$if j <= i-1 [[k$j]] $else [[-1]]]]> {
|
||||||
|
public:
|
||||||
|
typedef Result type($for j1, [[GMOCK_FIELD_(ArgumentTuple, k$j1)]]);
|
||||||
|
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||||
|
static SelectedArgs Select(const ArgumentTuple& [[]]
|
||||||
|
$if i == 1 [[/* args */]] $else [[args]]) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return SelectedArgs($for j1, [[get<k$j1>(args)]]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
#undef GMOCK_FIELD_
|
||||||
|
|
||||||
|
$var ks = [[$for i, [[k$i]]]]
|
||||||
|
|
||||||
|
// Implements the WithArgs action.
|
||||||
|
template <typename InnerAction, $for i, [[int k$i = -1]]>
|
||||||
|
class WithArgsAction {
|
||||||
|
public:
|
||||||
|
explicit WithArgsAction(const InnerAction& action) : action_(action) {}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename F>
|
||||||
|
class Impl : public ActionInterface<F> {
|
||||||
|
public:
|
||||||
|
typedef typename Function<F>::Result Result;
|
||||||
|
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
explicit Impl(const InnerAction& action) : action_(action) {}
|
||||||
|
|
||||||
|
virtual Result Perform(const ArgumentTuple& args) {
|
||||||
|
return action_.Perform(SelectArgs<Result, ArgumentTuple, $ks>::Select(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef typename SelectArgs<Result, ArgumentTuple,
|
||||||
|
$ks>::type InnerFunctionType;
|
||||||
|
|
||||||
|
Action<InnerFunctionType> action_;
|
||||||
|
};
|
||||||
|
|
||||||
|
const InnerAction action_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(WithArgsAction);
|
||||||
|
};
|
||||||
|
|
||||||
|
// A macro from the ACTION* family (defined later in this file)
|
||||||
|
// defines an action that can be used in a mock function. Typically,
|
||||||
|
// these actions only care about a subset of the arguments of the mock
|
||||||
|
// function. For example, if such an action only uses the second
|
||||||
|
// argument, it can be used in any mock function that takes >= 2
|
||||||
|
// arguments where the type of the second argument is compatible.
|
||||||
|
//
|
||||||
|
// Therefore, the action implementation must be prepared to take more
|
||||||
|
// arguments than it needs. The ExcessiveArg type is used to
|
||||||
|
// represent those excessive arguments. In order to keep the compiler
|
||||||
|
// error messages tractable, we define it in the testing namespace
|
||||||
|
// instead of testing::internal. However, this is an INTERNAL TYPE
|
||||||
|
// and subject to change without notice, so a user MUST NOT USE THIS
|
||||||
|
// TYPE DIRECTLY.
|
||||||
|
struct ExcessiveArg {};
|
||||||
|
|
||||||
|
// A helper class needed for implementing the ACTION* macros.
|
||||||
|
template <typename Result, class Impl>
|
||||||
|
class ActionHelper {
|
||||||
|
public:
|
||||||
|
$range i 0..n
|
||||||
|
$for i
|
||||||
|
|
||||||
|
[[
|
||||||
|
$var template = [[$if i==0 [[]] $else [[
|
||||||
|
$range j 0..i-1
|
||||||
|
template <$for j, [[typename A$j]]>
|
||||||
|
]]]]
|
||||||
|
$range j 0..i-1
|
||||||
|
$var As = [[$for j, [[A$j]]]]
|
||||||
|
$var as = [[$for j, [[get<$j>(args)]]]]
|
||||||
|
$range k 1..n-i
|
||||||
|
$var eas = [[$for k, [[ExcessiveArg()]]]]
|
||||||
|
$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]]
|
||||||
|
$template
|
||||||
|
static Result Perform(Impl* impl, const ::std::tr1::tuple<$As>& args) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return impl->template gmock_PerformImpl<$As>(args, $arg_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Various overloads for Invoke().
|
||||||
|
|
||||||
|
// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
|
||||||
|
// the selected arguments of the mock function to an_action and
|
||||||
|
// performs it. It serves as an adaptor between actions with
|
||||||
|
// different argument lists. C++ doesn't support default arguments for
|
||||||
|
// function templates, so we have to overload it.
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
template <$for j [[int k$j, ]]typename InnerAction>
|
||||||
|
inline internal::WithArgsAction<InnerAction$for j [[, k$j]]>
|
||||||
|
WithArgs(const InnerAction& action) {
|
||||||
|
return internal::WithArgsAction<InnerAction$for j [[, k$j]]>(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
// Creates an action that does actions a1, a2, ..., sequentially in
|
||||||
|
// each invocation.
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 2..i
|
||||||
|
$var types = [[$for j, [[typename Action$j]]]]
|
||||||
|
$var Aas = [[$for j [[, Action$j a$j]]]]
|
||||||
|
|
||||||
|
template <typename Action1, $types>
|
||||||
|
$range k 1..i-1
|
||||||
|
|
||||||
|
inline $for k [[internal::DoBothAction<Action$k, ]]Action$i$for k [[>]]
|
||||||
|
|
||||||
|
DoAll(Action1 a1$Aas) {
|
||||||
|
$if i==2 [[
|
||||||
|
|
||||||
|
return internal::DoBothAction<Action1, Action2>(a1, a2);
|
||||||
|
]] $else [[
|
||||||
|
$range j2 2..i
|
||||||
|
|
||||||
|
return DoAll(a1, DoAll($for j2, [[a$j2]]));
|
||||||
|
]]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
// The ACTION* family of macros can be used in a namespace scope to
|
||||||
|
// define custom actions easily. The syntax:
|
||||||
|
//
|
||||||
|
// ACTION(name) { statements; }
|
||||||
|
//
|
||||||
|
// will define an action with the given name that executes the
|
||||||
|
// statements. The value returned by the statements will be used as
|
||||||
|
// the return value of the action. Inside the statements, you can
|
||||||
|
// refer to the K-th (0-based) argument of the mock function by
|
||||||
|
// 'argK', and refer to its type by 'argK_type'. For example:
|
||||||
|
//
|
||||||
|
// ACTION(IncrementArg1) {
|
||||||
|
// arg1_type temp = arg1;
|
||||||
|
// return ++(*temp);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// allows you to write
|
||||||
|
//
|
||||||
|
// ...WillOnce(IncrementArg1());
|
||||||
|
//
|
||||||
|
// You can also refer to the entire argument tuple and its type by
|
||||||
|
// 'args' and 'args_type', and refer to the mock function type and its
|
||||||
|
// return type by 'function_type' and 'return_type'.
|
||||||
|
//
|
||||||
|
// Note that you don't need to specify the types of the mock function
|
||||||
|
// arguments. However rest assured that your code is still type-safe:
|
||||||
|
// you'll get a compiler error if *arg1 doesn't support the ++
|
||||||
|
// operator, or if the type of ++(*arg1) isn't compatible with the
|
||||||
|
// mock function's return type, for example.
|
||||||
|
//
|
||||||
|
// Sometimes you'll want to parameterize the action. For that you can use
|
||||||
|
// another macro:
|
||||||
|
//
|
||||||
|
// ACTION_P(name, param_name) { statements; }
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// ACTION_P(Add, n) { return arg0 + n; }
|
||||||
|
//
|
||||||
|
// will allow you to write:
|
||||||
|
//
|
||||||
|
// ...WillOnce(Add(5));
|
||||||
|
//
|
||||||
|
// Note that you don't need to provide the type of the parameter
|
||||||
|
// either. If you need to reference the type of a parameter named
|
||||||
|
// 'foo', you can write 'foo_type'. For example, in the body of
|
||||||
|
// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
|
||||||
|
// of 'n'.
|
||||||
|
//
|
||||||
|
// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P$n to support
|
||||||
|
// multi-parameter actions.
|
||||||
|
//
|
||||||
|
// For the purpose of typing, you can view
|
||||||
|
//
|
||||||
|
// ACTION_Pk(Foo, p1, ..., pk) { ... }
|
||||||
|
//
|
||||||
|
// as shorthand for
|
||||||
|
//
|
||||||
|
// template <typename p1_type, ..., typename pk_type>
|
||||||
|
// FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||||
|
//
|
||||||
|
// In particular, you can provide the template type arguments
|
||||||
|
// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
|
||||||
|
// although usually you can rely on the compiler to infer the types
|
||||||
|
// for you automatically. You can assign the result of expression
|
||||||
|
// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
|
||||||
|
// pk_type>. This can be useful when composing actions.
|
||||||
|
//
|
||||||
|
// You can also overload actions with different numbers of parameters:
|
||||||
|
//
|
||||||
|
// ACTION_P(Plus, a) { ... }
|
||||||
|
// ACTION_P2(Plus, a, b) { ... }
|
||||||
|
//
|
||||||
|
// While it's tempting to always use the ACTION* macros when defining
|
||||||
|
// a new action, you should also consider implementing ActionInterface
|
||||||
|
// or using MakePolymorphicAction() instead, especially if you need to
|
||||||
|
// use the action a lot. While these approaches require more work,
|
||||||
|
// they give you more control on the types of the mock function
|
||||||
|
// arguments and the action parameters, which in general leads to
|
||||||
|
// better compiler error messages that pay off in the long run. They
|
||||||
|
// also allow overloading actions based on parameter types (as opposed
|
||||||
|
// to just based on the number of parameters).
|
||||||
|
//
|
||||||
|
// CAVEAT:
|
||||||
|
//
|
||||||
|
// ACTION*() can only be used in a namespace scope. The reason is
|
||||||
|
// that C++ doesn't yet allow function-local types to be used to
|
||||||
|
// instantiate templates. The up-coming C++0x standard will fix this.
|
||||||
|
// Once that's done, we'll consider supporting using ACTION*() inside
|
||||||
|
// a function.
|
||||||
|
//
|
||||||
|
// MORE INFORMATION:
|
||||||
|
//
|
||||||
|
// To learn more about using these macros, please search for 'ACTION'
|
||||||
|
// on http://code.google.com/p/googlemock/wiki/CookBook.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$range k 0..n-1
|
||||||
|
|
||||||
|
// An internal macro needed for implementing ACTION*().
|
||||||
|
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
|
||||||
|
const args_type& args GTEST_ATTRIBUTE_UNUSED_
|
||||||
|
$for k [[,\
|
||||||
|
arg$k[[]]_type arg$k GTEST_ATTRIBUTE_UNUSED_]]
|
||||||
|
|
||||||
|
|
||||||
|
// Sometimes you want to give an action explicit template parameters
|
||||||
|
// that cannot be inferred from its value parameters. ACTION() and
|
||||||
|
// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that
|
||||||
|
// and can be viewed as an extension to ACTION() and ACTION_P*().
|
||||||
|
//
|
||||||
|
// The syntax:
|
||||||
|
//
|
||||||
|
// ACTION_TEMPLATE(ActionName,
|
||||||
|
// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
|
||||||
|
// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
|
||||||
|
//
|
||||||
|
// defines an action template that takes m explicit template
|
||||||
|
// parameters and n value parameters. name_i is the name of the i-th
|
||||||
|
// template parameter, and kind_i specifies whether it's a typename,
|
||||||
|
// an integral constant, or a template. p_i is the name of the i-th
|
||||||
|
// value parameter.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// // DuplicateArg<k, T>(output) converts the k-th argument of the mock
|
||||||
|
// // function to type T and copies it to *output.
|
||||||
|
// ACTION_TEMPLATE(DuplicateArg,
|
||||||
|
// HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
|
||||||
|
// AND_1_VALUE_PARAMS(output)) {
|
||||||
|
// *output = T(std::tr1::get<k>(args));
|
||||||
|
// }
|
||||||
|
// ...
|
||||||
|
// int n;
|
||||||
|
// EXPECT_CALL(mock, Foo(_, _))
|
||||||
|
// .WillOnce(DuplicateArg<1, unsigned char>(&n));
|
||||||
|
//
|
||||||
|
// To create an instance of an action template, write:
|
||||||
|
//
|
||||||
|
// ActionName<t1, ..., t_m>(v1, ..., v_n)
|
||||||
|
//
|
||||||
|
// where the ts are the template arguments and the vs are the value
|
||||||
|
// arguments. The value argument types are inferred by the compiler.
|
||||||
|
// If you want to explicitly specify the value argument types, you can
|
||||||
|
// provide additional template arguments:
|
||||||
|
//
|
||||||
|
// ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
|
||||||
|
//
|
||||||
|
// where u_i is the desired type of v_i.
|
||||||
|
//
|
||||||
|
// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
|
||||||
|
// number of value parameters, but not on the number of template
|
||||||
|
// parameters. Without the restriction, the meaning of the following
|
||||||
|
// is unclear:
|
||||||
|
//
|
||||||
|
// OverloadedAction<int, bool>(x);
|
||||||
|
//
|
||||||
|
// Are we using a single-template-parameter action where 'bool' refers
|
||||||
|
// to the type of x, or are we using a two-template-parameter action
|
||||||
|
// where the compiler is asked to infer the type of x?
|
||||||
|
//
|
||||||
|
// Implementation notes:
|
||||||
|
//
|
||||||
|
// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
|
||||||
|
// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
|
||||||
|
// implementing ACTION_TEMPLATE. The main trick we use is to create
|
||||||
|
// new macro invocations when expanding a macro. For example, we have
|
||||||
|
//
|
||||||
|
// #define ACTION_TEMPLATE(name, template_params, value_params)
|
||||||
|
// ... GMOCK_INTERNAL_DECL_##template_params ...
|
||||||
|
//
|
||||||
|
// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
|
||||||
|
// to expand to
|
||||||
|
//
|
||||||
|
// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
|
||||||
|
//
|
||||||
|
// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
|
||||||
|
// preprocessor will continue to expand it to
|
||||||
|
//
|
||||||
|
// ... typename T ...
|
||||||
|
//
|
||||||
|
// This technique conforms to the C++ standard and is portable. It
|
||||||
|
// allows us to implement action templates using O(N) code, where N is
|
||||||
|
// the maximum number of template/value parameters supported. Without
|
||||||
|
// using it, we'd have to devote O(N^2) amount of code to implement all
|
||||||
|
// combinations of m and n.
|
||||||
|
|
||||||
|
// Declares the template parameters.
|
||||||
|
|
||||||
|
$range j 1..n
|
||||||
|
$for j [[
|
||||||
|
$range m 0..j-1
|
||||||
|
#define GMOCK_INTERNAL_DECL_HAS_$j[[]]
|
||||||
|
_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[kind$m name$m]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Lists the template parameters.
|
||||||
|
|
||||||
|
$for j [[
|
||||||
|
$range m 0..j-1
|
||||||
|
#define GMOCK_INTERNAL_LIST_HAS_$j[[]]
|
||||||
|
_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[name$m]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Declares the types of value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_DECL_TYPE_AND_$i[[]]
|
||||||
|
_VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Initializes the value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\
|
||||||
|
($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(gmock_p$j)]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Declares the fields for storing the value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_DEFN_AND_$i[[]]
|
||||||
|
_VALUE_PARAMS($for j, [[p$j]]) $for j [[p$j##_type p$j; ]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Lists the value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_LIST_AND_$i[[]]
|
||||||
|
_VALUE_PARAMS($for j, [[p$j]]) $for j, [[p$j]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Lists the value parameter types.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_LIST_TYPE_AND_$i[[]]
|
||||||
|
_VALUE_PARAMS($for j, [[p$j]]) $for j [[, p$j##_type]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Declares the value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_DECL_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
|
||||||
|
$for j, [[p$j##_type p$j]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// The suffix of the class template implementing the action template.
|
||||||
|
$for i [[
|
||||||
|
|
||||||
|
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_COUNT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
|
||||||
|
$if i==1 [[P]] $elif i>=2 [[P$i]]
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
// The name of the class template implementing the action template.
|
||||||
|
#define GMOCK_ACTION_CLASS_(name, value_params)\
|
||||||
|
GMOCK_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
|
||||||
|
|
||||||
|
$range k 0..n-1
|
||||||
|
|
||||||
|
#define ACTION_TEMPLATE(name, template_params, value_params)\
|
||||||
|
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||||
|
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||||
|
class GMOCK_ACTION_CLASS_(name, value_params) {\
|
||||||
|
public:\
|
||||||
|
GMOCK_ACTION_CLASS_(name, value_params)\
|
||||||
|
GMOCK_INTERNAL_INIT_##value_params {}\
|
||||||
|
template <typename F>\
|
||||||
|
class gmock_Impl : public ::testing::ActionInterface<F> {\
|
||||||
|
public:\
|
||||||
|
typedef F function_type;\
|
||||||
|
typedef typename ::testing::internal::Function<F>::Result return_type;\
|
||||||
|
typedef typename ::testing::internal::Function<F>::ArgumentTuple\
|
||||||
|
args_type;\
|
||||||
|
explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\
|
||||||
|
virtual return_type Perform(const args_type& args) {\
|
||||||
|
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
|
||||||
|
Perform(this, args);\
|
||||||
|
}\
|
||||||
|
template <$for k, [[typename arg$k[[]]_type]]>\
|
||||||
|
return_type gmock_PerformImpl(const args_type& args[[]]
|
||||||
|
$for k [[, arg$k[[]]_type arg$k]]) const;\
|
||||||
|
GMOCK_INTERNAL_DEFN_##value_params\
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||||
|
};\
|
||||||
|
template <typename F> operator ::testing::Action<F>() const {\
|
||||||
|
return ::testing::Action<F>(\
|
||||||
|
new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\
|
||||||
|
}\
|
||||||
|
GMOCK_INTERNAL_DEFN_##value_params\
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\
|
||||||
|
};\
|
||||||
|
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||||
|
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||||
|
inline GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||||
|
GMOCK_INTERNAL_LIST_##template_params\
|
||||||
|
GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\
|
||||||
|
GMOCK_INTERNAL_DECL_##value_params) {\
|
||||||
|
return GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||||
|
GMOCK_INTERNAL_LIST_##template_params\
|
||||||
|
GMOCK_INTERNAL_LIST_TYPE_##value_params>(\
|
||||||
|
GMOCK_INTERNAL_LIST_##value_params);\
|
||||||
|
}\
|
||||||
|
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||||
|
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||||
|
template <typename F>\
|
||||||
|
template <typename arg0_type, typename arg1_type, typename arg2_type,\
|
||||||
|
typename arg3_type, typename arg4_type, typename arg5_type,\
|
||||||
|
typename arg6_type, typename arg7_type, typename arg8_type,\
|
||||||
|
typename arg9_type>\
|
||||||
|
typename ::testing::internal::Function<F>::Result\
|
||||||
|
GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||||
|
GMOCK_INTERNAL_LIST_##template_params\
|
||||||
|
GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\
|
||||||
|
gmock_PerformImpl(\
|
||||||
|
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
|
||||||
|
|
||||||
|
$for i
|
||||||
|
|
||||||
|
[[
|
||||||
|
$var template = [[$if i==0 [[]] $else [[
|
||||||
|
$range j 0..i-1
|
||||||
|
|
||||||
|
template <$for j, [[typename p$j##_type]]>\
|
||||||
|
]]]]
|
||||||
|
$var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]]
|
||||||
|
$else [[P$i]]]]]]
|
||||||
|
$range j 0..i-1
|
||||||
|
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||||
|
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
||||||
|
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
|
||||||
|
$var param_field_decls = [[$for j
|
||||||
|
[[
|
||||||
|
|
||||||
|
p$j##_type p$j;\
|
||||||
|
]]]]
|
||||||
|
$var param_field_decls2 = [[$for j
|
||||||
|
[[
|
||||||
|
|
||||||
|
p$j##_type p$j;\
|
||||||
|
]]]]
|
||||||
|
$var params = [[$for j, [[p$j]]]]
|
||||||
|
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
||||||
|
$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]]
|
||||||
|
$var arg_types_and_names = [[$for k, [[arg$k[[]]_type arg$k]]]]
|
||||||
|
$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]]
|
||||||
|
$else [[ACTION_P$i]]]]
|
||||||
|
|
||||||
|
#define $macro_name(name$for j [[, p$j]])\$template
|
||||||
|
class $class_name {\
|
||||||
|
public:\
|
||||||
|
$class_name($ctor_param_list)$inits {}\
|
||||||
|
template <typename F>\
|
||||||
|
class gmock_Impl : public ::testing::ActionInterface<F> {\
|
||||||
|
public:\
|
||||||
|
typedef F function_type;\
|
||||||
|
typedef typename ::testing::internal::Function<F>::Result return_type;\
|
||||||
|
typedef typename ::testing::internal::Function<F>::ArgumentTuple\
|
||||||
|
args_type;\
|
||||||
|
[[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\
|
||||||
|
virtual return_type Perform(const args_type& args) {\
|
||||||
|
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
|
||||||
|
Perform(this, args);\
|
||||||
|
}\
|
||||||
|
template <$typename_arg_types>\
|
||||||
|
return_type gmock_PerformImpl(const args_type& args, [[]]
|
||||||
|
$arg_types_and_names) const;\$param_field_decls
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||||
|
};\
|
||||||
|
template <typename F> operator ::testing::Action<F>() const {\
|
||||||
|
return ::testing::Action<F>(new gmock_Impl<F>($params));\
|
||||||
|
}\$param_field_decls2
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_($class_name);\
|
||||||
|
};\$template
|
||||||
|
inline $class_name$param_types name($param_types_and_names) {\
|
||||||
|
return $class_name$param_types($params);\
|
||||||
|
}\$template
|
||||||
|
template <typename F>\
|
||||||
|
template <$typename_arg_types>\
|
||||||
|
typename ::testing::internal::Function<F>::Result\
|
||||||
|
$class_name$param_types::gmock_Impl<F>::gmock_PerformImpl(\
|
||||||
|
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
|
||||||
|
]]
|
||||||
|
$$ } // This meta comment fixes auto-indentation in Emacs. It won't
|
||||||
|
$$ // show up in the generated code.
|
||||||
|
|
||||||
|
|
||||||
|
// TODO(wan@google.com): move the following to a different .h file
|
||||||
|
// such that we don't have to run 'pump' every time the code is
|
||||||
|
// updated.
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||||
|
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||||
|
// the macro definition, as the warnings are generated when the macro
|
||||||
|
// is expanded and macro expansion cannot contain #pragma. Therefore
|
||||||
|
// we suppress them here.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4100)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Various overloads for InvokeArgument<N>().
|
||||||
|
//
|
||||||
|
// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
|
||||||
|
// (0-based) argument, which must be a k-ary callable, of the mock
|
||||||
|
// function, with arguments a1, a2, ..., a_k.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// 1. The arguments are passed by value by default. If you need to
|
||||||
|
// pass an argument by reference, wrap it inside ByRef(). For
|
||||||
|
// example,
|
||||||
|
//
|
||||||
|
// InvokeArgument<1>(5, string("Hello"), ByRef(foo))
|
||||||
|
//
|
||||||
|
// passes 5 and string("Hello") by value, and passes foo by
|
||||||
|
// reference.
|
||||||
|
//
|
||||||
|
// 2. If the callable takes an argument by reference but ByRef() is
|
||||||
|
// not used, it will receive the reference to a copy of the value,
|
||||||
|
// instead of the original value. For example, when the 0-th
|
||||||
|
// argument of the mock function takes a const string&, the action
|
||||||
|
//
|
||||||
|
// InvokeArgument<0>(string("Hello"))
|
||||||
|
//
|
||||||
|
// makes a copy of the temporary string("Hello") object and passes a
|
||||||
|
// reference of the copy, instead of the original temporary object,
|
||||||
|
// to the callable. This makes it easy for a user to define an
|
||||||
|
// InvokeArgument action from temporary values and have it performed
|
||||||
|
// later.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
|
||||||
|
ACTION_TEMPLATE(InvokeArgument,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) {
|
||||||
|
return internal::CallableHelper<return_type>::Call(
|
||||||
|
::std::tr1::get<k>(args)$for j [[, p$j]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Various overloads for ReturnNew<T>().
|
||||||
|
//
|
||||||
|
// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
|
||||||
|
// instance of type T, constructed on the heap with constructor arguments
|
||||||
|
// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
$var ps = [[$for j, [[p$j]]]]
|
||||||
|
|
||||||
|
ACTION_TEMPLATE(ReturnNew,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(typename, T),
|
||||||
|
AND_$i[[]]_VALUE_PARAMS($ps)) {
|
||||||
|
return new T($ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
|
@ -0,0 +1,924 @@
|
||||||
|
// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
|
||||||
|
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements function mockers of various arities.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
|
||||||
|
#include <gmock/gmock-spec-builders.h>
|
||||||
|
#include <gmock/internal/gmock-internal-utils.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
class FunctionMockerBase;
|
||||||
|
|
||||||
|
// Note: class FunctionMocker really belongs to the ::testing
|
||||||
|
// namespace. However if we define it in ::testing, MSVC will
|
||||||
|
// complain when classes in ::testing::internal declare it as a
|
||||||
|
// friend class template. To workaround this compiler bug, we define
|
||||||
|
// FunctionMocker in ::testing::internal and import it into ::testing.
|
||||||
|
template <typename F>
|
||||||
|
class FunctionMocker;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class FunctionMocker<R()> : public
|
||||||
|
internal::FunctionMockerBase<R()> {
|
||||||
|
public:
|
||||||
|
typedef R F();
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With() {
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke() {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
class FunctionMocker<R(A1)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
class FunctionMocker<R(A1, A2)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3>
|
||||||
|
class FunctionMocker<R(A1, A2, A3)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4,
|
||||||
|
m5));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6, A7);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6, const Matcher<A7>& m7) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6, m7));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6, m7, m8));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8, typename A9>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
|
||||||
|
const Matcher<A9>& m9) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6, m7, m8, m9));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8, typename A9,
|
||||||
|
typename A10>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
|
||||||
|
const Matcher<A9>& m9, const Matcher<A10>& m10) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6, m7, m8, m9, m10));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9,
|
||||||
|
A10 a10) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9,
|
||||||
|
a10));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// The style guide prohibits "using" statements in a namespace scope
|
||||||
|
// inside a header file. However, the FunctionMocker class template
|
||||||
|
// is meant to be defined in the ::testing namespace. The following
|
||||||
|
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||||
|
// cannot handle it if we define FunctionMocker in ::testing.
|
||||||
|
using internal::FunctionMocker;
|
||||||
|
|
||||||
|
// The result type of function type F.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_RESULT_(tn, F) tn ::testing::internal::Function<F>::Result
|
||||||
|
|
||||||
|
// The type of argument N of function type F.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_ARG_(tn, F, N) tn ::testing::internal::Function<F>::Argument##N
|
||||||
|
|
||||||
|
// The matcher type for argument N of function type F.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_MATCHER_(tn, F, N) const ::testing::Matcher<GMOCK_ARG_(tn, F, N)>&
|
||||||
|
|
||||||
|
// The variable for mocking the given method.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||||
|
GMOCK_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD0_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method() constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 0, \
|
||||||
|
this_method_does_not_take_0_arguments); \
|
||||||
|
GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(0, constness, Method).Invoke(); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method() constness { \
|
||||||
|
return GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this).With(); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(0, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD1_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 1, \
|
||||||
|
this_method_does_not_take_1_argument); \
|
||||||
|
GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(1, constness, Method).Invoke(gmock_a1); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1) constness { \
|
||||||
|
return GMOCK_MOCKER_(1, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(1, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD2_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 2, \
|
||||||
|
this_method_does_not_take_2_arguments); \
|
||||||
|
GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(2, constness, Method).Invoke(gmock_a1, gmock_a2); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2) constness { \
|
||||||
|
return GMOCK_MOCKER_(2, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(2, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD3_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, F, 3) gmock_a3) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 3, \
|
||||||
|
this_method_does_not_take_3_arguments); \
|
||||||
|
GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(3, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 3) gmock_a3) constness { \
|
||||||
|
return GMOCK_MOCKER_(3, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(3, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD4_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, F, 4) gmock_a4) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 4, \
|
||||||
|
this_method_does_not_take_4_arguments); \
|
||||||
|
GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(4, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 4) gmock_a4) constness { \
|
||||||
|
return GMOCK_MOCKER_(4, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
|
||||||
|
gmock_a4); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(4, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD5_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, F, 5) gmock_a5) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 5, \
|
||||||
|
this_method_does_not_take_5_arguments); \
|
||||||
|
GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(5, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 5) gmock_a5) constness { \
|
||||||
|
return GMOCK_MOCKER_(5, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
|
||||||
|
gmock_a4, gmock_a5); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(5, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD6_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, F, 6) gmock_a6) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 6, \
|
||||||
|
this_method_does_not_take_6_arguments); \
|
||||||
|
GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(6, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 6) gmock_a6) constness { \
|
||||||
|
return GMOCK_MOCKER_(6, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
|
||||||
|
gmock_a4, gmock_a5, gmock_a6); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(6, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD7_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, F, 6) gmock_a6, \
|
||||||
|
GMOCK_ARG_(tn, F, 7) gmock_a7) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 7, \
|
||||||
|
this_method_does_not_take_7_arguments); \
|
||||||
|
GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(7, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 7) gmock_a7) constness { \
|
||||||
|
return GMOCK_MOCKER_(7, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
|
||||||
|
gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(7, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD8_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, F, 6) gmock_a6, \
|
||||||
|
GMOCK_ARG_(tn, F, 7) gmock_a7, \
|
||||||
|
GMOCK_ARG_(tn, F, 8) gmock_a8) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 8, \
|
||||||
|
this_method_does_not_take_8_arguments); \
|
||||||
|
GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(8, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 8) gmock_a8) constness { \
|
||||||
|
return GMOCK_MOCKER_(8, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
|
||||||
|
gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(8, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD9_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, F, 6) gmock_a6, \
|
||||||
|
GMOCK_ARG_(tn, F, 7) gmock_a7, \
|
||||||
|
GMOCK_ARG_(tn, F, 8) gmock_a8, \
|
||||||
|
GMOCK_ARG_(tn, F, 9) gmock_a9) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 9, \
|
||||||
|
this_method_does_not_take_9_arguments); \
|
||||||
|
GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(9, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
|
||||||
|
gmock_a9); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 9) gmock_a9) constness { \
|
||||||
|
return GMOCK_MOCKER_(9, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
|
||||||
|
gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(9, constness, Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD10_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, F, 6) gmock_a6, \
|
||||||
|
GMOCK_ARG_(tn, F, 7) gmock_a7, \
|
||||||
|
GMOCK_ARG_(tn, F, 8) gmock_a8, \
|
||||||
|
GMOCK_ARG_(tn, F, 9) gmock_a9, \
|
||||||
|
GMOCK_ARG_(tn, F, 10) gmock_a10) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == 10, \
|
||||||
|
this_method_does_not_take_10_arguments); \
|
||||||
|
GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(10, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
|
||||||
|
gmock_a10); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 9) gmock_a9, \
|
||||||
|
GMOCK_MATCHER_(tn, F, 10) gmock_a10) constness { \
|
||||||
|
return GMOCK_MOCKER_(10, constness, \
|
||||||
|
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
|
||||||
|
gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
|
||||||
|
gmock_a10); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(10, constness, Method)
|
||||||
|
|
||||||
|
#define MOCK_METHOD0(m, F) GMOCK_METHOD0_(, , , m, F)
|
||||||
|
#define MOCK_METHOD1(m, F) GMOCK_METHOD1_(, , , m, F)
|
||||||
|
#define MOCK_METHOD2(m, F) GMOCK_METHOD2_(, , , m, F)
|
||||||
|
#define MOCK_METHOD3(m, F) GMOCK_METHOD3_(, , , m, F)
|
||||||
|
#define MOCK_METHOD4(m, F) GMOCK_METHOD4_(, , , m, F)
|
||||||
|
#define MOCK_METHOD5(m, F) GMOCK_METHOD5_(, , , m, F)
|
||||||
|
#define MOCK_METHOD6(m, F) GMOCK_METHOD6_(, , , m, F)
|
||||||
|
#define MOCK_METHOD7(m, F) GMOCK_METHOD7_(, , , m, F)
|
||||||
|
#define MOCK_METHOD8(m, F) GMOCK_METHOD8_(, , , m, F)
|
||||||
|
#define MOCK_METHOD9(m, F) GMOCK_METHOD9_(, , , m, F)
|
||||||
|
#define MOCK_METHOD10(m, F) GMOCK_METHOD10_(, , , m, F)
|
||||||
|
|
||||||
|
#define MOCK_CONST_METHOD0(m, F) GMOCK_METHOD0_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD1(m, F) GMOCK_METHOD1_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD2(m, F) GMOCK_METHOD2_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD3(m, F) GMOCK_METHOD3_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD4(m, F) GMOCK_METHOD4_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD5(m, F) GMOCK_METHOD5_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD6(m, F) GMOCK_METHOD6_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD7(m, F) GMOCK_METHOD7_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD8(m, F) GMOCK_METHOD8_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD9(m, F) GMOCK_METHOD9_(, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD10(m, F) GMOCK_METHOD10_(, const, , m, F)
|
||||||
|
|
||||||
|
#define MOCK_METHOD0_T(m, F) GMOCK_METHOD0_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD1_T(m, F) GMOCK_METHOD1_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD2_T(m, F) GMOCK_METHOD2_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD3_T(m, F) GMOCK_METHOD3_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD4_T(m, F) GMOCK_METHOD4_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD5_T(m, F) GMOCK_METHOD5_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD6_T(m, F) GMOCK_METHOD6_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD7_T(m, F) GMOCK_METHOD7_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD8_T(m, F) GMOCK_METHOD8_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD9_T(m, F) GMOCK_METHOD9_(typename, , , m, F)
|
||||||
|
#define MOCK_METHOD10_T(m, F) GMOCK_METHOD10_(typename, , , m, F)
|
||||||
|
|
||||||
|
#define MOCK_CONST_METHOD0_T(m, F) GMOCK_METHOD0_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD1_T(m, F) GMOCK_METHOD1_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD2_T(m, F) GMOCK_METHOD2_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD3_T(m, F) GMOCK_METHOD3_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD4_T(m, F) GMOCK_METHOD4_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD5_T(m, F) GMOCK_METHOD5_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD6_T(m, F) GMOCK_METHOD6_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD7_T(m, F) GMOCK_METHOD7_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD8_T(m, F) GMOCK_METHOD8_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD9_T(m, F) GMOCK_METHOD9_(typename, const, , m, F)
|
||||||
|
#define MOCK_CONST_METHOD10_T(m, F) GMOCK_METHOD10_(typename, const, , m, F)
|
||||||
|
|
||||||
|
#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD0_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD1_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD2_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD3_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD4_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD5_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD6_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD7_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD8_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD9_(, , ct, m, F)
|
||||||
|
#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD10_(, , ct, m, F)
|
||||||
|
|
||||||
|
#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD0_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD1_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD2_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD3_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD4_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD5_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD6_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD7_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD8_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD9_(, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD10_(, const, ct, m, F)
|
||||||
|
|
||||||
|
#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD0_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD1_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD2_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD3_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD4_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD5_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD6_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD7_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD8_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD9_(typename, , ct, m, F)
|
||||||
|
#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD10_(typename, , ct, m, F)
|
||||||
|
|
||||||
|
#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD0_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD1_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD2_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD3_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD4_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD5_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD6_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD7_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD8_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD9_(typename, const, ct, m, F)
|
||||||
|
#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD10_(typename, const, ct, m, F)
|
||||||
|
|
||||||
|
// A MockFunction<F> class has one mock method whose type is F. It is
|
||||||
|
// useful when you just want your test code to emit some messages and
|
||||||
|
// have Google Mock verify the right messages are sent (and perhaps at
|
||||||
|
// the right times). For example, if you are exercising code:
|
||||||
|
//
|
||||||
|
// Foo(1);
|
||||||
|
// Foo(2);
|
||||||
|
// Foo(3);
|
||||||
|
//
|
||||||
|
// and want to verify that Foo(1) and Foo(3) both invoke
|
||||||
|
// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
|
||||||
|
//
|
||||||
|
// TEST(FooTest, InvokesBarCorrectly) {
|
||||||
|
// MyMock mock;
|
||||||
|
// MockFunction<void(string check_point_name)> check;
|
||||||
|
// {
|
||||||
|
// InSequence s;
|
||||||
|
//
|
||||||
|
// EXPECT_CALL(mock, Bar("a"));
|
||||||
|
// EXPECT_CALL(check, Call("1"));
|
||||||
|
// EXPECT_CALL(check, Call("2"));
|
||||||
|
// EXPECT_CALL(mock, Bar("a"));
|
||||||
|
// }
|
||||||
|
// Foo(1);
|
||||||
|
// check.Call("1");
|
||||||
|
// Foo(2);
|
||||||
|
// check.Call("2");
|
||||||
|
// Foo(3);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The expectation spec says that the first Bar("a") must happen
|
||||||
|
// before check point "1", the second Bar("a") must happen after check
|
||||||
|
// point "2", and nothing should happen between the two check
|
||||||
|
// points. The explicit check points make it easy to tell which
|
||||||
|
// Bar("a") is called by which call to Foo().
|
||||||
|
template <typename F>
|
||||||
|
class MockFunction;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class MockFunction<R()> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD0_T(Call, R());
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0>
|
||||||
|
class MockFunction<R(A0)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD1_T(Call, R(A0));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1>
|
||||||
|
class MockFunction<R(A0, A1)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD2_T(Call, R(A0, A1));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2>
|
||||||
|
class MockFunction<R(A0, A1, A2)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD3_T(Call, R(A0, A1, A2));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD4_T(Call, R(A0, A1, A2, A3));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD5_T(Call, R(A0, A1, A2, A3, A4));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD6_T(Call, R(A0, A1, A2, A3, A4, A5));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5, typename A6>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD7_T(Call, R(A0, A1, A2, A3, A4, A5, A6));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5, typename A6, typename A7>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD8_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5, typename A6, typename A7, typename A8>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD9_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5, typename A6, typename A7, typename A8,
|
||||||
|
typename A9>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD10_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
|
@ -0,0 +1,257 @@
|
||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-function-mockers.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements function mockers of various arities.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
|
||||||
|
#include <gmock/gmock-spec-builders.h>
|
||||||
|
#include <gmock/internal/gmock-internal-utils.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
class FunctionMockerBase;
|
||||||
|
|
||||||
|
// Note: class FunctionMocker really belongs to the ::testing
|
||||||
|
// namespace. However if we define it in ::testing, MSVC will
|
||||||
|
// complain when classes in ::testing::internal declare it as a
|
||||||
|
// friend class template. To workaround this compiler bug, we define
|
||||||
|
// FunctionMocker in ::testing::internal and import it into ::testing.
|
||||||
|
template <typename F>
|
||||||
|
class FunctionMocker;
|
||||||
|
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var typename_As = [[$for j [[, typename A$j]]]]
|
||||||
|
$var As = [[$for j, [[A$j]]]]
|
||||||
|
$var as = [[$for j, [[a$j]]]]
|
||||||
|
$var Aas = [[$for j, [[A$j a$j]]]]
|
||||||
|
$var ms = [[$for j, [[m$j]]]]
|
||||||
|
$var matchers = [[$for j, [[const Matcher<A$j>& m$j]]]]
|
||||||
|
template <typename R$typename_As>
|
||||||
|
class FunctionMocker<R($As)> : public
|
||||||
|
internal::FunctionMockerBase<R($As)> {
|
||||||
|
public:
|
||||||
|
typedef R F($As);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With($matchers) {
|
||||||
|
|
||||||
|
$if i >= 1 [[
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple($ms));
|
||||||
|
|
||||||
|
]]
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke($Aas) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple($as));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// The style guide prohibits "using" statements in a namespace scope
|
||||||
|
// inside a header file. However, the FunctionMocker class template
|
||||||
|
// is meant to be defined in the ::testing namespace. The following
|
||||||
|
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||||
|
// cannot handle it if we define FunctionMocker in ::testing.
|
||||||
|
using internal::FunctionMocker;
|
||||||
|
|
||||||
|
// The result type of function type F.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_RESULT_(tn, F) tn ::testing::internal::Function<F>::Result
|
||||||
|
|
||||||
|
// The type of argument N of function type F.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_ARG_(tn, F, N) tn ::testing::internal::Function<F>::Argument##N
|
||||||
|
|
||||||
|
// The matcher type for argument N of function type F.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_MATCHER_(tn, F, N) const ::testing::Matcher<GMOCK_ARG_(tn, F, N)>&
|
||||||
|
|
||||||
|
// The variable for mocking the given method.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||||
|
GMOCK_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var arg_as = [[$for j, \
|
||||||
|
[[GMOCK_ARG_(tn, F, $j) gmock_a$j]]]]
|
||||||
|
$var as = [[$for j, [[gmock_a$j]]]]
|
||||||
|
$var matcher_as = [[$for j, \
|
||||||
|
[[GMOCK_MATCHER_(tn, F, $j) gmock_a$j]]]]
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, F) \
|
||||||
|
GMOCK_RESULT_(tn, F) ct Method($arg_as) constness { \
|
||||||
|
GMOCK_COMPILE_ASSERT_(::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<F>::ArgumentTuple>::value == $i, \
|
||||||
|
this_method_does_not_take_$i[[]]_argument[[$if i != 1 [[s]]]]); \
|
||||||
|
GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<F>& \
|
||||||
|
gmock_##Method($matcher_as) constness { \
|
||||||
|
return GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this).With($as); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_($i, constness, Method)
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_METHOD$i(m, F) GMOCK_METHOD$i[[]]_(, , , m, F)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_CONST_METHOD$i(m, F) GMOCK_METHOD$i[[]]_(, const, , m, F)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_METHOD$i[[]]_T(m, F) GMOCK_METHOD$i[[]]_(typename, , , m, F)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_CONST_METHOD$i[[]]_T(m, F) [[]]
|
||||||
|
GMOCK_METHOD$i[[]]_(typename, const, , m, F)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, F) [[]]
|
||||||
|
GMOCK_METHOD$i[[]]_(, , ct, m, F)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD$i[[]]_(, const, ct, m, F)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD$i[[]]_(typename, , ct, m, F)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, F) \
|
||||||
|
GMOCK_METHOD$i[[]]_(typename, const, ct, m, F)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// A MockFunction<F> class has one mock method whose type is F. It is
|
||||||
|
// useful when you just want your test code to emit some messages and
|
||||||
|
// have Google Mock verify the right messages are sent (and perhaps at
|
||||||
|
// the right times). For example, if you are exercising code:
|
||||||
|
//
|
||||||
|
// Foo(1);
|
||||||
|
// Foo(2);
|
||||||
|
// Foo(3);
|
||||||
|
//
|
||||||
|
// and want to verify that Foo(1) and Foo(3) both invoke
|
||||||
|
// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
|
||||||
|
//
|
||||||
|
// TEST(FooTest, InvokesBarCorrectly) {
|
||||||
|
// MyMock mock;
|
||||||
|
// MockFunction<void(string check_point_name)> check;
|
||||||
|
// {
|
||||||
|
// InSequence s;
|
||||||
|
//
|
||||||
|
// EXPECT_CALL(mock, Bar("a"));
|
||||||
|
// EXPECT_CALL(check, Call("1"));
|
||||||
|
// EXPECT_CALL(check, Call("2"));
|
||||||
|
// EXPECT_CALL(mock, Bar("a"));
|
||||||
|
// }
|
||||||
|
// Foo(1);
|
||||||
|
// check.Call("1");
|
||||||
|
// Foo(2);
|
||||||
|
// check.Call("2");
|
||||||
|
// Foo(3);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The expectation spec says that the first Bar("a") must happen
|
||||||
|
// before check point "1", the second Bar("a") must happen after check
|
||||||
|
// point "2", and nothing should happen between the two check
|
||||||
|
// points. The explicit check points make it easy to tell which
|
||||||
|
// Bar("a") is called by which call to Foo().
|
||||||
|
template <typename F>
|
||||||
|
class MockFunction;
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
template <typename R$for j [[, typename A$j]]>
|
||||||
|
class MockFunction<R($for j, [[A$j]])> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD$i[[]]_T(Call, R($for j, [[A$j]]));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,599 @@
|
||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-actions.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
$$ }} This line fixes auto-indentation of the following code in Emacs.
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some commonly used variadic matchers.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <gmock/gmock-matchers.h>
|
||||||
|
#include <gmock/gmock-printers.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
$range i 0..n-1
|
||||||
|
|
||||||
|
// The type of the i-th (0-based) field of Tuple.
|
||||||
|
#define GMOCK_FIELD_TYPE_(Tuple, i) \
|
||||||
|
typename ::std::tr1::tuple_element<i, Tuple>::type
|
||||||
|
|
||||||
|
// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
|
||||||
|
// tuple of type Tuple. It has two members:
|
||||||
|
//
|
||||||
|
// type: a tuple type whose i-th field is the ki-th field of Tuple.
|
||||||
|
// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
|
||||||
|
//
|
||||||
|
// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
|
||||||
|
//
|
||||||
|
// type is tuple<int, bool>, and
|
||||||
|
// GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
|
||||||
|
|
||||||
|
template <class Tuple$for i [[, int k$i = -1]]>
|
||||||
|
class TupleFields;
|
||||||
|
|
||||||
|
// This generic version is used when there are $n selectors.
|
||||||
|
template <class Tuple$for i [[, int k$i]]>
|
||||||
|
class TupleFields {
|
||||||
|
public:
|
||||||
|
typedef ::std::tr1::tuple<$for i, [[GMOCK_FIELD_TYPE_(Tuple, k$i)]]> type;
|
||||||
|
static type GetSelectedFields(const Tuple& t) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return type($for i, [[get<k$i>(t)]]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following specialization is used for 0 ~ $(n-1) selectors.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$$ }}}
|
||||||
|
$range j 0..i-1
|
||||||
|
$range k 0..n-1
|
||||||
|
|
||||||
|
template <class Tuple$for j [[, int k$j]]>
|
||||||
|
class TupleFields<Tuple, $for k, [[$if k < i [[k$k]] $else [[-1]]]]> {
|
||||||
|
public:
|
||||||
|
typedef ::std::tr1::tuple<$for j, [[GMOCK_FIELD_TYPE_(Tuple, k$j)]]> type;
|
||||||
|
static type GetSelectedFields(const Tuple& $if i==0 [[/* t */]] $else [[t]]) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return type($for j, [[get<k$j>(t)]]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
#undef GMOCK_FIELD_TYPE_
|
||||||
|
|
||||||
|
// Implements the Args() matcher.
|
||||||
|
|
||||||
|
$var ks = [[$for i, [[k$i]]]]
|
||||||
|
template <class ArgsTuple$for i [[, int k$i = -1]]>
|
||||||
|
class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
|
||||||
|
public:
|
||||||
|
// ArgsTuple may have top-level const or reference modifiers.
|
||||||
|
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(ArgsTuple)) RawArgsTuple;
|
||||||
|
typedef typename internal::TupleFields<RawArgsTuple, $ks>::type SelectedArgs;
|
||||||
|
typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
|
||||||
|
|
||||||
|
template <typename InnerMatcher>
|
||||||
|
explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
|
||||||
|
: inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
|
||||||
|
|
||||||
|
virtual bool MatchAndExplain(ArgsTuple args,
|
||||||
|
MatchResultListener* listener) const {
|
||||||
|
const SelectedArgs& selected_args = GetSelectedArgs(args);
|
||||||
|
if (!listener->IsInterested())
|
||||||
|
return inner_matcher_.Matches(selected_args);
|
||||||
|
|
||||||
|
PrintIndices(listener->stream());
|
||||||
|
*listener << "are " << PrintToString(selected_args);
|
||||||
|
|
||||||
|
StringMatchResultListener inner_listener;
|
||||||
|
const bool match = inner_matcher_.MatchAndExplain(selected_args,
|
||||||
|
&inner_listener);
|
||||||
|
PrintIfNotEmpty(inner_listener.str(), listener->stream());
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const {
|
||||||
|
*os << "are a tuple ";
|
||||||
|
PrintIndices(os);
|
||||||
|
inner_matcher_.DescribeTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||||
|
*os << "are a tuple ";
|
||||||
|
PrintIndices(os);
|
||||||
|
inner_matcher_.DescribeNegationTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static SelectedArgs GetSelectedArgs(ArgsTuple args) {
|
||||||
|
return TupleFields<RawArgsTuple, $ks>::GetSelectedFields(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the indices of the selected fields.
|
||||||
|
static void PrintIndices(::std::ostream* os) {
|
||||||
|
*os << "whose fields (";
|
||||||
|
const int indices[$n] = { $ks };
|
||||||
|
for (int i = 0; i < $n; i++) {
|
||||||
|
if (indices[i] < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i >= 1)
|
||||||
|
*os << ", ";
|
||||||
|
|
||||||
|
*os << "#" << indices[i];
|
||||||
|
}
|
||||||
|
*os << ") ";
|
||||||
|
}
|
||||||
|
|
||||||
|
const MonomorphicInnerMatcher inner_matcher_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class InnerMatcher$for i [[, int k$i = -1]]>
|
||||||
|
class ArgsMatcher {
|
||||||
|
public:
|
||||||
|
explicit ArgsMatcher(const InnerMatcher& inner_matcher)
|
||||||
|
: inner_matcher_(inner_matcher) {}
|
||||||
|
|
||||||
|
template <typename ArgsTuple>
|
||||||
|
operator Matcher<ArgsTuple>() const {
|
||||||
|
return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, $ks>(inner_matcher_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const InnerMatcher inner_matcher_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implements ElementsAre() of 1-$n arguments.
|
||||||
|
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
template <$for j, [[typename T$j]]>
|
||||||
|
class ElementsAreMatcher$i {
|
||||||
|
public:
|
||||||
|
$if i==1 [[explicit ]]ElementsAreMatcher$i($for j, [[const T$j& e$j]])$if i > 0 [[ : ]]
|
||||||
|
$for j, [[e$j[[]]_(e$j)]] {}
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
operator Matcher<Container>() const {
|
||||||
|
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||||
|
RawContainer;
|
||||||
|
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||||
|
Element;
|
||||||
|
|
||||||
|
$if i==1 [[
|
||||||
|
|
||||||
|
// Nokia's Symbian Compiler has a nasty bug where the object put
|
||||||
|
// in a one-element local array is not destructed when the array
|
||||||
|
// goes out of scope. This leads to obvious badness as we've
|
||||||
|
// added the linked_ptr in it to our other linked_ptrs list.
|
||||||
|
// Hence we implement ElementsAreMatcher1 specially to avoid using
|
||||||
|
// a local array.
|
||||||
|
const Matcher<const Element&> matcher =
|
||||||
|
MatcherCast<const Element&>(e1_);
|
||||||
|
return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher, 1));
|
||||||
|
]] $else [[
|
||||||
|
|
||||||
|
const Matcher<const Element&> matchers[] = {
|
||||||
|
|
||||||
|
$for j [[
|
||||||
|
MatcherCast<const Element&>(e$j[[]]_),
|
||||||
|
|
||||||
|
]]
|
||||||
|
};
|
||||||
|
|
||||||
|
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, $i));
|
||||||
|
]]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
$for j [[
|
||||||
|
const T$j& e$j[[]]_;
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher$i);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
|
||||||
|
// fields of it matches a_matcher. C++ doesn't support default
|
||||||
|
// arguments for function templates, so we have to overload it.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
template <$for j [[int k$j, ]]typename InnerMatcher>
|
||||||
|
inline internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>
|
||||||
|
Args(const InnerMatcher& matcher) {
|
||||||
|
return internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>(matcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
// ElementsAre(e0, e1, ..., e_n) matches an STL-style container with
|
||||||
|
// (n + 1) elements, where the i-th element in the container must
|
||||||
|
// match the i-th argument in the list. Each argument of
|
||||||
|
// ElementsAre() can be either a value or a matcher. We support up to
|
||||||
|
// $n arguments.
|
||||||
|
//
|
||||||
|
// NOTE: Since ElementsAre() cares about the order of the elements, it
|
||||||
|
// must not be used with containers whose elements's order is
|
||||||
|
// undefined (e.g. hash_map).
|
||||||
|
|
||||||
|
inline internal::ElementsAreMatcher0 ElementsAre() {
|
||||||
|
return internal::ElementsAreMatcher0();
|
||||||
|
}
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
|
||||||
|
template <$for j, [[typename T$j]]>
|
||||||
|
inline internal::ElementsAreMatcher$i<$for j, [[T$j]]> ElementsAre($for j, [[const T$j& e$j]]) {
|
||||||
|
return internal::ElementsAreMatcher$i<$for j, [[T$j]]>($for j, [[e$j]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// ElementsAreArray(array) and ElementAreArray(array, count) are like
|
||||||
|
// ElementsAre(), except that they take an array of values or
|
||||||
|
// matchers. The former form infers the size of 'array', which must
|
||||||
|
// be a static C-style array. In the latter form, 'array' can either
|
||||||
|
// be a static array or a pointer to a dynamically created array.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
|
||||||
|
const T* first, size_t count) {
|
||||||
|
return internal::ElementsAreArrayMatcher<T>(first, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
inline internal::ElementsAreArrayMatcher<T>
|
||||||
|
ElementsAreArray(const T (&array)[N]) {
|
||||||
|
return internal::ElementsAreArrayMatcher<T>(array, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
$$ } // This Pump meta comment fixes auto-indentation in Emacs. It will not
|
||||||
|
$$ // show up in the generated code.
|
||||||
|
|
||||||
|
|
||||||
|
// The MATCHER* family of macros can be used in a namespace scope to
|
||||||
|
// define custom matchers easily.
|
||||||
|
//
|
||||||
|
// Basic Usage
|
||||||
|
// ===========
|
||||||
|
//
|
||||||
|
// The syntax
|
||||||
|
//
|
||||||
|
// MATCHER(name, description_string) { statements; }
|
||||||
|
//
|
||||||
|
// defines a matcher with the given name that executes the statements,
|
||||||
|
// which must return a bool to indicate if the match succeeds. Inside
|
||||||
|
// the statements, you can refer to the value being matched by 'arg',
|
||||||
|
// and refer to its type by 'arg_type'.
|
||||||
|
//
|
||||||
|
// The description string documents what the matcher does, and is used
|
||||||
|
// to generate the failure message when the match fails. Since a
|
||||||
|
// MATCHER() is usually defined in a header file shared by multiple
|
||||||
|
// C++ source files, we require the description to be a C-string
|
||||||
|
// literal to avoid possible side effects. It can be empty, in which
|
||||||
|
// case we'll use the sequence of words in the matcher name as the
|
||||||
|
// description.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
|
||||||
|
//
|
||||||
|
// allows you to write
|
||||||
|
//
|
||||||
|
// // Expects mock_foo.Bar(n) to be called where n is even.
|
||||||
|
// EXPECT_CALL(mock_foo, Bar(IsEven()));
|
||||||
|
//
|
||||||
|
// or,
|
||||||
|
//
|
||||||
|
// // Verifies that the value of some_expression is even.
|
||||||
|
// EXPECT_THAT(some_expression, IsEven());
|
||||||
|
//
|
||||||
|
// If the above assertion fails, it will print something like:
|
||||||
|
//
|
||||||
|
// Value of: some_expression
|
||||||
|
// Expected: is even
|
||||||
|
// Actual: 7
|
||||||
|
//
|
||||||
|
// where the description "is even" is automatically calculated from the
|
||||||
|
// matcher name IsEven.
|
||||||
|
//
|
||||||
|
// Argument Type
|
||||||
|
// =============
|
||||||
|
//
|
||||||
|
// Note that the type of the value being matched (arg_type) is
|
||||||
|
// determined by the context in which you use the matcher and is
|
||||||
|
// supplied to you by the compiler, so you don't need to worry about
|
||||||
|
// declaring it (nor can you). This allows the matcher to be
|
||||||
|
// polymorphic. For example, IsEven() can be used to match any type
|
||||||
|
// where the value of "(arg % 2) == 0" can be implicitly converted to
|
||||||
|
// a bool. In the "Bar(IsEven())" example above, if method Bar()
|
||||||
|
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
|
||||||
|
// 'arg_type' will be unsigned long; and so on.
|
||||||
|
//
|
||||||
|
// Parameterizing Matchers
|
||||||
|
// =======================
|
||||||
|
//
|
||||||
|
// Sometimes you'll want to parameterize the matcher. For that you
|
||||||
|
// can use another macro:
|
||||||
|
//
|
||||||
|
// MATCHER_P(name, param_name, description_string) { statements; }
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
|
||||||
|
//
|
||||||
|
// will allow you to write:
|
||||||
|
//
|
||||||
|
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
|
||||||
|
//
|
||||||
|
// which may lead to this message (assuming n is 10):
|
||||||
|
//
|
||||||
|
// Value of: Blah("a")
|
||||||
|
// Expected: has absolute value 10
|
||||||
|
// Actual: -9
|
||||||
|
//
|
||||||
|
// Note that both the matcher description and its parameter are
|
||||||
|
// printed, making the message human-friendly.
|
||||||
|
//
|
||||||
|
// In the matcher definition body, you can write 'foo_type' to
|
||||||
|
// reference the type of a parameter named 'foo'. For example, in the
|
||||||
|
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
|
||||||
|
// 'value_type' to refer to the type of 'value'.
|
||||||
|
//
|
||||||
|
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
|
||||||
|
// support multi-parameter matchers.
|
||||||
|
//
|
||||||
|
// Describing Parameterized Matchers
|
||||||
|
// =================================
|
||||||
|
//
|
||||||
|
// When defining a parameterized matcher, you can use Python-style
|
||||||
|
// interpolations in the description string to refer to the parameter
|
||||||
|
// values. We support the following syntax currently:
|
||||||
|
//
|
||||||
|
// %% a single '%' character
|
||||||
|
// %(*)s all parameters of the matcher printed as a tuple
|
||||||
|
// %(foo)s value of the matcher parameter named 'foo'
|
||||||
|
//
|
||||||
|
// For example,
|
||||||
|
//
|
||||||
|
// MATCHER_P2(InClosedRange, low, hi, "is in range [%(low)s, %(hi)s]") {
|
||||||
|
// return low <= arg && arg <= hi;
|
||||||
|
// }
|
||||||
|
// ...
|
||||||
|
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||||
|
//
|
||||||
|
// would generate a failure that contains the message:
|
||||||
|
//
|
||||||
|
// Expected: is in range [4, 6]
|
||||||
|
//
|
||||||
|
// If you specify "" as the description, the failure message will
|
||||||
|
// contain the sequence of words in the matcher name followed by the
|
||||||
|
// parameter values printed as a tuple. For example,
|
||||||
|
//
|
||||||
|
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
|
||||||
|
// ...
|
||||||
|
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||||
|
//
|
||||||
|
// would generate a failure that contains the text:
|
||||||
|
//
|
||||||
|
// Expected: in closed range (4, 6)
|
||||||
|
//
|
||||||
|
// Types of Matcher Parameters
|
||||||
|
// ===========================
|
||||||
|
//
|
||||||
|
// For the purpose of typing, you can view
|
||||||
|
//
|
||||||
|
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
|
||||||
|
//
|
||||||
|
// as shorthand for
|
||||||
|
//
|
||||||
|
// template <typename p1_type, ..., typename pk_type>
|
||||||
|
// FooMatcherPk<p1_type, ..., pk_type>
|
||||||
|
// Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||||
|
//
|
||||||
|
// When you write Foo(v1, ..., vk), the compiler infers the types of
|
||||||
|
// the parameters v1, ..., and vk for you. If you are not happy with
|
||||||
|
// the result of the type inference, you can specify the types by
|
||||||
|
// explicitly instantiating the template, as in Foo<long, bool>(5,
|
||||||
|
// false). As said earlier, you don't get to (or need to) specify
|
||||||
|
// 'arg_type' as that's determined by the context in which the matcher
|
||||||
|
// is used. You can assign the result of expression Foo(p1, ..., pk)
|
||||||
|
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This
|
||||||
|
// can be useful when composing matchers.
|
||||||
|
//
|
||||||
|
// While you can instantiate a matcher template with reference types,
|
||||||
|
// passing the parameters by pointer usually makes your code more
|
||||||
|
// readable. If, however, you still want to pass a parameter by
|
||||||
|
// reference, be aware that in the failure message generated by the
|
||||||
|
// matcher you will see the value of the referenced object but not its
|
||||||
|
// address.
|
||||||
|
//
|
||||||
|
// Explaining Match Results
|
||||||
|
// ========================
|
||||||
|
//
|
||||||
|
// Sometimes the matcher description alone isn't enough to explain why
|
||||||
|
// the match has failed or succeeded. For example, when expecting a
|
||||||
|
// long string, it can be very helpful to also print the diff between
|
||||||
|
// the expected string and the actual one. To achieve that, you can
|
||||||
|
// optionally stream additional information to a special variable
|
||||||
|
// named result_listener, whose type is a pointer to class
|
||||||
|
// MatchResultListener:
|
||||||
|
//
|
||||||
|
// MATCHER_P(EqualsLongString, str, "") {
|
||||||
|
// if (arg == str) return true;
|
||||||
|
//
|
||||||
|
// *result_listener << "the difference: "
|
||||||
|
/// << DiffStrings(str, arg);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Overloading Matchers
|
||||||
|
// ====================
|
||||||
|
//
|
||||||
|
// You can overload matchers with different numbers of parameters:
|
||||||
|
//
|
||||||
|
// MATCHER_P(Blah, a, description_string1) { ... }
|
||||||
|
// MATCHER_P2(Blah, a, b, description_string2) { ... }
|
||||||
|
//
|
||||||
|
// Caveats
|
||||||
|
// =======
|
||||||
|
//
|
||||||
|
// When defining a new matcher, you should also consider implementing
|
||||||
|
// MatcherInterface or using MakePolymorphicMatcher(). These
|
||||||
|
// approaches require more work than the MATCHER* macros, but also
|
||||||
|
// give you more control on the types of the value being matched and
|
||||||
|
// the matcher parameters, which may leads to better compiler error
|
||||||
|
// messages when the matcher is used wrong. They also allow
|
||||||
|
// overloading matchers based on parameter types (as opposed to just
|
||||||
|
// based on the number of parameters).
|
||||||
|
//
|
||||||
|
// MATCHER*() can only be used in a namespace scope. The reason is
|
||||||
|
// that C++ doesn't yet allow function-local types to be used to
|
||||||
|
// instantiate templates. The up-coming C++0x standard will fix this.
|
||||||
|
// Once that's done, we'll consider supporting using MATCHER*() inside
|
||||||
|
// a function.
|
||||||
|
//
|
||||||
|
// More Information
|
||||||
|
// ================
|
||||||
|
//
|
||||||
|
// To learn more about using these macros, please search for 'MATCHER'
|
||||||
|
// on http://code.google.com/p/googlemock/wiki/CookBook.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i
|
||||||
|
|
||||||
|
[[
|
||||||
|
$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]]
|
||||||
|
$else [[MATCHER_P$i]]]]
|
||||||
|
$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]]
|
||||||
|
$else [[P$i]]]]]]
|
||||||
|
$range j 0..i-1
|
||||||
|
$var template = [[$if i==0 [[]] $else [[
|
||||||
|
|
||||||
|
template <$for j, [[typename p$j##_type]]>\
|
||||||
|
]]]]
|
||||||
|
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||||
|
$var impl_ctor_param_list = [[$for j [[p$j##_type gmock_p$j, ]]
|
||||||
|
const ::testing::internal::Interpolations& gmock_interp]]
|
||||||
|
$var impl_inits = [[ : $for j [[p$j(gmock_p$j), ]]gmock_interp_(gmock_interp)]]
|
||||||
|
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
|
||||||
|
$var params_and_interp = [[$for j [[p$j, ]]gmock_interp_]]
|
||||||
|
$var params = [[$for j, [[p$j]]]]
|
||||||
|
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
||||||
|
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
||||||
|
$var param_field_decls = [[$for j
|
||||||
|
[[
|
||||||
|
|
||||||
|
p$j##_type p$j;\
|
||||||
|
]]]]
|
||||||
|
$var param_field_decls2 = [[$for j
|
||||||
|
[[
|
||||||
|
|
||||||
|
p$j##_type p$j;\
|
||||||
|
]]]]
|
||||||
|
|
||||||
|
#define $macro_name(name$for j [[, p$j]], description)\$template
|
||||||
|
class $class_name {\
|
||||||
|
public:\
|
||||||
|
template <typename arg_type>\
|
||||||
|
class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
|
||||||
|
public:\
|
||||||
|
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
|
||||||
|
$impl_inits {}\
|
||||||
|
virtual bool MatchAndExplain(\
|
||||||
|
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
|
||||||
|
virtual void DescribeTo(::std::ostream* gmock_os) const {\
|
||||||
|
const ::testing::internal::Strings& gmock_printed_params = \
|
||||||
|
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||||
|
::std::tr1::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]]));\
|
||||||
|
*gmock_os << ::testing::internal::FormatMatcherDescription(\
|
||||||
|
#name, description, gmock_interp_, gmock_printed_params);\
|
||||||
|
}\$param_field_decls
|
||||||
|
const ::testing::internal::Interpolations gmock_interp_;\
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||||
|
};\
|
||||||
|
template <typename arg_type>\
|
||||||
|
operator ::testing::Matcher<arg_type>() const {\
|
||||||
|
return ::testing::Matcher<arg_type>(\
|
||||||
|
new gmock_Impl<arg_type>($params_and_interp));\
|
||||||
|
}\
|
||||||
|
$class_name($ctor_param_list)$inits {\
|
||||||
|
const char* gmock_param_names[] = { $for j [[#p$j, ]]NULL };\
|
||||||
|
gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\
|
||||||
|
gmock_param_names, ("" description ""));\
|
||||||
|
}\$param_field_decls2
|
||||||
|
private:\
|
||||||
|
::testing::internal::Interpolations gmock_interp_;\
|
||||||
|
GTEST_DISALLOW_ASSIGN_($class_name);\
|
||||||
|
};\$template
|
||||||
|
inline $class_name$param_types name($param_types_and_names) {\
|
||||||
|
return $class_name$param_types($params);\
|
||||||
|
}\$template
|
||||||
|
template <typename arg_type>\
|
||||||
|
bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||||
|
arg_type arg,\
|
||||||
|
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||||
|
const
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
|
@ -0,0 +1,274 @@
|
||||||
|
// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
|
||||||
|
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Implements class templates NiceMock and StrictMock.
|
||||||
|
//
|
||||||
|
// Given a mock class MockFoo that is created using Google Mock,
|
||||||
|
// NiceMock<MockFoo> is a subclass of MockFoo that allows
|
||||||
|
// uninteresting calls (i.e. calls to mock methods that have no
|
||||||
|
// EXPECT_CALL specs), and StrictMock<MockFoo> is a subclass of
|
||||||
|
// MockFoo that treats all uninteresting calls as errors.
|
||||||
|
//
|
||||||
|
// NiceMock and StrictMock "inherits" the constructors of their
|
||||||
|
// respective base class, with up-to 10 arguments. Therefore you can
|
||||||
|
// write NiceMock<MockFoo>(5, "a") to construct a nice mock where
|
||||||
|
// MockFoo has a constructor that accepts (int, const char*), for
|
||||||
|
// example.
|
||||||
|
//
|
||||||
|
// A known limitation is that NiceMock<MockFoo> and
|
||||||
|
// StrictMock<MockFoo> only works for mock methods defined using the
|
||||||
|
// MOCK_METHOD* family of macros DIRECTLY in the MockFoo class. If a
|
||||||
|
// mock method is defined in a base class of MockFoo, the "nice" or
|
||||||
|
// "strict" modifier may not affect it, depending on the compiler. In
|
||||||
|
// particular, nesting NiceMock and StrictMock is NOT supported.
|
||||||
|
//
|
||||||
|
// Another known limitation is that the constructors of the base mock
|
||||||
|
// cannot have arguments passed by non-const reference, which are
|
||||||
|
// banned by the Google C++ style guide anyway.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
|
|
||||||
|
#include <gmock/gmock-spec-builders.h>
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class NiceMock : public MockClass {
|
||||||
|
public:
|
||||||
|
// We don't factor out the constructor body to a common method, as
|
||||||
|
// we have to avoid a possible clash with members of MockClass.
|
||||||
|
NiceMock() {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++ doesn't (yet) allow inheritance of constructors, so we have
|
||||||
|
// to define it for each arity.
|
||||||
|
template <typename A1>
|
||||||
|
explicit NiceMock(const A1& a1) : MockClass(a1) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
NiceMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3,
|
||||||
|
const A4& a4) : MockClass(a1, a2, a3, a4) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
|
||||||
|
a6, a7) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
|
||||||
|
a2, a3, a4, a5, a6, a7, a8) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8,
|
||||||
|
const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9, typename A10>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
|
||||||
|
const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~NiceMock() {
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class StrictMock : public MockClass {
|
||||||
|
public:
|
||||||
|
// We don't factor out the constructor body to a common method, as
|
||||||
|
// we have to avoid a possible clash with members of MockClass.
|
||||||
|
StrictMock() {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1>
|
||||||
|
explicit StrictMock(const A1& a1) : MockClass(a1) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
StrictMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3,
|
||||||
|
const A4& a4) : MockClass(a1, a2, a3, a4) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
|
||||||
|
a6, a7) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
|
||||||
|
a2, a3, a4, a5, a6, a7, a8) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8,
|
||||||
|
const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9, typename A10>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
|
||||||
|
const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~StrictMock() {
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following specializations catch some (relatively more common)
|
||||||
|
// user errors of nesting nice and strict mocks. They do NOT catch
|
||||||
|
// all possible errors.
|
||||||
|
|
||||||
|
// These specializations are declared but not defined, as NiceMock and
|
||||||
|
// StrictMock cannot be nested.
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<StrictMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<StrictMock<MockClass> >;
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
|
@ -0,0 +1,160 @@
|
||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-nice-strict.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we 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.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Implements class templates NiceMock and StrictMock.
|
||||||
|
//
|
||||||
|
// Given a mock class MockFoo that is created using Google Mock,
|
||||||
|
// NiceMock<MockFoo> is a subclass of MockFoo that allows
|
||||||
|
// uninteresting calls (i.e. calls to mock methods that have no
|
||||||
|
// EXPECT_CALL specs), and StrictMock<MockFoo> is a subclass of
|
||||||
|
// MockFoo that treats all uninteresting calls as errors.
|
||||||
|
//
|
||||||
|
// NiceMock and StrictMock "inherits" the constructors of their
|
||||||
|
// respective base class, with up-to $n arguments. Therefore you can
|
||||||
|
// write NiceMock<MockFoo>(5, "a") to construct a nice mock where
|
||||||
|
// MockFoo has a constructor that accepts (int, const char*), for
|
||||||
|
// example.
|
||||||
|
//
|
||||||
|
// A known limitation is that NiceMock<MockFoo> and
|
||||||
|
// StrictMock<MockFoo> only works for mock methods defined using the
|
||||||
|
// MOCK_METHOD* family of macros DIRECTLY in the MockFoo class. If a
|
||||||
|
// mock method is defined in a base class of MockFoo, the "nice" or
|
||||||
|
// "strict" modifier may not affect it, depending on the compiler. In
|
||||||
|
// particular, nesting NiceMock and StrictMock is NOT supported.
|
||||||
|
//
|
||||||
|
// Another known limitation is that the constructors of the base mock
|
||||||
|
// cannot have arguments passed by non-const reference, which are
|
||||||
|
// banned by the Google C++ style guide anyway.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
|
|
||||||
|
#include <gmock/gmock-spec-builders.h>
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class NiceMock : public MockClass {
|
||||||
|
public:
|
||||||
|
// We don't factor out the constructor body to a common method, as
|
||||||
|
// we have to avoid a possible clash with members of MockClass.
|
||||||
|
NiceMock() {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++ doesn't (yet) allow inheritance of constructors, so we have
|
||||||
|
// to define it for each arity.
|
||||||
|
template <typename A1>
|
||||||
|
explicit NiceMock(const A1& a1) : MockClass(a1) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
template <$for j, [[typename A$j]]>
|
||||||
|
NiceMock($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
virtual ~NiceMock() {
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class StrictMock : public MockClass {
|
||||||
|
public:
|
||||||
|
// We don't factor out the constructor body to a common method, as
|
||||||
|
// we have to avoid a possible clash with members of MockClass.
|
||||||
|
StrictMock() {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1>
|
||||||
|
explicit StrictMock(const A1& a1) : MockClass(a1) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
template <$for j, [[typename A$j]]>
|
||||||
|
StrictMock($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
virtual ~StrictMock() {
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::implicit_cast<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following specializations catch some (relatively more common)
|
||||||
|
// user errors of nesting nice and strict mocks. They do NOT catch
|
||||||
|
// all possible errors.
|
||||||
|
|
||||||
|
// These specializations are declared but not defined, as NiceMock and
|
||||||
|
// StrictMock cannot be nested.
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<StrictMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<StrictMock<MockClass> >;
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,210 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some actions that depend on gmock-generated-actions.h.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||||
|
|
||||||
|
#include <gmock/gmock-generated-actions.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Implements the Invoke(f) action. The template argument
|
||||||
|
// FunctionImpl is the implementation type of f, which can be either a
|
||||||
|
// function pointer or a functor. Invoke(f) can be used as an
|
||||||
|
// Action<F> as long as f's type is compatible with F (i.e. f can be
|
||||||
|
// assigned to a tr1::function<F>).
|
||||||
|
template <typename FunctionImpl>
|
||||||
|
class InvokeAction {
|
||||||
|
public:
|
||||||
|
// The c'tor makes a copy of function_impl (either a function
|
||||||
|
// pointer or a functor).
|
||||||
|
explicit InvokeAction(FunctionImpl function_impl)
|
||||||
|
: function_impl_(function_impl) {}
|
||||||
|
|
||||||
|
template <typename Result, typename ArgumentTuple>
|
||||||
|
Result Perform(const ArgumentTuple& args) {
|
||||||
|
return InvokeHelper<Result, ArgumentTuple>::Invoke(function_impl_, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionImpl function_impl_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(InvokeAction);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implements the Invoke(object_ptr, &Class::Method) action.
|
||||||
|
template <class Class, typename MethodPtr>
|
||||||
|
class InvokeMethodAction {
|
||||||
|
public:
|
||||||
|
InvokeMethodAction(Class* obj_ptr, MethodPtr method_ptr)
|
||||||
|
: obj_ptr_(obj_ptr), method_ptr_(method_ptr) {}
|
||||||
|
|
||||||
|
template <typename Result, typename ArgumentTuple>
|
||||||
|
Result Perform(const ArgumentTuple& args) const {
|
||||||
|
return InvokeHelper<Result, ArgumentTuple>::InvokeMethod(
|
||||||
|
obj_ptr_, method_ptr_, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Class* const obj_ptr_;
|
||||||
|
const MethodPtr method_ptr_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(InvokeMethodAction);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Various overloads for Invoke().
|
||||||
|
|
||||||
|
// Creates an action that invokes 'function_impl' with the mock
|
||||||
|
// function's arguments.
|
||||||
|
template <typename FunctionImpl>
|
||||||
|
PolymorphicAction<internal::InvokeAction<FunctionImpl> > Invoke(
|
||||||
|
FunctionImpl function_impl) {
|
||||||
|
return MakePolymorphicAction(
|
||||||
|
internal::InvokeAction<FunctionImpl>(function_impl));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an action that invokes the given method on the given object
|
||||||
|
// with the mock function's arguments.
|
||||||
|
template <class Class, typename MethodPtr>
|
||||||
|
PolymorphicAction<internal::InvokeMethodAction<Class, MethodPtr> > Invoke(
|
||||||
|
Class* obj_ptr, MethodPtr method_ptr) {
|
||||||
|
return MakePolymorphicAction(
|
||||||
|
internal::InvokeMethodAction<Class, MethodPtr>(obj_ptr, method_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutArgs(inner_action) can be used in a mock function with a
|
||||||
|
// non-empty argument list to perform inner_action, which takes no
|
||||||
|
// argument. In other words, it adapts an action accepting no
|
||||||
|
// argument to one that accepts (and ignores) arguments.
|
||||||
|
template <typename InnerAction>
|
||||||
|
inline internal::WithArgsAction<InnerAction>
|
||||||
|
WithoutArgs(const InnerAction& action) {
|
||||||
|
return internal::WithArgsAction<InnerAction>(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithArg<k>(an_action) creates an action that passes the k-th
|
||||||
|
// (0-based) argument of the mock function to an_action and performs
|
||||||
|
// it. It adapts an action accepting one argument to one that accepts
|
||||||
|
// multiple arguments. For convenience, we also provide
|
||||||
|
// WithArgs<k>(an_action) (defined below) as a synonym.
|
||||||
|
template <int k, typename InnerAction>
|
||||||
|
inline internal::WithArgsAction<InnerAction, k>
|
||||||
|
WithArg(const InnerAction& action) {
|
||||||
|
return internal::WithArgsAction<InnerAction, k>(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||||
|
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||||
|
// the macro definition, as the warnings are generated when the macro
|
||||||
|
// is expanded and macro expansion cannot contain #pragma. Therefore
|
||||||
|
// we suppress them here.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4100)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Action ReturnArg<k>() returns the k-th argument of the mock function.
|
||||||
|
ACTION_TEMPLATE(ReturnArg,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_0_VALUE_PARAMS()) {
|
||||||
|
return std::tr1::get<k>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
|
||||||
|
// mock function to *pointer.
|
||||||
|
ACTION_TEMPLATE(SaveArg,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_1_VALUE_PARAMS(pointer)) {
|
||||||
|
*pointer = ::std::tr1::get<k>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action SetArgReferee<k>(value) assigns 'value' to the variable
|
||||||
|
// referenced by the k-th (0-based) argument of the mock function.
|
||||||
|
ACTION_TEMPLATE(SetArgReferee,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_1_VALUE_PARAMS(value)) {
|
||||||
|
typedef typename ::std::tr1::tuple_element<k, args_type>::type argk_type;
|
||||||
|
// Ensures that argument #k is a reference. If you get a compiler
|
||||||
|
// error on the next line, you are using SetArgReferee<k>(value) in
|
||||||
|
// a mock function whose k-th (0-based) argument is not a reference.
|
||||||
|
GMOCK_COMPILE_ASSERT_(internal::is_reference<argk_type>::value,
|
||||||
|
SetArgReferee_must_be_used_with_a_reference_argument);
|
||||||
|
::std::tr1::get<k>(args) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action SetArrayArgument<k>(first, last) copies the elements in
|
||||||
|
// source range [first, last) to the array pointed to by the k-th
|
||||||
|
// (0-based) argument, which can be either a pointer or an
|
||||||
|
// iterator. The action does not take ownership of the elements in the
|
||||||
|
// source range.
|
||||||
|
ACTION_TEMPLATE(SetArrayArgument,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_2_VALUE_PARAMS(first, last)) {
|
||||||
|
// Microsoft compiler deprecates ::std::copy, so we want to suppress warning
|
||||||
|
// 4996 (Function call with parameters that may be unsafe) there.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push) // Saves the current warning state.
|
||||||
|
#pragma warning(disable:4996) // Temporarily disables warning 4996.
|
||||||
|
#endif
|
||||||
|
::std::copy(first, last, ::std::tr1::get<k>(args));
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop) // Restores the warning state.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
|
||||||
|
// function.
|
||||||
|
ACTION_TEMPLATE(DeleteArg,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_0_VALUE_PARAMS()) {
|
||||||
|
delete ::std::tr1::get<k>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action Throw(exception) can be used in a mock function of any type
|
||||||
|
// to throw the given exception. Any copyable value can be thrown.
|
||||||
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
|
ACTION_P(Throw, exception) { throw exception; }
|
||||||
|
#endif // GTEST_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
|
@ -0,0 +1,725 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements a universal value printer that can print a
|
||||||
|
// value of any type T:
|
||||||
|
//
|
||||||
|
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
|
||||||
|
//
|
||||||
|
// A user can teach this function how to print a class type T by
|
||||||
|
// defining either operator<<() or PrintTo() in the namespace that
|
||||||
|
// defines T. More specifically, the FIRST defined function in the
|
||||||
|
// following list will be used (assuming T is defined in namespace
|
||||||
|
// foo):
|
||||||
|
//
|
||||||
|
// 1. foo::PrintTo(const T&, ostream*)
|
||||||
|
// 2. operator<<(ostream&, const T&) defined in either foo or the
|
||||||
|
// global namespace.
|
||||||
|
//
|
||||||
|
// If none of the above is defined, it will print the debug string of
|
||||||
|
// the value if it is a protocol buffer, or print the raw bytes in the
|
||||||
|
// value otherwise.
|
||||||
|
//
|
||||||
|
// To aid debugging: when T is a reference type, the address of the
|
||||||
|
// value is also printed; when T is a (const) char pointer, both the
|
||||||
|
// pointer value and the NUL-terminated string it points to are
|
||||||
|
// printed.
|
||||||
|
//
|
||||||
|
// We also provide some convenient wrappers:
|
||||||
|
//
|
||||||
|
// // Prints a value to a string. For a (const or not) char
|
||||||
|
// // pointer, the NUL-terminated string (but not the pointer) is
|
||||||
|
// // printed.
|
||||||
|
// std::string ::testing::PrintToString(const T& value);
|
||||||
|
//
|
||||||
|
// // Prints a value tersely: for a reference type, the referenced
|
||||||
|
// // value (but not the address) is printed; for a (const or not) char
|
||||||
|
// // pointer, the NUL-terminated string (but not the pointer) is
|
||||||
|
// // printed.
|
||||||
|
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
|
||||||
|
//
|
||||||
|
// // Prints value using the type inferred by the compiler. The difference
|
||||||
|
// // from UniversalTersePrint() is that this function prints both the
|
||||||
|
// // pointer and the NUL-terminated string for a (const or not) char pointer.
|
||||||
|
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
|
||||||
|
//
|
||||||
|
// // Prints the fields of a tuple tersely to a string vector, one
|
||||||
|
// // element for each field.
|
||||||
|
// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
|
||||||
|
// const Tuple& value);
|
||||||
|
//
|
||||||
|
// Known limitation:
|
||||||
|
//
|
||||||
|
// The print primitives print the elements of an STL-style container
|
||||||
|
// using the compiler-inferred type of *iter where iter is a
|
||||||
|
// const_iterator of the container. When const_iterator is an input
|
||||||
|
// iterator but not a forward iterator, this inferred type may not
|
||||||
|
// match value_type, and the print output may be incorrect. In
|
||||||
|
// practice, this is rarely a problem as for most containers
|
||||||
|
// const_iterator is a forward iterator. We'll fix this if there's an
|
||||||
|
// actual need for it. Note that this fix cannot rely on value_type
|
||||||
|
// being defined as many user-defined container types don't have
|
||||||
|
// value_type.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
|
||||||
|
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <gmock/internal/gmock-internal-utils.h>
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Definitions in the 'internal' and 'internal2' name spaces are
|
||||||
|
// subject to change without notice. DO NOT USE THEM IN USER CODE!
|
||||||
|
namespace internal2 {
|
||||||
|
|
||||||
|
// Prints the given number of bytes in the given object to the given
|
||||||
|
// ostream.
|
||||||
|
void PrintBytesInObjectTo(const unsigned char* obj_bytes,
|
||||||
|
size_t count,
|
||||||
|
::std::ostream* os);
|
||||||
|
|
||||||
|
// TypeWithoutFormatter<T, kIsProto>::PrintValue(value, os) is called
|
||||||
|
// by the universal printer to print a value of type T when neither
|
||||||
|
// operator<< nor PrintTo() is defined for type T. When T is
|
||||||
|
// ProtocolMessage, proto2::Message, or a subclass of those, kIsProto
|
||||||
|
// will be true and the short debug string of the protocol message
|
||||||
|
// value will be printed; otherwise kIsProto will be false and the
|
||||||
|
// bytes in the value will be printed.
|
||||||
|
template <typename T, bool kIsProto>
|
||||||
|
class TypeWithoutFormatter {
|
||||||
|
public:
|
||||||
|
static void PrintValue(const T& value, ::std::ostream* os) {
|
||||||
|
PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
|
||||||
|
sizeof(value), os);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// We print a protobuf using its ShortDebugString() when the string
|
||||||
|
// doesn't exceed this many characters; otherwise we print it using
|
||||||
|
// DebugString() for better readability.
|
||||||
|
const size_t kProtobufOneLinerMaxLength = 50;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class TypeWithoutFormatter<T, true> {
|
||||||
|
public:
|
||||||
|
static void PrintValue(const T& value, ::std::ostream* os) {
|
||||||
|
const ::testing::internal::string short_str = value.ShortDebugString();
|
||||||
|
const ::testing::internal::string pretty_str =
|
||||||
|
short_str.length() <= kProtobufOneLinerMaxLength ?
|
||||||
|
short_str : ("\n" + value.DebugString());
|
||||||
|
::std::operator<<(*os, "<" + pretty_str + ">");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prints the given value to the given ostream. If the value is a
|
||||||
|
// protocol message, its short debug string is printed; otherwise the
|
||||||
|
// bytes in the value are printed. This is what
|
||||||
|
// UniversalPrinter<T>::Print() does when it knows nothing about type
|
||||||
|
// T and T has no << operator.
|
||||||
|
//
|
||||||
|
// A user can override this behavior for a class type Foo by defining
|
||||||
|
// a << operator in the namespace where Foo is defined.
|
||||||
|
//
|
||||||
|
// We put this operator in namespace 'internal2' instead of 'internal'
|
||||||
|
// to simplify the implementation, as much code in 'internal' needs to
|
||||||
|
// use << in STL, which would conflict with our own << were it defined
|
||||||
|
// in 'internal'.
|
||||||
|
//
|
||||||
|
// Note that this operator<< takes a generic std::basic_ostream<Char,
|
||||||
|
// CharTraits> type instead of the more restricted std::ostream. If
|
||||||
|
// we define it to take an std::ostream instead, we'll get an
|
||||||
|
// "ambiguous overloads" compiler error when trying to print a type
|
||||||
|
// Foo that supports streaming to std::basic_ostream<Char,
|
||||||
|
// CharTraits>, as the compiler cannot tell whether
|
||||||
|
// operator<<(std::ostream&, const T&) or
|
||||||
|
// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
|
||||||
|
// specific.
|
||||||
|
template <typename Char, typename CharTraits, typename T>
|
||||||
|
::std::basic_ostream<Char, CharTraits>& operator<<(
|
||||||
|
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
|
||||||
|
TypeWithoutFormatter<T, ::testing::internal::IsAProtocolMessage<T>::value>::
|
||||||
|
PrintValue(x, &os);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal2
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
|
||||||
|
// magic needed for implementing UniversalPrinter won't work.
|
||||||
|
namespace testing_internal {
|
||||||
|
|
||||||
|
// Used to print a value that is not an STL-style container when the
|
||||||
|
// user doesn't define PrintTo() for it.
|
||||||
|
template <typename T>
|
||||||
|
void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
|
||||||
|
// With the following statement, during unqualified name lookup,
|
||||||
|
// testing::internal2::operator<< appears as if it was declared in
|
||||||
|
// the nearest enclosing namespace that contains both
|
||||||
|
// ::testing_internal and ::testing::internal2, i.e. the global
|
||||||
|
// namespace. For more details, refer to the C++ Standard section
|
||||||
|
// 7.3.4-1 [namespace.udir]. This allows us to fall back onto
|
||||||
|
// testing::internal2::operator<< in case T doesn't come with a <<
|
||||||
|
// operator.
|
||||||
|
//
|
||||||
|
// We cannot write 'using ::testing::internal2::operator<<;', which
|
||||||
|
// gcc 3.3 fails to compile due to a compiler bug.
|
||||||
|
using namespace ::testing::internal2; // NOLINT
|
||||||
|
|
||||||
|
// Assuming T is defined in namespace foo, in the next statement,
|
||||||
|
// the compiler will consider all of:
|
||||||
|
//
|
||||||
|
// 1. foo::operator<< (thanks to Koenig look-up),
|
||||||
|
// 2. ::operator<< (as the current namespace is enclosed in ::),
|
||||||
|
// 3. testing::internal2::operator<< (thanks to the using statement above).
|
||||||
|
//
|
||||||
|
// The operator<< whose type matches T best will be picked.
|
||||||
|
//
|
||||||
|
// We deliberately allow #2 to be a candidate, as sometimes it's
|
||||||
|
// impossible to define #1 (e.g. when foo is ::std, defining
|
||||||
|
// anything in it is undefined behavior unless you are a compiler
|
||||||
|
// vendor.).
|
||||||
|
*os << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing_internal
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
|
||||||
|
// value to the given ostream. The caller must ensure that
|
||||||
|
// 'ostream_ptr' is not NULL, or the behavior is undefined.
|
||||||
|
//
|
||||||
|
// We define UniversalPrinter as a class template (as opposed to a
|
||||||
|
// function template), as we need to partially specialize it for
|
||||||
|
// reference types, which cannot be done with function templates.
|
||||||
|
template <typename T>
|
||||||
|
class UniversalPrinter;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void UniversalPrint(const T& value, ::std::ostream* os);
|
||||||
|
|
||||||
|
// Used to print an STL-style container when the user doesn't define
|
||||||
|
// a PrintTo() for it.
|
||||||
|
template <typename C>
|
||||||
|
void DefaultPrintTo(IsContainer /* dummy */,
|
||||||
|
false_type /* is not a pointer */,
|
||||||
|
const C& container, ::std::ostream* os) {
|
||||||
|
const size_t kMaxCount = 32; // The maximum number of elements to print.
|
||||||
|
*os << '{';
|
||||||
|
size_t count = 0;
|
||||||
|
for (typename C::const_iterator it = container.begin();
|
||||||
|
it != container.end(); ++it, ++count) {
|
||||||
|
if (count > 0) {
|
||||||
|
*os << ',';
|
||||||
|
if (count == kMaxCount) { // Enough has been printed.
|
||||||
|
*os << " ...";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*os << ' ';
|
||||||
|
// We cannot call PrintTo(*it, os) here as PrintTo() doesn't
|
||||||
|
// handle *it being a native array.
|
||||||
|
internal::UniversalPrint(*it, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
*os << ' ';
|
||||||
|
}
|
||||||
|
*os << '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to print a pointer that is neither a char pointer nor a member
|
||||||
|
// pointer, when the user doesn't define PrintTo() for it. (A member
|
||||||
|
// variable pointer or member function pointer doesn't really point to
|
||||||
|
// a location in the address space. Their representation is
|
||||||
|
// implementation-defined. Therefore they will be printed as raw
|
||||||
|
// bytes.)
|
||||||
|
template <typename T>
|
||||||
|
void DefaultPrintTo(IsNotContainer /* dummy */,
|
||||||
|
true_type /* is a pointer */,
|
||||||
|
T* p, ::std::ostream* os) {
|
||||||
|
if (p == NULL) {
|
||||||
|
*os << "NULL";
|
||||||
|
} else {
|
||||||
|
// We want to print p as a const void*. However, we cannot cast
|
||||||
|
// it to const void* directly, even using reinterpret_cast, as
|
||||||
|
// earlier versions of gcc (e.g. 3.4.5) cannot compile the cast
|
||||||
|
// when p is a function pointer. Casting to UInt64 first solves
|
||||||
|
// the problem.
|
||||||
|
*os << reinterpret_cast<const void*>(reinterpret_cast<internal::UInt64>(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to print a non-container, non-pointer value when the user
|
||||||
|
// doesn't define PrintTo() for it.
|
||||||
|
template <typename T>
|
||||||
|
void DefaultPrintTo(IsNotContainer /* dummy */,
|
||||||
|
false_type /* is not a pointer */,
|
||||||
|
const T& value, ::std::ostream* os) {
|
||||||
|
::testing_internal::DefaultPrintNonContainerTo(value, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given value using the << operator if it has one;
|
||||||
|
// otherwise prints the bytes in it. This is what
|
||||||
|
// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
|
||||||
|
// or overloaded for type T.
|
||||||
|
//
|
||||||
|
// A user can override this behavior for a class type Foo by defining
|
||||||
|
// an overload of PrintTo() in the namespace where Foo is defined. We
|
||||||
|
// give the user this option as sometimes defining a << operator for
|
||||||
|
// Foo is not desirable (e.g. the coding style may prevent doing it,
|
||||||
|
// or there is already a << operator but it doesn't do what the user
|
||||||
|
// wants).
|
||||||
|
template <typename T>
|
||||||
|
void PrintTo(const T& value, ::std::ostream* os) {
|
||||||
|
// DefaultPrintTo() is overloaded. The type of its first two
|
||||||
|
// arguments determine which version will be picked. If T is an
|
||||||
|
// STL-style container, the version for container will be called; if
|
||||||
|
// T is a pointer, the pointer version will be called; otherwise the
|
||||||
|
// generic version will be called.
|
||||||
|
//
|
||||||
|
// Note that we check for container types here, prior to we check
|
||||||
|
// for protocol message types in our operator<<. The rationale is:
|
||||||
|
//
|
||||||
|
// For protocol messages, we want to give people a chance to
|
||||||
|
// override Google Mock's format by defining a PrintTo() or
|
||||||
|
// operator<<. For STL containers, other formats can be
|
||||||
|
// incompatible with Google Mock's format for the container
|
||||||
|
// elements; therefore we check for container types here to ensure
|
||||||
|
// that our format is used.
|
||||||
|
//
|
||||||
|
// The second argument of DefaultPrintTo() is needed to bypass a bug
|
||||||
|
// in Symbian's C++ compiler that prevents it from picking the right
|
||||||
|
// overload between:
|
||||||
|
//
|
||||||
|
// PrintTo(const T& x, ...);
|
||||||
|
// PrintTo(T* x, ...);
|
||||||
|
DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following list of PrintTo() overloads tells
|
||||||
|
// UniversalPrinter<T>::Print() how to print standard types (built-in
|
||||||
|
// types, strings, plain arrays, and pointers).
|
||||||
|
|
||||||
|
// Overloads for various char types.
|
||||||
|
void PrintCharTo(char c, int char_code, ::std::ostream* os);
|
||||||
|
inline void PrintTo(unsigned char c, ::std::ostream* os) {
|
||||||
|
PrintCharTo(c, c, os);
|
||||||
|
}
|
||||||
|
inline void PrintTo(signed char c, ::std::ostream* os) {
|
||||||
|
PrintCharTo(c, c, os);
|
||||||
|
}
|
||||||
|
inline void PrintTo(char c, ::std::ostream* os) {
|
||||||
|
// When printing a plain char, we always treat it as unsigned. This
|
||||||
|
// way, the output won't be affected by whether the compiler thinks
|
||||||
|
// char is signed or not.
|
||||||
|
PrintTo(static_cast<unsigned char>(c), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overloads for other simple built-in types.
|
||||||
|
inline void PrintTo(bool x, ::std::ostream* os) {
|
||||||
|
*os << (x ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overload for wchar_t type.
|
||||||
|
// Prints a wchar_t as a symbol if it is printable or as its internal
|
||||||
|
// code otherwise and also as its decimal code (except for L'\0').
|
||||||
|
// The L'\0' char is printed as "L'\\0'". The decimal code is printed
|
||||||
|
// as signed integer when wchar_t is implemented by the compiler
|
||||||
|
// as a signed type and is printed as an unsigned integer when wchar_t
|
||||||
|
// is implemented as an unsigned type.
|
||||||
|
void PrintTo(wchar_t wc, ::std::ostream* os);
|
||||||
|
|
||||||
|
// Overloads for C strings.
|
||||||
|
void PrintTo(const char* s, ::std::ostream* os);
|
||||||
|
inline void PrintTo(char* s, ::std::ostream* os) {
|
||||||
|
PrintTo(implicit_cast<const char*>(s), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MSVC can be configured to define wchar_t as a typedef of unsigned
|
||||||
|
// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
|
||||||
|
// type. When wchar_t is a typedef, defining an overload for const
|
||||||
|
// wchar_t* would cause unsigned short* be printed as a wide string,
|
||||||
|
// possibly causing invalid memory accesses.
|
||||||
|
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||||
|
// Overloads for wide C strings
|
||||||
|
void PrintTo(const wchar_t* s, ::std::ostream* os);
|
||||||
|
inline void PrintTo(wchar_t* s, ::std::ostream* os) {
|
||||||
|
PrintTo(implicit_cast<const wchar_t*>(s), os);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Overload for C arrays. Multi-dimensional arrays are printed
|
||||||
|
// properly.
|
||||||
|
|
||||||
|
// Prints the given number of elements in an array, without printing
|
||||||
|
// the curly braces.
|
||||||
|
template <typename T>
|
||||||
|
void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
|
||||||
|
UniversalPrinter<T>::Print(a[0], os);
|
||||||
|
for (size_t i = 1; i != count; i++) {
|
||||||
|
*os << ", ";
|
||||||
|
UniversalPrinter<T>::Print(a[i], os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overloads for ::string and ::std::string.
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
void PrintStringTo(const ::string&s, ::std::ostream* os);
|
||||||
|
inline void PrintTo(const ::string& s, ::std::ostream* os) {
|
||||||
|
PrintStringTo(s, os);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
|
void PrintStringTo(const ::std::string&s, ::std::ostream* os);
|
||||||
|
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
|
||||||
|
PrintStringTo(s, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overloads for ::wstring and ::std::wstring.
|
||||||
|
#if GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
|
||||||
|
inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
|
||||||
|
PrintWideStringTo(s, os);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
|
||||||
|
#if GTEST_HAS_STD_WSTRING
|
||||||
|
void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
|
||||||
|
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
||||||
|
PrintWideStringTo(s, os);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
|
// Overload for ::std::tr1::tuple. Needed for printing function
|
||||||
|
// arguments, which are packed as tuples.
|
||||||
|
|
||||||
|
// Helper function for printing a tuple. T must be instantiated with
|
||||||
|
// a tuple type.
|
||||||
|
template <typename T>
|
||||||
|
void PrintTupleTo(const T& t, ::std::ostream* os);
|
||||||
|
|
||||||
|
// Overloaded PrintTo() for tuples of various arities. We support
|
||||||
|
// tuples of up-to 10 fields. The following implementation works
|
||||||
|
// regardless of whether tr1::tuple is implemented using the
|
||||||
|
// non-standard variadic template feature or not.
|
||||||
|
|
||||||
|
inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
|
||||||
|
::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
|
||||||
|
::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
|
||||||
|
::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7, typename T8>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
|
||||||
|
::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7, typename T8, typename T9>
|
||||||
|
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
|
||||||
|
::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||||
|
void PrintTo(
|
||||||
|
const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
|
||||||
|
::std::ostream* os) {
|
||||||
|
PrintTupleTo(t, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overload for std::pair.
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
|
||||||
|
*os << '(';
|
||||||
|
UniversalPrinter<T1>::Print(value.first, os);
|
||||||
|
*os << ", ";
|
||||||
|
UniversalPrinter<T2>::Print(value.second, os);
|
||||||
|
*os << ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements printing a non-reference type T by letting the compiler
|
||||||
|
// pick the right overload of PrintTo() for T.
|
||||||
|
template <typename T>
|
||||||
|
class UniversalPrinter {
|
||||||
|
public:
|
||||||
|
// MSVC warns about adding const to a function type, so we want to
|
||||||
|
// disable the warning.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push) // Saves the current warning state.
|
||||||
|
#pragma warning(disable:4180) // Temporarily disables warning 4180.
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
// Note: we deliberately don't call this PrintTo(), as that name
|
||||||
|
// conflicts with ::testing::internal::PrintTo in the body of the
|
||||||
|
// function.
|
||||||
|
static void Print(const T& value, ::std::ostream* os) {
|
||||||
|
// By default, ::testing::internal::PrintTo() is used for printing
|
||||||
|
// the value.
|
||||||
|
//
|
||||||
|
// Thanks to Koenig look-up, if T is a class and has its own
|
||||||
|
// PrintTo() function defined in its namespace, that function will
|
||||||
|
// be visible here. Since it is more specific than the generic ones
|
||||||
|
// in ::testing::internal, it will be picked by the compiler in the
|
||||||
|
// following statement - exactly what we want.
|
||||||
|
PrintTo(value, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop) // Restores the warning state.
|
||||||
|
#endif // _MSC_VER
|
||||||
|
};
|
||||||
|
|
||||||
|
// UniversalPrintArray(begin, len, os) prints an array of 'len'
|
||||||
|
// elements, starting at address 'begin'.
|
||||||
|
template <typename T>
|
||||||
|
void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
|
||||||
|
if (len == 0) {
|
||||||
|
*os << "{}";
|
||||||
|
} else {
|
||||||
|
*os << "{ ";
|
||||||
|
const size_t kThreshold = 18;
|
||||||
|
const size_t kChunkSize = 8;
|
||||||
|
// If the array has more than kThreshold elements, we'll have to
|
||||||
|
// omit some details by printing only the first and the last
|
||||||
|
// kChunkSize elements.
|
||||||
|
// TODO(wan@google.com): let the user control the threshold using a flag.
|
||||||
|
if (len <= kThreshold) {
|
||||||
|
PrintRawArrayTo(begin, len, os);
|
||||||
|
} else {
|
||||||
|
PrintRawArrayTo(begin, kChunkSize, os);
|
||||||
|
*os << ", ..., ";
|
||||||
|
PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
|
||||||
|
}
|
||||||
|
*os << " }";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This overload prints a (const) char array compactly.
|
||||||
|
void UniversalPrintArray(const char* begin, size_t len, ::std::ostream* os);
|
||||||
|
|
||||||
|
// Implements printing an array type T[N].
|
||||||
|
template <typename T, size_t N>
|
||||||
|
class UniversalPrinter<T[N]> {
|
||||||
|
public:
|
||||||
|
// Prints the given array, omitting some elements when there are too
|
||||||
|
// many.
|
||||||
|
static void Print(const T (&a)[N], ::std::ostream* os) {
|
||||||
|
UniversalPrintArray(a, N, os);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implements printing a reference type T&.
|
||||||
|
template <typename T>
|
||||||
|
class UniversalPrinter<T&> {
|
||||||
|
public:
|
||||||
|
// MSVC warns about adding const to a function type, so we want to
|
||||||
|
// disable the warning.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push) // Saves the current warning state.
|
||||||
|
#pragma warning(disable:4180) // Temporarily disables warning 4180.
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
static void Print(const T& value, ::std::ostream* os) {
|
||||||
|
// Prints the address of the value. We use reinterpret_cast here
|
||||||
|
// as static_cast doesn't compile when T is a function type.
|
||||||
|
*os << "@" << reinterpret_cast<const void*>(&value) << " ";
|
||||||
|
|
||||||
|
// Then prints the value itself.
|
||||||
|
UniversalPrinter<T>::Print(value, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop) // Restores the warning state.
|
||||||
|
#endif // _MSC_VER
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prints a value tersely: for a reference type, the referenced value
|
||||||
|
// (but not the address) is printed; for a (const) char pointer, the
|
||||||
|
// NUL-terminated string (but not the pointer) is printed.
|
||||||
|
template <typename T>
|
||||||
|
void UniversalTersePrint(const T& value, ::std::ostream* os) {
|
||||||
|
UniversalPrinter<T>::Print(value, os);
|
||||||
|
}
|
||||||
|
inline void UniversalTersePrint(const char* str, ::std::ostream* os) {
|
||||||
|
if (str == NULL) {
|
||||||
|
*os << "NULL";
|
||||||
|
} else {
|
||||||
|
UniversalPrinter<string>::Print(string(str), os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void UniversalTersePrint(char* str, ::std::ostream* os) {
|
||||||
|
UniversalTersePrint(static_cast<const char*>(str), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints a value using the type inferred by the compiler. The
|
||||||
|
// difference between this and UniversalTersePrint() is that for a
|
||||||
|
// (const) char pointer, this prints both the pointer and the
|
||||||
|
// NUL-terminated string.
|
||||||
|
template <typename T>
|
||||||
|
void UniversalPrint(const T& value, ::std::ostream* os) {
|
||||||
|
UniversalPrinter<T>::Print(value, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ::std::vector<string> Strings;
|
||||||
|
|
||||||
|
// This helper template allows PrintTo() for tuples and
|
||||||
|
// UniversalTersePrintTupleFieldsToStrings() to be defined by
|
||||||
|
// induction on the number of tuple fields. The idea is that
|
||||||
|
// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
|
||||||
|
// fields in tuple t, and can be defined in terms of
|
||||||
|
// TuplePrefixPrinter<N - 1>.
|
||||||
|
|
||||||
|
// The inductive case.
|
||||||
|
template <size_t N>
|
||||||
|
struct TuplePrefixPrinter {
|
||||||
|
// Prints the first N fields of a tuple.
|
||||||
|
template <typename Tuple>
|
||||||
|
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
|
||||||
|
TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
|
||||||
|
*os << ", ";
|
||||||
|
UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
|
||||||
|
::Print(::std::tr1::get<N - 1>(t), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tersely prints the first N fields of a tuple to a string vector,
|
||||||
|
// one element for each field.
|
||||||
|
template <typename Tuple>
|
||||||
|
static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
|
||||||
|
TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
|
||||||
|
::std::stringstream ss;
|
||||||
|
UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
|
||||||
|
strings->push_back(ss.str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Base cases.
|
||||||
|
template <>
|
||||||
|
struct TuplePrefixPrinter<0> {
|
||||||
|
template <typename Tuple>
|
||||||
|
static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
|
||||||
|
|
||||||
|
template <typename Tuple>
|
||||||
|
static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
template <typename Tuple>
|
||||||
|
void TuplePrefixPrinter<1>::PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
|
||||||
|
UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
|
||||||
|
Print(::std::tr1::get<0>(t), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for printing a tuple. T must be instantiated with
|
||||||
|
// a tuple type.
|
||||||
|
template <typename T>
|
||||||
|
void PrintTupleTo(const T& t, ::std::ostream* os) {
|
||||||
|
*os << "(";
|
||||||
|
TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
|
||||||
|
PrintPrefixTo(t, os);
|
||||||
|
*os << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the fields of a tuple tersely to a string vector, one
|
||||||
|
// element for each field. See the comment before
|
||||||
|
// UniversalTersePrint() for how we define "tersely".
|
||||||
|
template <typename Tuple>
|
||||||
|
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
||||||
|
Strings result;
|
||||||
|
TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
|
||||||
|
TersePrintPrefixToStrings(value, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
::std::string PrintToString(const T& value) {
|
||||||
|
::std::stringstream ss;
|
||||||
|
internal::UniversalTersePrint(value, &ss);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This is the main header file a user should include.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
||||||
|
|
||||||
|
// This file implements the following syntax:
|
||||||
|
//
|
||||||
|
// ON_CALL(mock_object.Method(...))
|
||||||
|
// .With(...) ?
|
||||||
|
// .WillByDefault(...);
|
||||||
|
//
|
||||||
|
// where With() is optional and WillByDefault() must appear exactly
|
||||||
|
// once.
|
||||||
|
//
|
||||||
|
// EXPECT_CALL(mock_object.Method(...))
|
||||||
|
// .With(...) ?
|
||||||
|
// .Times(...) ?
|
||||||
|
// .InSequence(...) *
|
||||||
|
// .WillOnce(...) *
|
||||||
|
// .WillRepeatedly(...) ?
|
||||||
|
// .RetiresOnSaturation() ? ;
|
||||||
|
//
|
||||||
|
// where all clauses are optional and WillOnce() can be repeated.
|
||||||
|
|
||||||
|
#include <gmock/gmock-actions.h>
|
||||||
|
#include <gmock/gmock-cardinalities.h>
|
||||||
|
#include <gmock/gmock-generated-actions.h>
|
||||||
|
#include <gmock/gmock-generated-function-mockers.h>
|
||||||
|
#include <gmock/gmock-generated-matchers.h>
|
||||||
|
#include <gmock/gmock-more-actions.h>
|
||||||
|
#include <gmock/gmock-generated-nice-strict.h>
|
||||||
|
#include <gmock/gmock-matchers.h>
|
||||||
|
#include <gmock/gmock-printers.h>
|
||||||
|
#include <gmock/internal/gmock-internal-utils.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Declares Google Mock flags that we want a user to use programmatically.
|
||||||
|
GMOCK_DECLARE_bool_(catch_leaked_mocks);
|
||||||
|
GMOCK_DECLARE_string_(verbose);
|
||||||
|
|
||||||
|
// Initializes Google Mock. This must be called before running the
|
||||||
|
// tests. In particular, it parses the command line for the flags
|
||||||
|
// that Google Mock recognizes. Whenever a Google Mock flag is seen,
|
||||||
|
// it is removed from argv, and *argc is decremented.
|
||||||
|
//
|
||||||
|
// No value is returned. Instead, the Google Mock flag variables are
|
||||||
|
// updated.
|
||||||
|
//
|
||||||
|
// Since Google Test is needed for Google Mock to work, this function
|
||||||
|
// also initializes Google Test and parses its flags, if that hasn't
|
||||||
|
// been done.
|
||||||
|
void InitGoogleMock(int* argc, char** argv);
|
||||||
|
|
||||||
|
// This overloaded version can be used in Windows programs compiled in
|
||||||
|
// UNICODE mode.
|
||||||
|
void InitGoogleMock(int* argc, wchar_t** argv);
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
|
@ -0,0 +1,277 @@
|
||||||
|
// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
|
||||||
|
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file contains template meta-programming utility classes needed
|
||||||
|
// for implementing Google Mock.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
|
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Matcher;
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// An IgnoredValue object can be implicitly constructed from ANY value.
|
||||||
|
// This is used in implementing the IgnoreResult(a) action.
|
||||||
|
class IgnoredValue {
|
||||||
|
public:
|
||||||
|
// This constructor template allows any value to be implicitly
|
||||||
|
// converted to IgnoredValue. The object has no data member and
|
||||||
|
// doesn't try to remember anything about the argument. We
|
||||||
|
// deliberately omit the 'explicit' keyword in order to allow the
|
||||||
|
// conversion to be implicit.
|
||||||
|
template <typename T>
|
||||||
|
IgnoredValue(const T&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// MatcherTuple<T>::type is a tuple type where each field is a Matcher
|
||||||
|
// for the corresponding field in tuple type T.
|
||||||
|
template <typename Tuple>
|
||||||
|
struct MatcherTuple;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<> > {
|
||||||
|
typedef ::std::tr1::tuple< > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>,
|
||||||
|
Matcher<A4> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6>, Matcher<A7> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9, typename A10>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
|
||||||
|
A10> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9>,
|
||||||
|
Matcher<A10> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Template struct Function<F>, where F must be a function type, contains
|
||||||
|
// the following typedefs:
|
||||||
|
//
|
||||||
|
// Result: the function's return type.
|
||||||
|
// ArgumentN: the type of the N-th argument, where N starts with 1.
|
||||||
|
// ArgumentTuple: the tuple type consisting of all parameters of F.
|
||||||
|
// ArgumentMatcherTuple: the tuple type consisting of Matchers for all
|
||||||
|
// parameters of F.
|
||||||
|
// MakeResultVoid: the function type obtained by substituting void
|
||||||
|
// for the return type of F.
|
||||||
|
// MakeResultIgnoredValue:
|
||||||
|
// the function type obtained by substituting Something
|
||||||
|
// for the return type of F.
|
||||||
|
template <typename F>
|
||||||
|
struct Function;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct Function<R()> {
|
||||||
|
typedef R Result;
|
||||||
|
typedef ::std::tr1::tuple<> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid();
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct Function<R(A1)>
|
||||||
|
: Function<R()> {
|
||||||
|
typedef A1 Argument1;
|
||||||
|
typedef ::std::tr1::tuple<A1> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct Function<R(A1, A2)>
|
||||||
|
: Function<R(A1)> {
|
||||||
|
typedef A2 Argument2;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3>
|
||||||
|
struct Function<R(A1, A2, A3)>
|
||||||
|
: Function<R(A1, A2)> {
|
||||||
|
typedef A3 Argument3;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||||
|
struct Function<R(A1, A2, A3, A4)>
|
||||||
|
: Function<R(A1, A2, A3)> {
|
||||||
|
typedef A4 Argument4;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5)>
|
||||||
|
: Function<R(A1, A2, A3, A4)> {
|
||||||
|
typedef A5 Argument5;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5)> {
|
||||||
|
typedef A6 Argument6;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6, A7)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5, A6)> {
|
||||||
|
typedef A7 Argument7;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5, A6, A7)> {
|
||||||
|
typedef A8 Argument8;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8, typename A9>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
|
||||||
|
typedef A9 Argument9;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
|
||||||
|
A9);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8, typename A9,
|
||||||
|
typename A10>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
|
||||||
|
typedef A10 Argument10;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
|
||||||
|
A10> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
|
||||||
|
A9, A10);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
136
3rdparty/gmock/include/gmock/internal/gmock-generated-internal-utils.h.pump
vendored
Normal file
136
3rdparty/gmock/include/gmock/internal/gmock-generated-internal-utils.h.pump
vendored
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-function-mockers.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file contains template meta-programming utility classes needed
|
||||||
|
// for implementing Google Mock.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
|
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Matcher;
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// An IgnoredValue object can be implicitly constructed from ANY value.
|
||||||
|
// This is used in implementing the IgnoreResult(a) action.
|
||||||
|
class IgnoredValue {
|
||||||
|
public:
|
||||||
|
// This constructor template allows any value to be implicitly
|
||||||
|
// converted to IgnoredValue. The object has no data member and
|
||||||
|
// doesn't try to remember anything about the argument. We
|
||||||
|
// deliberately omit the 'explicit' keyword in order to allow the
|
||||||
|
// conversion to be implicit.
|
||||||
|
template <typename T>
|
||||||
|
IgnoredValue(const T&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// MatcherTuple<T>::type is a tuple type where each field is a Matcher
|
||||||
|
// for the corresponding field in tuple type T.
|
||||||
|
template <typename Tuple>
|
||||||
|
struct MatcherTuple;
|
||||||
|
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var typename_As = [[$for j, [[typename A$j]]]]
|
||||||
|
$var As = [[$for j, [[A$j]]]]
|
||||||
|
$var matcher_As = [[$for j, [[Matcher<A$j>]]]]
|
||||||
|
template <$typename_As>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<$As> > {
|
||||||
|
typedef ::std::tr1::tuple<$matcher_As > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
// Template struct Function<F>, where F must be a function type, contains
|
||||||
|
// the following typedefs:
|
||||||
|
//
|
||||||
|
// Result: the function's return type.
|
||||||
|
// ArgumentN: the type of the N-th argument, where N starts with 1.
|
||||||
|
// ArgumentTuple: the tuple type consisting of all parameters of F.
|
||||||
|
// ArgumentMatcherTuple: the tuple type consisting of Matchers for all
|
||||||
|
// parameters of F.
|
||||||
|
// MakeResultVoid: the function type obtained by substituting void
|
||||||
|
// for the return type of F.
|
||||||
|
// MakeResultIgnoredValue:
|
||||||
|
// the function type obtained by substituting Something
|
||||||
|
// for the return type of F.
|
||||||
|
template <typename F>
|
||||||
|
struct Function;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct Function<R()> {
|
||||||
|
typedef R Result;
|
||||||
|
typedef ::std::tr1::tuple<> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid();
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var typename_As = [[$for j [[, typename A$j]]]]
|
||||||
|
$var As = [[$for j, [[A$j]]]]
|
||||||
|
$var matcher_As = [[$for j, [[Matcher<A$j>]]]]
|
||||||
|
$range k 1..i-1
|
||||||
|
$var prev_As = [[$for k, [[A$k]]]]
|
||||||
|
template <typename R$typename_As>
|
||||||
|
struct Function<R($As)>
|
||||||
|
: Function<R($prev_As)> {
|
||||||
|
typedef A$i Argument$i;
|
||||||
|
typedef ::std::tr1::tuple<$As> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid($As);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue($As);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
|
@ -0,0 +1,763 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file defines some utilities useful for implementing Google
|
||||||
|
// Mock. They are subject to change without notice, so please DO NOT
|
||||||
|
// USE THEM IN USER CODE.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <gmock/internal/gmock-generated-internal-utils.h>
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
// Concatenates two pre-processor symbols; works for concatenating
|
||||||
|
// built-in macros like __FILE__ and __LINE__.
|
||||||
|
#define GMOCK_CONCAT_TOKEN_IMPL_(foo, bar) foo##bar
|
||||||
|
#define GMOCK_CONCAT_TOKEN_(foo, bar) GMOCK_CONCAT_TOKEN_IMPL_(foo, bar)
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define GMOCK_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
|
||||||
|
#else
|
||||||
|
#define GMOCK_ATTRIBUTE_UNUSED_
|
||||||
|
#endif // __GNUC__
|
||||||
|
|
||||||
|
class ProtocolMessage;
|
||||||
|
namespace proto2 { class Message; }
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Converts an identifier name to a space-separated list of lower-case
|
||||||
|
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
|
||||||
|
// treated as one word. For example, both "FooBar123" and
|
||||||
|
// "foo_bar_123" are converted to "foo bar 123".
|
||||||
|
string ConvertIdentifierNameToWords(const char* id_name);
|
||||||
|
|
||||||
|
// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
|
||||||
|
// compiler error iff T1 and T2 are different types.
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
struct CompileAssertTypesEqual;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct CompileAssertTypesEqual<T, T> {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Removes the reference from a type if it is a reference type,
|
||||||
|
// otherwise leaves it unchanged. This is the same as
|
||||||
|
// tr1::remove_reference, which is not widely available yet.
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveReference { typedef T type; }; // NOLINT
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveReference<T&> { typedef T type; }; // NOLINT
|
||||||
|
|
||||||
|
// A handy wrapper around RemoveReference that works when the argument
|
||||||
|
// T depends on template parameters.
|
||||||
|
#define GMOCK_REMOVE_REFERENCE_(T) \
|
||||||
|
typename ::testing::internal::RemoveReference<T>::type
|
||||||
|
|
||||||
|
// Removes const from a type if it is a const type, otherwise leaves
|
||||||
|
// it unchanged. This is the same as tr1::remove_const, which is not
|
||||||
|
// widely available yet.
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveConst { typedef T type; }; // NOLINT
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveConst<const T> { typedef T type; }; // NOLINT
|
||||||
|
|
||||||
|
// MSVC 8.0 has a bug which causes the above definition to fail to
|
||||||
|
// remove the const in 'const int[3]'. The following specialization
|
||||||
|
// works around the bug. However, it causes trouble with gcc and thus
|
||||||
|
// needs to be conditionally compiled.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
template <typename T, size_t N>
|
||||||
|
struct RemoveConst<T[N]> {
|
||||||
|
typedef typename RemoveConst<T>::type type[N];
|
||||||
|
};
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
// A handy wrapper around RemoveConst that works when the argument
|
||||||
|
// T depends on template parameters.
|
||||||
|
#define GMOCK_REMOVE_CONST_(T) \
|
||||||
|
typename ::testing::internal::RemoveConst<T>::type
|
||||||
|
|
||||||
|
// Adds reference to a type if it is not a reference type,
|
||||||
|
// otherwise leaves it unchanged. This is the same as
|
||||||
|
// tr1::add_reference, which is not widely available yet.
|
||||||
|
template <typename T>
|
||||||
|
struct AddReference { typedef T& type; }; // NOLINT
|
||||||
|
template <typename T>
|
||||||
|
struct AddReference<T&> { typedef T& type; }; // NOLINT
|
||||||
|
|
||||||
|
// A handy wrapper around AddReference that works when the argument T
|
||||||
|
// depends on template parameters.
|
||||||
|
#define GMOCK_ADD_REFERENCE_(T) \
|
||||||
|
typename ::testing::internal::AddReference<T>::type
|
||||||
|
|
||||||
|
// Adds a reference to const on top of T as necessary. For example,
|
||||||
|
// it transforms
|
||||||
|
//
|
||||||
|
// char ==> const char&
|
||||||
|
// const char ==> const char&
|
||||||
|
// char& ==> const char&
|
||||||
|
// const char& ==> const char&
|
||||||
|
//
|
||||||
|
// The argument T must depend on some template parameters.
|
||||||
|
#define GMOCK_REFERENCE_TO_CONST_(T) \
|
||||||
|
GMOCK_ADD_REFERENCE_(const GMOCK_REMOVE_REFERENCE_(T))
|
||||||
|
|
||||||
|
// PointeeOf<Pointer>::type is the type of a value pointed to by a
|
||||||
|
// Pointer, which can be either a smart pointer or a raw pointer. The
|
||||||
|
// following default implementation is for the case where Pointer is a
|
||||||
|
// smart pointer.
|
||||||
|
template <typename Pointer>
|
||||||
|
struct PointeeOf {
|
||||||
|
// Smart pointer classes define type element_type as the type of
|
||||||
|
// their pointees.
|
||||||
|
typedef typename Pointer::element_type type;
|
||||||
|
};
|
||||||
|
// This specialization is for the raw pointer case.
|
||||||
|
template <typename T>
|
||||||
|
struct PointeeOf<T*> { typedef T type; }; // NOLINT
|
||||||
|
|
||||||
|
// GetRawPointer(p) returns the raw pointer underlying p when p is a
|
||||||
|
// smart pointer, or returns p itself when p is already a raw pointer.
|
||||||
|
// The following default implementation is for the smart pointer case.
|
||||||
|
template <typename Pointer>
|
||||||
|
inline typename Pointer::element_type* GetRawPointer(const Pointer& p) {
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
// This overloaded version is for the raw pointer case.
|
||||||
|
template <typename Element>
|
||||||
|
inline Element* GetRawPointer(Element* p) { return p; }
|
||||||
|
|
||||||
|
// This comparator allows linked_ptr to be stored in sets.
|
||||||
|
template <typename T>
|
||||||
|
struct LinkedPtrLessThan {
|
||||||
|
bool operator()(const ::testing::internal::linked_ptr<T>& lhs,
|
||||||
|
const ::testing::internal::linked_ptr<T>& rhs) const {
|
||||||
|
return lhs.get() < rhs.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ImplicitlyConvertible<From, To>::value is a compile-time bool
|
||||||
|
// constant that's true iff type From can be implicitly converted to
|
||||||
|
// type To.
|
||||||
|
template <typename From, typename To>
|
||||||
|
class ImplicitlyConvertible {
|
||||||
|
private:
|
||||||
|
// We need the following helper functions only for their types.
|
||||||
|
// They have no implementations.
|
||||||
|
|
||||||
|
// MakeFrom() is an expression whose type is From. We cannot simply
|
||||||
|
// use From(), as the type From may not have a public default
|
||||||
|
// constructor.
|
||||||
|
static From MakeFrom();
|
||||||
|
|
||||||
|
// These two functions are overloaded. Given an expression
|
||||||
|
// Helper(x), the compiler will pick the first version if x can be
|
||||||
|
// implicitly converted to type To; otherwise it will pick the
|
||||||
|
// second version.
|
||||||
|
//
|
||||||
|
// The first version returns a value of size 1, and the second
|
||||||
|
// version returns a value of size 2. Therefore, by checking the
|
||||||
|
// size of Helper(x), which can be done at compile time, we can tell
|
||||||
|
// which version of Helper() is used, and hence whether x can be
|
||||||
|
// implicitly converted to type To.
|
||||||
|
static char Helper(To);
|
||||||
|
static char (&Helper(...))[2]; // NOLINT
|
||||||
|
|
||||||
|
// We have to put the 'public' section after the 'private' section,
|
||||||
|
// or MSVC refuses to compile the code.
|
||||||
|
public:
|
||||||
|
// MSVC warns about implicitly converting from double to int for
|
||||||
|
// possible loss of data, so we need to temporarily disable the
|
||||||
|
// warning.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push) // Saves the current warning state.
|
||||||
|
#pragma warning(disable:4244) // Temporarily disables warning 4244.
|
||||||
|
static const bool value =
|
||||||
|
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
|
||||||
|
#pragma warning(pop) // Restores the warning state.
|
||||||
|
#else
|
||||||
|
static const bool value =
|
||||||
|
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
|
||||||
|
#endif // _MSV_VER
|
||||||
|
};
|
||||||
|
template <typename From, typename To>
|
||||||
|
const bool ImplicitlyConvertible<From, To>::value;
|
||||||
|
|
||||||
|
// Symbian compilation can be done with wchar_t being either a native
|
||||||
|
// type or a typedef. Using Google Mock with OpenC without wchar_t
|
||||||
|
// should require the definition of _STLP_NO_WCHAR_T.
|
||||||
|
//
|
||||||
|
// MSVC treats wchar_t as a native type usually, but treats it as the
|
||||||
|
// same as unsigned short when the compiler option /Zc:wchar_t- is
|
||||||
|
// specified. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
|
||||||
|
// is a native type.
|
||||||
|
#if (GTEST_OS_SYMBIAN && defined(_STLP_NO_WCHAR_T)) || \
|
||||||
|
(defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED))
|
||||||
|
// wchar_t is a typedef.
|
||||||
|
#else
|
||||||
|
#define GMOCK_WCHAR_T_IS_NATIVE_ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// signed wchar_t and unsigned wchar_t are NOT in the C++ standard.
|
||||||
|
// Using them is a bad practice and not portable. So DON'T use them.
|
||||||
|
//
|
||||||
|
// Still, Google Mock is designed to work even if the user uses signed
|
||||||
|
// wchar_t or unsigned wchar_t (obviously, assuming the compiler
|
||||||
|
// supports them).
|
||||||
|
//
|
||||||
|
// To gcc,
|
||||||
|
// wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define GMOCK_HAS_SIGNED_WCHAR_T_ 1 // signed/unsigned wchar_t are valid types.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// In what follows, we use the term "kind" to indicate whether a type
|
||||||
|
// is bool, an integer type (excluding bool), a floating-point type,
|
||||||
|
// or none of them. This categorization is useful for determining
|
||||||
|
// when a matcher argument type can be safely converted to another
|
||||||
|
// type in the implementation of SafeMatcherCast.
|
||||||
|
enum TypeKind {
|
||||||
|
kBool, kInteger, kFloatingPoint, kOther
|
||||||
|
};
|
||||||
|
|
||||||
|
// KindOf<T>::value is the kind of type T.
|
||||||
|
template <typename T> struct KindOf {
|
||||||
|
enum { value = kOther }; // The default kind.
|
||||||
|
};
|
||||||
|
|
||||||
|
// This macro declares that the kind of 'type' is 'kind'.
|
||||||
|
#define GMOCK_DECLARE_KIND_(type, kind) \
|
||||||
|
template <> struct KindOf<type> { enum { value = kind }; }
|
||||||
|
|
||||||
|
GMOCK_DECLARE_KIND_(bool, kBool);
|
||||||
|
|
||||||
|
// All standard integer types.
|
||||||
|
GMOCK_DECLARE_KIND_(char, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(signed char, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(unsigned char, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(short, kInteger); // NOLINT
|
||||||
|
GMOCK_DECLARE_KIND_(unsigned short, kInteger); // NOLINT
|
||||||
|
GMOCK_DECLARE_KIND_(int, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(unsigned int, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT
|
||||||
|
GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT
|
||||||
|
|
||||||
|
#if GMOCK_WCHAR_T_IS_NATIVE_
|
||||||
|
GMOCK_DECLARE_KIND_(wchar_t, kInteger);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Non-standard integer types.
|
||||||
|
GMOCK_DECLARE_KIND_(Int64, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(UInt64, kInteger);
|
||||||
|
|
||||||
|
// All standard floating-point types.
|
||||||
|
GMOCK_DECLARE_KIND_(float, kFloatingPoint);
|
||||||
|
GMOCK_DECLARE_KIND_(double, kFloatingPoint);
|
||||||
|
GMOCK_DECLARE_KIND_(long double, kFloatingPoint);
|
||||||
|
|
||||||
|
#undef GMOCK_DECLARE_KIND_
|
||||||
|
|
||||||
|
// Evaluates to the kind of 'type'.
|
||||||
|
#define GMOCK_KIND_OF_(type) \
|
||||||
|
static_cast< ::testing::internal::TypeKind>( \
|
||||||
|
::testing::internal::KindOf<type>::value)
|
||||||
|
|
||||||
|
// Evaluates to true iff integer type T is signed.
|
||||||
|
#define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0)
|
||||||
|
|
||||||
|
// LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value
|
||||||
|
// is true iff arithmetic type From can be losslessly converted to
|
||||||
|
// arithmetic type To.
|
||||||
|
//
|
||||||
|
// It's the user's responsibility to ensure that both From and To are
|
||||||
|
// raw (i.e. has no CV modifier, is not a pointer, and is not a
|
||||||
|
// reference) built-in arithmetic types, kFromKind is the kind of
|
||||||
|
// From, and kToKind is the kind of To; the value is
|
||||||
|
// implementation-defined when the above pre-condition is violated.
|
||||||
|
template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl : public false_type {};
|
||||||
|
|
||||||
|
// Converting bool to bool is lossless.
|
||||||
|
template <>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool>
|
||||||
|
: public true_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting bool to any integer type is lossless.
|
||||||
|
template <typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To>
|
||||||
|
: public true_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting bool to any floating-point type is lossless.
|
||||||
|
template <typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To>
|
||||||
|
: public true_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting an integer to bool is lossy.
|
||||||
|
template <typename From>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool>
|
||||||
|
: public false_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting an integer to another non-bool integer is lossless iff
|
||||||
|
// the target type's range encloses the source type's range.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To>
|
||||||
|
: public bool_constant<
|
||||||
|
// When converting from a smaller size to a larger size, we are
|
||||||
|
// fine as long as we are not converting from signed to unsigned.
|
||||||
|
((sizeof(From) < sizeof(To)) &&
|
||||||
|
(!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) ||
|
||||||
|
// When converting between the same size, the signedness must match.
|
||||||
|
((sizeof(From) == sizeof(To)) &&
|
||||||
|
(GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {}; // NOLINT
|
||||||
|
|
||||||
|
#undef GMOCK_IS_SIGNED_
|
||||||
|
|
||||||
|
// Converting an integer to a floating-point type may be lossy, since
|
||||||
|
// the format of a floating-point number is implementation-defined.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To>
|
||||||
|
: public false_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting a floating-point to bool is lossy.
|
||||||
|
template <typename From>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool>
|
||||||
|
: public false_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting a floating-point to an integer is lossy.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To>
|
||||||
|
: public false_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting a floating-point to another floating-point is lossless
|
||||||
|
// iff the target type is at least as big as the source type.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<
|
||||||
|
kFloatingPoint, From, kFloatingPoint, To>
|
||||||
|
: public bool_constant<sizeof(From) <= sizeof(To)> {}; // NOLINT
|
||||||
|
|
||||||
|
// LosslessArithmeticConvertible<From, To>::value is true iff arithmetic
|
||||||
|
// type From can be losslessly converted to arithmetic type To.
|
||||||
|
//
|
||||||
|
// It's the user's responsibility to ensure that both From and To are
|
||||||
|
// raw (i.e. has no CV modifier, is not a pointer, and is not a
|
||||||
|
// reference) built-in arithmetic types; the value is
|
||||||
|
// implementation-defined when the above pre-condition is violated.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertible
|
||||||
|
: public LosslessArithmeticConvertibleImpl<
|
||||||
|
GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {}; // NOLINT
|
||||||
|
|
||||||
|
// IsAProtocolMessage<T>::value is a compile-time bool constant that's
|
||||||
|
// true iff T is type ProtocolMessage, proto2::Message, or a subclass
|
||||||
|
// of those.
|
||||||
|
template <typename T>
|
||||||
|
struct IsAProtocolMessage
|
||||||
|
: public bool_constant<
|
||||||
|
ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
|
||||||
|
ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
|
||||||
|
};
|
||||||
|
|
||||||
|
// When the compiler sees expression IsContainerTest<C>(0), the first
|
||||||
|
// overload of IsContainerTest will be picked if C is an STL-style
|
||||||
|
// container class (since C::const_iterator* is a valid type and 0 can
|
||||||
|
// be converted to it), while the second overload will be picked
|
||||||
|
// otherwise (since C::const_iterator will be an invalid type in this
|
||||||
|
// case). Therefore, we can determine whether C is a container class
|
||||||
|
// by checking the type of IsContainerTest<C>(0). The value of the
|
||||||
|
// expression is insignificant.
|
||||||
|
typedef int IsContainer;
|
||||||
|
template <class C>
|
||||||
|
IsContainer IsContainerTest(typename C::const_iterator*) { return 0; }
|
||||||
|
|
||||||
|
typedef char IsNotContainer;
|
||||||
|
template <class C>
|
||||||
|
IsNotContainer IsContainerTest(...) { return '\0'; }
|
||||||
|
|
||||||
|
// This interface knows how to report a Google Mock failure (either
|
||||||
|
// non-fatal or fatal).
|
||||||
|
class FailureReporterInterface {
|
||||||
|
public:
|
||||||
|
// The type of a failure (either non-fatal or fatal).
|
||||||
|
enum FailureType {
|
||||||
|
NONFATAL, FATAL
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~FailureReporterInterface() {}
|
||||||
|
|
||||||
|
// Reports a failure that occurred at the given source file location.
|
||||||
|
virtual void ReportFailure(FailureType type, const char* file, int line,
|
||||||
|
const string& message) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the failure reporter used by Google Mock.
|
||||||
|
FailureReporterInterface* GetFailureReporter();
|
||||||
|
|
||||||
|
// Asserts that condition is true; aborts the process with the given
|
||||||
|
// message if condition is false. We cannot use LOG(FATAL) or CHECK()
|
||||||
|
// as Google Mock might be used to mock the log sink itself. We
|
||||||
|
// inline this function to prevent it from showing up in the stack
|
||||||
|
// trace.
|
||||||
|
inline void Assert(bool condition, const char* file, int line,
|
||||||
|
const string& msg) {
|
||||||
|
if (!condition) {
|
||||||
|
GetFailureReporter()->ReportFailure(FailureReporterInterface::FATAL,
|
||||||
|
file, line, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void Assert(bool condition, const char* file, int line) {
|
||||||
|
Assert(condition, file, line, "Assertion failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies that condition is true; generates a non-fatal failure if
|
||||||
|
// condition is false.
|
||||||
|
inline void Expect(bool condition, const char* file, int line,
|
||||||
|
const string& msg) {
|
||||||
|
if (!condition) {
|
||||||
|
GetFailureReporter()->ReportFailure(FailureReporterInterface::NONFATAL,
|
||||||
|
file, line, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void Expect(bool condition, const char* file, int line) {
|
||||||
|
Expect(condition, file, line, "Expectation failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Severity level of a log.
|
||||||
|
enum LogSeverity {
|
||||||
|
INFO = 0,
|
||||||
|
WARNING = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Valid values for the --gmock_verbose flag.
|
||||||
|
|
||||||
|
// All logs (informational and warnings) are printed.
|
||||||
|
const char kInfoVerbosity[] = "info";
|
||||||
|
// Only warnings are printed.
|
||||||
|
const char kWarningVerbosity[] = "warning";
|
||||||
|
// No logs are printed.
|
||||||
|
const char kErrorVerbosity[] = "error";
|
||||||
|
|
||||||
|
// Returns true iff a log with the given severity is visible according
|
||||||
|
// to the --gmock_verbose flag.
|
||||||
|
bool LogIsVisible(LogSeverity severity);
|
||||||
|
|
||||||
|
// Prints the given message to stdout iff 'severity' >= the level
|
||||||
|
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
|
||||||
|
// 0, also prints the stack trace excluding the top
|
||||||
|
// stack_frames_to_skip frames. In opt mode, any positive
|
||||||
|
// stack_frames_to_skip is treated as 0, since we don't know which
|
||||||
|
// function calls will be inlined by the compiler and need to be
|
||||||
|
// conservative.
|
||||||
|
void Log(LogSeverity severity, const string& message, int stack_frames_to_skip);
|
||||||
|
|
||||||
|
// TODO(wan@google.com): group all type utilities together.
|
||||||
|
|
||||||
|
// Type traits.
|
||||||
|
|
||||||
|
// is_reference<T>::value is non-zero iff T is a reference type.
|
||||||
|
template <typename T> struct is_reference : public false_type {};
|
||||||
|
template <typename T> struct is_reference<T&> : public true_type {};
|
||||||
|
|
||||||
|
// type_equals<T1, T2>::value is non-zero iff T1 and T2 are the same type.
|
||||||
|
template <typename T1, typename T2> struct type_equals : public false_type {};
|
||||||
|
template <typename T> struct type_equals<T, T> : public true_type {};
|
||||||
|
|
||||||
|
// remove_reference<T>::type removes the reference from type T, if any.
|
||||||
|
template <typename T> struct remove_reference { typedef T type; }; // NOLINT
|
||||||
|
template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT
|
||||||
|
|
||||||
|
// Invalid<T>() returns an invalid value of type T. This is useful
|
||||||
|
// when a value of type T is needed for compilation, but the statement
|
||||||
|
// will not really be executed (or we don't care if the statement
|
||||||
|
// crashes).
|
||||||
|
template <typename T>
|
||||||
|
inline T Invalid() {
|
||||||
|
return *static_cast<typename remove_reference<T>::type*>(NULL);
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
inline void Invalid<void>() {}
|
||||||
|
|
||||||
|
// Utilities for native arrays.
|
||||||
|
|
||||||
|
// ArrayEq() compares two k-dimensional native arrays using the
|
||||||
|
// elements' operator==, where k can be any integer >= 0. When k is
|
||||||
|
// 0, ArrayEq() degenerates into comparing a single pair of values.
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
bool ArrayEq(const T* lhs, size_t size, const U* rhs);
|
||||||
|
|
||||||
|
// This generic version is used when k is 0.
|
||||||
|
template <typename T, typename U>
|
||||||
|
inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
|
||||||
|
|
||||||
|
// This overload is used when k >= 1.
|
||||||
|
template <typename T, typename U, size_t N>
|
||||||
|
inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
|
||||||
|
return internal::ArrayEq(lhs, N, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This helper reduces code bloat. If we instead put its logic inside
|
||||||
|
// the previous ArrayEq() function, arrays with different sizes would
|
||||||
|
// lead to different copies of the template code.
|
||||||
|
template <typename T, typename U>
|
||||||
|
bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
|
||||||
|
for (size_t i = 0; i != size; i++) {
|
||||||
|
if (!internal::ArrayEq(lhs[i], rhs[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds the first element in the iterator range [begin, end) that
|
||||||
|
// equals elem. Element may be a native array type itself.
|
||||||
|
template <typename Iter, typename Element>
|
||||||
|
Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
|
||||||
|
for (Iter it = begin; it != end; ++it) {
|
||||||
|
if (internal::ArrayEq(*it, elem))
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyArray() copies a k-dimensional native array using the elements'
|
||||||
|
// operator=, where k can be any integer >= 0. When k is 0,
|
||||||
|
// CopyArray() degenerates into copying a single value.
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
void CopyArray(const T* from, size_t size, U* to);
|
||||||
|
|
||||||
|
// This generic version is used when k is 0.
|
||||||
|
template <typename T, typename U>
|
||||||
|
inline void CopyArray(const T& from, U* to) { *to = from; }
|
||||||
|
|
||||||
|
// This overload is used when k >= 1.
|
||||||
|
template <typename T, typename U, size_t N>
|
||||||
|
inline void CopyArray(const T(&from)[N], U(*to)[N]) {
|
||||||
|
internal::CopyArray(from, N, *to);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This helper reduces code bloat. If we instead put its logic inside
|
||||||
|
// the previous CopyArray() function, arrays with different sizes
|
||||||
|
// would lead to different copies of the template code.
|
||||||
|
template <typename T, typename U>
|
||||||
|
void CopyArray(const T* from, size_t size, U* to) {
|
||||||
|
for (size_t i = 0; i != size; i++) {
|
||||||
|
internal::CopyArray(from[i], to + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The relation between an NativeArray object (see below) and the
|
||||||
|
// native array it represents.
|
||||||
|
enum RelationToSource {
|
||||||
|
kReference, // The NativeArray references the native array.
|
||||||
|
kCopy // The NativeArray makes a copy of the native array and
|
||||||
|
// owns the copy.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Adapts a native array to a read-only STL-style container. Instead
|
||||||
|
// of the complete STL container concept, this adaptor only implements
|
||||||
|
// members useful for Google Mock's container matchers. New members
|
||||||
|
// should be added as needed. To simplify the implementation, we only
|
||||||
|
// support Element being a raw type (i.e. having no top-level const or
|
||||||
|
// reference modifier). It's the client's responsibility to satisfy
|
||||||
|
// this requirement. Element can be an array type itself (hence
|
||||||
|
// multi-dimensional arrays are supported).
|
||||||
|
template <typename Element>
|
||||||
|
class NativeArray {
|
||||||
|
public:
|
||||||
|
// STL-style container typedefs.
|
||||||
|
typedef Element value_type;
|
||||||
|
typedef const Element* const_iterator;
|
||||||
|
|
||||||
|
// Constructs from a native array.
|
||||||
|
NativeArray(const Element* array, size_t count, RelationToSource relation) {
|
||||||
|
Init(array, count, relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy constructor.
|
||||||
|
NativeArray(const NativeArray& rhs) {
|
||||||
|
Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~NativeArray() {
|
||||||
|
// Ensures that the user doesn't instantiate NativeArray with a
|
||||||
|
// const or reference type.
|
||||||
|
testing::StaticAssertTypeEq<Element,
|
||||||
|
GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Element))>();
|
||||||
|
if (relation_to_source_ == kCopy)
|
||||||
|
delete[] array_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STL-style container methods.
|
||||||
|
size_t size() const { return size_; }
|
||||||
|
const_iterator begin() const { return array_; }
|
||||||
|
const_iterator end() const { return array_ + size_; }
|
||||||
|
bool operator==(const NativeArray& rhs) const {
|
||||||
|
return size() == rhs.size() &&
|
||||||
|
ArrayEq(begin(), size(), rhs.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Not implemented as we don't want to support assignment.
|
||||||
|
void operator=(const NativeArray& rhs);
|
||||||
|
|
||||||
|
// Initializes this object; makes a copy of the input array if
|
||||||
|
// 'relation' is kCopy.
|
||||||
|
void Init(const Element* array, size_t a_size, RelationToSource relation) {
|
||||||
|
if (relation == kReference) {
|
||||||
|
array_ = array;
|
||||||
|
} else {
|
||||||
|
Element* const copy = new Element[a_size];
|
||||||
|
CopyArray(array, a_size, copy);
|
||||||
|
array_ = copy;
|
||||||
|
}
|
||||||
|
size_ = a_size;
|
||||||
|
relation_to_source_ = relation;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Element* array_;
|
||||||
|
size_t size_;
|
||||||
|
RelationToSource relation_to_source_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Given a raw type (i.e. having no top-level reference or const
|
||||||
|
// modifier) RawContainer that's either an STL-style container or a
|
||||||
|
// native array, class StlContainerView<RawContainer> has the
|
||||||
|
// following members:
|
||||||
|
//
|
||||||
|
// - type is a type that provides an STL-style container view to
|
||||||
|
// (i.e. implements the STL container concept for) RawContainer;
|
||||||
|
// - const_reference is a type that provides a reference to a const
|
||||||
|
// RawContainer;
|
||||||
|
// - ConstReference(raw_container) returns a const reference to an STL-style
|
||||||
|
// container view to raw_container, which is a RawContainer.
|
||||||
|
// - Copy(raw_container) returns an STL-style container view of a
|
||||||
|
// copy of raw_container, which is a RawContainer.
|
||||||
|
//
|
||||||
|
// This generic version is used when RawContainer itself is already an
|
||||||
|
// STL-style container.
|
||||||
|
template <class RawContainer>
|
||||||
|
class StlContainerView {
|
||||||
|
public:
|
||||||
|
typedef RawContainer type;
|
||||||
|
typedef const type& const_reference;
|
||||||
|
|
||||||
|
static const_reference ConstReference(const RawContainer& container) {
|
||||||
|
// Ensures that RawContainer is not a const type.
|
||||||
|
testing::StaticAssertTypeEq<RawContainer,
|
||||||
|
GMOCK_REMOVE_CONST_(RawContainer)>();
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
static type Copy(const RawContainer& container) { return container; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// This specialization is used when RawContainer is a native array type.
|
||||||
|
template <typename Element, size_t N>
|
||||||
|
class StlContainerView<Element[N]> {
|
||||||
|
public:
|
||||||
|
typedef GMOCK_REMOVE_CONST_(Element) RawElement;
|
||||||
|
typedef internal::NativeArray<RawElement> type;
|
||||||
|
// NativeArray<T> can represent a native array either by value or by
|
||||||
|
// reference (selected by a constructor argument), so 'const type'
|
||||||
|
// can be used to reference a const native array. We cannot
|
||||||
|
// 'typedef const type& const_reference' here, as that would mean
|
||||||
|
// ConstReference() has to return a reference to a local variable.
|
||||||
|
typedef const type const_reference;
|
||||||
|
|
||||||
|
static const_reference ConstReference(const Element (&array)[N]) {
|
||||||
|
// Ensures that Element is not a const type.
|
||||||
|
testing::StaticAssertTypeEq<Element, RawElement>();
|
||||||
|
#if GTEST_OS_SYMBIAN
|
||||||
|
// The Nokia Symbian compiler confuses itself in template instantiation
|
||||||
|
// for this call without the cast to Element*:
|
||||||
|
// function call '[testing::internal::NativeArray<char *>].NativeArray(
|
||||||
|
// {lval} const char *[4], long, testing::internal::RelationToSource)'
|
||||||
|
// does not match
|
||||||
|
// 'testing::internal::NativeArray<char *>::NativeArray(
|
||||||
|
// char *const *, unsigned int, testing::internal::RelationToSource)'
|
||||||
|
// (instantiating: 'testing::internal::ContainsMatcherImpl
|
||||||
|
// <const char * (&)[4]>::Matches(const char * (&)[4]) const')
|
||||||
|
// (instantiating: 'testing::internal::StlContainerView<char *[4]>::
|
||||||
|
// ConstReference(const char * (&)[4])')
|
||||||
|
// (and though the N parameter type is mismatched in the above explicit
|
||||||
|
// conversion of it doesn't help - only the conversion of the array).
|
||||||
|
return type(const_cast<Element*>(&array[0]), N, kReference);
|
||||||
|
#else
|
||||||
|
return type(array, N, kReference);
|
||||||
|
#endif // GTEST_OS_SYMBIAN
|
||||||
|
}
|
||||||
|
static type Copy(const Element (&array)[N]) {
|
||||||
|
#if GTEST_OS_SYMBIAN
|
||||||
|
return type(const_cast<Element*>(&array[0]), N, kCopy);
|
||||||
|
#else
|
||||||
|
return type(array, N, kCopy);
|
||||||
|
#endif // GTEST_OS_SYMBIAN
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This specialization is used when RawContainer is a native array
|
||||||
|
// represented as a (pointer, size) tuple.
|
||||||
|
template <typename ElementPointer, typename Size>
|
||||||
|
class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
|
||||||
|
public:
|
||||||
|
typedef GMOCK_REMOVE_CONST_(
|
||||||
|
typename internal::PointeeOf<ElementPointer>::type) RawElement;
|
||||||
|
typedef internal::NativeArray<RawElement> type;
|
||||||
|
typedef const type const_reference;
|
||||||
|
|
||||||
|
static const_reference ConstReference(
|
||||||
|
const ::std::tr1::tuple<ElementPointer, Size>& array) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return type(get<0>(array), get<1>(array), kReference);
|
||||||
|
}
|
||||||
|
static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return type(get<0>(array), get<1>(array), kCopy);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following specialization prevents the user from instantiating
|
||||||
|
// StlContainer with a reference type.
|
||||||
|
template <typename T> class StlContainerView<T&>;
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
|
|
@ -0,0 +1,215 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: vadimb@google.com (Vadim Berman)
|
||||||
|
//
|
||||||
|
// Low-level types and utilities for porting Google Mock to various
|
||||||
|
// platforms. They are subject to change without notice. DO NOT USE
|
||||||
|
// THEM IN USER CODE.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// Most of the types needed for porting Google Mock are also required
|
||||||
|
// for Google Test and are defined in gtest-port.h.
|
||||||
|
#include <gtest/internal/gtest-linked_ptr.h>
|
||||||
|
#include <gtest/internal/gtest-port.h>
|
||||||
|
|
||||||
|
// To avoid conditional compilation everywhere, we make it
|
||||||
|
// gmock-port.h's responsibility to #include the header implementing
|
||||||
|
// tr1/tuple. gmock-port.h does this via gtest-port.h, which is
|
||||||
|
// guaranteed to pull in the tuple header.
|
||||||
|
|
||||||
|
#if GTEST_OS_LINUX
|
||||||
|
|
||||||
|
#endif // GTEST_OS_LINUX
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// For MS Visual C++, check the compiler version. At least VS 2003 is
|
||||||
|
// required to compile Google Mock.
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1310
|
||||||
|
#error "At least Visual C++ 2003 (7.1) is required to compile Google Mock."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use implicit_cast as a safe version of static_cast for upcasting in
|
||||||
|
// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
|
||||||
|
// const Foo*). When you use implicit_cast, the compiler checks that
|
||||||
|
// the cast is safe. Such explicit implicit_casts are necessary in
|
||||||
|
// surprisingly many situations where C++ demands an exact type match
|
||||||
|
// instead of an argument type convertable to a target type.
|
||||||
|
//
|
||||||
|
// The syntax for using implicit_cast is the same as for static_cast:
|
||||||
|
//
|
||||||
|
// implicit_cast<ToType>(expr)
|
||||||
|
//
|
||||||
|
// implicit_cast would have been part of the C++ standard library,
|
||||||
|
// but the proposal was submitted too late. It will probably make
|
||||||
|
// its way into the language in the future.
|
||||||
|
template<typename To>
|
||||||
|
inline To implicit_cast(To x) { return x; }
|
||||||
|
|
||||||
|
// When you upcast (that is, cast a pointer from type Foo to type
|
||||||
|
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
|
||||||
|
// always succeed. When you downcast (that is, cast a pointer from
|
||||||
|
// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
|
||||||
|
// how do you know the pointer is really of type SubclassOfFoo? It
|
||||||
|
// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
|
||||||
|
// when you downcast, you should use this macro. In debug mode, we
|
||||||
|
// use dynamic_cast<> to double-check the downcast is legal (we die
|
||||||
|
// if it's not). In normal mode, we do the efficient static_cast<>
|
||||||
|
// instead. Thus, it's important to test in debug mode to make sure
|
||||||
|
// the cast is legal!
|
||||||
|
// This is the only place in the code we should use dynamic_cast<>.
|
||||||
|
// In particular, you SHOULDN'T be using dynamic_cast<> in order to
|
||||||
|
// do RTTI (eg code like this:
|
||||||
|
// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
|
||||||
|
// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
|
||||||
|
// You should design the code some other way not to need this.
|
||||||
|
template<typename To, typename From> // use like this: down_cast<T*>(foo);
|
||||||
|
inline To down_cast(From* f) { // so we only accept pointers
|
||||||
|
// Ensures that To is a sub-type of From *. This test is here only
|
||||||
|
// for compile-time type checking, and has no overhead in an
|
||||||
|
// optimized build at run-time, as it will be optimized away
|
||||||
|
// completely.
|
||||||
|
if (false) {
|
||||||
|
const To to = NULL;
|
||||||
|
::testing::internal::implicit_cast<From*>(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GTEST_HAS_RTTI
|
||||||
|
assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
|
||||||
|
#endif
|
||||||
|
return static_cast<To>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The GMOCK_COMPILE_ASSERT_ macro can be used to verify that a compile time
|
||||||
|
// expression is true. For example, you could use it to verify the
|
||||||
|
// size of a static array:
|
||||||
|
//
|
||||||
|
// GMOCK_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
|
||||||
|
// content_type_names_incorrect_size);
|
||||||
|
//
|
||||||
|
// or to make sure a struct is smaller than a certain size:
|
||||||
|
//
|
||||||
|
// GMOCK_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
|
||||||
|
//
|
||||||
|
// The second argument to the macro is the name of the variable. If
|
||||||
|
// the expression is false, most compilers will issue a warning/error
|
||||||
|
// containing the name of the variable.
|
||||||
|
|
||||||
|
template <bool>
|
||||||
|
struct CompileAssert {
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GMOCK_COMPILE_ASSERT_(expr, msg) \
|
||||||
|
typedef ::testing::internal::CompileAssert<(bool(expr))> \
|
||||||
|
msg[bool(expr) ? 1 : -1]
|
||||||
|
|
||||||
|
// Implementation details of GMOCK_COMPILE_ASSERT_:
|
||||||
|
//
|
||||||
|
// - GMOCK_COMPILE_ASSERT_ works by defining an array type that has -1
|
||||||
|
// elements (and thus is invalid) when the expression is false.
|
||||||
|
//
|
||||||
|
// - The simpler definition
|
||||||
|
//
|
||||||
|
// #define GMOCK_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
|
||||||
|
//
|
||||||
|
// does not work, as gcc supports variable-length arrays whose sizes
|
||||||
|
// are determined at run-time (this is gcc's extension and not part
|
||||||
|
// of the C++ standard). As a result, gcc fails to reject the
|
||||||
|
// following code with the simple definition:
|
||||||
|
//
|
||||||
|
// int foo;
|
||||||
|
// GMOCK_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
|
||||||
|
// // not a compile-time constant.
|
||||||
|
//
|
||||||
|
// - By using the type CompileAssert<(bool(expr))>, we ensures that
|
||||||
|
// expr is a compile-time constant. (Template arguments must be
|
||||||
|
// determined at compile-time.)
|
||||||
|
//
|
||||||
|
// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
|
||||||
|
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
|
||||||
|
//
|
||||||
|
// CompileAssert<bool(expr)>
|
||||||
|
//
|
||||||
|
// instead, these compilers will refuse to compile
|
||||||
|
//
|
||||||
|
// GMOCK_COMPILE_ASSERT_(5 > 0, some_message);
|
||||||
|
//
|
||||||
|
// (They seem to think the ">" in "5 > 0" marks the end of the
|
||||||
|
// template argument list.)
|
||||||
|
//
|
||||||
|
// - The array size is (bool(expr) ? 1 : -1), instead of simply
|
||||||
|
//
|
||||||
|
// ((expr) ? 1 : -1).
|
||||||
|
//
|
||||||
|
// This is to avoid running into a bug in MS VC 7.1, which
|
||||||
|
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
|
||||||
|
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
typedef ::string string;
|
||||||
|
#else
|
||||||
|
typedef ::std::string string;
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
|
#if GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
typedef ::wstring wstring;
|
||||||
|
#elif GTEST_HAS_STD_WSTRING
|
||||||
|
typedef ::std::wstring wstring;
|
||||||
|
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
// Macro for referencing flags. This is public as we want the user to
|
||||||
|
// use this syntax to reference Google Mock flags.
|
||||||
|
#define GMOCK_FLAG(name) FLAGS_gmock_##name
|
||||||
|
|
||||||
|
// Macros for declaring flags.
|
||||||
|
#define GMOCK_DECLARE_bool_(name) extern bool GMOCK_FLAG(name)
|
||||||
|
#define GMOCK_DECLARE_int32_(name) \
|
||||||
|
extern ::testing::internal::Int32 GMOCK_FLAG(name)
|
||||||
|
#define GMOCK_DECLARE_string_(name) \
|
||||||
|
extern ::testing::internal::String GMOCK_FLAG(name)
|
||||||
|
|
||||||
|
// Macros for defining flags.
|
||||||
|
#define GMOCK_DEFINE_bool_(name, default_val, doc) \
|
||||||
|
bool GMOCK_FLAG(name) = (default_val)
|
||||||
|
#define GMOCK_DEFINE_int32_(name, default_val, doc) \
|
||||||
|
::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
|
||||||
|
#define GMOCK_DEFINE_string_(name, default_val, doc) \
|
||||||
|
::testing::internal::String GMOCK_FLAG(name) = (default_val)
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
//
|
||||||
|
// Google C++ Mocking Framework (Google Mock)
|
||||||
|
//
|
||||||
|
// This file #includes all Google Mock implementation .cc files. The
|
||||||
|
// purpose is to allow a user to build Google Mock by compiling this
|
||||||
|
// file alone.
|
||||||
|
|
||||||
|
// This line ensures that gmock.h can be compiled on its own, even
|
||||||
|
// when it's fused.
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
// The following lines pull in the real gmock *.cc files.
|
||||||
|
#include "src/gmock-cardinalities.cc"
|
||||||
|
#include "src/gmock-internal-utils.cc"
|
||||||
|
#include "src/gmock-matchers.cc"
|
||||||
|
#include "src/gmock-printers.cc"
|
||||||
|
#include "src/gmock-spec-builders.cc"
|
||||||
|
#include "src/gmock.cc"
|
|
@ -0,0 +1,155 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements cardinalities.
|
||||||
|
|
||||||
|
#include <gmock/gmock-cardinalities.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <gmock/internal/gmock-internal-utils.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Implements the Between(m, n) cardinality.
|
||||||
|
class BetweenCardinalityImpl : public CardinalityInterface {
|
||||||
|
public:
|
||||||
|
BetweenCardinalityImpl(int min, int max)
|
||||||
|
: min_(min >= 0 ? min : 0),
|
||||||
|
max_(max >= min_ ? max : min_) {
|
||||||
|
std::stringstream ss;
|
||||||
|
if (min < 0) {
|
||||||
|
ss << "The invocation lower bound must be >= 0, "
|
||||||
|
<< "but is actually " << min << ".";
|
||||||
|
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||||
|
} else if (max < 0) {
|
||||||
|
ss << "The invocation upper bound must be >= 0, "
|
||||||
|
<< "but is actually " << max << ".";
|
||||||
|
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||||
|
} else if (min > max) {
|
||||||
|
ss << "The invocation upper bound (" << max
|
||||||
|
<< ") must be >= the invocation lower bound (" << min
|
||||||
|
<< ").";
|
||||||
|
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conservative estimate on the lower/upper bound of the number of
|
||||||
|
// calls allowed.
|
||||||
|
virtual int ConservativeLowerBound() const { return min_; }
|
||||||
|
virtual int ConservativeUpperBound() const { return max_; }
|
||||||
|
|
||||||
|
virtual bool IsSatisfiedByCallCount(int call_count) const {
|
||||||
|
return min_ <= call_count && call_count <= max_ ;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsSaturatedByCallCount(int call_count) const {
|
||||||
|
return call_count >= max_;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const;
|
||||||
|
private:
|
||||||
|
const int min_;
|
||||||
|
const int max_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(BetweenCardinalityImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Formats "n times" in a human-friendly way.
|
||||||
|
inline internal::string FormatTimes(int n) {
|
||||||
|
if (n == 1) {
|
||||||
|
return "once";
|
||||||
|
} else if (n == 2) {
|
||||||
|
return "twice";
|
||||||
|
} else {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << n << " times";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes the Between(m, n) cardinality in human-friendly text.
|
||||||
|
void BetweenCardinalityImpl::DescribeTo(::std::ostream* os) const {
|
||||||
|
if (min_ == 0) {
|
||||||
|
if (max_ == 0) {
|
||||||
|
*os << "never called";
|
||||||
|
} else if (max_ == INT_MAX) {
|
||||||
|
*os << "called any number of times";
|
||||||
|
} else {
|
||||||
|
*os << "called at most " << FormatTimes(max_);
|
||||||
|
}
|
||||||
|
} else if (min_ == max_) {
|
||||||
|
*os << "called " << FormatTimes(min_);
|
||||||
|
} else if (max_ == INT_MAX) {
|
||||||
|
*os << "called at least " << FormatTimes(min_);
|
||||||
|
} else {
|
||||||
|
// 0 < min_ < max_ < INT_MAX
|
||||||
|
*os << "called between " << min_ << " and " << max_ << " times";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Unnamed namespace
|
||||||
|
|
||||||
|
// Describes the given call count to an ostream.
|
||||||
|
void Cardinality::DescribeActualCallCountTo(int actual_call_count,
|
||||||
|
::std::ostream* os) {
|
||||||
|
if (actual_call_count > 0) {
|
||||||
|
*os << "called " << FormatTimes(actual_call_count);
|
||||||
|
} else {
|
||||||
|
*os << "never called";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a cardinality that allows at least n calls.
|
||||||
|
Cardinality AtLeast(int n) { return Between(n, INT_MAX); }
|
||||||
|
|
||||||
|
// Creates a cardinality that allows at most n calls.
|
||||||
|
Cardinality AtMost(int n) { return Between(0, n); }
|
||||||
|
|
||||||
|
// Creates a cardinality that allows any number of calls.
|
||||||
|
Cardinality AnyNumber() { return AtLeast(0); }
|
||||||
|
|
||||||
|
// Creates a cardinality that allows between min and max calls.
|
||||||
|
Cardinality Between(int min, int max) {
|
||||||
|
return Cardinality(new BetweenCardinalityImpl(min, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a cardinality that allows exactly n calls.
|
||||||
|
Cardinality Exactly(int n) { return Between(n, n); }
|
||||||
|
|
||||||
|
} // namespace testing
|
|
@ -0,0 +1,173 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file defines some utilities useful for implementing Google
|
||||||
|
// Mock. They are subject to change without notice, so please DO NOT
|
||||||
|
// USE THEM IN USER CODE.
|
||||||
|
|
||||||
|
#include <gmock/internal/gmock-internal-utils.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <string>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Converts an identifier name to a space-separated list of lower-case
|
||||||
|
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
|
||||||
|
// treated as one word. For example, both "FooBar123" and
|
||||||
|
// "foo_bar_123" are converted to "foo bar 123".
|
||||||
|
string ConvertIdentifierNameToWords(const char* id_name) {
|
||||||
|
string result;
|
||||||
|
char prev_char = '\0';
|
||||||
|
for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
|
||||||
|
// We don't care about the current locale as the input is
|
||||||
|
// guaranteed to be a valid C++ identifier name.
|
||||||
|
const bool starts_new_word = isupper(*p) ||
|
||||||
|
(!isalpha(prev_char) && islower(*p)) ||
|
||||||
|
(!isdigit(prev_char) && isdigit(*p));
|
||||||
|
|
||||||
|
if (isalnum(*p)) {
|
||||||
|
if (starts_new_word && result != "")
|
||||||
|
result += ' ';
|
||||||
|
result += static_cast<char>(tolower(*p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class reports Google Mock failures as Google Test failures. A
|
||||||
|
// user can define another class in a similar fashion if he intends to
|
||||||
|
// use Google Mock with a testing framework other than Google Test.
|
||||||
|
class GoogleTestFailureReporter : public FailureReporterInterface {
|
||||||
|
public:
|
||||||
|
virtual void ReportFailure(FailureType type, const char* file, int line,
|
||||||
|
const string& message) {
|
||||||
|
AssertHelper(type == FATAL ?
|
||||||
|
TestPartResult::kFatalFailure :
|
||||||
|
TestPartResult::kNonFatalFailure,
|
||||||
|
file,
|
||||||
|
line,
|
||||||
|
message.c_str()) = Message();
|
||||||
|
if (type == FATAL) {
|
||||||
|
posix::Abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the global failure reporter. Will create a
|
||||||
|
// GoogleTestFailureReporter and return it the first time called.
|
||||||
|
FailureReporterInterface* GetFailureReporter() {
|
||||||
|
// Points to the global failure reporter used by Google Mock. gcc
|
||||||
|
// guarantees that the following use of failure_reporter is
|
||||||
|
// thread-safe. We may need to add additional synchronization to
|
||||||
|
// protect failure_reporter if we port Google Mock to other
|
||||||
|
// compilers.
|
||||||
|
static FailureReporterInterface* const failure_reporter =
|
||||||
|
new GoogleTestFailureReporter();
|
||||||
|
return failure_reporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protects global resources (stdout in particular) used by Log().
|
||||||
|
static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
|
||||||
|
|
||||||
|
// Returns true iff a log with the given severity is visible according
|
||||||
|
// to the --gmock_verbose flag.
|
||||||
|
bool LogIsVisible(LogSeverity severity) {
|
||||||
|
if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
|
||||||
|
// Always show the log if --gmock_verbose=info.
|
||||||
|
return true;
|
||||||
|
} else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
|
||||||
|
// Always hide it if --gmock_verbose=error.
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// If --gmock_verbose is neither "info" nor "error", we treat it
|
||||||
|
// as "warning" (its default value).
|
||||||
|
return severity == WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given message to stdout iff 'severity' >= the level
|
||||||
|
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
|
||||||
|
// 0, also prints the stack trace excluding the top
|
||||||
|
// stack_frames_to_skip frames. In opt mode, any positive
|
||||||
|
// stack_frames_to_skip is treated as 0, since we don't know which
|
||||||
|
// function calls will be inlined by the compiler and need to be
|
||||||
|
// conservative.
|
||||||
|
void Log(LogSeverity severity, const string& message,
|
||||||
|
int stack_frames_to_skip) {
|
||||||
|
if (!LogIsVisible(severity))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ensures that logs from different threads don't interleave.
|
||||||
|
MutexLock l(&g_log_mutex);
|
||||||
|
|
||||||
|
// "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a
|
||||||
|
// macro.
|
||||||
|
|
||||||
|
if (severity == WARNING) {
|
||||||
|
// Prints a GMOCK WARNING marker to make the warnings easily searchable.
|
||||||
|
std::cout << "\nGMOCK WARNING:";
|
||||||
|
}
|
||||||
|
// Pre-pends a new-line to message if it doesn't start with one.
|
||||||
|
if (message.empty() || message[0] != '\n') {
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
std::cout << message;
|
||||||
|
if (stack_frames_to_skip >= 0) {
|
||||||
|
#ifdef NDEBUG
|
||||||
|
// In opt mode, we have to be conservative and skip no stack frame.
|
||||||
|
const int actual_to_skip = 0;
|
||||||
|
#else
|
||||||
|
// In dbg mode, we can do what the caller tell us to do (plus one
|
||||||
|
// for skipping this function's stack frame).
|
||||||
|
const int actual_to_skip = stack_frames_to_skip + 1;
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
// Appends a new-line to message if it doesn't end with one.
|
||||||
|
if (!message.empty() && *message.rbegin() != '\n') {
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
std::cout << "Stack trace:\n"
|
||||||
|
<< ::testing::internal::GetCurrentOsStackTraceExceptTop(
|
||||||
|
::testing::UnitTest::GetInstance(), actual_to_skip);
|
||||||
|
}
|
||||||
|
std::cout << ::std::flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
|
@ -0,0 +1,190 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements Matcher<const string&>, Matcher<string>, and
|
||||||
|
// utilities for defining matchers.
|
||||||
|
|
||||||
|
#include <gmock/gmock-matchers.h>
|
||||||
|
#include <gmock/gmock-generated-matchers.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const internal::string&>::Matcher(const internal::string& s) {
|
||||||
|
*this = Eq(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const internal::string&>::Matcher(const char* s) {
|
||||||
|
*this = Eq(internal::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a string whose value is equal to s.
|
||||||
|
Matcher<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); }
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a string whose value is equal to s.
|
||||||
|
Matcher<internal::string>::Matcher(const char* s) {
|
||||||
|
*this = Eq(internal::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Utilities for validating and formatting description strings in the
|
||||||
|
// MATCHER*() macros.
|
||||||
|
|
||||||
|
// Returns the 0-based index of the given parameter in the
|
||||||
|
// NULL-terminated parameter array; if the parameter is "*", returns
|
||||||
|
// kTupleInterpolation; if it's not found in the list, returns
|
||||||
|
// kInvalidInterpolation.
|
||||||
|
int GetParamIndex(const char* param_names[], const string& param_name) {
|
||||||
|
if (param_name == "*")
|
||||||
|
return kTupleInterpolation;
|
||||||
|
|
||||||
|
for (int i = 0; param_names[i] != NULL; i++) {
|
||||||
|
if (param_name == param_names[i])
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return kInvalidInterpolation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function used by ValidateMatcherDescription() to format
|
||||||
|
// error messages.
|
||||||
|
string FormatMatcherDescriptionSyntaxError(const char* description,
|
||||||
|
const char* error_pos) {
|
||||||
|
::std::stringstream ss;
|
||||||
|
ss << "Syntax error at index " << (error_pos - description)
|
||||||
|
<< " in matcher description \"" << description << "\": ";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses a matcher description string and returns a vector of
|
||||||
|
// interpolations that appear in the string; generates non-fatal
|
||||||
|
// failures iff 'description' is an invalid matcher description.
|
||||||
|
// 'param_names' is a NULL-terminated array of parameter names in the
|
||||||
|
// order they appear in the MATCHER_P*() parameter list.
|
||||||
|
Interpolations ValidateMatcherDescription(
|
||||||
|
const char* param_names[], const char* description) {
|
||||||
|
Interpolations interps;
|
||||||
|
for (const char* p = description; *p != '\0';) {
|
||||||
|
if (SkipPrefix("%%", &p)) {
|
||||||
|
interps.push_back(Interpolation(p - 2, p, kPercentInterpolation));
|
||||||
|
} else if (SkipPrefix("%(", &p)) {
|
||||||
|
const char* const q = strstr(p, ")s");
|
||||||
|
if (q == NULL) {
|
||||||
|
// TODO(wan@google.com): change the source file location in
|
||||||
|
// the failure to point to where the MATCHER*() macro is used.
|
||||||
|
ADD_FAILURE() << FormatMatcherDescriptionSyntaxError(description, p - 2)
|
||||||
|
<< "an interpolation must end with \")s\", "
|
||||||
|
<< "but \"" << (p - 2) << "\" does not.";
|
||||||
|
} else {
|
||||||
|
const string param_name(p, q);
|
||||||
|
const int param_index = GetParamIndex(param_names, param_name);
|
||||||
|
if (param_index == kInvalidInterpolation) {
|
||||||
|
ADD_FAILURE() << FormatMatcherDescriptionSyntaxError(description, p)
|
||||||
|
<< "\"" << param_name
|
||||||
|
<< "\" is an invalid parameter name.";
|
||||||
|
} else {
|
||||||
|
interps.push_back(Interpolation(p - 2, q + 2, param_index));
|
||||||
|
p = q + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EXPECT_NE(*p, '%') << FormatMatcherDescriptionSyntaxError(description, p)
|
||||||
|
<< "use \"%%\" instead of \"%\" to print \"%\".";
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return interps;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Joins a vector of strings as if they are fields of a tuple; returns
|
||||||
|
// the joined string.
|
||||||
|
string JoinAsTuple(const Strings& fields) {
|
||||||
|
switch (fields.size()) {
|
||||||
|
case 0:
|
||||||
|
return "";
|
||||||
|
case 1:
|
||||||
|
return fields[0];
|
||||||
|
default:
|
||||||
|
string result = "(" + fields[0];
|
||||||
|
for (size_t i = 1; i < fields.size(); i++) {
|
||||||
|
result += ", ";
|
||||||
|
result += fields[i];
|
||||||
|
}
|
||||||
|
result += ")";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the actual matcher description, given the matcher name,
|
||||||
|
// user-supplied description template string, interpolations in the
|
||||||
|
// string, and the printed values of the matcher parameters.
|
||||||
|
string FormatMatcherDescription(
|
||||||
|
const char* matcher_name, const char* description,
|
||||||
|
const Interpolations& interp, const Strings& param_values) {
|
||||||
|
string result;
|
||||||
|
if (*description == '\0') {
|
||||||
|
// When the user supplies an empty description, we calculate one
|
||||||
|
// from the matcher name.
|
||||||
|
result = ConvertIdentifierNameToWords(matcher_name);
|
||||||
|
if (param_values.size() >= 1)
|
||||||
|
result += " " + JoinAsTuple(param_values);
|
||||||
|
} else {
|
||||||
|
// The end position of the last interpolation.
|
||||||
|
const char* last_interp_end = description;
|
||||||
|
for (size_t i = 0; i < interp.size(); i++) {
|
||||||
|
result.append(last_interp_end, interp[i].start_pos);
|
||||||
|
const int param_index = interp[i].param_index;
|
||||||
|
if (param_index == kTupleInterpolation) {
|
||||||
|
result += JoinAsTuple(param_values);
|
||||||
|
} else if (param_index == kPercentInterpolation) {
|
||||||
|
result += '%';
|
||||||
|
} else if (param_index != kInvalidInterpolation) {
|
||||||
|
result += param_values[param_index];
|
||||||
|
}
|
||||||
|
last_interp_end = interp[i].end_pos;
|
||||||
|
}
|
||||||
|
result += last_interp_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
|
@ -0,0 +1,318 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements a universal value printer that can print a
|
||||||
|
// value of any type T:
|
||||||
|
//
|
||||||
|
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
|
||||||
|
//
|
||||||
|
// It uses the << operator when possible, and prints the bytes in the
|
||||||
|
// object otherwise. A user can override its behavior for a class
|
||||||
|
// type Foo by defining either operator<<(::std::ostream&, const Foo&)
|
||||||
|
// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
|
||||||
|
// defines Foo.
|
||||||
|
|
||||||
|
#include <gmock/gmock-printers.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <string>
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::std::ostream;
|
||||||
|
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s.
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf.
|
||||||
|
#define snprintf _snprintf_s
|
||||||
|
#elif _MSC_VER
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
|
// Prints a segment of bytes in the given object.
|
||||||
|
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||||
|
size_t count, ostream* os) {
|
||||||
|
char text[5] = "";
|
||||||
|
for (size_t i = 0; i != count; i++) {
|
||||||
|
const size_t j = start + i;
|
||||||
|
if (i != 0) {
|
||||||
|
// Organizes the bytes into groups of 2 for easy parsing by
|
||||||
|
// human.
|
||||||
|
if ((j % 2) == 0) {
|
||||||
|
*os << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
|
||||||
|
*os << text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the bytes in the given value to the given ostream.
|
||||||
|
void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
||||||
|
ostream* os) {
|
||||||
|
// Tells the user how big the object is.
|
||||||
|
*os << count << "-byte object <";
|
||||||
|
|
||||||
|
const size_t kThreshold = 132;
|
||||||
|
const size_t kChunkSize = 64;
|
||||||
|
// If the object size is bigger than kThreshold, we'll have to omit
|
||||||
|
// some details by printing only the first and the last kChunkSize
|
||||||
|
// bytes.
|
||||||
|
// TODO(wan): let the user control the threshold using a flag.
|
||||||
|
if (count < kThreshold) {
|
||||||
|
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
|
||||||
|
} else {
|
||||||
|
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
|
||||||
|
*os << " ... ";
|
||||||
|
// Rounds up to 2-byte boundary.
|
||||||
|
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
|
||||||
|
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
|
||||||
|
}
|
||||||
|
*os << ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace internal2 {
|
||||||
|
|
||||||
|
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
|
||||||
|
// given object. The delegation simplifies the implementation, which
|
||||||
|
// uses the << operator and thus is easier done outside of the
|
||||||
|
// ::testing::internal namespace, which contains a << operator that
|
||||||
|
// sometimes conflicts with the one in STL.
|
||||||
|
void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
|
||||||
|
ostream* os) {
|
||||||
|
PrintBytesInObjectToImpl(obj_bytes, count, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal2
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Prints a wide char as a char literal without the quotes, escaping it
|
||||||
|
// when necessary.
|
||||||
|
static void PrintAsWideCharLiteralTo(wchar_t c, ostream* os) {
|
||||||
|
switch (c) {
|
||||||
|
case L'\0':
|
||||||
|
*os << "\\0";
|
||||||
|
break;
|
||||||
|
case L'\'':
|
||||||
|
*os << "\\'";
|
||||||
|
break;
|
||||||
|
case L'\?':
|
||||||
|
*os << "\\?";
|
||||||
|
break;
|
||||||
|
case L'\\':
|
||||||
|
*os << "\\\\";
|
||||||
|
break;
|
||||||
|
case L'\a':
|
||||||
|
*os << "\\a";
|
||||||
|
break;
|
||||||
|
case L'\b':
|
||||||
|
*os << "\\b";
|
||||||
|
break;
|
||||||
|
case L'\f':
|
||||||
|
*os << "\\f";
|
||||||
|
break;
|
||||||
|
case L'\n':
|
||||||
|
*os << "\\n";
|
||||||
|
break;
|
||||||
|
case L'\r':
|
||||||
|
*os << "\\r";
|
||||||
|
break;
|
||||||
|
case L'\t':
|
||||||
|
*os << "\\t";
|
||||||
|
break;
|
||||||
|
case L'\v':
|
||||||
|
*os << "\\v";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Checks whether c is printable or not. Printable characters are in
|
||||||
|
// the range [0x20,0x7E].
|
||||||
|
// We test the value of c directly instead of calling isprint(), as
|
||||||
|
// isprint() is buggy on Windows mobile.
|
||||||
|
if (0x20 <= c && c <= 0x7E) {
|
||||||
|
*os << static_cast<char>(c);
|
||||||
|
} else {
|
||||||
|
// Buffer size enough for the maximum number of digits and \0.
|
||||||
|
char text[2 * sizeof(unsigned long) + 1] = "";
|
||||||
|
snprintf(text, sizeof(text), "%lX", static_cast<unsigned long>(c));
|
||||||
|
*os << "\\x" << text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints a char as if it's part of a string literal, escaping it when
|
||||||
|
// necessary.
|
||||||
|
static void PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
|
||||||
|
switch (c) {
|
||||||
|
case L'\'':
|
||||||
|
*os << "'";
|
||||||
|
break;
|
||||||
|
case L'"':
|
||||||
|
*os << "\\\"";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAsWideCharLiteralTo(c, os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints a char as a char literal without the quotes, escaping it
|
||||||
|
// when necessary.
|
||||||
|
static void PrintAsCharLiteralTo(char c, ostream* os) {
|
||||||
|
PrintAsWideCharLiteralTo(static_cast<unsigned char>(c), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints a char as if it's part of a string literal, escaping it when
|
||||||
|
// necessary.
|
||||||
|
static void PrintAsStringLiteralTo(char c, ostream* os) {
|
||||||
|
PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints a char and its code. The '\0' char is printed as "'\\0'",
|
||||||
|
// other unprintable characters are also properly escaped using the
|
||||||
|
// standard C++ escape sequence.
|
||||||
|
void PrintCharTo(char c, int char_code, ostream* os) {
|
||||||
|
*os << "'";
|
||||||
|
PrintAsCharLiteralTo(c, os);
|
||||||
|
*os << "'";
|
||||||
|
if (c != '\0')
|
||||||
|
*os << " (" << char_code << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints a wchar_t as a symbol if it is printable or as its internal
|
||||||
|
// code otherwise and also as its decimal code (except for L'\0').
|
||||||
|
// The L'\0' char is printed as "L'\\0'". The decimal code is printed
|
||||||
|
// as signed integer when wchar_t is implemented by the compiler
|
||||||
|
// as a signed type and is printed as an unsigned integer when wchar_t
|
||||||
|
// is implemented as an unsigned type.
|
||||||
|
void PrintTo(wchar_t wc, ostream* os) {
|
||||||
|
*os << "L'";
|
||||||
|
PrintAsWideCharLiteralTo(wc, os);
|
||||||
|
*os << "'";
|
||||||
|
if (wc != L'\0') {
|
||||||
|
// Type Int64 is used because it provides more storage than wchar_t thus
|
||||||
|
// when the compiler converts signed or unsigned implementation of wchar_t
|
||||||
|
// to Int64 it fills higher bits with either zeros or the sign bit
|
||||||
|
// passing it to operator <<() as either signed or unsigned integer.
|
||||||
|
*os << " (" << static_cast<Int64>(wc) << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given array of characters to the ostream.
|
||||||
|
// The array starts at *begin, the length is len, it may include '\0' characters
|
||||||
|
// and may not be null-terminated.
|
||||||
|
static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
|
||||||
|
*os << "\"";
|
||||||
|
for (size_t index = 0; index < len; ++index) {
|
||||||
|
PrintAsStringLiteralTo(begin[index], os);
|
||||||
|
}
|
||||||
|
*os << "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
|
||||||
|
void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
|
||||||
|
PrintCharsAsStringTo(begin, len, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given array of wide characters to the ostream.
|
||||||
|
// The array starts at *begin, the length is len, it may include L'\0'
|
||||||
|
// characters and may not be null-terminated.
|
||||||
|
static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
|
||||||
|
ostream* os) {
|
||||||
|
*os << "L\"";
|
||||||
|
for (size_t index = 0; index < len; ++index) {
|
||||||
|
PrintAsWideStringLiteralTo(begin[index], os);
|
||||||
|
}
|
||||||
|
*os << "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given C string to the ostream.
|
||||||
|
void PrintTo(const char* s, ostream* os) {
|
||||||
|
if (s == NULL) {
|
||||||
|
*os << "NULL";
|
||||||
|
} else {
|
||||||
|
*os << implicit_cast<const void*>(s) << " pointing to ";
|
||||||
|
PrintCharsAsStringTo(s, strlen(s), os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MSVC compiler can be configured to define whar_t as a typedef
|
||||||
|
// of unsigned short. Defining an overload for const wchar_t* in that case
|
||||||
|
// would cause pointers to unsigned shorts be printed as wide strings,
|
||||||
|
// possibly accessing more memory than intended and causing invalid
|
||||||
|
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
|
||||||
|
// wchar_t is implemented as a native type.
|
||||||
|
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||||
|
// Prints the given wide C string to the ostream.
|
||||||
|
void PrintTo(const wchar_t* s, ostream* os) {
|
||||||
|
if (s == NULL) {
|
||||||
|
*os << "NULL";
|
||||||
|
} else {
|
||||||
|
*os << implicit_cast<const void*>(s) << " pointing to ";
|
||||||
|
PrintWideCharsAsStringTo(s, wcslen(s), os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // wchar_t is native
|
||||||
|
|
||||||
|
// Prints a ::string object.
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
void PrintStringTo(const ::string& s, ostream* os) {
|
||||||
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
|
void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||||
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints a ::wstring object.
|
||||||
|
#if GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
void PrintWideStringTo(const ::wstring& s, ostream* os) {
|
||||||
|
PrintWideCharsAsStringTo(s.data(), s.size(), os);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
|
||||||
|
#if GTEST_HAS_STD_WSTRING
|
||||||
|
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
||||||
|
PrintWideCharsAsStringTo(s.data(), s.size(), os);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace testing
|
|
@ -0,0 +1,465 @@
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements the spec builder syntax (ON_CALL and
|
||||||
|
// EXPECT_CALL).
|
||||||
|
|
||||||
|
#include <gmock/gmock-spec-builders.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iostream> // NOLINT
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC
|
||||||
|
#include <unistd.h> // NOLINT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Protects the mock object registry (in class Mock), all function
|
||||||
|
// mockers, and all expectations.
|
||||||
|
GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex);
|
||||||
|
|
||||||
|
// Constructs an ExpectationBase object.
|
||||||
|
ExpectationBase::ExpectationBase(const char* a_file,
|
||||||
|
int a_line,
|
||||||
|
const string& a_source_text)
|
||||||
|
: file_(a_file),
|
||||||
|
line_(a_line),
|
||||||
|
source_text_(a_source_text),
|
||||||
|
cardinality_specified_(false),
|
||||||
|
cardinality_(Exactly(1)),
|
||||||
|
call_count_(0),
|
||||||
|
retired_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructs an ExpectationBase object.
|
||||||
|
ExpectationBase::~ExpectationBase() {}
|
||||||
|
|
||||||
|
// Explicitly specifies the cardinality of this expectation. Used by
|
||||||
|
// the subclasses to implement the .Times() clause.
|
||||||
|
void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) {
|
||||||
|
cardinality_specified_ = true;
|
||||||
|
cardinality_ = a_cardinality;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retires all pre-requisites of this expectation.
|
||||||
|
void ExpectationBase::RetireAllPreRequisites() {
|
||||||
|
if (is_retired()) {
|
||||||
|
// We can take this short-cut as we never retire an expectation
|
||||||
|
// until we have retired all its pre-requisites.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
|
ExpectationBase* const prerequisite = it->expectation_base().get();
|
||||||
|
if (!prerequisite->is_retired()) {
|
||||||
|
prerequisite->RetireAllPreRequisites();
|
||||||
|
prerequisite->Retire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff all pre-requisites of this expectation have been
|
||||||
|
// satisfied.
|
||||||
|
// L >= g_gmock_mutex
|
||||||
|
bool ExpectationBase::AllPrerequisitesAreSatisfied() const {
|
||||||
|
g_gmock_mutex.AssertHeld();
|
||||||
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
|
if (!(it->expectation_base()->IsSatisfied()) ||
|
||||||
|
!(it->expectation_base()->AllPrerequisitesAreSatisfied()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds unsatisfied pre-requisites of this expectation to 'result'.
|
||||||
|
// L >= g_gmock_mutex
|
||||||
|
void ExpectationBase::FindUnsatisfiedPrerequisites(
|
||||||
|
ExpectationSet* result) const {
|
||||||
|
g_gmock_mutex.AssertHeld();
|
||||||
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
|
if (it->expectation_base()->IsSatisfied()) {
|
||||||
|
// If *it is satisfied and has a call count of 0, some of its
|
||||||
|
// pre-requisites may not be satisfied yet.
|
||||||
|
if (it->expectation_base()->call_count_ == 0) {
|
||||||
|
it->expectation_base()->FindUnsatisfiedPrerequisites(result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Now that we know *it is unsatisfied, we are not so interested
|
||||||
|
// in whether its pre-requisites are satisfied. Therefore we
|
||||||
|
// don't recursively call FindUnsatisfiedPrerequisites() here.
|
||||||
|
*result += *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Points to the implicit sequence introduced by a living InSequence
|
||||||
|
// object (if any) in the current thread or NULL.
|
||||||
|
ThreadLocal<Sequence*> g_gmock_implicit_sequence;
|
||||||
|
|
||||||
|
// Reports an uninteresting call (whose description is in msg) in the
|
||||||
|
// manner specified by 'reaction'.
|
||||||
|
void ReportUninterestingCall(CallReaction reaction, const string& msg) {
|
||||||
|
switch (reaction) {
|
||||||
|
case ALLOW:
|
||||||
|
Log(INFO, msg, 3);
|
||||||
|
break;
|
||||||
|
case WARN:
|
||||||
|
Log(WARNING, msg, 3);
|
||||||
|
break;
|
||||||
|
default: // FAIL
|
||||||
|
Expect(false, NULL, -1, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Class Mock.
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers;
|
||||||
|
|
||||||
|
// The current state of a mock object. Such information is needed for
|
||||||
|
// detecting leaked mock objects and explicitly verifying a mock's
|
||||||
|
// expectations.
|
||||||
|
struct MockObjectState {
|
||||||
|
MockObjectState()
|
||||||
|
: first_used_file(NULL), first_used_line(-1), leakable(false) {}
|
||||||
|
|
||||||
|
// Where in the source file an ON_CALL or EXPECT_CALL is first
|
||||||
|
// invoked on this mock object.
|
||||||
|
const char* first_used_file;
|
||||||
|
int first_used_line;
|
||||||
|
::std::string first_used_test_case;
|
||||||
|
::std::string first_used_test;
|
||||||
|
bool leakable; // true iff it's OK to leak the object.
|
||||||
|
FunctionMockers function_mockers; // All registered methods of the object.
|
||||||
|
};
|
||||||
|
|
||||||
|
// A global registry holding the state of all mock objects that are
|
||||||
|
// alive. A mock object is added to this registry the first time
|
||||||
|
// Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it. It
|
||||||
|
// is removed from the registry in the mock object's destructor.
|
||||||
|
class MockObjectRegistry {
|
||||||
|
public:
|
||||||
|
// Maps a mock object (identified by its address) to its state.
|
||||||
|
typedef std::map<const void*, MockObjectState> StateMap;
|
||||||
|
|
||||||
|
// This destructor will be called when a program exits, after all
|
||||||
|
// tests in it have been run. By then, there should be no mock
|
||||||
|
// object alive. Therefore we report any living object as test
|
||||||
|
// failure, unless the user explicitly asked us to ignore it.
|
||||||
|
~MockObjectRegistry() {
|
||||||
|
|
||||||
|
// "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
|
||||||
|
// a macro.
|
||||||
|
|
||||||
|
if (!GMOCK_FLAG(catch_leaked_mocks))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int leaked_count = 0;
|
||||||
|
for (StateMap::const_iterator it = states_.begin(); it != states_.end();
|
||||||
|
++it) {
|
||||||
|
if (it->second.leakable) // The user said it's fine to leak this object.
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO(wan@google.com): Print the type of the leaked object.
|
||||||
|
// This can help the user identify the leaked object.
|
||||||
|
std::cout << "\n";
|
||||||
|
const MockObjectState& state = it->second;
|
||||||
|
std::cout << internal::FormatFileLocation(state.first_used_file,
|
||||||
|
state.first_used_line);
|
||||||
|
std::cout << " ERROR: this mock object";
|
||||||
|
if (state.first_used_test != "") {
|
||||||
|
std::cout << " (used in test " << state.first_used_test_case << "."
|
||||||
|
<< state.first_used_test << ")";
|
||||||
|
}
|
||||||
|
std::cout << " should be deleted but never is. Its address is @"
|
||||||
|
<< it->first << ".";
|
||||||
|
leaked_count++;
|
||||||
|
}
|
||||||
|
if (leaked_count > 0) {
|
||||||
|
std::cout << "\nERROR: " << leaked_count
|
||||||
|
<< " leaked mock " << (leaked_count == 1 ? "object" : "objects")
|
||||||
|
<< " found at program exit.\n";
|
||||||
|
std::cout.flush();
|
||||||
|
::std::cerr.flush();
|
||||||
|
// RUN_ALL_TESTS() has already returned when this destructor is
|
||||||
|
// called. Therefore we cannot use the normal Google Test
|
||||||
|
// failure reporting mechanism.
|
||||||
|
_exit(1); // We cannot call exit() as it is not reentrant and
|
||||||
|
// may already have been called.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StateMap& states() { return states_; }
|
||||||
|
private:
|
||||||
|
StateMap states_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Protected by g_gmock_mutex.
|
||||||
|
MockObjectRegistry g_mock_object_registry;
|
||||||
|
|
||||||
|
// Maps a mock object to the reaction Google Mock should have when an
|
||||||
|
// uninteresting method is called. Protected by g_gmock_mutex.
|
||||||
|
std::map<const void*, internal::CallReaction> g_uninteresting_call_reaction;
|
||||||
|
|
||||||
|
// Sets the reaction Google Mock should have when an uninteresting
|
||||||
|
// method of the given mock object is called.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
void SetReactionOnUninterestingCalls(const void* mock_obj,
|
||||||
|
internal::CallReaction reaction) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
g_uninteresting_call_reaction[mock_obj] = reaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Tells Google Mock to allow uninteresting calls on the given mock
|
||||||
|
// object.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
void Mock::AllowUninterestingCalls(const void* mock_obj) {
|
||||||
|
SetReactionOnUninterestingCalls(mock_obj, internal::ALLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock to warn the user about uninteresting calls on the
|
||||||
|
// given mock object.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
void Mock::WarnUninterestingCalls(const void* mock_obj) {
|
||||||
|
SetReactionOnUninterestingCalls(mock_obj, internal::WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock to fail uninteresting calls on the given mock
|
||||||
|
// object.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
void Mock::FailUninterestingCalls(const void* mock_obj) {
|
||||||
|
SetReactionOnUninterestingCalls(mock_obj, internal::FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock the given mock object is being destroyed and its
|
||||||
|
// entry in the call-reaction table should be removed.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
void Mock::UnregisterCallReaction(const void* mock_obj) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
g_uninteresting_call_reaction.erase(mock_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the reaction Google Mock will have on uninteresting calls
|
||||||
|
// made on the given mock object.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
internal::CallReaction Mock::GetReactionOnUninterestingCalls(
|
||||||
|
const void* mock_obj) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
return (g_uninteresting_call_reaction.count(mock_obj) == 0) ?
|
||||||
|
internal::WARN : g_uninteresting_call_reaction[mock_obj];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock to ignore mock_obj when checking for leaked mock
|
||||||
|
// objects.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
void Mock::AllowLeak(const void* mock_obj) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
g_mock_object_registry.states()[mock_obj].leakable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies and clears all expectations on the given mock object. If
|
||||||
|
// the expectations aren't satisfied, generates one or more Google
|
||||||
|
// Test non-fatal failures and returns false.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
bool Mock::VerifyAndClearExpectations(void* mock_obj) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies all expectations on the given mock object and clears its
|
||||||
|
// default actions and expectations. Returns true iff the
|
||||||
|
// verification was successful.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
bool Mock::VerifyAndClear(void* mock_obj) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
ClearDefaultActionsLocked(mock_obj);
|
||||||
|
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies and clears all expectations on the given mock object. If
|
||||||
|
// the expectations aren't satisfied, generates one or more Google
|
||||||
|
// Test non-fatal failures and returns false.
|
||||||
|
// L >= g_gmock_mutex
|
||||||
|
bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) {
|
||||||
|
internal::g_gmock_mutex.AssertHeld();
|
||||||
|
if (g_mock_object_registry.states().count(mock_obj) == 0) {
|
||||||
|
// No EXPECT_CALL() was set on the given mock object.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies and clears the expectations on each mock method in the
|
||||||
|
// given mock object.
|
||||||
|
bool expectations_met = true;
|
||||||
|
FunctionMockers& mockers =
|
||||||
|
g_mock_object_registry.states()[mock_obj].function_mockers;
|
||||||
|
for (FunctionMockers::const_iterator it = mockers.begin();
|
||||||
|
it != mockers.end(); ++it) {
|
||||||
|
if (!(*it)->VerifyAndClearExpectationsLocked()) {
|
||||||
|
expectations_met = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't clear the content of mockers, as they may still be
|
||||||
|
// needed by ClearDefaultActionsLocked().
|
||||||
|
return expectations_met;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers a mock object and a mock method it owns.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
void Mock::Register(const void* mock_obj,
|
||||||
|
internal::UntypedFunctionMockerBase* mocker) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock where in the source code mock_obj is used in an
|
||||||
|
// ON_CALL or EXPECT_CALL. In case mock_obj is leaked, this
|
||||||
|
// information helps the user identify which object it is.
|
||||||
|
// L < g_gmock_mutex
|
||||||
|
void Mock::RegisterUseByOnCallOrExpectCall(
|
||||||
|
const void* mock_obj, const char* file, int line) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
MockObjectState& state = g_mock_object_registry.states()[mock_obj];
|
||||||
|
if (state.first_used_file == NULL) {
|
||||||
|
state.first_used_file = file;
|
||||||
|
state.first_used_line = line;
|
||||||
|
const TestInfo* const test_info =
|
||||||
|
UnitTest::GetInstance()->current_test_info();
|
||||||
|
if (test_info != NULL) {
|
||||||
|
// TODO(wan@google.com): record the test case name when the
|
||||||
|
// ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or
|
||||||
|
// TearDownTestCase().
|
||||||
|
state.first_used_test_case = test_info->test_case_name();
|
||||||
|
state.first_used_test = test_info->name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unregisters a mock method; removes the owning mock object from the
|
||||||
|
// registry when the last mock method associated with it has been
|
||||||
|
// unregistered. This is called only in the destructor of
|
||||||
|
// FunctionMockerBase.
|
||||||
|
// L >= g_gmock_mutex
|
||||||
|
void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) {
|
||||||
|
internal::g_gmock_mutex.AssertHeld();
|
||||||
|
for (MockObjectRegistry::StateMap::iterator it =
|
||||||
|
g_mock_object_registry.states().begin();
|
||||||
|
it != g_mock_object_registry.states().end(); ++it) {
|
||||||
|
FunctionMockers& mockers = it->second.function_mockers;
|
||||||
|
if (mockers.erase(mocker) > 0) {
|
||||||
|
// mocker was in mockers and has been just removed.
|
||||||
|
if (mockers.empty()) {
|
||||||
|
g_mock_object_registry.states().erase(it);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears all ON_CALL()s set on the given mock object.
|
||||||
|
// L >= g_gmock_mutex
|
||||||
|
void Mock::ClearDefaultActionsLocked(void* mock_obj) {
|
||||||
|
internal::g_gmock_mutex.AssertHeld();
|
||||||
|
|
||||||
|
if (g_mock_object_registry.states().count(mock_obj) == 0) {
|
||||||
|
// No ON_CALL() was set on the given mock object.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears the default actions for each mock method in the given mock
|
||||||
|
// object.
|
||||||
|
FunctionMockers& mockers =
|
||||||
|
g_mock_object_registry.states()[mock_obj].function_mockers;
|
||||||
|
for (FunctionMockers::const_iterator it = mockers.begin();
|
||||||
|
it != mockers.end(); ++it) {
|
||||||
|
(*it)->ClearDefaultActionsLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't clear the content of mockers, as they may still be
|
||||||
|
// needed by VerifyAndClearExpectationsLocked().
|
||||||
|
}
|
||||||
|
|
||||||
|
Expectation::Expectation() {}
|
||||||
|
|
||||||
|
Expectation::Expectation(
|
||||||
|
const internal::linked_ptr<internal::ExpectationBase>& an_expectation_base)
|
||||||
|
: expectation_base_(an_expectation_base) {}
|
||||||
|
|
||||||
|
Expectation::~Expectation() {}
|
||||||
|
|
||||||
|
// Adds an expectation to a sequence.
|
||||||
|
void Sequence::AddExpectation(const Expectation& expectation) const {
|
||||||
|
if (*last_expectation_ != expectation) {
|
||||||
|
if (last_expectation_->expectation_base() != NULL) {
|
||||||
|
expectation.expectation_base()->immediate_prerequisites_
|
||||||
|
+= *last_expectation_;
|
||||||
|
}
|
||||||
|
*last_expectation_ = expectation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the implicit sequence if there isn't one.
|
||||||
|
InSequence::InSequence() {
|
||||||
|
if (internal::g_gmock_implicit_sequence.get() == NULL) {
|
||||||
|
internal::g_gmock_implicit_sequence.set(new Sequence);
|
||||||
|
sequence_created_ = true;
|
||||||
|
} else {
|
||||||
|
sequence_created_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deletes the implicit sequence if it was created by the constructor
|
||||||
|
// of this object.
|
||||||
|
InSequence::~InSequence() {
|
||||||
|
if (sequence_created_) {
|
||||||
|
delete internal::g_gmock_implicit_sequence.get();
|
||||||
|
internal::g_gmock_implicit_sequence.set(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
|
@ -0,0 +1,182 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gmock/internal/gmock-port.h>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// TODO(wan@google.com): support using environment variables to
|
||||||
|
// control the flag values, like what Google Test does.
|
||||||
|
|
||||||
|
GMOCK_DEFINE_bool_(catch_leaked_mocks, true,
|
||||||
|
"true iff Google Mock should report leaked mock objects "
|
||||||
|
"as failures.");
|
||||||
|
|
||||||
|
GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity,
|
||||||
|
"Controls how verbose Google Mock's output is."
|
||||||
|
" Valid values:\n"
|
||||||
|
" info - prints all messages.\n"
|
||||||
|
" warning - prints warnings and errors.\n"
|
||||||
|
" error - prints errors only.");
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Parses a string as a command line flag. The string should have the
|
||||||
|
// format "--gmock_flag=value". When def_optional is true, the
|
||||||
|
// "=value" part can be omitted.
|
||||||
|
//
|
||||||
|
// Returns the value of the flag, or NULL if the parsing failed.
|
||||||
|
static const char* ParseGoogleMockFlagValue(const char* str,
|
||||||
|
const char* flag,
|
||||||
|
bool def_optional) {
|
||||||
|
// str and flag must not be NULL.
|
||||||
|
if (str == NULL || flag == NULL) return NULL;
|
||||||
|
|
||||||
|
// The flag must start with "--gmock_".
|
||||||
|
const String flag_str = String::Format("--gmock_%s", flag);
|
||||||
|
const size_t flag_len = flag_str.length();
|
||||||
|
if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
|
||||||
|
|
||||||
|
// Skips the flag name.
|
||||||
|
const char* flag_end = str + flag_len;
|
||||||
|
|
||||||
|
// When def_optional is true, it's OK to not have a "=value" part.
|
||||||
|
if (def_optional && (flag_end[0] == '\0')) {
|
||||||
|
return flag_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If def_optional is true and there are more characters after the
|
||||||
|
// flag name, or if def_optional is false, there must be a '=' after
|
||||||
|
// the flag name.
|
||||||
|
if (flag_end[0] != '=') return NULL;
|
||||||
|
|
||||||
|
// Returns the string after "=".
|
||||||
|
return flag_end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses a string for a Google Mock bool flag, in the form of
|
||||||
|
// "--gmock_flag=value".
|
||||||
|
//
|
||||||
|
// On success, stores the value of the flag in *value, and returns
|
||||||
|
// true. On failure, returns false without changing *value.
|
||||||
|
static bool ParseGoogleMockBoolFlag(const char* str, const char* flag,
|
||||||
|
bool* value) {
|
||||||
|
// Gets the value of the flag as a string.
|
||||||
|
const char* const value_str = ParseGoogleMockFlagValue(str, flag, true);
|
||||||
|
|
||||||
|
// Aborts if the parsing failed.
|
||||||
|
if (value_str == NULL) return false;
|
||||||
|
|
||||||
|
// Converts the string value to a bool.
|
||||||
|
*value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses a string for a Google Mock string flag, in the form of
|
||||||
|
// "--gmock_flag=value".
|
||||||
|
//
|
||||||
|
// On success, stores the value of the flag in *value, and returns
|
||||||
|
// true. On failure, returns false without changing *value.
|
||||||
|
static bool ParseGoogleMockStringFlag(const char* str, const char* flag,
|
||||||
|
String* value) {
|
||||||
|
// Gets the value of the flag as a string.
|
||||||
|
const char* const value_str = ParseGoogleMockFlagValue(str, flag, false);
|
||||||
|
|
||||||
|
// Aborts if the parsing failed.
|
||||||
|
if (value_str == NULL) return false;
|
||||||
|
|
||||||
|
// Sets *value to the value of the flag.
|
||||||
|
*value = value_str;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The internal implementation of InitGoogleMock().
|
||||||
|
//
|
||||||
|
// The type parameter CharType can be instantiated to either char or
|
||||||
|
// wchar_t.
|
||||||
|
template <typename CharType>
|
||||||
|
void InitGoogleMockImpl(int* argc, CharType** argv) {
|
||||||
|
// Makes sure Google Test is initialized. InitGoogleTest() is
|
||||||
|
// idempotent, so it's fine if the user has already called it.
|
||||||
|
InitGoogleTest(argc, argv);
|
||||||
|
if (*argc <= 0) return;
|
||||||
|
|
||||||
|
for (int i = 1; i != *argc; i++) {
|
||||||
|
const String arg_string = StreamableToString(argv[i]);
|
||||||
|
const char* const arg = arg_string.c_str();
|
||||||
|
|
||||||
|
// Do we see a Google Mock flag?
|
||||||
|
if (ParseGoogleMockBoolFlag(arg, "catch_leaked_mocks",
|
||||||
|
&GMOCK_FLAG(catch_leaked_mocks)) ||
|
||||||
|
ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) {
|
||||||
|
// Yes. Shift the remainder of the argv list left by one. Note
|
||||||
|
// that argv has (*argc + 1) elements, the last one always being
|
||||||
|
// NULL. The following loop moves the trailing NULL element as
|
||||||
|
// well.
|
||||||
|
for (int j = i; j != *argc; j++) {
|
||||||
|
argv[j] = argv[j + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrements the argument count.
|
||||||
|
(*argc)--;
|
||||||
|
|
||||||
|
// We also need to decrement the iterator as we just removed
|
||||||
|
// an element.
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Initializes Google Mock. This must be called before running the
|
||||||
|
// tests. In particular, it parses a command line for the flags that
|
||||||
|
// Google Mock recognizes. Whenever a Google Mock flag is seen, it is
|
||||||
|
// removed from argv, and *argc is decremented.
|
||||||
|
//
|
||||||
|
// No value is returned. Instead, the Google Mock flag variables are
|
||||||
|
// updated.
|
||||||
|
//
|
||||||
|
// Since Google Test is needed for Google Mock to work, this function
|
||||||
|
// also initializes Google Test and parses its flags, if that hasn't
|
||||||
|
// been done.
|
||||||
|
void InitGoogleMock(int* argc, char** argv) {
|
||||||
|
internal::InitGoogleMockImpl(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This overloaded version can be used in Windows programs compiled in
|
||||||
|
// UNICODE mode.
|
||||||
|
void InitGoogleMock(int* argc, wchar_t** argv) {
|
||||||
|
internal::InitGoogleMockImpl(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
// MS C++ compiler/linker has a bug on Windows (not on Windows CE), which
|
||||||
|
// causes a link error when _tmain is defined in a static library and UNICODE
|
||||||
|
// is enabled. For this reason instead of _tmain, main function is used on
|
||||||
|
// Windows. See the following link to track the current status of this bug:
|
||||||
|
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464 // NOLINT
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
#include <tchar.h> // NOLINT
|
||||||
|
|
||||||
|
int _tmain(int argc, TCHAR** argv) {
|
||||||
|
#else
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
std::cout << "Running main() from gmock_main.cc\n";
|
||||||
|
// Since Google Mock depends on Google Test, InitGoogleMock() is
|
||||||
|
// also responsible for initializing Google Test. Therefore there's
|
||||||
|
// no need for calling testing::InitGoogleTest() separately.
|
||||||
|
testing::InitGoogleMock(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
language: cpp
|
||||||
|
sudo: false
|
||||||
|
dist: trusty
|
||||||
|
env:
|
||||||
|
- USE_QT4=yes
|
||||||
|
- USE_QT4=no
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- cmake
|
||||||
|
- make
|
||||||
|
- libqt4-dev
|
||||||
|
- qt5-default
|
||||||
|
before_script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake -DQT4_BUILD=$USE_QT4 -DQJSON_BUILD_TESTS=yes ..
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
- make test
|
|
@ -0,0 +1,37 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8.11)
|
||||||
|
|
||||||
|
set(QJSON-SOURCES
|
||||||
|
src/parser.cpp
|
||||||
|
src/qobjecthelper.cpp
|
||||||
|
src/json_scanner.cpp
|
||||||
|
src/json_parser.cc
|
||||||
|
src/parserrunnable.cpp
|
||||||
|
src/serializer.cpp
|
||||||
|
src/serializerrunnable.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(QJSON-MOC-HEADERS
|
||||||
|
src/parser.h
|
||||||
|
src/parserrunnable.h
|
||||||
|
src/qobjecthelper.h
|
||||||
|
src/serializer.h
|
||||||
|
src/serializerrunnable.h
|
||||||
|
src/qjson_export.h
|
||||||
|
)
|
||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
QT5_WRAP_CPP(QJSON-SOURCES-MOC ${QJSON-MOC-HEADERS})
|
||||||
|
|
||||||
|
add_library(qjson STATIC
|
||||||
|
${QJSON-SOURCES}
|
||||||
|
${QJSON-SOURCES-MOC}
|
||||||
|
${QJSON-WIN32-RESOURCES}
|
||||||
|
)
|
||||||
|
|
||||||
|
set_property(TARGET qjson PROPERTY QT_STATICPLUGIN 1)
|
||||||
|
|
||||||
|
target_link_libraries(qjson
|
||||||
|
Qt5::Core
|
||||||
|
${QJSON_LIBRARIES}
|
||||||
|
)
|
|
@ -0,0 +1,149 @@
|
||||||
|
PROJECT(qjson)
|
||||||
|
|
||||||
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII" )
|
||||||
|
|
||||||
|
# Force cmake 2.8.8 in order to have a decent support of Qt5
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
|
||||||
|
CMAKE_POLICY(SET CMP0003 NEW)
|
||||||
|
|
||||||
|
# Do not link against qtmain on Windows
|
||||||
|
if(POLICY CMP0020)
|
||||||
|
cmake_policy(SET CMP0020 OLD)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_INSTALL_NAME_DIR ${LIB_INSTALL_DIR})
|
||||||
|
|
||||||
|
IF("${CMAKE_BUILD_TYPE}" MATCHES "^Rel.*")
|
||||||
|
ADD_DEFINITIONS("-DQT_NO_DEBUG_OUTPUT")
|
||||||
|
ENDIF("${CMAKE_BUILD_TYPE}" MATCHES "^Rel.*")
|
||||||
|
|
||||||
|
# Ability to disable verbose debug output
|
||||||
|
IF(QJSON_VERBOSE_DEBUG_OUTPUT)
|
||||||
|
ADD_DEFINITIONS("-DQJSON_VERBOSE_DEBUG_OUTPUT")
|
||||||
|
endif(QJSON_VERBOSE_DEBUG_OUTPUT)
|
||||||
|
|
||||||
|
# On Windows debug library should have 'd' postfix.
|
||||||
|
IF (WIN32)
|
||||||
|
SET(CMAKE_DEBUG_POSTFIX "d")
|
||||||
|
elseif (APPLE)
|
||||||
|
set(CMAKE_DEBUG_POSTFIX "_debug")
|
||||||
|
endif (WIN32)
|
||||||
|
|
||||||
|
# BUILD_SHARED_LIBS is cmake variable. Need to change default value.
|
||||||
|
option(BUILD_SHARED_LIBS "Build shared library" ON)
|
||||||
|
|
||||||
|
OPTION(OSX_FRAMEWORK "Build a Mac OS X Framework")
|
||||||
|
SET(FRAMEWORK_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/Library/Frameworks"
|
||||||
|
CACHE PATH "Where to place qjson.framework if OSX_FRAMEWORK is selected")
|
||||||
|
|
||||||
|
option(QT4_BUILD "Force building with Qt4 even if Qt5 is found")
|
||||||
|
IF (NOT QT4_BUILD)
|
||||||
|
FIND_PACKAGE( Qt5Core QUIET )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF (Qt5Core_FOUND)
|
||||||
|
MESSAGE ("Qt5 found")
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(${Qt5Core_INCLUDE_DIRS})
|
||||||
|
ADD_DEFINITIONS(${Qt5Core_DEFINITIONS})
|
||||||
|
SET(PC_Requires "Qt5Core")
|
||||||
|
set(QJSON_SUFFIX "-qt5")
|
||||||
|
# Tell CMake to run moc when necessary:
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
# As moc files are generated in the binary dir, tell CMake
|
||||||
|
# to always look for includes there:
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_USE_QSTRINGBUILDER" )
|
||||||
|
MESSAGE ("Enable QStringBuilder")
|
||||||
|
ELSE()
|
||||||
|
MESSAGE ("Qt5 not found, searching for Qt4")
|
||||||
|
|
||||||
|
# Don't use absolute path in qjson-targets-*.cmake
|
||||||
|
# (This will have no effect with CMake < 2.8)
|
||||||
|
# Workaround for no stdlib.h error. In this case it must be used with
|
||||||
|
# -DQT_INCLUDE_DIRS_NO_SYSTEM=ON. So cmake must be invoked with
|
||||||
|
# -DQT_USE_IMPORTED_TARGETS=OFF -DQT_INCLUDE_DIRS_NO_SYSTEM=ON
|
||||||
|
# See https://bugzilla.redhat.com/show_bug.cgi?id=1470809 for details
|
||||||
|
OPTION(QT_USE_IMPORTED_TARGETS "Use imported targets" ON)
|
||||||
|
|
||||||
|
# Find Qt4
|
||||||
|
FIND_PACKAGE( Qt4 4.5 REQUIRED QtCore)
|
||||||
|
# QStringBuilder is supported since Qt 4.8 for both QString and QByteArray
|
||||||
|
IF (NOT (${QT_VERSION_MINOR} STRLESS "8"))
|
||||||
|
MESSAGE ("Enable QStringBuilder")
|
||||||
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_USE_QSTRINGBUILDER" )
|
||||||
|
ELSE()
|
||||||
|
MESSAGE ("Disable QStringBuilder")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Ensure to be linked with static Qt library on Widnows
|
||||||
|
IF(WIN32 AND NOT BUILD_SHARED_LIBS)
|
||||||
|
STRING(REPLACE "-DQT_DLL" "" QT_DEFINITIONS "${QT_DEFINITIONS}")
|
||||||
|
SET(QT_DEFINITIONS ${QT_DEFINITIONS} "-DQT_NODLL")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Include the cmake file needed to use qt4
|
||||||
|
INCLUDE( ${QT_USE_FILE} )
|
||||||
|
SET(PC_Requires "QtCore")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF (NOT WIN32)
|
||||||
|
SET( QT_DONT_USE_QTGUI TRUE )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
|
#add extra search paths for libraries and includes
|
||||||
|
SET (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
|
||||||
|
SET (LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Directory where lib will install")
|
||||||
|
SET (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The directory the headers are installed in")
|
||||||
|
SET (CMAKECONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake/${CMAKE_PROJECT_NAME}${QJSON_SUFFIX}" CACHE PATH "Directory where to install QJSONConfig.cmake")
|
||||||
|
|
||||||
|
set(QJSON_LIB_MAJOR_VERSION "0")
|
||||||
|
set(QJSON_LIB_MINOR_VERSION "9")
|
||||||
|
set(QJSON_LIB_PATCH_VERSION "0")
|
||||||
|
|
||||||
|
set(QJSON_LIB_VERSION_STRING "${QJSON_LIB_MAJOR_VERSION}.${QJSON_LIB_MINOR_VERSION}.${QJSON_LIB_PATCH_VERSION}")
|
||||||
|
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" )
|
||||||
|
|
||||||
|
# pkg-config
|
||||||
|
IF (NOT WIN32)
|
||||||
|
CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/QJson.pc.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/QJson${QJSON_SUFFIX}.pc
|
||||||
|
@ONLY)
|
||||||
|
INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/QJson${QJSON_SUFFIX}.pc
|
||||||
|
DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
||||||
|
ENDIF (NOT WIN32)
|
||||||
|
|
||||||
|
# Subdirs
|
||||||
|
ADD_SUBDIRECTORY(src)
|
||||||
|
IF (KDE4_BUILD_TESTS OR QJSON_BUILD_TESTS)
|
||||||
|
enable_testing()
|
||||||
|
ADD_SUBDIRECTORY(tests)
|
||||||
|
ENDIF (KDE4_BUILD_TESTS OR QJSON_BUILD_TESTS)
|
||||||
|
|
||||||
|
CONFIGURE_FILE(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
|
IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
INSTALL(EXPORT qjson-export DESTINATION ${CMAKECONFIG_INSTALL_DIR} FILE QJSON${QJSON_SUFFIX}Targets.cmake)
|
||||||
|
|
||||||
|
# figure out the relative path from the installed Config.cmake file to the install prefix (which may be at
|
||||||
|
# runtime different from the chosen CMAKE_INSTALL_PREFIX if under Windows the package was installed anywhere)
|
||||||
|
# This relative path will be configured into the QJSONConfig.cmake
|
||||||
|
file(RELATIVE_PATH relInstallDir ${CMAKE_INSTALL_PREFIX}/${CMAKECONFIG_INSTALL_DIR} ${CMAKE_INSTALL_PREFIX} )
|
||||||
|
|
||||||
|
# cmake-modules
|
||||||
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/QJSONConfig.cmake.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/QJSON${QJSON_SUFFIX}Config.cmake
|
||||||
|
@ONLY)
|
||||||
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/QJSONConfigVersion.cmake.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/QJSON${QJSON_SUFFIX}ConfigVersion.cmake
|
||||||
|
@ONLY)
|
||||||
|
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/QJSON${QJSON_SUFFIX}Config.cmake
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/QJSON${QJSON_SUFFIX}ConfigVersion.cmake
|
||||||
|
DESTINATION "${CMAKECONFIG_INSTALL_DIR}")
|
||||||
|
|
||||||
|
ADD_CUSTOM_TARGET(uninstall
|
||||||
|
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
|
@ -0,0 +1,504 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License version 2.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
Tue Nov 29 16:35:04 CET 2016 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Release 0.9.0:
|
||||||
|
- Qt5 support
|
||||||
|
- Added indent to arrays
|
||||||
|
- Replaced the scanner with a new Flex-based one
|
||||||
|
- Bison 2.7 compatibility
|
||||||
|
|
||||||
|
Mon Jan 28 23:01:40 CET 2013 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Fix compilation on BlackBerry 10.
|
||||||
|
|
||||||
|
Tue Nov 27 11:04:12 CET 2012 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Relase 0.8.1:
|
||||||
|
- ensure API and ABI compatibility with 0.7.1
|
||||||
|
|
||||||
|
Thu Nov 22 21:20:11 CET 2012 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Fix unsafe pointer usage in Serializer::serialize()
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Wed Nov 21 22:01:51 CET 2012 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Version 0.8.0 released
|
||||||
|
|
||||||
|
Tue Nov 20 11:19:49 CET 2012 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Serializer: handle QVariantHash
|
||||||
|
|
||||||
|
Tue Oct 30 15:50:10 CET 2012 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Improve error handling inside of Serializer
|
||||||
|
* Serializer: handle quint16.
|
||||||
|
|
||||||
|
Tue Jan 31 10:15:06 CET 2012 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Make possible to build qjson as an OS X framework.
|
||||||
|
|
||||||
|
Fri Nov 04 16:50:56 CET 2011 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Make possible to set double precision during serialization.
|
||||||
|
|
||||||
|
Wed Aug 24 17:58:56 CEST 2011 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Buildsystem adjustments, fix issues mentioned here:
|
||||||
|
- http://lists.kde.org/?l=kde-buildsystem&m=130947194605100&w=3
|
||||||
|
- http://lists.kde.org/?l=kde-buildsystem&m=128835747626464&w=3
|
||||||
|
The biggest difference now is that FindQJSON.cmake is not provided
|
||||||
|
anymore. Instead, QJSONConfig.cmake and QJSONConfigVersion.cmake are
|
||||||
|
installed and can be used in find_package(QJSON) calls. Applications
|
||||||
|
using QJson can write their own FindQJSON.cmake files if they need to.
|
||||||
|
|
||||||
|
Fri Apr 23:04:29 CEST 2011 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Fixed QVariant de-serialization. QVariant properties were ignored
|
||||||
|
during QVariant -> QObject conversion.
|
||||||
|
|
||||||
|
Sun Dec 18:59:28 CET 2010 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* It's now possible to indent the output produced by the Serializer.
|
||||||
|
|
||||||
|
Mon Sep 06 18:53:02 CEST 2010 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* 50% performance improvement when parsing numbers.
|
||||||
|
|
||||||
|
Sun Jul 04 15:41:08 CEST 2010 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* fix make install when not installing as root
|
||||||
|
* provide "make uninstall"
|
||||||
|
|
||||||
|
Tue Jun 15 13:16:57 CEST 2010 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
* Allow top level values
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Sat Mar 13 23:57:00 CEST 2009 - flavio@castelli.name
|
||||||
|
|
||||||
|
* Merged the symbian branch into master,
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Sun Oct 11 19:18:00 CEST 2009 - flavio@castelli.name
|
||||||
|
|
||||||
|
* Updated to 0.6.3: fixed a bug affecting ulonglong numbers serialization.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Sep 15 19:21:00 CEST 2009 - flavio@castelli.name
|
||||||
|
|
||||||
|
* Updated to 0.6.2: fixed a bug affecting ulonglong numbers parsing.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Sep 09 09:55:00 CEST 2009 - flavio@castelli.name
|
||||||
|
|
||||||
|
* Updated to 0.6.1: relevant bugs fixed.
|
||||||
|
* Moved the SerializerRunnable class inside QJson namespace.
|
||||||
|
* Fixed a bug in cmdline_tester.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Jul 20 15:24:32 CEST 2009 - prusnak@suse.cz
|
||||||
|
|
||||||
|
* Updated to 0.6.0 (KDE SVN rev 999750).
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Apr 07 00:00:00 UTC 2009 - flavio@castelli.name
|
||||||
|
|
||||||
|
* Released 0.5.1 - added unicode support.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Apr 03 00:00:00 UTC 2009 - flavio@castelli.name
|
||||||
|
|
||||||
|
* First release.
|
|
@ -0,0 +1,6 @@
|
||||||
|
GET_FILENAME_COMPONENT(myDir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||||
|
|
||||||
|
SET(QJSON_LIBRARIES qjson)
|
||||||
|
SET(QJSON_INCLUDE_DIR "@INCLUDE_INSTALL_DIR@")
|
||||||
|
|
||||||
|
include(${myDir}/QJSON@QJSON_SUFFIX@Targets.cmake)
|
|
@ -0,0 +1,9 @@
|
||||||
|
SET(PACKAGE_VERSION "@QJSON_LIB_VERSION_STRING@")
|
||||||
|
IF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
|
||||||
|
SET(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
ENDIF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
|
||||||
|
IF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
|
||||||
|
SET(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
ELSE (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
|
||||||
|
SET(PACKAGE_VERSION_UNSUITABLE TRUE)
|
||||||
|
ENDIF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
|
|
@ -0,0 +1,11 @@
|
||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
libdir=@LIB_INSTALL_DIR@
|
||||||
|
includedir=@INCLUDE_INSTALL_DIR@
|
||||||
|
|
||||||
|
Name: QJson
|
||||||
|
Description: QJson is a qt-based library that maps JSON data to QVariant objects
|
||||||
|
Version: @QJSON_LIB_MAJOR_VERSION@.@QJSON_LIB_MINOR_VERSION@.@QJSON_LIB_PATCH_VERSION@
|
||||||
|
Requires: @PC_Requires@
|
||||||
|
Libs: -L${libdir} -lqjson@QJSON_SUFFIX@
|
||||||
|
Cflags: -I${includedir}
|
|
@ -0,0 +1,89 @@
|
||||||
|
Qjson version xxxx, Date
|
||||||
|
|
||||||
|
The following files are licensed under LGPL V2.1:
|
||||||
|
------------------------------------------------
|
||||||
|
src/json_parser.yy
|
||||||
|
src/json_scanner.cpp
|
||||||
|
src/json_scanner.h
|
||||||
|
src/parser.cpp
|
||||||
|
src/parser.h
|
||||||
|
src/parser_p.h
|
||||||
|
src/parserrunnable.cpp
|
||||||
|
src/parserrunnable.h
|
||||||
|
src/qjson_debug.h
|
||||||
|
src/qjson_export.h
|
||||||
|
src/qobjecthelper.cpp
|
||||||
|
src/serializer.cpp
|
||||||
|
src/qobjecthelper.h
|
||||||
|
src/serializer.h
|
||||||
|
src/serializerrunnable.cpp
|
||||||
|
src/serializerrunnable.h
|
||||||
|
tests/cmdline_tester/cmdline_tester.cpp
|
||||||
|
tests/cmdline_tester/cmdlineparser.cpp
|
||||||
|
tests/cmdline_tester/cmdlineparser.h
|
||||||
|
tests/parser/testparser.cpp
|
||||||
|
tests/qobjecthelper/person.h
|
||||||
|
tests/qobjecthelper/testqobjecthelper.cpp
|
||||||
|
tests/serializer/testserializer.cpp
|
||||||
|
|
||||||
|
|
||||||
|
The following files are licensed under GPL V2 with Bison Exception:
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
/src/json_parser.cc
|
||||||
|
/src/stack.hh
|
||||||
|
/src/location.hh
|
||||||
|
/src/position.hh
|
||||||
|
/src/json_parser.hh
|
||||||
|
|
||||||
|
|
||||||
|
Copyrights:
|
||||||
|
----------
|
||||||
|
Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||||
|
Copyright (C) 2009 Flavio Castelli <flavio@castelli.name> 2009 Frank Osterfeld <osterfeld@kde.org>
|
||||||
|
Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
|
||||||
|
Copyright (C) 2009 Till Adam <adam@kde.org>
|
||||||
|
Copyright (C) 2009 Michael Leupold <lemma@confuego.org>
|
||||||
|
Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
|
||||||
|
Copyright (C) 2009 Frank Osterfeld <osterfeld@kde.org>
|
||||||
|
Copyright (C) 2009 Pino Toscano <pino@kde.org>
|
||||||
|
Copyright (C) 2010 Flavio Castelli <flavio@castelli.name>
|
||||||
|
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999:
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
Checkout COPYING.lib
|
||||||
|
|
||||||
|
|
||||||
|
GPL V2 with Bison Exception:
|
||||||
|
----------------------------
|
||||||
|
Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
As a special exception, you may create a larger work that contains
|
||||||
|
part or all of the Bison parser skeleton and distribute that work
|
||||||
|
under terms of your choice, so long as that work isn't itself a
|
||||||
|
parser generator using the skeleton or a modified version thereof
|
||||||
|
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||||
|
the parser skeleton itself, you may (at your option) remove this
|
||||||
|
special exception, which will cause the skeleton and the resulting
|
||||||
|
Bison output files to be licensed under the GNU General Public
|
||||||
|
License without this special exception.
|
||||||
|
|
||||||
|
This special exception was added by the Free Software Foundation in
|
||||||
|
version 2.2 of Bison.
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
# QJson [![Build Status](https://travis-ci.org/flavio/qjson.svg?branch=master)](https://travis-ci.org/flavio/qjson)
|
||||||
|
|
||||||
|
JSON (JavaScript Object Notation) is a lightweight data-interchange format.
|
||||||
|
It can represents integer, real number, string, an ordered sequence of value, and a collection of name/value pairs.
|
||||||
|
|
||||||
|
QJson is a qt-based library that maps JSON data to QVariant objects.
|
||||||
|
JSON arrays will be mapped to QVariantList instances, while JSON's objects will be mapped to QVariantMap.
|
||||||
|
|
||||||
|
# Install
|
||||||
|
|
||||||
|
QJson requires:
|
||||||
|
- Qt 4.5 or greater
|
||||||
|
- cmake 2.6 or greater
|
||||||
|
|
||||||
|
Some possible cmake options:
|
||||||
|
- `-DCMAKE_BUILD_TYPE=DEBUG`: enables some debug output (other than making
|
||||||
|
easier to debug the code)
|
||||||
|
- `-DQJSON_BUILD_TESTS=yes` or `-DKDE4_BUILD_TESTS=yes`: builds the unit tests
|
||||||
|
- `-DCMAKE_INSTALL_PREFIX=${HOME}/testinstall`: install qjson in a custom directory
|
||||||
|
- `-DCMAKE_INCLUDE_PATH=${HOME}/testinstall/include`: include a custom include directory
|
||||||
|
- `-DCMAKE_LIBRARY_PATH=${HOME}/testinstall/lib`: include a custom library directory
|
||||||
|
- `-DLIB_DESTINATION=lib64`: if you have a 64 bit system with separate
|
||||||
|
libraries for 64 bit libraries
|
||||||
|
- `-DQJSON_VERBOSE_DEBUG_OUTPUT:BOOL=ON`: more debugging statements are
|
||||||
|
generated by the parser. It's useful only if you are trying to fix
|
||||||
|
the bison grammar.
|
||||||
|
|
||||||
|
For Unix/Linux/Mac:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX=_preferred_path_ ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
/sbin/ldconfig #if necessary
|
||||||
|
|
||||||
|
# Contribute
|
||||||
|
|
||||||
|
The recommended way to submit your changes is via a pull request.
|
||||||
|
|
||||||
|
Before submitting a patch please ensure:
|
||||||
|
|
||||||
|
* Patched code compiles.
|
||||||
|
* The patch is fixing a specific issue or implementing a new feature
|
||||||
|
(it’s not doing multiple things at the same time).
|
||||||
|
* QJson unit tests have been updated.
|
||||||
|
* QJson unit tests are passing.
|
||||||
|
|
||||||
|
## Unit testing
|
||||||
|
|
||||||
|
QJson unit tests are located under the `tests` directory. You can enable them
|
||||||
|
passing the `-DQJSON_BUILD_TESTS=yes` option to `cmake`.
|
||||||
|
|
||||||
|
> Note well: make sure you followed the build instructions.
|
||||||
|
|
||||||
|
|
||||||
|
To run all the unit tests move into the build directory and type:
|
||||||
|
|
||||||
|
```
|
||||||
|
make tests
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to run the `QJson::Parser` unit tests just type:
|
||||||
|
|
||||||
|
```
|
||||||
|
./test/parser/testparser
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to run the `QJson::Serializer` unit tests just type:
|
||||||
|
|
||||||
|
```
|
||||||
|
./test/serializer/testserializer
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to run the `QJson::QObjectHelper` tests just type:
|
||||||
|
|
||||||
|
```
|
||||||
|
./tests/qobjecthelper/testqobjecthelper
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to test the QJson parser against a specific JSON object you can
|
||||||
|
use the `cmdline_tester` program.
|
||||||
|
|
||||||
|
This binary is located under the `tests` directory and has a
|
||||||
|
straightforward syntax:
|
||||||
|
|
||||||
|
```
|
||||||
|
./tests/cmdline_tester/cmdline_tester text_file_containing_json_object
|
||||||
|
```
|
||||||
|
|
||||||
|
The command will convert the JSON object to a `QVariant` and dump it to stdout.
|
||||||
|
More options are available via cli options, just checkout the `--help` output.
|
||||||
|
|
||||||
|
|
||||||
|
**Note well:** cmdline_tester relies on `qDebug()` to dump the object. `qDebug`
|
||||||
|
has some limitations, like being unable to print utf8 chars.
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
This library is licensed under the Lesser GNU General Public License version 2.1.
|
||||||
|
See the COPYING.lib file for more information.
|
||||||
|
|
||||||
|
# Resources
|
||||||
|
|
||||||
|
* [Website](http://qjson.sourceforge.net/)
|
||||||
|
* [Mailing List](https://lists.sourceforge.net/mailman/listinfo/qjson-devel)
|
||||||
|
* Project Lead/Maintainer (2008-current): [Flavio Castelli](mailto:flavio@castelli.name).
|
|
@ -0,0 +1,17 @@
|
||||||
|
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
|
||||||
|
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
|
||||||
|
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||||
|
STRING(REGEX REPLACE "\n" ";" files "${files}")
|
||||||
|
FOREACH(file ${files})
|
||||||
|
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
|
||||||
|
EXEC_PROGRAM(
|
||||||
|
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||||
|
OUTPUT_VARIABLE rm_out
|
||||||
|
RETURN_VALUE rm_retval
|
||||||
|
)
|
||||||
|
IF(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
|
||||||
|
ENDIF(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
ENDFOREACH(file)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,32 @@
|
||||||
|
<hr>
|
||||||
|
<table width="100%">
|
||||||
|
<tr>
|
||||||
|
<td width="10%" align="left" valign="center">
|
||||||
|
<a href="http://sourceforge.net">
|
||||||
|
<img
|
||||||
|
src="http://sourceforge.net/sflogo.php?group_id=144446"
|
||||||
|
width="88" height="31" border="0" alt="SourceForge Logo"></a>
|
||||||
|
</td>
|
||||||
|
<td width="20%" align="left" valign="center">
|
||||||
|
hosts this site.
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td align="right" valign="center">
|
||||||
|
Send comments to:<br>
|
||||||
|
<a href="mailto:qjson-devel@lists.sourceforge.net">QJson Developers</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||||
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var pageTracker = _gat._getTracker("UA-3214988-2");
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>
|
||||||
|
QJson - a Qt based library for mapping JSON data to QVariant objects
|
||||||
|
</title>
|
||||||
|
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="tabs.css" rel="stylesheet" type="text/css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#ffffff">
|
||||||
|
<a href="http://qjson.sourceforge.net">QJson home page</a>
|
||||||
|
|
||||||
|
<hr>
|
|
@ -0,0 +1,87 @@
|
||||||
|
/**
|
||||||
|
\mainpage
|
||||||
|
\section _intro Introduction
|
||||||
|
|
||||||
|
<a HREF="http://www.json.org/">JSON (JavaScript Object Notation)</a>
|
||||||
|
is a lightweight data-interchange format.
|
||||||
|
It can represents integer, real number, string, an ordered sequence of value, and
|
||||||
|
a collection of name/value pairs.
|
||||||
|
|
||||||
|
QJson is a qt-based library that maps JSON data to QVariant objects.
|
||||||
|
|
||||||
|
JSON arrays will be mapped to QVariantList instances, while JSON's objects will
|
||||||
|
be mapped to QVariantMap.
|
||||||
|
|
||||||
|
\section _usage Usage
|
||||||
|
Converting JSON's data to QVariant instance is really simple:
|
||||||
|
\code
|
||||||
|
// create a JSonDriver instance
|
||||||
|
QJson::Parser parser;
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
// json is a QString containing the data to convert
|
||||||
|
QVariant result = parser.parse (json, &ok);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Suppose you're going to convert this JSON data:
|
||||||
|
\verbatim
|
||||||
|
{
|
||||||
|
"encoding" : "UTF-8",
|
||||||
|
"plug-ins" : [
|
||||||
|
"python",
|
||||||
|
"c++",
|
||||||
|
"ruby"
|
||||||
|
],
|
||||||
|
"indent" : { "length" : 3, "use_space" : true }
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
The following code would convert the JSON data and parse it:
|
||||||
|
\code
|
||||||
|
QJson::Parser parser;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
QVariantMap result = parser.parse (json, &ok).toMap();
|
||||||
|
if (!ok) {
|
||||||
|
qFatal("An error occured during parsing");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "encoding:" << result["encoding"].toString();
|
||||||
|
qDebug() << "plugins:";
|
||||||
|
|
||||||
|
foreach (QVariant plugin, result["plug-ins"].toList()) {
|
||||||
|
qDebug() << "\t-" << plugin.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap nestedMap = result["indent"].toMap();
|
||||||
|
qDebug() << "length:" << nestedMap["length"].toInt();
|
||||||
|
qDebug() << "use_space:" << nestedMap["use_space"].toBool();
|
||||||
|
\endcode
|
||||||
|
The output would be:
|
||||||
|
\verbatim
|
||||||
|
encoding: "UTF-8"
|
||||||
|
plugins:
|
||||||
|
- "python"
|
||||||
|
- "c++"
|
||||||
|
- "ruby"
|
||||||
|
length: 3
|
||||||
|
use_space: true
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
The QJson::QObjectHelper class permits to serialize QObject instances into JSON. QJson::QObjectHelper also allows to
|
||||||
|
initialize a QObject using the values stored inside of a JSON object.
|
||||||
|
|
||||||
|
\section _build Build instructions
|
||||||
|
QJson build system is based on cmake. Download QJson sources, extract them, move inside the sources directory and then:
|
||||||
|
\code
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\author Flavio Castelli <flavio@castelli.name>
|
||||||
|
*/
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../../src/parser.h"
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../../src/qobjecthelper.h"
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../../src/serializer.h"
|
|
@ -0,0 +1,3 @@
|
||||||
|
moc_*
|
||||||
|
*.o
|
||||||
|
Makefile
|
|
@ -0,0 +1,73 @@
|
||||||
|
# add_custom_command (OUTPUT ${qjson_SOURCE_DIR}/lib/json_parser.cc
|
||||||
|
# PRE_BUILD
|
||||||
|
# COMMAND bison -t -o json_parser.cc -d json_parser.yy
|
||||||
|
# DEPENDS json_parser.yy
|
||||||
|
# WORKING_DIRECTORY ${qjson_SOURCE_DIR}/lib/
|
||||||
|
# )
|
||||||
|
|
||||||
|
# To regenerate json_scanner.cc use:
|
||||||
|
# flex json_scanner.yy
|
||||||
|
|
||||||
|
set(qjson_MOC_HDRS
|
||||||
|
parserrunnable.h
|
||||||
|
serializerrunnable.h
|
||||||
|
)
|
||||||
|
|
||||||
|
IF (NOT Qt5Core_FOUND)
|
||||||
|
qt4_wrap_cpp(qjson_MOC_SRCS ${qjson_MOC_HDRS})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
set (qjson_SRCS parser.cpp qobjecthelper.cpp json_scanner.cpp json_parser.cc parserrunnable.cpp serializer.cpp serializerrunnable.cpp)
|
||||||
|
set (qjson_HEADERS parser.h parserrunnable.h qobjecthelper.h serializer.h serializerrunnable.h qjson_export.h)
|
||||||
|
|
||||||
|
# Required to use the intree copy of FlexLexer.h
|
||||||
|
INCLUDE_DIRECTORIES(.)
|
||||||
|
|
||||||
|
# Special hack to fix scanner test compilation on Windows
|
||||||
|
# JsonScanner class is not for export. So need to make static
|
||||||
|
# lib what can be compiled against scanner test.
|
||||||
|
if(WIN32 AND QJSON_BUILD_TESTS AND BUILD_SHARED_LIBS)
|
||||||
|
add_library(qjson_scanner STATIC json_scanner.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library (qjson${QJSON_SUFFIX} ${qjson_SRCS} ${qjson_MOC_SRCS} ${qjson_HEADERS})
|
||||||
|
IF (Qt5Core_FOUND)
|
||||||
|
target_link_libraries( qjson${QJSON_SUFFIX} ${Qt5Core_LIBRARIES})
|
||||||
|
ELSE()
|
||||||
|
target_link_libraries( qjson${QJSON_SUFFIX} ${QT_LIBRARIES})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
if(NOT ANDROID)
|
||||||
|
set_target_properties(qjson${QJSON_SUFFIX} PROPERTIES
|
||||||
|
VERSION ${QJSON_LIB_MAJOR_VERSION}.${QJSON_LIB_MINOR_VERSION}.${QJSON_LIB_PATCH_VERSION}
|
||||||
|
SOVERSION ${QJSON_LIB_MAJOR_VERSION}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT BUILD_SHARED_LIBS)
|
||||||
|
set_target_properties( qjson${QJSON_SUFFIX} PROPERTIES COMPILE_DEFINITIONS "QJSON_STATIC")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(qjson${QJSON_SUFFIX} PROPERTIES
|
||||||
|
DEFINE_SYMBOL QJSON_MAKEDLL
|
||||||
|
PUBLIC_HEADER "${qjson_HEADERS}"
|
||||||
|
FRAMEWORK ${OSX_FRAMEWORK}
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALL(TARGETS qjson${QJSON_SUFFIX} EXPORT qjson-export
|
||||||
|
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||||
|
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||||
|
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
|
||||||
|
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/qjson${QJSON_SUFFIX}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
get_target_property(LOCATION qjson LOCATION_DEBUG)
|
||||||
|
string(REGEX REPLACE "\\.[^.]*$" ".pdb" LOCATION "${LOCATION}")
|
||||||
|
install(FILES ${LOCATION} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin CONFIGURATIONS Debug)
|
||||||
|
|
||||||
|
get_target_property(LOCATION qjson LOCATION_RELWITHDEBINFO)
|
||||||
|
string(REGEX REPLACE "\\.[^.]*$" ".pdb" LOCATION "${LOCATION}")
|
||||||
|
install(FILES ${LOCATION} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin CONFIGURATIONS RelWithDebInfo)
|
||||||
|
endif(MSVC)
|
|
@ -0,0 +1,206 @@
|
||||||
|
// -*-C++-*-
|
||||||
|
// FlexLexer.h -- define interfaces for lexical analyzer classes generated
|
||||||
|
// by flex
|
||||||
|
|
||||||
|
// Copyright (c) 1993 The Regents of the University of California.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This code is derived from software contributed to Berkeley by
|
||||||
|
// Kent Williams and Tom Epperly.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions
|
||||||
|
// are met:
|
||||||
|
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// 2. 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 the University 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||||
|
// IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE.
|
||||||
|
|
||||||
|
// This file defines FlexLexer, an abstract class which specifies the
|
||||||
|
// external interface provided to flex C++ lexer objects, and yyFlexLexer,
|
||||||
|
// which defines a particular lexer class.
|
||||||
|
//
|
||||||
|
// If you want to create multiple lexer classes, you use the -P flag
|
||||||
|
// to rename each yyFlexLexer to some other xxFlexLexer. You then
|
||||||
|
// include <FlexLexer.h> in your other sources once per lexer class:
|
||||||
|
//
|
||||||
|
// #undef yyFlexLexer
|
||||||
|
// #define yyFlexLexer xxFlexLexer
|
||||||
|
// #include <FlexLexer.h>
|
||||||
|
//
|
||||||
|
// #undef yyFlexLexer
|
||||||
|
// #define yyFlexLexer zzFlexLexer
|
||||||
|
// #include <FlexLexer.h>
|
||||||
|
// ...
|
||||||
|
|
||||||
|
#ifndef __FLEX_LEXER_H
|
||||||
|
// Never included before - need to define base class.
|
||||||
|
#define __FLEX_LEXER_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
# ifndef FLEX_STD
|
||||||
|
# define FLEX_STD std::
|
||||||
|
# endif
|
||||||
|
|
||||||
|
extern "C++" {
|
||||||
|
|
||||||
|
struct yy_buffer_state;
|
||||||
|
typedef int yy_state_type;
|
||||||
|
|
||||||
|
class FlexLexer {
|
||||||
|
public:
|
||||||
|
virtual ~FlexLexer() { }
|
||||||
|
|
||||||
|
const char* YYText() const { return yytext; }
|
||||||
|
int YYLeng() const { return yyleng; }
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0;
|
||||||
|
virtual struct yy_buffer_state*
|
||||||
|
yy_create_buffer( FLEX_STD istream* s, int size ) = 0;
|
||||||
|
virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0;
|
||||||
|
virtual void yyrestart( FLEX_STD istream* s ) = 0;
|
||||||
|
|
||||||
|
virtual int yylex() = 0;
|
||||||
|
|
||||||
|
// Call yylex with new input/output sources.
|
||||||
|
int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 )
|
||||||
|
{
|
||||||
|
switch_streams( new_in, new_out );
|
||||||
|
return yylex();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to new input/output streams. A nil stream pointer
|
||||||
|
// indicates "keep the current one".
|
||||||
|
virtual void switch_streams( FLEX_STD istream* new_in = 0,
|
||||||
|
FLEX_STD ostream* new_out = 0 ) = 0;
|
||||||
|
|
||||||
|
int lineno() const { return yylineno; }
|
||||||
|
|
||||||
|
int debug() const { return yy_flex_debug; }
|
||||||
|
void set_debug( int flag ) { yy_flex_debug = flag; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
char* yytext;
|
||||||
|
int yyleng;
|
||||||
|
int yylineno; // only maintained if you use %option yylineno
|
||||||
|
int yy_flex_debug; // only has effect with -d or "%option debug"
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // FLEXLEXER_H
|
||||||
|
|
||||||
|
#if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce)
|
||||||
|
// Either this is the first time through (yyFlexLexerOnce not defined),
|
||||||
|
// or this is a repeated include to define a different flavor of
|
||||||
|
// yyFlexLexer, as discussed in the flex manual.
|
||||||
|
#define yyFlexLexerOnce
|
||||||
|
|
||||||
|
extern "C++" {
|
||||||
|
|
||||||
|
class yyFlexLexer : public FlexLexer {
|
||||||
|
public:
|
||||||
|
// arg_yyin and arg_yyout default to the cin and cout, but we
|
||||||
|
// only make that assignment when initializing in yylex().
|
||||||
|
yyFlexLexer( FLEX_STD istream* arg_yyin = 0, FLEX_STD ostream* arg_yyout = 0 );
|
||||||
|
|
||||||
|
virtual ~yyFlexLexer();
|
||||||
|
|
||||||
|
void yy_switch_to_buffer( struct yy_buffer_state* new_buffer );
|
||||||
|
struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size );
|
||||||
|
void yy_delete_buffer( struct yy_buffer_state* b );
|
||||||
|
void yyrestart( FLEX_STD istream* s );
|
||||||
|
|
||||||
|
void yypush_buffer_state( struct yy_buffer_state* new_buffer );
|
||||||
|
void yypop_buffer_state();
|
||||||
|
|
||||||
|
virtual int yylex();
|
||||||
|
virtual void switch_streams( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 );
|
||||||
|
virtual int yywrap();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int LexerInput( char* buf, int max_size );
|
||||||
|
virtual void LexerOutput( const char* buf, int size );
|
||||||
|
virtual void LexerError( const char* msg );
|
||||||
|
|
||||||
|
void yyunput( int c, char* buf_ptr );
|
||||||
|
int yyinput();
|
||||||
|
|
||||||
|
void yy_load_buffer_state();
|
||||||
|
void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream* s );
|
||||||
|
void yy_flush_buffer( struct yy_buffer_state* b );
|
||||||
|
|
||||||
|
int yy_start_stack_ptr;
|
||||||
|
int yy_start_stack_depth;
|
||||||
|
int* yy_start_stack;
|
||||||
|
|
||||||
|
void yy_push_state( int new_state );
|
||||||
|
void yy_pop_state();
|
||||||
|
int yy_top_state();
|
||||||
|
|
||||||
|
yy_state_type yy_get_previous_state();
|
||||||
|
yy_state_type yy_try_NUL_trans( yy_state_type current_state );
|
||||||
|
int yy_get_next_buffer();
|
||||||
|
|
||||||
|
FLEX_STD istream* yyin; // input source for default LexerInput
|
||||||
|
FLEX_STD ostream* yyout; // output sink for default LexerOutput
|
||||||
|
|
||||||
|
// yy_hold_char holds the character lost when yytext is formed.
|
||||||
|
char yy_hold_char;
|
||||||
|
|
||||||
|
// Number of characters read into yy_ch_buf.
|
||||||
|
int yy_n_chars;
|
||||||
|
|
||||||
|
// Points to current character in buffer.
|
||||||
|
char* yy_c_buf_p;
|
||||||
|
|
||||||
|
int yy_init; // whether we need to initialize
|
||||||
|
int yy_start; // start state number
|
||||||
|
|
||||||
|
// Flag which is used to allow yywrap()'s to do buffer switches
|
||||||
|
// instead of setting up a fresh yyin. A bit of a hack ...
|
||||||
|
int yy_did_buffer_switch_on_eof;
|
||||||
|
|
||||||
|
|
||||||
|
size_t yy_buffer_stack_top; /**< index of top of stack. */
|
||||||
|
size_t yy_buffer_stack_max; /**< capacity of stack. */
|
||||||
|
struct yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */
|
||||||
|
void yyensure_buffer_stack(void);
|
||||||
|
|
||||||
|
// The following are not always needed, but may be depending
|
||||||
|
// on use of certain flex features (like REJECT or yymore()).
|
||||||
|
|
||||||
|
yy_state_type yy_last_accepting_state;
|
||||||
|
char* yy_last_accepting_cpos;
|
||||||
|
|
||||||
|
yy_state_type* yy_state_buf;
|
||||||
|
yy_state_type* yy_state_ptr;
|
||||||
|
|
||||||
|
char* yy_full_match;
|
||||||
|
int* yy_full_state;
|
||||||
|
int yy_full_lp;
|
||||||
|
|
||||||
|
int yy_lp;
|
||||||
|
int yy_looking_for_trail_begin;
|
||||||
|
|
||||||
|
int yy_more_flag;
|
||||||
|
int yy_more_len;
|
||||||
|
int yy_more_offset;
|
||||||
|
int yy_prev_more_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // yyFlexLexer || ! yyFlexLexerOnce
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,300 @@
|
||||||
|
/* A Bison parser, made by GNU Bison 2.7. */
|
||||||
|
|
||||||
|
/* Skeleton interface for Bison LALR(1) parsers in C++
|
||||||
|
|
||||||
|
Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* As a special exception, you may create a larger work that contains
|
||||||
|
part or all of the Bison parser skeleton and distribute that work
|
||||||
|
under terms of your choice, so long as that work isn't itself a
|
||||||
|
parser generator using the skeleton or a modified version thereof
|
||||||
|
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||||
|
the parser skeleton itself, you may (at your option) remove this
|
||||||
|
special exception, which will cause the skeleton and the resulting
|
||||||
|
Bison output files to be licensed under the GNU General Public
|
||||||
|
License without this special exception.
|
||||||
|
|
||||||
|
This special exception was added by the Free Software Foundation in
|
||||||
|
version 2.2 of Bison. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
** \file json_parser.hh
|
||||||
|
** Define the yy::parser class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* C++ LALR(1) parser skeleton written by Akim Demaille. */
|
||||||
|
|
||||||
|
#ifndef YY_YY_JSON_PARSER_HH_INCLUDED
|
||||||
|
# define YY_YY_JSON_PARSER_HH_INCLUDED
|
||||||
|
|
||||||
|
/* "%code requires" blocks. */
|
||||||
|
/* Line 33 of lalr1.cc */
|
||||||
|
#line 26 "json_parser.yy"
|
||||||
|
|
||||||
|
#include "parser_p.h"
|
||||||
|
#include "json_scanner.h"
|
||||||
|
#include "qjson_debug.h"
|
||||||
|
|
||||||
|
#include <QtCore/QByteArray>
|
||||||
|
#include <QtCore/QMap>
|
||||||
|
#include <QtCore/QString>
|
||||||
|
#include <QtCore/QVariant>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
class JSonScanner;
|
||||||
|
|
||||||
|
namespace QJson {
|
||||||
|
class Parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YYERROR_VERBOSE 1
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(QVector<QVariant>*)
|
||||||
|
Q_DECLARE_METATYPE(QVariantMap*)
|
||||||
|
|
||||||
|
|
||||||
|
/* Line 33 of lalr1.cc */
|
||||||
|
#line 72 "json_parser.hh"
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include "stack.hh"
|
||||||
|
#include "location.hh"
|
||||||
|
|
||||||
|
/* Enabling traces. */
|
||||||
|
#ifndef YYDEBUG
|
||||||
|
# define YYDEBUG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace yy {
|
||||||
|
/* Line 33 of lalr1.cc */
|
||||||
|
#line 88 "json_parser.hh"
|
||||||
|
|
||||||
|
/// A Bison parser.
|
||||||
|
class json_parser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Symbol semantic values.
|
||||||
|
#ifndef YYSTYPE
|
||||||
|
typedef int semantic_type;
|
||||||
|
#else
|
||||||
|
typedef YYSTYPE semantic_type;
|
||||||
|
#endif
|
||||||
|
/// Symbol locations.
|
||||||
|
typedef location location_type;
|
||||||
|
/// Tokens.
|
||||||
|
struct token
|
||||||
|
{
|
||||||
|
/* Tokens. */
|
||||||
|
enum yytokentype {
|
||||||
|
END = 0,
|
||||||
|
CURLY_BRACKET_OPEN = 1,
|
||||||
|
CURLY_BRACKET_CLOSE = 2,
|
||||||
|
SQUARE_BRACKET_OPEN = 3,
|
||||||
|
SQUARE_BRACKET_CLOSE = 4,
|
||||||
|
COLON = 5,
|
||||||
|
COMMA = 6,
|
||||||
|
NUMBER = 7,
|
||||||
|
TRUE_VAL = 8,
|
||||||
|
FALSE_VAL = 9,
|
||||||
|
NULL_VAL = 10,
|
||||||
|
STRING = 11,
|
||||||
|
INVALID = 12
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
/// Token type.
|
||||||
|
typedef token::yytokentype token_type;
|
||||||
|
|
||||||
|
/// Build a parser object.
|
||||||
|
json_parser (QJson::ParserPrivate* driver_yyarg);
|
||||||
|
virtual ~json_parser ();
|
||||||
|
|
||||||
|
/// Parse.
|
||||||
|
/// \returns 0 iff parsing succeeded.
|
||||||
|
virtual int parse ();
|
||||||
|
|
||||||
|
#if YYDEBUG
|
||||||
|
/// The current debugging stream.
|
||||||
|
std::ostream& debug_stream () const;
|
||||||
|
/// Set the current debugging stream.
|
||||||
|
void set_debug_stream (std::ostream &);
|
||||||
|
|
||||||
|
/// Type for debugging levels.
|
||||||
|
typedef int debug_level_type;
|
||||||
|
/// The current debugging level.
|
||||||
|
debug_level_type debug_level () const;
|
||||||
|
/// Set the current debugging level.
|
||||||
|
void set_debug_level (debug_level_type l);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Report a syntax error.
|
||||||
|
/// \param loc where the syntax error is found.
|
||||||
|
/// \param msg a description of the syntax error.
|
||||||
|
virtual void error (const location_type& loc, const std::string& msg);
|
||||||
|
|
||||||
|
/// Generate an error message.
|
||||||
|
/// \param state the state where the error occurred.
|
||||||
|
/// \param tok the lookahead token.
|
||||||
|
virtual std::string yysyntax_error_ (int yystate, int tok);
|
||||||
|
|
||||||
|
#if YYDEBUG
|
||||||
|
/// \brief Report a symbol value on the debug stream.
|
||||||
|
/// \param yytype The token type.
|
||||||
|
/// \param yyvaluep Its semantic value.
|
||||||
|
/// \param yylocationp Its location.
|
||||||
|
virtual void yy_symbol_value_print_ (int yytype,
|
||||||
|
const semantic_type* yyvaluep,
|
||||||
|
const location_type* yylocationp);
|
||||||
|
/// \brief Report a symbol on the debug stream.
|
||||||
|
/// \param yytype The token type.
|
||||||
|
/// \param yyvaluep Its semantic value.
|
||||||
|
/// \param yylocationp Its location.
|
||||||
|
virtual void yy_symbol_print_ (int yytype,
|
||||||
|
const semantic_type* yyvaluep,
|
||||||
|
const location_type* yylocationp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/// State numbers.
|
||||||
|
typedef int state_type;
|
||||||
|
/// State stack type.
|
||||||
|
typedef stack<state_type> state_stack_type;
|
||||||
|
/// Semantic value stack type.
|
||||||
|
typedef stack<semantic_type> semantic_stack_type;
|
||||||
|
/// location stack type.
|
||||||
|
typedef stack<location_type> location_stack_type;
|
||||||
|
|
||||||
|
/// The state stack.
|
||||||
|
state_stack_type yystate_stack_;
|
||||||
|
/// The semantic value stack.
|
||||||
|
semantic_stack_type yysemantic_stack_;
|
||||||
|
/// The location stack.
|
||||||
|
location_stack_type yylocation_stack_;
|
||||||
|
|
||||||
|
/// Whether the given \c yypact_ value indicates a defaulted state.
|
||||||
|
/// \param yyvalue the value to check
|
||||||
|
static bool yy_pact_value_is_default_ (int yyvalue);
|
||||||
|
|
||||||
|
/// Whether the given \c yytable_ value indicates a syntax error.
|
||||||
|
/// \param yyvalue the value to check
|
||||||
|
static bool yy_table_value_is_error_ (int yyvalue);
|
||||||
|
|
||||||
|
/// Internal symbol numbers.
|
||||||
|
typedef unsigned char token_number_type;
|
||||||
|
/* Tables. */
|
||||||
|
/// For a state, the index in \a yytable_ of its portion.
|
||||||
|
static const signed char yypact_[];
|
||||||
|
static const signed char yypact_ninf_;
|
||||||
|
|
||||||
|
/// For a state, default reduction number.
|
||||||
|
/// Unless\a yytable_ specifies something else to do.
|
||||||
|
/// Zero means the default is an error.
|
||||||
|
static const unsigned char yydefact_[];
|
||||||
|
|
||||||
|
static const signed char yypgoto_[];
|
||||||
|
static const signed char yydefgoto_[];
|
||||||
|
|
||||||
|
/// What to do in a state.
|
||||||
|
/// \a yytable_[yypact_[s]]: what to do in state \a s.
|
||||||
|
/// - if positive, shift that token.
|
||||||
|
/// - if negative, reduce the rule which number is the opposite.
|
||||||
|
/// - if zero, do what YYDEFACT says.
|
||||||
|
static const unsigned char yytable_[];
|
||||||
|
static const signed char yytable_ninf_;
|
||||||
|
|
||||||
|
static const signed char yycheck_[];
|
||||||
|
|
||||||
|
/// For a state, its accessing symbol.
|
||||||
|
static const unsigned char yystos_[];
|
||||||
|
|
||||||
|
/// For a rule, its LHS.
|
||||||
|
static const unsigned char yyr1_[];
|
||||||
|
/// For a rule, its RHS length.
|
||||||
|
static const unsigned char yyr2_[];
|
||||||
|
|
||||||
|
/// Convert the symbol name \a n to a form suitable for a diagnostic.
|
||||||
|
static std::string yytnamerr_ (const char *n);
|
||||||
|
|
||||||
|
|
||||||
|
/// For a symbol, its name in clear.
|
||||||
|
static const char* const yytname_[];
|
||||||
|
#if YYDEBUG
|
||||||
|
/// A type to store symbol numbers and -1.
|
||||||
|
typedef signed char rhs_number_type;
|
||||||
|
/// A `-1'-separated list of the rules' RHS.
|
||||||
|
static const rhs_number_type yyrhs_[];
|
||||||
|
/// For each rule, the index of the first RHS symbol in \a yyrhs_.
|
||||||
|
static const unsigned char yyprhs_[];
|
||||||
|
/// For each rule, its source line number.
|
||||||
|
static const unsigned char yyrline_[];
|
||||||
|
/// For each scanner token number, its symbol number.
|
||||||
|
static const unsigned short int yytoken_number_[];
|
||||||
|
/// Report on the debug stream that the rule \a r is going to be reduced.
|
||||||
|
virtual void yy_reduce_print_ (int r);
|
||||||
|
/// Print the state stack on the debug stream.
|
||||||
|
virtual void yystack_print_ ();
|
||||||
|
|
||||||
|
/* Debugging. */
|
||||||
|
int yydebug_;
|
||||||
|
std::ostream* yycdebug_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Convert a scanner token number \a t to a symbol number.
|
||||||
|
token_number_type yytranslate_ (int t);
|
||||||
|
|
||||||
|
/// \brief Reclaim the memory associated to a symbol.
|
||||||
|
/// \param yymsg Why this token is reclaimed.
|
||||||
|
/// If null, do not display the symbol, just free it.
|
||||||
|
/// \param yytype The symbol type.
|
||||||
|
/// \param yyvaluep Its semantic value.
|
||||||
|
/// \param yylocationp Its location.
|
||||||
|
inline void yydestruct_ (const char* yymsg,
|
||||||
|
int yytype,
|
||||||
|
semantic_type* yyvaluep,
|
||||||
|
location_type* yylocationp);
|
||||||
|
|
||||||
|
/// Pop \a n symbols the three stacks.
|
||||||
|
inline void yypop_ (unsigned int n = 1);
|
||||||
|
|
||||||
|
/* Constants. */
|
||||||
|
static const int yyeof_;
|
||||||
|
/* LAST_ -- Last index in TABLE_. */
|
||||||
|
static const int yylast_;
|
||||||
|
static const int yynnts_;
|
||||||
|
static const int yyempty_;
|
||||||
|
static const int yyfinal_;
|
||||||
|
static const int yyterror_;
|
||||||
|
static const int yyerrcode_;
|
||||||
|
static const int yyntokens_;
|
||||||
|
static const unsigned int yyuser_token_number_max_;
|
||||||
|
static const token_number_type yyundef_token_;
|
||||||
|
|
||||||
|
/* User arguments. */
|
||||||
|
QJson::ParserPrivate* driver;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // yy
|
||||||
|
/* Line 33 of lalr1.cc */
|
||||||
|
#line 297 "json_parser.hh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !YY_YY_JSON_PARSER_HH_INCLUDED */
|
|
@ -0,0 +1,161 @@
|
||||||
|
/* This file is part of QJSon
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
|
||||||
|
* Copyright (C) 2013 Silvio Moioli <silvio@moioli.net>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; see the file COPYING.LIB. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
%skeleton "lalr1.cc"
|
||||||
|
%defines
|
||||||
|
%define "parser_class_name" "json_parser"
|
||||||
|
|
||||||
|
%code requires{
|
||||||
|
#include "parser_p.h"
|
||||||
|
#include "json_scanner.h"
|
||||||
|
#include "qjson_debug.h"
|
||||||
|
|
||||||
|
#include <QtCore/QByteArray>
|
||||||
|
#include <QtCore/QMap>
|
||||||
|
#include <QtCore/QString>
|
||||||
|
#include <QtCore/QVariant>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
class JSonScanner;
|
||||||
|
|
||||||
|
namespace QJson {
|
||||||
|
class Parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YYERROR_VERBOSE 1
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(QVector<QVariant>*)
|
||||||
|
Q_DECLARE_METATYPE(QVariantMap*)
|
||||||
|
}
|
||||||
|
|
||||||
|
%parse-param { QJson::ParserPrivate* driver }
|
||||||
|
%lex-param { QJson::ParserPrivate* driver }
|
||||||
|
|
||||||
|
%locations
|
||||||
|
|
||||||
|
%debug
|
||||||
|
%error-verbose
|
||||||
|
|
||||||
|
%token END 0 "end of file"
|
||||||
|
|
||||||
|
%token CURLY_BRACKET_OPEN 1 "{"
|
||||||
|
%token CURLY_BRACKET_CLOSE 2 "}"
|
||||||
|
%token SQUARE_BRACKET_OPEN 3 "["
|
||||||
|
%token SQUARE_BRACKET_CLOSE 4 "]"
|
||||||
|
%token COLON 5 ":"
|
||||||
|
%token COMMA 6 ","
|
||||||
|
|
||||||
|
%token NUMBER 7 "number"
|
||||||
|
%token TRUE_VAL 8 "true"
|
||||||
|
%token FALSE_VAL 9 "false"
|
||||||
|
%token NULL_VAL 10 "null"
|
||||||
|
%token STRING 11 "string"
|
||||||
|
|
||||||
|
%token INVALID 12 "invalid"
|
||||||
|
|
||||||
|
// define the initial token
|
||||||
|
%start start
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
// grammar rules
|
||||||
|
|
||||||
|
start: data {
|
||||||
|
driver->m_result = $1;
|
||||||
|
qjsonDebug() << "json_parser - parsing finished";
|
||||||
|
};
|
||||||
|
|
||||||
|
data: value { $$ = $1; }
|
||||||
|
| error
|
||||||
|
{
|
||||||
|
qCritical()<< "json_parser - syntax error found, "
|
||||||
|
<< "forcing abort, Line" << @$.begin.line << "Column" << @$.begin.column;
|
||||||
|
YYABORT;
|
||||||
|
};
|
||||||
|
|
||||||
|
object: CURLY_BRACKET_OPEN CURLY_BRACKET_CLOSE {
|
||||||
|
$$ = QVariant(QVariantMap());
|
||||||
|
}
|
||||||
|
| CURLY_BRACKET_OPEN members CURLY_BRACKET_CLOSE {
|
||||||
|
QVariantMap* map = $2.value<QVariantMap*>();
|
||||||
|
$$ = QVariant(*map);
|
||||||
|
delete map;
|
||||||
|
};
|
||||||
|
|
||||||
|
members: STRING COLON value {
|
||||||
|
QVariantMap* pair = new QVariantMap();
|
||||||
|
pair->insert($1.toString(), $3);
|
||||||
|
$$.setValue<QVariantMap* >(pair);
|
||||||
|
}
|
||||||
|
| members COMMA STRING COLON value {
|
||||||
|
$$.value<QVariantMap*>()->insert($3.toString(), $5);
|
||||||
|
};
|
||||||
|
|
||||||
|
array: SQUARE_BRACKET_OPEN SQUARE_BRACKET_CLOSE {
|
||||||
|
$$ = QVariant(QVariantList());
|
||||||
|
}
|
||||||
|
| SQUARE_BRACKET_OPEN values SQUARE_BRACKET_CLOSE {
|
||||||
|
QVector<QVariant>* list = $2.value<QVector<QVariant>* >();
|
||||||
|
$$ = QVariant(list->toList());
|
||||||
|
delete list;
|
||||||
|
};
|
||||||
|
|
||||||
|
values: value {
|
||||||
|
QVector<QVariant>* list = new QVector<QVariant>(1);
|
||||||
|
list->replace(0, $1);
|
||||||
|
$$.setValue(list);
|
||||||
|
}
|
||||||
|
| values COMMA value {
|
||||||
|
$$.value<QVector<QVariant>* >()->append($3);
|
||||||
|
};
|
||||||
|
|
||||||
|
value: STRING
|
||||||
|
| NUMBER
|
||||||
|
| TRUE_VAL
|
||||||
|
| FALSE_VAL
|
||||||
|
| NULL_VAL
|
||||||
|
| object
|
||||||
|
| array;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver)
|
||||||
|
{
|
||||||
|
JSonScanner* scanner = driver->m_scanner;
|
||||||
|
yylval->clear();
|
||||||
|
int ret = scanner->yylex(yylval, yylloc);
|
||||||
|
|
||||||
|
qjsonDebug() << "json_parser::yylex - calling scanner yylval==|"
|
||||||
|
<< yylval->toByteArray() << "|, ret==|" << QString::number(ret) << "|";
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void yy::json_parser::error (const yy::location& yyloc, const std::string& error)
|
||||||
|
{
|
||||||
|
/*qjsonDebug() << yyloc.begin.line;
|
||||||
|
qjsonDebug() << yyloc.begin.column;
|
||||||
|
qjsonDebug() << yyloc.end.line;
|
||||||
|
qjsonDebug() << yyloc.end.column;*/
|
||||||
|
qjsonDebug() << "json_parser::error [line" << yyloc.end.line << "] -" << error.c_str() ;
|
||||||
|
driver->setError(QString::fromLatin1(error.c_str()), yyloc.end.line);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,82 @@
|
||||||
|
/* This file is part of QJson
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
|
||||||
|
* Copyright (C) 2013 Silvio Moioli <silvio@moioli.net>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; see the file COPYING.LIB. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "json_scanner.cc"
|
||||||
|
|
||||||
|
#include "qjson_debug.h"
|
||||||
|
#include "json_scanner.h"
|
||||||
|
#include "json_parser.hh"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QRegExp>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
|
JSonScanner::JSonScanner(QIODevice* io)
|
||||||
|
: m_allowSpecialNumbers(false),
|
||||||
|
m_io (io),
|
||||||
|
m_criticalError(false),
|
||||||
|
m_C_locale(QLocale::C)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
JSonScanner::~JSonScanner()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void JSonScanner::allowSpecialNumbers(bool allow) {
|
||||||
|
m_allowSpecialNumbers = allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc) {
|
||||||
|
m_yylval = yylval;
|
||||||
|
m_yylloc = yylloc;
|
||||||
|
m_yylloc->step();
|
||||||
|
int result = yylex();
|
||||||
|
|
||||||
|
if (m_criticalError) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JSonScanner::LexerInput(char* buf, int max_size) {
|
||||||
|
if (!m_io->isOpen()) {
|
||||||
|
qCritical() << "JSonScanner::yylex - io device is not open";
|
||||||
|
m_criticalError = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readBytes = m_io->read(buf, max_size);
|
||||||
|
if(readBytes < 0) {
|
||||||
|
qCritical() << "JSonScanner::yylex - error while reading from io device";
|
||||||
|
m_criticalError = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return readBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue